from __future__ import annotations from pygui.backend.models.frame import Frame from pygui.backend.wafer.zwafer_models import ZWaferData def frames_from_wafer_data(data: ZWaferData, records) -> list[Frame]: """Build Frames from parsed DataRecords (records = list[DataRecord].)""" return [Frame(seq=i, time=r.time, values=list(r.values)) for i, r in enumerate(records)] class FramePlayer: def __init__(self) -> None: self._frames: list[Frame] =[] self._i =0 def load(self, frames: list[Frame]) -> "FramePlayer": self._frames = frames self._i = 0 return self @property def total(self) -> int: return len(self._frames) @property def index(self) -> int: return self._i @property def at_end(self) -> bool: return self._i >= len(self._frames) -1 def current(self) -> Frame | None: if not self._frames: return None return self._frames[self._i] def _clamp(self, i:int): return max(0, min(i, len(self._frames) - 1)) if self._frames else 0 def step(self, delta: int) -> "FramePlayer": self._i = self._clamp(self._i + delta) return self def seek(self, i: int) -> "FramePlayer": self._i = self._clamp(i) return self def next_frame_ms(self) -> float: """Wall-clock ms until the next frame based on recorded timestamps; 0 if at end.""" if self._i + 1 >= len(self._frames): return 0.0 return (self._frames[self._i + 1].time - self._frames[self._i].time) * 1000.0