import bisect class ReplayController: def __init__(self, journal): self.journal = journal self.index = 0 self.playing = False # pre-sorted events for deterministic replay self.timeline = sorted( journal.events, key=lambda e: e["ts"] ) # ------------------------- # CURRENT EVENT # ------------------------- def current(self): if 0 <= self.index < len(self.timeline): return self.timeline[self.index] return None # ------------------------- # STEP FORWARD # ------------------------- def step(self): if self.index < len(self.timeline) - 1: self.index += 1 return self.current() # ------------------------- # STEP BACKWARD # ------------------------- def back(self): if self.index > 0: self.index -= 1 return self.current() # ------------------------- # SEEK BY TIMESTAMP # ------------------------- def seek(self, timestamp): times = [e["ts"] for e in self.timeline] self.index = bisect.bisect_left(times, timestamp) return self.current() # ------------------------- # RESET # ------------------------- def reset(self): self.index = 0 return self.current() # ------------------------- # PLAY (ITERATOR MODE) # ------------------------- def play(self): for i in range(self.index, len(self.timeline)): self.index = i yield self.timeline[i]