1 | import json
|
---|
2 | from copy import deepcopy
|
---|
3 | from flowtimer.Phase import Phase
|
---|
4 |
|
---|
5 |
|
---|
6 | class RecurringPhaseSequence:
|
---|
7 |
|
---|
8 | @classmethod
|
---|
9 | def from_json(cls, a_json_string):
|
---|
10 | def custom_object_hook(d):
|
---|
11 | if 'title' in d and 'duration' in d:
|
---|
12 | return Phase(d['title'], d['duration'])
|
---|
13 | if 'phase_list' in d and 'repetitions' in d:
|
---|
14 | return RecurringPhaseSequence(d['phase_list'], d['repetitions'])
|
---|
15 | return d
|
---|
16 | return json.loads(a_json_string, object_hook=custom_object_hook)
|
---|
17 |
|
---|
18 | @classmethod
|
---|
19 | def default_json_string(cls):
|
---|
20 | return json.dumps({"phase_list": [{"title": "Huddle", "duration": 10},
|
---|
21 | {"title": "Tasking", "duration": 5},
|
---|
22 | {"title": "Work", "duration": 45},
|
---|
23 | {"title": "Break", "duration": 15}],
|
---|
24 | "repetitions": 3})
|
---|
25 |
|
---|
26 | @classmethod
|
---|
27 | def default(cls):
|
---|
28 | return cls.from_json(cls.default_json_string())
|
---|
29 |
|
---|
30 | def __init__(self, phase_list, repetitions):
|
---|
31 | assert repetitions > 0
|
---|
32 | assert phase_list is not []
|
---|
33 | self.state = "initial"
|
---|
34 | self.phase_list = phase_list
|
---|
35 | self.current_phase = phase_list[0]
|
---|
36 | self.initial_repetitions = repetitions
|
---|
37 | self.passes_left = repetitions
|
---|
38 |
|
---|
39 | def to_json(self):
|
---|
40 | return json.dumps(self.__dict__, default=lambda each: each.to_json())
|
---|
41 |
|
---|
42 | def upcoming_phases_in_pass(self):
|
---|
43 | index = self.phase_list.index(self.current_phase)
|
---|
44 | if index < len(self.phase_list) - 1:
|
---|
45 | return self.phase_list[index+1:]
|
---|
46 | return []
|
---|
47 |
|
---|
48 | def ticks_left(self):
|
---|
49 | return (self.passes_left * sum([each.initial_ticks for each in self.phase_list]) +
|
---|
50 | self.current_phase.ticks_left +
|
---|
51 | sum([each.ticks_left for each in self.upcoming_phases_in_pass()]))
|
---|
52 |
|
---|
53 | def finished(self):
|
---|
54 | return (self.passes_left < 1) and (not self.upcoming_phases_in_pass())
|
---|
55 |
|
---|
56 | def abort(self):
|
---|
57 | self.current_phase.abort()
|
---|
58 | self.state = "finished"
|
---|
59 |
|
---|
60 | def tick(self, ticks):
|
---|
61 | if not self.finished():
|
---|
62 | result = self.current_phase.tick(ticks)
|
---|
63 | print("Current phase", self.current_phase)
|
---|
64 | print("Passes left:", self.passes_left)
|
---|
65 | if self.current_phase.finished():
|
---|
66 | if self.upcoming_phases_in_pass():
|
---|
67 | self.current_phase.reset()
|
---|
68 | self.current_phase = self.upcoming_phases_in_pass()[0]
|
---|
69 | self.current_phase.start()
|
---|
70 | print("New phase:", self.current_phase)
|
---|
71 | self.tick(abs(result))
|
---|
72 | return True
|
---|
73 | self.passes_left -= 1
|
---|
74 | if self.finished():
|
---|
75 | self.state = "finished"
|
---|
76 | else:
|
---|
77 | self.current_phase.reset()
|
---|
78 | self.current_phase = self.phase_list[0]
|
---|
79 | return True
|
---|
80 |
|
---|
81 | def unrolled(self):
|
---|
82 | return [deepcopy(seq) for seq in [each for each in self.repetitions * self.phase_list]]
|
---|