taskcheck 0.3.2__tar.gz → 0.3.2.post2__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/taskcheck.egg-info → taskcheck-0.3.2.post2}/PKG-INFO +5 -1
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/README.md +4 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/pyproject.toml +1 -1
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck/__main__.py +0 -1
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck/parallel.py +41 -18
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2/taskcheck.egg-info}/PKG-INFO +5 -1
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/LICENSE +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/setup.cfg +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck/common.py +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck/ical.py +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck/install.py +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck/report.py +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck.egg-info/SOURCES.txt +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck.egg-info/dependency_links.txt +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck.egg-info/entry_points.txt +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck.egg-info/requires.txt +0 -0
- {taskcheck-0.3.2 → taskcheck-0.3.2.post2}/taskcheck.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: taskcheck
|
|
3
|
-
Version: 0.3.2
|
|
3
|
+
Version: 0.3.2.post2
|
|
4
4
|
Summary: Automatic scheduler for taskwarrior
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -144,3 +144,7 @@ additional_attributes_unplanned = ["due", "urgency"] # additional attributes to
|
|
|
144
144
|
-i, --install: install taskcheck configuration
|
|
145
145
|
-r, --report: show tasks planned until a certain time
|
|
146
146
|
```
|
|
147
|
+
|
|
148
|
+
## TODO
|
|
149
|
+
|
|
150
|
+
- [ ] Consider due dates are nearer while planning in the future
|
|
@@ -131,3 +131,7 @@ additional_attributes_unplanned = ["due", "urgency"] # additional attributes to
|
|
|
131
131
|
-i, --install: install taskcheck configuration
|
|
132
132
|
-r, --report: show tasks planned until a certain time
|
|
133
133
|
```
|
|
134
|
+
|
|
135
|
+
## TODO
|
|
136
|
+
|
|
137
|
+
- [ ] Consider due dates are nearer while planning in the future
|
|
@@ -64,9 +64,7 @@ def compute_estimated_urgency(remaining_hours, urgency_coefficients):
|
|
|
64
64
|
key=lambda x: abs(pdth_to_hours(x) - remaining_hours),
|
|
65
65
|
)
|
|
66
66
|
coefficient = urgency_coefficients.estimated[closest_match]
|
|
67
|
-
|
|
68
|
-
estimated_urgency = coefficient * remaining_hours
|
|
69
|
-
return estimated_urgency
|
|
67
|
+
return coefficient
|
|
70
68
|
|
|
71
69
|
|
|
72
70
|
def check_tasks_parallel(config, verbose=False):
|
|
@@ -82,10 +80,7 @@ def check_tasks_parallel(config, verbose=False):
|
|
|
82
80
|
)
|
|
83
81
|
|
|
84
82
|
for day_offset in range(days_ahead):
|
|
85
|
-
|
|
86
|
-
allocate_time_for_day(
|
|
87
|
-
task_info, day_offset, date, urgency_coefficients, verbose
|
|
88
|
-
)
|
|
83
|
+
allocate_time_for_day(task_info, day_offset, urgency_coefficients, verbose)
|
|
89
84
|
|
|
90
85
|
update_tasks_with_scheduling_info(task_info, verbose)
|
|
91
86
|
|
|
@@ -120,10 +115,11 @@ def initialize_task_info(tasks, time_maps, days_ahead, urgency_coefficients, cal
|
|
|
120
115
|
return task_info
|
|
121
116
|
|
|
122
117
|
|
|
123
|
-
def allocate_time_for_day(task_info, day_offset,
|
|
118
|
+
def allocate_time_for_day(task_info, day_offset, urgency_coefficients, verbose):
|
|
119
|
+
date = datetime.today().date() + timedelta(days=day_offset)
|
|
124
120
|
total_available_hours = compute_total_available_hours(task_info, day_offset)
|
|
125
|
-
if verbose:
|
|
126
|
-
|
|
121
|
+
# if verbose:
|
|
122
|
+
# print(f"Day {date}, total available hours: {total_available_hours:.2f}")
|
|
127
123
|
if total_available_hours <= 0:
|
|
128
124
|
return
|
|
129
125
|
|
|
@@ -134,7 +130,7 @@ def allocate_time_for_day(task_info, day_offset, date, urgency_coefficients, ver
|
|
|
134
130
|
recompute_urgencies(tasks_remaining, urgency_coefficients)
|
|
135
131
|
sorted_task_ids = sorted(
|
|
136
132
|
tasks_remaining.keys(),
|
|
137
|
-
key=lambda x:
|
|
133
|
+
key=lambda x: tasks_remaining[x]["urgency"],
|
|
138
134
|
reverse=True,
|
|
139
135
|
)
|
|
140
136
|
|
|
@@ -146,6 +142,23 @@ def allocate_time_for_day(task_info, day_offset, date, urgency_coefficients, ver
|
|
|
146
142
|
info = tasks_remaining[uuid]
|
|
147
143
|
if any(d in tasks_remaining for d in info["task"].get("depends", [])):
|
|
148
144
|
# cannot execute this task until all its dependencies are completed
|
|
145
|
+
if verbose:
|
|
146
|
+
print(
|
|
147
|
+
"Skipping task",
|
|
148
|
+
info["task"]["id"],
|
|
149
|
+
"due to dependency on:",
|
|
150
|
+
[
|
|
151
|
+
tasks_remaining[_d]["task"]["id"]
|
|
152
|
+
for _d in info["task"].get("depends", [])
|
|
153
|
+
if _d in tasks_remaining
|
|
154
|
+
],
|
|
155
|
+
)
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
wait = info["task"].get("wait")
|
|
159
|
+
if wait and date <= datetime.strptime(wait, "%Y%m%dT%H%M%SZ").date():
|
|
160
|
+
if verbose:
|
|
161
|
+
print(f"Skipping task {info['task']['id']} due to wait date {wait}")
|
|
149
162
|
continue
|
|
150
163
|
allocation = allocate_time_to_task(info, day_offset, day_remaining_hours)
|
|
151
164
|
if allocation > 0:
|
|
@@ -155,7 +168,7 @@ def allocate_time_for_day(task_info, day_offset, date, urgency_coefficients, ver
|
|
|
155
168
|
update_task_scheduling(info, allocation, date_str)
|
|
156
169
|
if verbose:
|
|
157
170
|
print(
|
|
158
|
-
f"Allocated {allocation:.2f} hours to task {info['task']['id']} on {date}"
|
|
171
|
+
f"Allocated {allocation:.2f} hours to task {info['task']['id']} on {date} with urgency {info['urgency']:.2f} and estimated-related urgency {info['estimated_urgency']:.2f}"
|
|
159
172
|
)
|
|
160
173
|
if (
|
|
161
174
|
info["remaining_hours"] <= 0
|
|
@@ -166,8 +179,8 @@ def allocate_time_for_day(task_info, day_offset, date, urgency_coefficients, ver
|
|
|
166
179
|
break
|
|
167
180
|
if not allocated:
|
|
168
181
|
break
|
|
169
|
-
if verbose and day_remaining_hours > 0:
|
|
170
|
-
|
|
182
|
+
# if verbose and day_remaining_hours > 0:
|
|
183
|
+
# print(f"Unused time on {date}: {day_remaining_hours:.2f} hours")
|
|
171
184
|
|
|
172
185
|
|
|
173
186
|
def compute_total_available_hours(task_info, day_offset):
|
|
@@ -207,8 +220,17 @@ def recompute_urgencies(tasks_remaining, urgency_coefficients):
|
|
|
207
220
|
if started_by_scheduler and not started_by_user:
|
|
208
221
|
# If the task was started by the scheduler, apply the active task coefficient
|
|
209
222
|
info["urgency"] += urgency_coefficients.active
|
|
223
|
+
info["started"] = False
|
|
210
224
|
|
|
211
225
|
if urgency_coefficients.inherit:
|
|
226
|
+
# Build reverse dependencies mapping
|
|
227
|
+
reverse_deps = {} # Map from task_uuid to list of tasks that depend on it
|
|
228
|
+
for task_uuid, info in tasks_remaining.items():
|
|
229
|
+
for dep_uuid in info["task"].get("depends", []):
|
|
230
|
+
if dep_uuid not in reverse_deps:
|
|
231
|
+
reverse_deps[dep_uuid] = []
|
|
232
|
+
reverse_deps[dep_uuid].append(task_uuid)
|
|
233
|
+
|
|
212
234
|
# Define a recursive function to compute the maximum urgency
|
|
213
235
|
def get_max_urgency(info, visited):
|
|
214
236
|
task_uuid = info["task"]["uuid"]
|
|
@@ -217,8 +239,8 @@ def recompute_urgencies(tasks_remaining, urgency_coefficients):
|
|
|
217
239
|
# Start with the current task's urgency
|
|
218
240
|
urgency = info["urgency"]
|
|
219
241
|
visited[task_uuid] = urgency # Mark as visited
|
|
220
|
-
# Recursively compute urgencies of
|
|
221
|
-
for dep_uuid in
|
|
242
|
+
# Recursively compute urgencies of tasks that depend on this task
|
|
243
|
+
for dep_uuid in reverse_deps.get(task_uuid, []):
|
|
222
244
|
if dep_uuid in tasks_remaining:
|
|
223
245
|
dep_info = tasks_remaining[dep_uuid]
|
|
224
246
|
dep_urgency = get_max_urgency(dep_info, visited)
|
|
@@ -226,7 +248,7 @@ def recompute_urgencies(tasks_remaining, urgency_coefficients):
|
|
|
226
248
|
visited[task_uuid] = urgency # Update with the maximum urgency found
|
|
227
249
|
return urgency
|
|
228
250
|
|
|
229
|
-
# Update urgencies based on
|
|
251
|
+
# Update urgencies based on tasks that depend on them
|
|
230
252
|
for info in tasks_remaining.values():
|
|
231
253
|
visited = {} # Reset visited dictionary for each task
|
|
232
254
|
max_urgency = get_max_urgency(info, visited)
|
|
@@ -248,9 +270,10 @@ def allocate_time_to_task(info, day_offset, day_remaining_hours):
|
|
|
248
270
|
if allocation <= 0.05:
|
|
249
271
|
return 0
|
|
250
272
|
|
|
273
|
+
if info["remaining_hours"] == info["task"]["estimated"]:
|
|
274
|
+
info["started"] = True
|
|
251
275
|
info["remaining_hours"] -= allocation
|
|
252
276
|
info["task_time_map"][day_offset] -= allocation
|
|
253
|
-
info["started"] = True
|
|
254
277
|
|
|
255
278
|
return allocation
|
|
256
279
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: taskcheck
|
|
3
|
-
Version: 0.3.2
|
|
3
|
+
Version: 0.3.2.post2
|
|
4
4
|
Summary: Automatic scheduler for taskwarrior
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
@@ -144,3 +144,7 @@ additional_attributes_unplanned = ["due", "urgency"] # additional attributes to
|
|
|
144
144
|
-i, --install: install taskcheck configuration
|
|
145
145
|
-r, --report: show tasks planned until a certain time
|
|
146
146
|
```
|
|
147
|
+
|
|
148
|
+
## TODO
|
|
149
|
+
|
|
150
|
+
- [ ] Consider due dates are nearer while planning in the future
|
|
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
|