| [84123db] | 1 | import json
|
|---|
| [37ae3b7] | 2 | from copy import deepcopy
|
|---|
| [3b76475] | 3 | from flowtimer.Phase import Phase
|
|---|
| [84123db] | 4 |
|
|---|
| 5 |
|
|---|
| 6 | class RecurringPhaseSequence:
|
|---|
| 7 |
|
|---|
| [37ae3b7] | 8 | @classmethod
|
|---|
| 9 | def from_json(cls, a_json_string):
|
|---|
| 10 | def custom_object_hook(d):
|
|---|
| [daa2276] | 11 | if 'title' in d and 'initial_ticks' in d:
|
|---|
| 12 | return Phase(d['title'], d['initial_ticks'])
|
|---|
| 13 | if 'phase_list' in d and 'initial_repetitions' in d:
|
|---|
| [1fd7029] | 14 | return RecurringPhaseSequence(d["title"], d['phase_list'], d['initial_repetitions'])
|
|---|
| 15 | print("Wrong format")
|
|---|
| [37ae3b7] | 16 | return d
|
|---|
| 17 | return json.loads(a_json_string, object_hook=custom_object_hook)
|
|---|
| 18 |
|
|---|
| 19 | @classmethod
|
|---|
| 20 | def default_json_string(cls):
|
|---|
| [1fd7029] | 21 | return json.dumps({"title": "default",
|
|---|
| 22 | "phase_list": [{"title": "Huddle", "initial_ticks": 10},
|
|---|
| [daa2276] | 23 | {"title": "Tasking", "initial_ticks": 5},
|
|---|
| 24 | {"title": "Work", "initial_ticks": 45},
|
|---|
| 25 | {"title": "Break", "initial_ticks": 15}],
|
|---|
| 26 | "initial_repetitions": 3})
|
|---|
| [37ae3b7] | 27 |
|
|---|
| [f959488] | 28 | @classmethod
|
|---|
| 29 | def default(cls):
|
|---|
| 30 | return cls.from_json(cls.default_json_string())
|
|---|
| 31 |
|
|---|
| [1fd7029] | 32 | def __init__(self, title, phase_list, repetitions):
|
|---|
| [f959488] | 33 | assert repetitions > 0
|
|---|
| 34 | assert phase_list is not []
|
|---|
| [1fd7029] | 35 | self._title = title
|
|---|
| [f959488] | 36 | self.state = "initial"
|
|---|
| [84123db] | 37 | self.phase_list = phase_list
|
|---|
| [f959488] | 38 | self.current_phase = phase_list[0]
|
|---|
| 39 | self.initial_repetitions = repetitions
|
|---|
| 40 | self.passes_left = repetitions
|
|---|
| [84123db] | 41 |
|
|---|
| 42 | def to_json(self):
|
|---|
| 43 | return json.dumps(self.__dict__, default=lambda each: each.to_json())
|
|---|
| 44 |
|
|---|
| [1fd7029] | 45 | @property
|
|---|
| [44c3377] | 46 | def title(self):
|
|---|
| [36c9ef5] | 47 | return self._title
|
|---|
| [44c3377] | 48 |
|
|---|
| [5741f6d] | 49 | def is_sequence(self):
|
|---|
| 50 | return True
|
|---|
| 51 |
|
|---|
| [daa2276] | 52 | def current_phase_number(self):
|
|---|
| 53 | return self.phase_list.index(self.current_phase)
|
|---|
| 54 |
|
|---|
| 55 | def phases_left_in_pass(self):
|
|---|
| 56 | return len(self.upcoming_phases_in_pass())
|
|---|
| 57 |
|
|---|
| [f959488] | 58 | def upcoming_phases_in_pass(self):
|
|---|
| [daa2276] | 59 | if self.current_phase_number() < len(self.phase_list) - 1:
|
|---|
| 60 | return self.phase_list[self.current_phase_number()+1:]
|
|---|
| [f959488] | 61 | return []
|
|---|
| 62 |
|
|---|
| [1fd7029] | 63 | @property
|
|---|
| 64 | def initial_ticks(self):
|
|---|
| 65 | return sum([each.initial_ticks for each in self.phase_list])
|
|---|
| 66 |
|
|---|
| [daa2276] | 67 | @property
|
|---|
| [f959488] | 68 | def ticks_left(self):
|
|---|
| [daa2276] | 69 | return (
|
|---|
| 70 | (self.passes_left-1) * sum([each.initial_ticks for each in self.phase_list]) +
|
|---|
| 71 | self.current_phase.ticks_left +
|
|---|
| 72 | sum([each.ticks_left for each in self.upcoming_phases_in_pass()]))
|
|---|
| [f959488] | 73 |
|
|---|
| 74 | def finished(self):
|
|---|
| [a438158] | 75 | return ((self.passes_left < 1) and
|
|---|
| 76 | (not self.upcoming_phases_in_pass() and
|
|---|
| 77 | self.current_phase.finished()))
|
|---|
| [f959488] | 78 |
|
|---|
| 79 | def abort(self):
|
|---|
| 80 | self.current_phase.abort()
|
|---|
| 81 | self.state = "finished"
|
|---|
| 82 |
|
|---|
| [1fd7029] | 83 | def start(self):
|
|---|
| 84 | self.state = "running"
|
|---|
| 85 |
|
|---|
| [36c9ef5] | 86 | def skip(self):
|
|---|
| 87 | if self.upcoming_phases_in_pass():
|
|---|
| 88 | self.current_phase.reset()
|
|---|
| 89 | self.current_phase = self.upcoming_phases_in_pass()[0]
|
|---|
| 90 | return
|
|---|
| 91 | else:
|
|---|
| [a438158] | 92 | print("Sequence finished")
|
|---|
| [36c9ef5] | 93 | if self.passes_left == 0:
|
|---|
| 94 | self.abort()
|
|---|
| 95 | return
|
|---|
| 96 | else:
|
|---|
| 97 | self.passes_left -= 1
|
|---|
| 98 | self.current_phase.reset()
|
|---|
| 99 | self.current_phase = self.phase_list[0]
|
|---|
| 100 |
|
|---|
| [f959488] | 101 | def tick(self, ticks):
|
|---|
| 102 | if not self.finished():
|
|---|
| 103 | result = self.current_phase.tick(ticks)
|
|---|
| 104 | if self.current_phase.finished():
|
|---|
| 105 | if self.upcoming_phases_in_pass():
|
|---|
| 106 | self.current_phase.reset()
|
|---|
| 107 | self.current_phase = self.upcoming_phases_in_pass()[0]
|
|---|
| 108 | self.current_phase.start()
|
|---|
| 109 | self.tick(abs(result))
|
|---|
| 110 | return True
|
|---|
| 111 | self.passes_left -= 1
|
|---|
| 112 | if self.finished():
|
|---|
| 113 | self.state = "finished"
|
|---|
| 114 | else:
|
|---|
| 115 | self.current_phase.reset()
|
|---|
| 116 | self.current_phase = self.phase_list[0]
|
|---|
| 117 | return True
|
|---|
| 118 |
|
|---|
| [84123db] | 119 | def unrolled(self):
|
|---|
| [daa2276] | 120 | return [deepcopy(seq) for seq in [each for each in self.initial_repetitions * self.phase_list]]
|
|---|