mirror of
https://github.com/GothenburgBitFactory/timewarrior.git
synced 2025-07-07 20:06:39 +02:00
600 lines
25 KiB
Text
600 lines
25 KiB
Text
Timewarrior
|
||
===========
|
||
Tracking time is complex and means different things to different people. It can
|
||
range from being as simple as:
|
||
|
||
$ timew track 9am - now "Prepare for staff meeting"
|
||
$ timew track "Staff meeting"
|
||
|
||
Or as sophisticated as:
|
||
|
||
$ timew track backfill last week "Design proposal"
|
||
|
||
For fully automated time tracking, as the line above exhibits, weekly and daily
|
||
schedules must be considered. For such a tool to be useful, it must support all
|
||
the above, and make time tracking very simple.
|
||
|
||
|
||
Goals
|
||
-----
|
||
Provide a personal tool to easily track time spent and generate reports in
|
||
multiple formats and styles. The tool will "do the right thing" as much as
|
||
possible, to make detailed time tracking easy, and not a burden.
|
||
|
||
Open Source. Localized.
|
||
|
||
|
||
Non-Goals
|
||
---------
|
||
- No cloud support.
|
||
- No multi-user support.
|
||
- No sync support.
|
||
- No precision higher than a minute.
|
||
|
||
|
||
Integration
|
||
-----------
|
||
- As a sister-product to Taskwarrior and Tasksh, integration should be as
|
||
simple as installing a hook script.
|
||
- An export and import feature, using JSON, will allow further integration with
|
||
arbitrary tools.
|
||
|
||
|
||
Definitions
|
||
-----------
|
||
- A timeline is a continuum that is the one-dimensional space that timestamps
|
||
and intervals map onto.
|
||
- A timestamp is a point on a timeline.
|
||
- An interval is a span of time on a timeline, consisting of two timestamps,
|
||
with associated tags. An interval may be an inclusion or an exclusion. A
|
||
weekend is an exclusion, time spent working is an inclusion.
|
||
- A tag is an arbitrary UTF8 string, which may contain whitespace.
|
||
- A workweek is defined by exclusions - a set of excluded intervals representing
|
||
time not spent working. Those intervals are tagged to be easily identifiable.
|
||
- Lunch could be an inclusion, but tagged as non-work. It could also be an
|
||
exclusion.
|
||
- The time resolution is 1 minute.
|
||
|
||
|
||
Rule System Use Cases
|
||
---------------------
|
||
A rule system should be able to evaluate conditions and perform actions, which
|
||
include continuing to process rules, or stopping. The conditions will need to
|
||
access configuration, exclusions, and tracking data.
|
||
|
||
- A constraint on total tracking time, "do not spend more than 4 hours on x".
|
||
- A constraint that only allows certain tags to be used together, to prevent
|
||
client 1 from being billed for project 2.
|
||
- A constraint that only allows multiples of 15-minute intervals.
|
||
|
||
Ref: http://martinfowler.com/bliki/RulesEngine.html
|
||
|
||
Example rules (assuming Python-like syntax):
|
||
|
||
define rule exclusions:
|
||
holidays eng-USA
|
||
workweek mon,tue,wed,thu,fri
|
||
workday start 510
|
||
workday end 1050
|
||
workday tue end 900
|
||
resolution 1min
|
||
|
||
define rule my_rule:
|
||
if sum_week(+tag1) > 12:
|
||
fail "The 'tag1' tag cannot exceed 12 hours/wk"
|
||
|
||
(needs work)
|
||
|
||
The 'sum_week' function is an example of exposed functionality, and there
|
||
needs to be many of these, in order to make the rule system capable.
|
||
|
||
|
||
CLI Syntax
|
||
----------
|
||
The CLI shall have a well-defined and unambiguous grammar.
|
||
|
||
timew start [<tagset>]
|
||
timew stop [<tagset>]
|
||
timew track [<interval>] [<tagset>]
|
||
timew [<filter>] report <report>
|
||
|
||
|
||
CLI Grammar
|
||
-----------
|
||
|
||
interval: <timestamp> "-" <timestamp>
|
||
<timestamp> "to" <timestamp>
|
||
"from" <timestamp> "to" <timestamp>
|
||
"until" <timestamp>
|
||
"from" <timestamp>
|
||
|
||
timestamp: <day> <time>
|
||
|
||
month: "january"
|
||
"february"
|
||
...
|
||
|
||
day: "monday"
|
||
"tuesday"
|
||
...
|
||
|
||
time: \d{4}
|
||
\d{1,2} ":" \d{2} <ampm>
|
||
\d{1,2} ":" \d{2}
|
||
\d{1,2} <ampm>
|
||
\d{1,2}
|
||
|
||
ampm: "AM"
|
||
"am"
|
||
"a.m."
|
||
"PM"
|
||
"pm"
|
||
"p.m."
|
||
|
||
tagset: <tag>+
|
||
|
||
tag: string
|
||
|
||
string: "\"" .+ "\""
|
||
.+
|
||
|
||
|
||
Tags
|
||
----
|
||
Tags represent tracking categories. Tags are arbitrary UTF8 strings. A tag may
|
||
be a single unquoted word, or a quoted phrase.
|
||
|
||
A tag may be used without being defined, but if a tags is defined, then it may
|
||
have associated metadata, such as a start date representing the first date on
|
||
which it may be used, or an end date, when it expires. A tag may have a budget,
|
||
which is the maximum trackable time for a period.
|
||
|
||
|
||
Commands
|
||
--------
|
||
The command set may include:
|
||
|
||
define Modify configuration
|
||
track Record tracked time
|
||
report Run a report
|
||
tags Show all tags
|
||
query Extract an interval set
|
||
import Import JSON data
|
||
export Export JSON data
|
||
x Run extension 'x'
|
||
|
||
|
||
Macros
|
||
------
|
||
A macro is a keyword that can take arguments, and expands to a set of one or
|
||
more other timew commands, with some dynamic aspect. For example, the macro
|
||
named 'staff meeting' could be an interval that is on Wednesdays at 10:00, and
|
||
has a set of associated tags. This would then create an appropriately tagged
|
||
interval.
|
||
|
||
|
||
General Use Cases
|
||
-----------------
|
||
Suppose 'today' is 2015-11-24, a Tuesday at noon. This date is chosen because
|
||
it is mid-week, a holiday is coming up, and workday exceptions are typical.
|
||
Here is the timeline, with the successive exclusions added, as a work week is
|
||
defined:
|
||
|
||
2015
|
||
November December
|
||
W48 W49
|
||
23rd 24th 25th 26th 27th 28th 29th 30th 1st
|
||
Monday Tuesday Wednesday Thursday Friday Saturday Sunday Monday Tuesday
|
||
: : : : : : : : : :
|
||
:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:..:
|
||
0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0 6 12 18 0
|
||
|
|
||
| ------------ $ timew holidays eng-USA
|
||
| ------------------------ $ timew define workweek mon-fri
|
||
---- ---- | ---- ---- ---- ---- ---- ---- ---- $ timew define workday start 8:30am
|
||
--- | --- --- --- --- --- --- --- --- $ timew define workday end 1730
|
||
| ---- $ timew define workday tue end 3pm
|
||
|
|
||
+++++ ++++ +++++ +++++ +++++ +++++ Resulting work week
|
||
|
|
||
now
|
||
|
||
On that same timeline, here are some example tracked intervals:
|
||
|
||
|
|
||
++++++++++++ tag1 tag2 $ timew track +tag1 +tag2 yesterday
|
||
++++++++++++ tag1 tag2 $ timew track +tag1 +tag2 today
|
||
+ tag1 tag2 $ timew start +tag1 +tag2
|
||
+++++++++++++++++++ tag1 tag2 $ timew start +tag1 +tag2 backfill
|
||
+ tag3 | $ timew track +tag3 yesterday 2pm - 4pm
|
||
+ tag4 | $ timew track -tag3 +tag4 yesterday 2pm - 4pm
|
||
|
|
||
now
|
||
|
||
Here is the example data storage for the above workweek:
|
||
|
||
define rule exclusions:
|
||
holidays eng-USA
|
||
workweek mon,tue,wed,thu,fri
|
||
workday start 510
|
||
workday end 1050
|
||
workday tue end 900
|
||
|
||
Time tracking is based on the inclusion intervals derived from the above rule.
|
||
For week 48 those would be:
|
||
|
||
2015-11-23 510-1050
|
||
2015-11-24 510-900
|
||
2015-11-25 510-1050
|
||
2015-11-27 510-1050
|
||
|
||
Given these intervals, tracking becomes a set of basic modifications:
|
||
|
||
The date 'yesterday' refers to the whole day, and overrides any other
|
||
intervals:
|
||
|
||
$ timew track +tag1 +tag2 yesterday
|
||
|
||
--> 'yesterday' resolves to 2015-11-23
|
||
--> delete all intervals for 2015-11-23
|
||
--> obtain inclusions for 2015-11-23: 510-1050
|
||
--> store: 2015-11-23 0-1439 tag1 tag2
|
||
--> Describe the above in feedback
|
||
|
||
The date 'today' refers to the whole day, and overrides any other intervals:
|
||
|
||
$ timew track +tag1 +tag2 today
|
||
|
||
--> 'today' resolves to 2015-11-24
|
||
--> delete all intervals for 2015-11-24
|
||
--> obtain inclusions for 2015-11-24: 510-900
|
||
--> store: 2015-11-24 0-1439 tag1 tag2
|
||
|
||
The 'start' command uses 'now' (12:00pm) in this alternate example:
|
||
|
||
$ timew start +tag1 +tag2
|
||
|
||
--> 'now' resolves to 2015-11-24T12:00
|
||
--> obtain inclusions for 2015-11-24: 510-900
|
||
--> store: 2015-11-24 720- tag1 tag2
|
||
Note the open-ended interval
|
||
|
||
The 'start' recognizes 'backfill' to indicate that earlier, untracked
|
||
inclusions should be tracked:
|
||
|
||
$ timew start +tag1 +tag2 backfill
|
||
|
||
--> 'now' resolves to 2015-11-24T12:00
|
||
--> obtain inclusions for 2015-11-24: 510-900
|
||
--> store: 2015-11-24 510- tag1 tag2
|
||
Note the open-ended, back-dated interval
|
||
|
||
Inserting tracked time into an existing set of intervals:
|
||
|
||
$ timew track +tag3 yesterday 2pm - 4pm
|
||
|
||
--> 'yesterday' resolves to 2015-11-23
|
||
--> '2pm' - '4pm' resolves to 840-960
|
||
--> obtain inclusions for 2015-11-23: 510-1050
|
||
--> store: 2015-11-23 840-960 tag3
|
||
|
||
Change tagging for an interval:
|
||
|
||
$ timew track -tag3 +tag4 yesterday 2pm - 4pm
|
||
|
||
TBD
|
||
|
||
|
||
Not shown:
|
||
- $ timew holidays work 2015-11-26 # override the holiday
|
||
|
||
|
||
Data Format
|
||
-----------
|
||
A work week can be defined by a rule:
|
||
|
||
define rule exclusions:
|
||
holidays eng-USA
|
||
workweek mon,tue,wed,thu,fri
|
||
workday start 510
|
||
workday end 1050
|
||
workday tue end 900
|
||
|
||
In this compact form, it is easy to expand this template into a set of intervals
|
||
for a given week, and keeping the definition in this form allows simple
|
||
modification.
|
||
|
||
Intervals of tracked time can be stored in a text file, with one line of text
|
||
representing one daẏ. Here is a single tracked interval:
|
||
|
||
YYYY-MM-DD <start>-<end> <tagset>
|
||
|
||
Here is an open-ended, currently tracked active interval, notice the missing
|
||
<end> timestamp:
|
||
|
||
YYYY-MM-DD <start>- <tagset>
|
||
|
||
A typical day might look like this:
|
||
|
||
2015-12-10 480-720 Upgrade Planning, 780- Upgrade Presentation "ABCD Inc"
|
||
|
||
The "480-720" is a time range, in this case from 8:00am to 12:00pm, associated
|
||
with the two tags "Upgrade" and "Planning". A second interval started at 1:00pm
|
||
and is incomplete, associated with three tags "Upgrade", "Presentation" and
|
||
"ABCD Inc". A tag must be quoted, if it contains whitespace.
|
||
|
||
|
||
Reporting
|
||
---------
|
||
- Reports should have multiple output formats: TTY, JSON, HTML.
|
||
- There will be a few different types of reports:
|
||
- Tabular Calendar
|
||
- List with subtotals, total
|
||
- Reports will be decorated, for example, subtotals, legend, title
|
||
- It should be possible to extend Timewarrior to add custom reports, via a
|
||
simple hook mechanism.
|
||
|
||
|
||
Extensions
|
||
----------
|
||
A simple extension mechanism, similar to Taskwarrior would require an executable
|
||
script found in a defined location with a conformant name, which then is fed
|
||
queried raw data as stdin.
|
||
|
||
For example, this script clearly defines that it is a 'report' extension named
|
||
'abc'.
|
||
|
||
~/.timewarrior/extensions/report_abc
|
||
|
||
|
||
Unsolved Issues
|
||
---------------
|
||
- Multiple timelines?
|
||
- Terminology for backwards and forwards tracking (backfill for the past, and
|
||
just assume everythign else is for the future)?
|
||
- Given this:
|
||
$ timew track yesterday 9am - 5pm tag1
|
||
What does this do:
|
||
$ timew track yesterday 10am - 11am tag2
|
||
Does it yield:
|
||
a) yesterday 540-1020 tag, 600-660 tag2 # overlap
|
||
b) yesterday 540-600 tag1, 600-660 tag2, 660-1020 tag1 # no overlap
|
||
c) yesterday 540-600 tag1, 600-660 tag1 tag2, 660-1020 tag1 # explicit overlap
|
||
Stating 'track yesterday 10am - 11am tag2' sounds imperative, thus overriding
|
||
any existing tags in that interval. Perhaps a 'merge' keyword could be added
|
||
to combined the results (track yesterday 10am - 11am tag2 merge)?
|
||
- If the timelines are not collapsed until needed (report/export), then a command
|
||
like this on day 1:
|
||
$ timew start tag1
|
||
Followed by this on day 5:
|
||
$ timew stop
|
||
Needs to create a tracking record for each of the 5 days.
|
||
|
||
|
||
Raw Notes (Slack)
|
||
-----------------
|
||
|
||
F: start (frontfill) and backfill (end) could be considered orthogonal to each other. They just operate into different directions. but I think they behave the same, more or less.
|
||
|
||
F: Which brings me to the topic of overlapping intervals. While most of things would not be multitasking/overlapping. I could think of a few things that could be reported overlapping.
|
||
P: Agreed, I can multitask and be pursuing two results at the same time.
|
||
|
||
P: I can do all these [manipulations] with my finger. But not at the CLI. That means lists, and ID numbers, I think. Any thoughts?
|
||
F: List… Hm. Don’t we already have one implicitly with the timeline and timestamps?
|
||
P: Yes, but you’d need to view it, in order to identify which block should be manipulated.
|
||
F: Can’t that list not be a list of key/value pairs? The keys are the minutes of the day, the values the different tags (another list of key/values).
|
||
F: Then you just traverse the minutes in either direction.
|
||
F: If you want to extend an event just look at the minutes after it and change the stored tags...
|
||
|
||
P: You said earlier about time points, like monitoring systems. If I jsut drop a point at 8:55, then it could merge it with the 9:00 point because the tags match.
|
||
F: OTOH the command at 9:50 could also mean that the first block should go from 8:55 to 9:40. It was originally 45 minutes long. Should it now also be 45 minutes. Or do you want to extend it with 5mins from 8:55 to 9:45?
|
||
P: Your question above: should we move the block intact, or stretch it? I think that’s an important flexibility we need. so both.
|
||
|
||
---
|
||
|
||
P: I think that it needs to support the following, with zero configuration (ie no exclusions defined):
|
||
$ timew track “Packing my bags”
|
||
That means track the tag “Packing my bags” starting now. Additionally, direct data capture, with no magic:
|
||
$ timew start “Painting the kitchen”
|
||
$ timew stop “Painting the kitchen”
|
||
This is equivalent to the tw 30-second tutorial, and is easy to learn.
|
||
So it works like a chess clock - you just hit it. All times are evaluated as “now”.
|
||
F: Yes.
|
||
P: The missing part is:
|
||
$ timew report foo
|
||
Which shows a report named ‘foo’ of the captured data. easy.
|
||
|
||
F: What about IDs to make this even easier or just “stop” that actuates on the last start?
|
||
P: I think a “start” leaves and open-ended time range: 2015-12-10 791- “Painting the kitchen"
|
||
The 791 corresponds to my local 1631EST (60 * 16 + 31), with no end time.
|
||
F: yes. but i mean more like...
|
||
$ timew track “Packing my bags"
|
||
Tracking [1] “packing my bags"
|
||
$ timew stop 1
|
||
or just
|
||
$ timew stop
|
||
P: The latter works in this example, so no need for ID there. IDs might be useful if I’m tracking two things at once, ie no single active thing.
|
||
F: exactly. it would avoid typing descriptions...
|
||
P: okay, good. Noted.
|
||
|
||
P: So only if you define a workweek, does the following make sense:
|
||
$ timew track last week “Installing shelves"
|
||
“last week” clearly means all week, so it can query the timeline for a list of untracked time, then add intervals to fill it. Similarly:
|
||
$ timew track today “Paint door”
|
||
That can mean fill all time up until now. You could add a keyword “fill” to that, and maybe it goes to end of day.
|
||
|
||
F: yes. or use other time modifiers...
|
||
today until now
|
||
today from now
|
||
|
||
P: Right. My point here is that “backfill” and “fill” are not necessarily needed, and can be implied from the “last week”. Obviously this implies no fill:
|
||
$ timew track yesterday 2pm - 4pm “Do this"
|
||
Yes - “today until now” could be an explicit version of “today”. “Today from now” is the same as “track”.
|
||
|
||
F: the fill thing could be used to indicate just a direction:
|
||
|
||
P: There is no open-ended fill though. The future is infinite, so we don’t want to actually record much. Anything bounded, yes (“until eod”), but anything unbounded (“track ‘do this’”) just leaves it open.
|
||
|
||
F: it fills from the last good point, goes backwards in time until it hits a stop/interval limit.
|
||
|
||
P: Yes, unless you bound it. ie “timew track last week ‘this thing’” can back fill within the “last week”, but exclude any otherwise tracked intervals.
|
||
Then we can support a “merge” keyword to overlap any tracked intervals.
|
||
|
||
F: If you add fill to this I would expect it to start at the end of last week, find the empty intervall and fill it until it hits a limit or another already filled interval.
|
||
So it only does one thing.
|
||
while the command without fill would operate on the entire week instead.
|
||
but this would just be me.
|
||
|
||
P: Let’s explore that. Suppose “last week” is 39 hours of nothing, and 1 hour of a meeting. Suppose we indicate (for clarity here) keywords as “:keyword”. The question then becomes what do the following do:
|
||
$ timew track last week “paint the thing”
|
||
$ timew track last week “paint the thing” :fill
|
||
Our choices are:
|
||
39 hours of “paint the thing” filled around the 1 hour “meeting”.
|
||
Or 40 hours of “paint the thing” overlapping with 1 hour “meeting”
|
||
Or 40 hours of “paint the thing”, and the meeting is gone
|
||
F: hm, b would be first choice.
|
||
“a" would be second or third.
|
||
P: Configurable maybe, or overridden with a keyword.
|
||
F: yeah. you could get a warning.
|
||
|
||
|
||
P: So there are lots of time specification formats to support:
|
||
until 4pm
|
||
from 11am
|
||
since 11am
|
||
3pm - 4pm
|
||
etc. Assume we support them all.
|
||
Also ranges:
|
||
last week
|
||
last month
|
||
monday
|
||
last monday
|
||
yesterday
|
||
etc. Assume we support them all
|
||
F: don’t forget 2000...
|
||
P: at 3pm for 2 hours Yes, 2000 - 9pm, mixing is okay
|
||
F: should we allow implicit tmes?
|
||
that is “guess” am or pm from the context.
|
||
P: Probably, yes, the same way that “monday” assumes the next one for tw, or maybe the last one in timew. Good point.
|
||
Tags are quoted strings or single words, all UTF8. If we don’t support whitespace, then you can’t track “Alpha Project” or some such code name, and I would anticipate complaints, as we have now for tw. So this means:
|
||
|
||
$ timew track “Paint the house” home painting
|
||
|
||
three “tags”.
|
||
|
||
|
||
|
||
P: Reports: We need some built-in reports:
|
||
$ timew report day
|
||
$ timew report day monday
|
||
$ timew report week
|
||
$ timew report month
|
||
$ timew report week +tag1 -tag2 <— has tag1, missing tag2, for creating client-specific reports
|
||
P: But we can’t anticipate all reports, and don’t have the manpower to implement them, therefore we need report extensions. Something like hooks for tw.
|
||
F: what would these create anyway? basic output format - some columns on the screen? how formatted?
|
||
I assume most people would want to feed the numbers into something else.
|
||
P: Yeah, not sure. Some kind of list, tabular, with subtotals.
|
||
Agree about what people might want.
|
||
But we could do this:
|
||
|
||
$ timew report week :tty (default)
|
||
$ timew report week :json
|
||
$ timew report week :html
|
||
|
||
They would support tags for filtering.
|
||
F: good.
|
||
P: But yes, most people will want custom, I expect. The number of reports would grow over time I think.
|
||
|
||
|
||
|
||
F: Let me short go back to fill.
|
||
P: ok
|
||
F: I think we could generally use it to “fill” around other already tracked events.
|
||
P: So a normal human only does one thing at a time.
|
||
F: Yes but then also to make a difference between this
|
||
say you had this:
|
||
timew track 9-10 meeting
|
||
so now a noon you realise that you don’t have anything tracked for 8-9 and 10-12.
|
||
If I then do timew track 8 "reading email” it either stops automatic tracking for email at 9 (or continues and erases meeting - whatever if that makes sence).
|
||
but with timew track 8 “reading email” fill it would do 8-9 mail and 10-12 mail around the 9-10 meeting.
|
||
I think it would be more logic to stop a tracking of an event if a new event comes along.
|
||
P: I like that: “timew track 8 read” fills in 8-9 and stops. “timew track 8 read :fill” fills in 8-9, 10-12.
|
||
F: Yes.
|
||
F: Perhaps this could be used in the same way for the yesterday example... So the double tracking would not occur.
|
||
P: Agreed.
|
||
F: Only when doing it explicitly.
|
||
P: There is a use-case for double tracking. Suppose I am a manager, and I do this:
|
||
$ timew track yesterday “paint the door” fredde
|
||
$ timew track yesterday “paint the window” paul
|
||
It’s a valid use case. So there would be some kind of configuration that says “this tag can overlap with that tag, but not itself”.
|
||
I thought of this: Using a tag with pre-defining it is what we have discussed so far.
|
||
But if a tag is predefined somehow (timew define tag “…”) then it could live in configuration, and have metadata, such as an expiration date. This corresponds to “you can’t bill this client after EOM”.
|
||
It could have a start date, which means “cannot bill before next month”.
|
||
Could also define overlap. This could be implemented using Rules.
|
||
|
||
|
||
|
||
On to Rules... The above, written in pseudo-python could be:
|
||
|
||
define rule xyz:
|
||
if tag == “foo” and start > 2015-12-31:
|
||
fail “tag ‘foo’ only valid until 2015-12-31"
|
||
|
||
So what we thought of in tw as configuration, could now be a rule. This approach covers several configurable settings, and is equivalent to:
|
||
|
||
tag.foo.end_date=2015-12-31
|
||
tag.foo.fail.message=tag ‘foo’ only valid until 2015-12-31
|
||
|
||
Same thing. But a rule has the potential to take multiple actions, or make the condition more complex. Therefore, more flexible.
|
||
F: So a rule could be invoked “once” after creating it to “translate” these un-explicit dates to real ones.
|
||
like an activation.
|
||
P: Maybe. Definitely if ‘EOM’ appears on the command line it gets expanded. I would think writing EOM in a rule file would be a mistake.
|
||
Notice that for the rule syntax, “define”, “if” and “fail” are all keywords that take arguments. Easy to parse/run.
|
||
F: yes.
|
||
Would timew group rules? Create some “namespace” for rules? So only certain rules are evaluated for certain tags?
|
||
would there be genereal rules? for all.(edited)
|
||
rule precedence? ordering of rules?
|
||
Just asking.(edited)
|
||
P: Yes. I did a fair amount of reading about rule systems. Here is briefly what I learned:
|
||
A rule system is just a way to iterate over a set of data items and apply late-bound logic. That is, it’s a loop that applies every rule in turn to the subject.
|
||
You need a way to maybe not run every rule. This can be done by storing them in memory, having scanned them to see what data is read to trigger them, then using that to filter a subset of the rules to apply.
|
||
Chaining rules is hard. Precedence is hard.
|
||
Having different species of rules is a good idea.
|
||
in other words, if the rule is:
|
||
|
||
define rule one:
|
||
if foo > 3:
|
||
fail “Error”
|
||
|
||
Then the rule is triggered by a change in foo. If foo isn’t changing, skip the rule, and assume it ran the last time foo was changed, and will run the next time also.
|
||
Precedence can be simply top to bottom.
|
||
Species:
|
||
|
||
define rule_type1 abc:
|
||
….
|
||
|
||
|
||
P: Final topic on my list: Data Format, and it’s very short.
|
||
data is a text file. one line per day.
|
||
Example:
|
||
|
||
2015-12-10 9am-10am “painting door”, 10am-11:29am “meeting with x”, 1:32pm-5pm “training"
|
||
|
||
Minimal. readable. Comma-separated intervals.
|
||
JSON would be more than twice as long. Available via ‘export’.
|
||
Could alternatively be one line per interval. Not sure it matters
|
||
F: have an archive file as well?(edited)
|
||
P: I was thinking that we could auto-archive, moving out records older than X into another file. Queries would then know in advance whether it needed to read the archive.
|
||
Think about the volume though: a month is 31 lines of text. Nothing.
|
||
F: not performance wise. just to reduce the clutter.
|
||
P: Agreed.
|
||
|
||
|
||
F: Should there be a possibility to freeze entries?
|
||
P: hmm. Good point, I tihnk yes.
|
||
For old data? Or so that a workweek redefine has no effect?
|
||
F: the first yes. the latter, hm. perhaps. would make sense to get the reports correct that depend on that.
|
||
|
||
--> If old data is frozen, what does that mean? It should mean that the inclusions and exclusions are collapsed, and the net inclusions recorded and frozen. This prevents changes to the work week from modifying old information.
|
||
|
||
---
|