taskcheck 0.3.2.post2__tar.gz → 0.3.3.post1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {taskcheck-0.3.2.post2/taskcheck.egg-info → taskcheck-0.3.3.post1}/PKG-INFO +1 -1
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/pyproject.toml +1 -1
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck/parallel.py +100 -25
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1/taskcheck.egg-info}/PKG-INFO +1 -1
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/LICENSE +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/README.md +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/setup.cfg +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck/__main__.py +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck/common.py +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck/ical.py +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck/install.py +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck/report.py +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck.egg-info/SOURCES.txt +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck.egg-info/dependency_links.txt +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck.egg-info/entry_points.txt +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck.egg-info/requires.txt +0 -0
- {taskcheck-0.3.2.post2 → taskcheck-0.3.3.post1}/taskcheck.egg-info/top_level.txt +0 -0
|
@@ -20,6 +20,9 @@ class UrgencyCoefficients:
|
|
|
20
20
|
estimated: dict
|
|
21
21
|
inherit: bool
|
|
22
22
|
active: float
|
|
23
|
+
age_max: int
|
|
24
|
+
urgency_due: int
|
|
25
|
+
urgency_age: int
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
def get_urgency_coefficients():
|
|
@@ -31,16 +34,22 @@ def get_urgency_coefficients():
|
|
|
31
34
|
result = subprocess.run(["task", "_show"], capture_output=True, text=True)
|
|
32
35
|
inherit_urgency = False
|
|
33
36
|
active_task_coefficient = 0
|
|
34
|
-
|
|
37
|
+
est_coeffs = {}
|
|
38
|
+
urgency_age_max = 0
|
|
39
|
+
urgency_age = 0
|
|
40
|
+
urgency_due = 0
|
|
35
41
|
pattern1 = re.compile(r"^urgency\.uda\.estimated\.(.+)\.coefficient=(.+)$")
|
|
36
42
|
pattern2 = re.compile(r"^urgency\.inherit=(.+)$")
|
|
37
|
-
pattern3 = re.compile(r"^urgency\.active
|
|
43
|
+
pattern3 = re.compile(r"^urgency\.active\.coefficient=(.+)$")
|
|
44
|
+
pattern4 = re.compile(r"^urgency\.age\.max=(.+)$")
|
|
45
|
+
pattern5 = re.compile(r"^urgency\.due\.coefficient=(.+)$")
|
|
46
|
+
pattern6 = re.compile(r"^urgency\.age\.coefficient=(.+)$")
|
|
38
47
|
for line in result.stdout.splitlines():
|
|
39
48
|
match = pattern1.match(line)
|
|
40
49
|
if match:
|
|
41
50
|
estimated_value = match.group(1)
|
|
42
51
|
coefficient = float(match.group(2))
|
|
43
|
-
|
|
52
|
+
est_coeffs[estimated_value] = coefficient
|
|
44
53
|
|
|
45
54
|
match = pattern2.match(line)
|
|
46
55
|
if match:
|
|
@@ -51,20 +60,26 @@ def get_urgency_coefficients():
|
|
|
51
60
|
active_coefficient = float(match.group(1))
|
|
52
61
|
active_task_coefficient = active_coefficient
|
|
53
62
|
|
|
54
|
-
|
|
63
|
+
match = pattern4.match(line)
|
|
64
|
+
if match:
|
|
65
|
+
urgency_age_max = int(match.group(1))
|
|
55
66
|
|
|
67
|
+
match = pattern5.match(line)
|
|
68
|
+
if match:
|
|
69
|
+
urgency_due = int(match.group(1))
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
match = pattern6.match(line)
|
|
72
|
+
if match:
|
|
73
|
+
urgency_age = int(match.group(1))
|
|
74
|
+
|
|
75
|
+
return UrgencyCoefficients(
|
|
76
|
+
est_coeffs,
|
|
77
|
+
inherit_urgency,
|
|
78
|
+
active_task_coefficient,
|
|
79
|
+
urgency_age_max,
|
|
80
|
+
urgency_due,
|
|
81
|
+
urgency_age,
|
|
65
82
|
)
|
|
66
|
-
coefficient = urgency_coefficients.estimated[closest_match]
|
|
67
|
-
return coefficient
|
|
68
83
|
|
|
69
84
|
|
|
70
85
|
def check_tasks_parallel(config, verbose=False):
|
|
@@ -72,7 +87,6 @@ def check_tasks_parallel(config, verbose=False):
|
|
|
72
87
|
time_maps = config["time_maps"]
|
|
73
88
|
days_ahead = config["scheduler"]["days_ahead"]
|
|
74
89
|
calendars = get_calendars(config)
|
|
75
|
-
today = datetime.today().date()
|
|
76
90
|
urgency_coefficients = get_urgency_coefficients()
|
|
77
91
|
|
|
78
92
|
task_info = initialize_task_info(
|
|
@@ -87,6 +101,7 @@ def check_tasks_parallel(config, verbose=False):
|
|
|
87
101
|
|
|
88
102
|
def initialize_task_info(tasks, time_maps, days_ahead, urgency_coefficients, calendars):
|
|
89
103
|
task_info = {}
|
|
104
|
+
today = datetime.today().date()
|
|
90
105
|
for task in tasks:
|
|
91
106
|
if task.get("status") in AVOID_STATUS:
|
|
92
107
|
continue
|
|
@@ -99,9 +114,11 @@ def initialize_task_info(tasks, time_maps, days_ahead, urgency_coefficients, cal
|
|
|
99
114
|
)
|
|
100
115
|
task_uuid = task["uuid"]
|
|
101
116
|
initial_urgency = float(task.get("urgency", 0))
|
|
102
|
-
estimated_urgency =
|
|
103
|
-
estimated_hours, urgency_coefficients
|
|
117
|
+
estimated_urgency = urgency_estimated(
|
|
118
|
+
{"remaining_hours": estimated_hours}, None, urgency_coefficients
|
|
104
119
|
)
|
|
120
|
+
due_urgency = urgency_due({"task": task}, today, urgency_coefficients)
|
|
121
|
+
age_urgency = urgency_age({"task": task}, today, urgency_coefficients)
|
|
105
122
|
task_info[task_uuid] = {
|
|
106
123
|
"task": task,
|
|
107
124
|
"remaining_hours": estimated_hours,
|
|
@@ -110,6 +127,8 @@ def initialize_task_info(tasks, time_maps, days_ahead, urgency_coefficients, cal
|
|
|
110
127
|
"scheduling": {},
|
|
111
128
|
"urgency": initial_urgency,
|
|
112
129
|
"estimated_urgency": estimated_urgency,
|
|
130
|
+
"due_urgency": due_urgency,
|
|
131
|
+
"age_urgency": age_urgency,
|
|
113
132
|
"started": False,
|
|
114
133
|
}
|
|
115
134
|
return task_info
|
|
@@ -127,7 +146,7 @@ def allocate_time_for_day(task_info, day_offset, urgency_coefficients, verbose):
|
|
|
127
146
|
tasks_remaining = prepare_tasks_remaining(task_info, day_offset)
|
|
128
147
|
|
|
129
148
|
while day_remaining_hours > 0 and tasks_remaining:
|
|
130
|
-
recompute_urgencies(tasks_remaining, urgency_coefficients)
|
|
149
|
+
recompute_urgencies(tasks_remaining, urgency_coefficients, date)
|
|
131
150
|
sorted_task_ids = sorted(
|
|
132
151
|
tasks_remaining.keys(),
|
|
133
152
|
key=lambda x: tasks_remaining[x]["urgency"],
|
|
@@ -205,16 +224,72 @@ def prepare_tasks_remaining(task_info, day_offset):
|
|
|
205
224
|
}
|
|
206
225
|
|
|
207
226
|
|
|
208
|
-
def
|
|
227
|
+
def urgency_due(info, date, urgency_coefficients):
|
|
228
|
+
lfs = 0
|
|
229
|
+
task = info["task"]
|
|
230
|
+
if "due" in task:
|
|
231
|
+
due = datetime.strptime(task["due"], "%Y%m%dT%H%M%SZ").date()
|
|
232
|
+
# Map a range of 21 days to the value 0.2 - 1.0
|
|
233
|
+
days_overdue = (date - due).days
|
|
234
|
+
if days_overdue >= 7.0:
|
|
235
|
+
lfs = 1.0 # < 1 wk ago
|
|
236
|
+
elif days_overdue >= -14.0:
|
|
237
|
+
lfs = ((days_overdue + 14.0) * 0.8 / 21.0) + 0.2
|
|
238
|
+
else:
|
|
239
|
+
lfs = 0.2 # 2 wks
|
|
240
|
+
return lfs * urgency_coefficients.urgency_due
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def urgency_age(info, date, urgency_coefficients):
|
|
244
|
+
urgency_age_max = urgency_coefficients.age_max
|
|
245
|
+
lfs = 1.0
|
|
246
|
+
task = info["task"]
|
|
247
|
+
if "entry" not in task:
|
|
248
|
+
return 1.0
|
|
249
|
+
entry = datetime.strptime(task["entry"], "%Y%m%dT%H%M%SZ").date()
|
|
250
|
+
age = (date - entry).days # in days
|
|
251
|
+
if urgency_age_max == 0 or age >= urgency_age_max:
|
|
252
|
+
lfs = 1.0
|
|
253
|
+
return lfs * age / urgency_age_max * urgency_coefficients.urgency_age
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def urgency_estimated(info, date, urgency_coefficients):
|
|
257
|
+
"""
|
|
258
|
+
Computes the estimated urgency for the given remaining hours using the coefficients.
|
|
259
|
+
"""
|
|
260
|
+
# Find the closest match (e.g., if '2h' is not available, use '1h' or '3h')
|
|
261
|
+
closest_match = min(
|
|
262
|
+
urgency_coefficients.estimated.keys(),
|
|
263
|
+
key=lambda x: abs(pdth_to_hours(x) - info["remaining_hours"]),
|
|
264
|
+
)
|
|
265
|
+
coefficient = urgency_coefficients.estimated[closest_match]
|
|
266
|
+
return coefficient
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def update_urgency(info, urgency_key, urgency_compute_fn, urgency_coefficients, date):
|
|
270
|
+
urgency_value = urgency_compute_fn(info, date, urgency_coefficients)
|
|
271
|
+
old_urgency = info[urgency_key]
|
|
272
|
+
# if old_urgency != urgency_value:
|
|
273
|
+
# print(
|
|
274
|
+
# f"new urgency value for task {info['task']['id']}: {urgency_key}: {urgency_value}"
|
|
275
|
+
# )
|
|
276
|
+
info[urgency_key] = urgency_value
|
|
277
|
+
info["urgency"] = info["urgency"] - old_urgency + urgency_value
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def recompute_urgencies(tasks_remaining, urgency_coefficients, date):
|
|
281
|
+
"""Recompute urgency simulating that today is `date`"""
|
|
209
282
|
# Recompute estimated urgencies as before
|
|
210
283
|
for info in tasks_remaining.values():
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
284
|
+
# Update estimated urgency
|
|
285
|
+
update_urgency(
|
|
286
|
+
info, "estimated_urgency", urgency_estimated, urgency_coefficients, date
|
|
214
287
|
)
|
|
215
|
-
|
|
216
|
-
info
|
|
217
|
-
|
|
288
|
+
# Update due partial urgency
|
|
289
|
+
update_urgency(info, "due_urgency", urgency_due, urgency_coefficients, date)
|
|
290
|
+
# Update age partial urgency
|
|
291
|
+
update_urgency(info, "age_urgency", urgency_age, urgency_coefficients, date)
|
|
292
|
+
|
|
218
293
|
started_by_user = info["task"].get("start", "") != ""
|
|
219
294
|
started_by_scheduler = info["started"]
|
|
220
295
|
if started_by_scheduler and not started_by_user:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|