-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstudy_planner.py
More file actions
104 lines (83 loc) · 3.1 KB
/
Copy pathstudy_planner.py
File metadata and controls
104 lines (83 loc) · 3.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""Collection practice for the study planner starter."""
SAMPLE_TASKS = [
{
"topic": "Functions",
"minutes": 30,
"done": False,
"tags": ["Core", "practice"],
},
{
"topic": "Loops",
"minutes": 45,
"done": False,
"tags": ["core"],
},
{
"topic": "Values",
"minutes": 20,
"done": True,
"tags": ["review"],
},
{
"topic": "Files",
"minutes": 20,
"done": False,
"tags": ["Practice"],
},
]
def _validate_tasks(tasks):
if not isinstance(tasks, list):
raise ValueError("tasks must be a list")
for index, task in enumerate(tasks):
prefix = f"tasks[{index}]"
if not isinstance(task, dict):
raise ValueError(f"{prefix} must be a dictionary")
topic = task.get("topic")
if not isinstance(topic, str) or not topic.strip():
raise ValueError(f"{prefix}.topic must be non-empty text")
minutes = task.get("minutes")
if isinstance(minutes, bool) or not isinstance(minutes, int) or minutes < 1:
raise ValueError(f"{prefix}.minutes must be a positive whole number")
if not isinstance(task.get("done"), bool):
raise ValueError(f"{prefix}.done must be True or False")
tags = task.get("tags")
if not isinstance(tags, list) or any(
not isinstance(tag, str) or not tag.strip() for tag in tags
):
raise ValueError(f"{prefix}.tags must be a list of non-empty strings")
def unfinished_topics(tasks):
"""Return unfinished topic names in plan order."""
_validate_tasks(tasks)
raise NotImplementedError(
"TODO: collect unfinished topic names in unfinished_topics()"
)
def unique_tags(tasks):
"""Return stripped, case-folded tags as a set."""
_validate_tasks(tasks)
raise NotImplementedError("TODO: build the normalised tag set in unique_tags()")
def total_minutes(tasks, include_done=False):
"""Return minutes for unfinished tasks, or all tasks when requested."""
_validate_tasks(tasks)
if not isinstance(include_done, bool):
raise ValueError("include_done must be True or False")
raise NotImplementedError("TODO: add the selected minutes in total_minutes()")
def fit_session(tasks, available_minutes):
"""Greedily copy unfinished tasks that fit the remaining minutes."""
_validate_tasks(tasks)
if (
isinstance(available_minutes, bool)
or not isinstance(available_minutes, int)
or available_minutes < 0
):
raise ValueError("available_minutes must be a non-negative whole number")
if not tasks or available_minutes == 0:
return []
raise NotImplementedError("TODO: choose copied tasks in fit_session()")
def demo():
session = fit_session(SAMPLE_TASKS, 55)
print("Unfinished:", unfinished_topics(SAMPLE_TASKS))
print("Unique tags:", sorted(unique_tags(SAMPLE_TASKS)))
print("Open minutes:", total_minutes(SAMPLE_TASKS))
print("55-minute session:", [task["topic"] for task in session])
if __name__ == "__main__":
demo()