import json from copy import deepcopy from flowtimer.Phase import Phase class RecurringPhaseSequence: @classmethod def from_json(cls, a_json_string): def custom_object_hook(d): if 'title' in d and 'duration' in d: return Phase(d['title'], d['duration']) if 'phase_list' in d and 'repetitions' in d: return RecurringPhaseSequence(d['phase_list'], d['repetitions']) return d return json.loads(a_json_string, object_hook=custom_object_hook) @classmethod def default_json_string(cls): return json.dumps({"phase_list": [{"title": "Huddle", "duration": 10}, {"title": "Tasking", "duration": 5}, {"title": "Work", "duration": 45}, {"title": "Break", "duration": 15}], "repetitions": 3}) @classmethod def default(cls): return cls.from_json(cls.default_json_string()) def __init__(self, phase_list, repetitions): assert repetitions > 0 assert phase_list is not [] self.state = "initial" self.phase_list = phase_list self.current_phase = phase_list[0] self.initial_repetitions = repetitions self.passes_left = repetitions def to_json(self): return json.dumps(self.__dict__, default=lambda each: each.to_json()) def upcoming_phases_in_pass(self): index = self.phase_list.index(self.current_phase) if index < len(self.phase_list) - 1: return self.phase_list[index+1:] return [] def ticks_left(self): return (self.passes_left * sum([each.initial_ticks for each in self.phase_list]) + self.current_phase.ticks_left + sum([each.ticks_left for each in self.upcoming_phases_in_pass()])) def finished(self): return (self.passes_left < 1) and (not self.upcoming_phases_in_pass()) def abort(self): self.current_phase.abort() self.state = "finished" def tick(self, ticks): if not self.finished(): result = self.current_phase.tick(ticks) print("Current phase", self.current_phase) print("Passes left:", self.passes_left) if self.current_phase.finished(): if self.upcoming_phases_in_pass(): self.current_phase.reset() self.current_phase = self.upcoming_phases_in_pass()[0] self.current_phase.start() print("New phase:", self.current_phase) self.tick(abs(result)) return True self.passes_left -= 1 if self.finished(): self.state = "finished" else: self.current_phase.reset() self.current_phase = self.phase_list[0] return True def unrolled(self): return [deepcopy(seq) for seq in [each for each in self.repetitions * self.phase_list]]