mirror of
https://github.com/GothenburgBitFactory/timewarrior.git
synced 2025-06-26 10:54:28 +02:00
239 lines
6.6 KiB
Text
239 lines
6.6 KiB
Text
Rules System
|
|
============
|
|
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
|
|
|
|
In addition to configuration, a rules system stores various settings and
|
|
configuration data as rules. There are several different types of rules, which
|
|
are loaded at launch time, and applied at various times during execution.
|
|
|
|
Some rules can be manipulated at the command line ('exclusions'), but most will
|
|
require editing the rules file. It is not intended that new users edit the
|
|
rules file, therefore some rules are automatically maintained from the command
|
|
line.
|
|
|
|
The rules are a mechanism to apply late-bound logic and data to various
|
|
functions. Whenever data changes, the rule system is run, which will run each
|
|
rule in turn, if it applies, going from top to bottom in the rules file. There
|
|
are no chained rules, but errors will terminate rule processing and program
|
|
execution.
|
|
|
|
As much functionality as possible is to be deferred to the rules.
|
|
|
|
|
|
Format
|
|
------
|
|
The rules are written in a UTF8 text file, in a known location. Other rules
|
|
files may be included:
|
|
|
|
import /path/to/other/rule/file
|
|
|
|
The syntax of rules is Python-like, in that indentation is significant.
|
|
|
|
|
|
Types of Rules
|
|
--------------
|
|
There are several different types of rules, for example there is the rule that
|
|
defines all exclusions:
|
|
|
|
define exclusions:
|
|
...
|
|
|
|
There is a rule that contains all the general configuration data:
|
|
|
|
define configuration:
|
|
name1 = value1
|
|
group1:
|
|
group2:
|
|
name2 = value2
|
|
|
|
There are general rules triggered by changes to the data:
|
|
|
|
define rule one:
|
|
...
|
|
|
|
There are rules that define tags and their metadata:
|
|
|
|
define tag "tag1":
|
|
...
|
|
|
|
There are rules that will serve as hooks:
|
|
|
|
define rule hook on_stop:
|
|
...
|
|
|
|
|
|
Rule Type: Exclusions
|
|
---------------------
|
|
Because exclusions are resolved at run time, and only when needed, they should
|
|
be stored in a form very close to the command line syntax, with no expansion.
|
|
For example:
|
|
|
|
$ timew define monday 8am - 12pm, 12:45pm - 5:30pm
|
|
$ timew define tuesday 8am - 12pm, 12:45pm - 6:30pm
|
|
$ timew define wednesday 8am - 12pm, 1:30pm - 5:30pm
|
|
$ timew define thursday 8am - 12pm, 12:45pm - 5:30pm
|
|
$ timew define friday 8am - 12pm, 12:45pm - 5:30pm
|
|
|
|
Will be stored in a rule, whose purpose is to return a set of exclusion
|
|
intervals:
|
|
|
|
define exclusions:
|
|
monday = 8:00:00-12:00:00 12:45:00-17:30:00
|
|
tuesday = 8:00:00-12:00:00 12:45:00-18:30:00
|
|
wednesday = 8:00:00-12:00:00 13:30:00-17:30:00
|
|
thursday = 8:00:00-12:00:00 12:45:00-17:30:00
|
|
friday = 8:00:00-12:00:00 12:45:00-17:30:00
|
|
|
|
Additional exclusions include:
|
|
|
|
$ timew define day on 2016-01-02
|
|
$ timew define day off 2016-01-01
|
|
|
|
Yielding:
|
|
|
|
define exclusions:
|
|
monday = 8:00:00-12:00:00 12:45:00-17:30:00
|
|
tuesday = 8:00:00-12:00:00 12:45:00-18:30:00
|
|
wednesday = 8:00:00-12:00:00 13:30:00-17:30:00
|
|
thursday = 8:00:00-12:00:00 12:45:00-17:30:00
|
|
friday = 8:00:00-12:00:00 12:45:00-17:30:00
|
|
days:
|
|
2016_01_01 = On
|
|
2016_01_02 = Off
|
|
|
|
If you want to track your lunch breaks, then you would make a tag for it, and
|
|
track it like any other project. If you do not want to track that time, add an
|
|
exclusion for it.
|
|
|
|
|
|
Rule Type: General
|
|
------------------
|
|
There are rules triggered by changes to the data. In this example, rule 'one'
|
|
is a constraint that prevents the value 'foo' from exceeding three. It is
|
|
triggered by a change to 'foo', which is a DOM reference, and can prevent the
|
|
update by failing:
|
|
|
|
define rule one:
|
|
tagset tag1
|
|
if foo > 3:
|
|
error "The value of 'foo' may not exceed 3."
|
|
|
|
Note that this rule is defined as applying to the tagset 'tag1'.
|
|
|
|
|
|
Rule Type: Tag
|
|
--------------
|
|
A defined tag is a way to associate metadata with a tag, such as a description
|
|
and start/end dates for use:
|
|
|
|
define tag "tag1":
|
|
description = "Description of tag1"
|
|
start = 2016-01-01
|
|
end = 2016-06-30
|
|
budget = 20 hours per week
|
|
budget = 400 hours total
|
|
overlap = yes
|
|
|
|
|
|
Rule Type: Configuration
|
|
------------------------
|
|
Configuration settings are stored in the 'configuration' rule, which uses a
|
|
hierarchy for grouping:
|
|
|
|
define configuration:
|
|
name1 = value1
|
|
group1:
|
|
group2:
|
|
name2 = value2
|
|
|
|
In the example, value2 can be referred to by it's normalized name
|
|
'group1.group2.name2'.
|
|
|
|
Initially, all settings are stored as simple name/value pairs at the top level
|
|
of the configuration files:
|
|
|
|
name = value
|
|
|
|
The hierarchy and 'configuration' rule will suupercede these.
|
|
|
|
|
|
Rule Type: Theme
|
|
----------------
|
|
A color theme is defined by a rule, and consists of color definitions for
|
|
various report and feedback elements:
|
|
|
|
define theme:
|
|
description = "A monochrome, 256-color theme"
|
|
color:
|
|
today = "black on rgb521"
|
|
...
|
|
palette:
|
|
color1 = "white on red"
|
|
color2 = "white on blue"
|
|
...
|
|
|
|
The palette group is a list (more is better) of themed colors for use when auto-
|
|
coloring tags.
|
|
|
|
|
|
Rule Type: Hook
|
|
---------------
|
|
While there may not be hooks in the traditional sense, with fixed arguments,
|
|
there will be rules that have the same role. Hook rules will allow an internal
|
|
event to trigger a rule that calls an external script, and passes an arbitrary
|
|
set of arguments.
|
|
|
|
[Mechanism TBD]
|
|
|
|
define rule hook on_start:
|
|
...
|
|
|
|
define rule hook on_stop:
|
|
...
|
|
|
|
define rule hook on_modify:
|
|
...
|
|
|
|
|
|
Rules Type: Hint
|
|
----------------
|
|
Hints may be defined using the rules system, to augment the built-in hints that
|
|
are used by almost every command.
|
|
|
|
define hint staff:
|
|
tag 'Staff Meeting'
|
|
tag 'Admin'
|
|
|
|
[More TBD]
|
|
|
|
|
|
Built-in Functions
|
|
------------------
|
|
There are several built-in functions, which may be used by rules:
|
|
|
|
error("...") Emits and terminates
|
|
warning("...") Emits and continues
|
|
info("...") Emits and continues
|
|
sum_week("tag1") Sums minutes in the current week for "tag1"
|
|
|
|
|
|
--- Raw Notes ---
|
|
|
|
- Need to distinguish between regular time and over time, with different rates
|
|
and limits.
|
|
|
|
- Policy support involves things like:
|
|
- warn after 40 hrs/wk
|
|
- cut off tracking a tag at x hrs/wk
|
|
- auto-tag intervals that exceed 40 hrs/wk
|
|
- auto-tag intervals during exclusion time
|
|
|