An ADHD-friendly regular task tracker
修订版 | 5e95eea18e5d87dd915e9ad159590a7be8281765 (tree) |
---|---|
时间 | 2024-03-10 06:12:32 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Fix up the calendrical maths.
@@ -18,26 +18,62 @@ def root(): return "Working on it..." | ||
18 | 18 | SHOW_QUERY = """ |
19 | 19 | select label, description, updated_at, consequences_after_s from tasks |
20 | 20 | where updated_at + available_every_s <= unixepoch() and wheel = ? |
21 | -order by updated_at + consequences_after_s | |
21 | +order by updated_at + consequences_after_s desc | |
22 | +""" | |
23 | + | |
24 | +SHOW_ALL_QUERY = """ | |
25 | +select description, available_every_s, consequences_after_s from tasks | |
26 | +where wheel=? | |
27 | +order by updated_at asc | |
22 | 28 | """ |
23 | 29 | |
24 | 30 | def roundUp(delta): return timedelta(seconds=delta).days + 1 |
25 | 31 | def roundDown(delta): return timedelta(seconds=delta).days - 1 |
26 | 32 | |
27 | 33 | def formatTask(row): |
34 | + label = html.escape(row[0]) | |
28 | 35 | now = datetime.now() |
29 | 36 | updated_at = datetime.fromtimestamp(row[2]) |
30 | 37 | updated_delta = now - updated_at |
31 | 38 | consequences_after = timedelta(seconds=row[3]) |
32 | 39 | consequences_at = updated_at + consequences_after |
33 | - consequences_delta = now - consequences_at | |
34 | - return "<li>{1} ({0}): Last done {2} ago, needs to be done within {3}</li>".format( | |
35 | - html.escape(row[0]), html.escape(row[1]), updated_delta, | |
36 | - consequences_delta) | |
40 | + if consequences_at <= now: | |
41 | + warning = "needs to be done immediately or there will be consequences" | |
42 | + else: | |
43 | + consequences_delta = consequences_at - now | |
44 | + warning = "needs to be done within %d days" % consequences_delta.days | |
45 | + return "<li>{1} ({0}): Last done {2} days ago, {3}</li>".format( | |
46 | + label, html.escape(row[1]), updated_delta.days + 1, warning) | |
47 | + | |
48 | +def formatEvery(row): | |
49 | + description = html.escape(row[0]) | |
50 | + available_every = timedelta(seconds=row[1]).days | |
51 | + consequences_after = timedelta(seconds=row[2]).days | |
52 | + return "<li>{0}: every {1} days, no less than every {2} days</li>".format( | |
53 | + description, available_every, consequences_after) | |
37 | 54 | |
38 | 55 | @app.route("/show/<wheel>") |
39 | 56 | def show(wheel): |
40 | - l = "".join(formatTask(row) for row in cursor().execute(SHOW_QUERY, (wheel,))) | |
41 | - return "<!DOCTYPE html><h1>Tasks for {0}</h1><ol>{1}</ol>".format(wheel, l) | |
57 | + c = cursor() | |
58 | + l = "".join(formatTask(row) for row in c.execute(SHOW_QUERY, (wheel,))) | |
59 | + dets = "".join(formatEvery(row) | |
60 | + for row in c.execute(SHOW_ALL_QUERY, (wheel,))) | |
61 | + return "<!DOCTYPE html><h1>Tasks for {0}</h1><ol>{1}</ol><details><ul>{2}</ul></details>".format(wheel, l, dets) | |
62 | + | |
63 | +UPDATED_AT_QUERY = """ | |
64 | +select 1 from tasks | |
65 | +where wheel=? and label=? | |
66 | +""" | |
67 | + | |
68 | +@app.route("/do/<wheel>/<label>", methods=("POST",)) | |
69 | +def do(wheel, label): | |
70 | + c = cursor() | |
71 | + t = c.execute(UPDATED_AT_QUERY, (wheel, label)).fetchone() | |
72 | + if not t: return "No such task!" | |
73 | + | |
74 | + c.execute("update tasks set updated_at=? where wheel=? and label=?", | |
75 | + (time.time(), wheel, label)) | |
76 | + c.commit() | |
77 | + return "Task done! Nice!" | |
42 | 78 | |
43 | 79 | app.run(debug=True, host="0.0.0.0", port=1312) |
@@ -49,7 +49,7 @@ def show(wheel): | ||
49 | 49 | for row in c.execute(SHOW_QUERY, (wheel,)): |
50 | 50 | print("Task:", row[1], "(" + row[0] + ")") |
51 | 51 | |
52 | -updated_at_query = """ | |
52 | +UPDATED_AT_QUERY = """ | |
53 | 53 | select updated_at from tasks |
54 | 54 | where wheel=? and label=? |
55 | 55 | """ |
@@ -59,7 +59,7 @@ where wheel=? and label=? | ||
59 | 59 | @click.argument("labels", nargs=-1) |
60 | 60 | def do(wheel, labels): |
61 | 61 | for label in labels: |
62 | - t = c.execute(updated_at_query, (wheel, label)).fetchone() | |
62 | + t = c.execute(UPDATED_AT_QUERY, (wheel, label)).fetchone() | |
63 | 63 | if not t: |
64 | 64 | print("No such task") |
65 | 65 | continue |
@@ -25,6 +25,10 @@ | ||
25 | 25 | chmod +x $out/bin/* |
26 | 26 | patchShebangs $out/bin/every{,-card} |
27 | 27 | ''; |
28 | + doCheck = true; | |
29 | + checkPhase = '' | |
30 | + ${pkgs.python311Packages.pyflakes}/bin/pyflakes $out/bin/* | |
31 | + ''; | |
28 | 32 | }; |
29 | 33 | in { |
30 | 34 | packages.default = every; |