from typing import Tuple from flickerstrip_py.models.pattern import Pattern, PatternData RGBColor = Tuple[int, int, int] class PatternBuilder: def __init__(self, name: str, fps=1, pixels_per_frame=1): self.data: list[RGBColor] = [] self.name = name self.fps = fps self.fps: int = fps self.frame_count: int = 1 self.pixels_per_frame: int = pixels_per_frame def set_pixel(self, f: int, i: int, color: RGBColor): offset = f * self.pixels_per_frame + i self.data[offset] = color def append_pixel(self, color: RGBColor): self.data.append(color) def get_frame(self, f: int) -> list[RGBColor]: start = f * self.pixels_per_frame end = start + self.pixels_per_frame return self.data[start:end] def next_frame(self): if not self.is_valid(): raise Exception("Not enough pixels for next frame") self.frame_count += 1 def is_valid(self): if self.frame_count == 0: return False if len(self.data) != self.frame_count * self.pixels_per_frame: return False return True def to_pattern_data(self) -> PatternData: data = bytes(y for x in self.data for y in x) return PatternData(data=data) def to_pattern(self) -> Pattern: return Pattern( id=0, flags=0, name=self.name, fps=self.fps, frames=self.frame_count, pixels=self.pixels_per_frame, ) @classmethod def from_data(cls, meta: Pattern, data: PatternData): builder = PatternBuilder(meta.name, meta.fps, meta.pixels) builder.data = [ tuple(data.data[x : x + 3]) for x in range(0, len(data.data), 3) ] builder.frame_count = meta.frames return builder