-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcooking.py
248 lines (226 loc) · 7.97 KB
/
cooking.py
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
"""
Cooking.py reads dishes.yaml, plans out a workflow, and broadcasts the workflow to the terminal
"""
import collections
import click
from modules import cook_functions
class Organizer:
"""
Oragnizer takes a collection of Dish.dish objects and structures them into self.dishes, and
then restructures self.dishes into self.epochs
Example Structure self.dishes
-----------------------------
{
"Salad": {
"description": "some salad",
"ingredients": [{"ingredient": "salad", "quantity_with_units": "1 bag"}],
"servings": 3,
"start_time": 0,
"steps": {
0: {"duration": 12, "instruction": "Make dressing"},
1: {"duration": 4, "instruction": "Toss salad"},
},
"total_duration": 16,
},
"Pasta": {
"description": "delish pasta",
"ingredients": [
{"ingredient": "noodles", "quantity_with_units": "16 oz"},
{"ingredient": "pesto", "quantity_with_units": "1 jar"},
],
"servings": 4,
"start_time": 0,
"steps": {
0: {"duration": 16, "instruction": "Boil noodles"},
1: {"duration": 3, "instruction": "Mix noodles with sauce"},
},
"total_duration": 19,
},
"Steak": {
"description": "STEAK",
"ingredients": [{"ingredient": "ny strip", "quantity_with_units": "1 kg"}],
"servings": 4,
"start_time": 0,
"steps": {0: {"duration": 16, "instruction": "Cook steak"}},
"total_duration": 16,
},
}
Example Structure self.epochs
-----------------------------
OrderedDict(
[
(0, {"Pasta": {"instruction": "Boil noodles", "duration": 16}}),
(
3,
{
"Salad": {"instruction": "Make dressing", "duration": 12},
"Steak": {"instruction": "Cook steak", "duration": 16},
},
),
(15, {"Salad": {"instruction": "Toss salad", "duration": 4}}),
(16, {"Pasta": {"instruction": "Mix noodles with sauce", "duration": 3}}),
]
)
"""
def __init__(self):
self.dishes = {}
self.epochs = {}
self.max_duration = 0
def assign_start_time(self) -> None:
"""
Append start times to each dish based on what other dishes are being made, and write start
times to epochs.
"""
for plate in self.dishes:
if self.dishes[plate]["total_duration"] != self.max_duration:
self.dishes[plate]["start_time"] = (
self.max_duration - self.dishes[plate]["total_duration"]
)
start_time = self.dishes[plate]["start_time"]
if start_time not in self.epochs.keys():
self.epochs[start_time] = {}
self.epochs[start_time].update(
{
plate: {
"instruction": self.dishes[plate]["steps"][0]["instruction"],
"duration": self.dishes[plate]["steps"][0]["duration"],
}
}
)
def assign_actions(self) -> None:
"""
Parse dishes and populate epochs with points in time that completes instructions for all
dishes.
"""
for plate in self.dishes:
for step in self.dishes[plate]["steps"]:
if step != 0:
point_in_time = (
self.dishes[plate]["start_time"]
+ self.dishes[plate]["steps"][step - 1]["duration"]
)
if point_in_time not in self.epochs.keys():
self.epochs[point_in_time] = {}
self.epochs[point_in_time].update(
{
plate: {
"instruction": self.dishes[plate]["steps"][step][
"instruction"
],
"duration": self.dishes[plate]["steps"][step][
"duration"
],
}
}
)
self.epochs = collections.OrderedDict(sorted(self.epochs.items()))
def broadcast_details(self) -> None:
"""
Print the ingredients and servings required to produce the various dishes
"""
for plate in self.dishes:
print(
f"{plate} serves {self.dishes[plate]['servings']}, "
"and requires the following ingredients:"
)
for ingredient_collection in self.dishes[plate]["ingredients"]:
print(
f"* {ingredient_collection['ingredient']}, "
f"{ingredient_collection['quantity_with_units']}"
)
print()
def broadcast_instructions(self) -> None:
"""
Print timings for various dishes
"""
print("INSTRUCTIONS:\n")
for idx, current_time in enumerate(self.epochs):
points_in_time = list(self.epochs.keys())
if current_time != points_in_time[-1]:
print(
f"Set timer for {points_in_time[idx + 1] - points_in_time[idx]} minutes"
)
for dish in self.epochs[current_time]:
print(f"» {dish}: {self.epochs[current_time][dish]['instruction']}")
if dish is list(self.epochs[current_time])[-1]:
print()
else:
print(f"Set timer for {self.max_duration - current_time} minutes.")
for dish in self.epochs[current_time]:
print(f"» {dish}: {self.epochs[current_time][dish]['instruction']}")
print("\nAll of your dishes should be finished. Enjoy!")
def parse_arguments(
modifier: str or None,
reader: str or None,
selector: str or None,
writer: str or None,
) -> None:
"""
Executes flow control to check commandline flag and run program accordingly
"""
for key in [modifier, reader, selector, writer]:
if key:
switch_function(key)
print("Please specify a flag as a command line argument.")
print('See "python cooking.py -h" for additional information.')
def switch_function(key: str) -> ():
"""
Reads parsed command line flag and runs corresponding workflow
Parameters
----------
key:
- modifier
- reader
- selector
- writer
Returns
-------
Call to function
- cook_functions.func_modifier()
- cook_functions.func_reader()
- cook_functions.func_selector()
- cook_functions.func_writer()
"""
return {
"modifier": cook_functions.func_modifier,
"reader": cook_functions.func_reader,
"selector": cook_functions.func_selector,
"writer": cook_functions.func_writer,
}.get(key)()
@click.command()
@click.option(
"-m",
"--modifier",
default=None,
flag_value="modifier",
help="modify all recipies in the persistent database by the same name as in a specified "
"yaml file",
)
@click.option(
"-r",
"--reader",
default=None,
flag_value="reader",
help="create cooking plan using dishes.yaml",
)
@click.option(
"-s",
"--selector",
default=None,
flag_value="selector",
help="create cooking plan using recipies existing in the persistent database",
)
@click.option(
"-w",
"--writer",
default=None,
flag_value="writer",
help="write recipies from dishes.yaml to the persistent database",
)
def main(modifier, reader, selector, writer):
"""
Reads command line arguments and begins workflow
"""
parse_arguments(modifier=modifier, reader=reader, selector=selector, writer=writer)
if __name__ == "__main__":
main()