diff --git a/100 b/100 new file mode 100644 index 0000000..e69de29 diff --git a/bruhanimate/bruheffect/audio_effect.py b/bruhanimate/bruheffect/audio_effect.py index 69c9d97..e945e4d 100644 --- a/bruhanimate/bruheffect/audio_effect.py +++ b/bruhanimate/bruheffect/audio_effect.py @@ -22,12 +22,25 @@ from bruhcolor import bruhcolored from .base_effect import BaseEffect + from ..bruhutil import Buffer class AudioEffect(BaseEffect): + """ + A base class for audio effects in a terminal-based visualizer. + """ def __init__( - self, buffer, background: str, num_bands: int = 24, audio_halt: int = 10 + self, buffer: Buffer, background: str, num_bands: int = 24, audio_halt: int = 10 ): + """ + Initialize the AudioEffect class. + + Args: + buffer (Buffer): The effect buffer to push updates to. + background (str): Character or string to use for the background. + num_bands (int, optional): Number of EQ bands to show. Defaults to 24. + audio_halt (int, optional): How often we should update the bands, (frame_number % halt == 0 then update). Defaults to 10. + """ super(AudioEffect, self).__init__(buffer, background) self.FORMAT = pyaudio.paInt16 self.CHANNELS = 1 @@ -78,6 +91,15 @@ def __init__( def set_audio_properties( self, num_bands=24, audio_halt=10, use_gradient=True, non_gradient_color=27 ): + """ + Set the properties for the AudioEffect class. + + Args: + num_bands (int, optional): Number of EQ bands to show. Defaults to 24. + audio_halt (int, optional): How often we should update the bands, (frame_number % halt == 0 then update). Defaults to 10. + use_gradient (bool, optional): Whether or not to use color gradient. Defaults to True. + non_gradient_color (int, optional): Color to use if not a gradient. Defaults to 27 (blue). + """ self.BANDS = num_bands self.audio_halt = audio_halt self.band_ranges = self.generate_even_ranges(self.BANDS, 0, self.buffer.width()) @@ -85,7 +107,17 @@ def set_audio_properties( self.use_gradient = use_gradient self.non_gradient_color = non_gradient_color - def evenly_distribute_original_values(self, original_list, desired_width): + def evenly_distribute_original_values(self, original_list: list[int], desired_width: int): + """ + Evenly distribute the values in a list to fit within a certain width. + + Args: + original_list (list[int]): The list of values to distribute. + desired_width (int): The width to which the values should be distributed. + + Returns: + list[int]: The evenly distributed list of values. + """ repeat_count = desired_width // len(original_list) extra_elements = desired_width % len(original_list) expanded_list = [] @@ -96,7 +128,13 @@ def evenly_distribute_original_values(self, original_list, desired_width): extra_elements -= 1 return expanded_list - def set_orientation(self, orientation): + def set_orientation(self, orientation: str): + """ + Set the orientation of the visualizer. + + Args: + orientation (str): The orientation to set ("top" or "bottom"). + """ if orientation in ["top", "bottom"]: self.orientation = orientation if self.orientation == "bottom": @@ -109,6 +147,13 @@ def set_audio_gradient( gradient=[232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255], mode="extend", ): + """ + Set the audio gradient for visualizing audio data. + + Args: + gradient (list, optional): List of colors to use for gradient. Defaults to [232, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255]. + mode (str, optional): Do we want to repeat the gradient or extend the list evenly. Defaults to "extend". + """ self.base_gradient = gradient self.gradient_mode = mode if self.gradient_mode == "repeat": @@ -129,6 +174,18 @@ def set_audio_gradient( ] def process_audio(self, data, frame_count, time_info, status): + """ + Process the audio data and update the visualizer buffer. + + Args: + data (_type_): Audio data from the stream. + frame_count (_type_): N/A + time_info (_type_): N/A + status (_type_): N/A + + Returns: + tuple: (data, pyaudio.paContinue) + """ audio_array = np.frombuffer(data, dtype=np.int16) fft_result = np.fft.rfft(audio_array) magnitudes = np.abs(fft_result) @@ -139,7 +196,16 @@ def process_audio(self, data, frame_count, time_info, status): ] return (data, pyaudio.paContinue) - def map_bands_to_range(self, N): + def map_bands_to_range(self, N: int): + """ + Map the bands to a range of values between 0 and N-1. + + Args: + N (int): The range of values to map the bands to. + + Returns: + list[int]: The mapped bands. + """ min_band = min(self.bands) max_band = max(self.bands) rand_band = max_band - min_band if max_band != min_band else 1 @@ -147,7 +213,18 @@ def map_bands_to_range(self, N): scaled_bands = [int(band * N) for band in normalized_bands] return scaled_bands - def generate_even_ranges(self, groups, start, end): + def generate_even_ranges(self, groups: list[any], start: int, end: int): + """ + Generate even ranges from a list of groups. + + Args: + groups (list[any]): The list of groups to generate ranges from. + start (int): The starting index of the ranges. + end (int): The ending index of the ranges. + + Returns: + _type_: _description_ + """ approximate_group_size = round((end - start) / groups) intervals = [] for i in range(groups): @@ -156,7 +233,13 @@ def generate_even_ranges(self, groups, start, end): intervals.append((group_start, min(group_end, end))) return intervals - def render_frame(self, frame_number): + def render_frame(self, frame_number: int): + """ + Render a single frame of the animation. + + Args: + frame_number (int): The current frame number of the animation. + """ if frame_number == 0: self.stream.start_stream() diff --git a/bruhanimate/bruheffect/chatbot_effect.py b/bruhanimate/bruheffect/chatbot_effect.py index 1153039..9f39189 100644 --- a/bruhanimate/bruheffect/chatbot_effect.py +++ b/bruhanimate/bruheffect/chatbot_effect.py @@ -23,12 +23,25 @@ from threading import Thread from bruhcolor import bruhcolored -from ..bruhutil import Screen +from ..bruhutil import Screen, Buffer from .base_effect import BaseEffect class Key: - def __init__(self, character, representation, value, x, y): + """ + A class representing a key on the keyboard with its position and value. + """ + def __init__(self, character: str, representation: list[str], value: int, x: int, y: int): + """ + Initializes a Key object with the given parameters. + + Args: + character (str): The character represented by the key. + representation (list[str]): The visual representation of the key. + value (int): The value of the key. + x (int): The x-coordinate of the key on the screen. + y (int): The y-coordinate of the key on the screen. + """ self.x = x self.y = y self.character = character @@ -43,7 +56,21 @@ def __repr__(self): class GradientNoise: - def __init__(self, x, y, length, char_halt=1, color_halt=1, gradient_length=1): + """ + A class representing a noise effect with a color gradient. + """ + def __init__(self, x: int, y: int, length: int, char_halt: int = 1, color_halt: int = 1, gradient_length: int = 1): + """ + Initializes a GradientNoise object with the given parameters. + + Args: + x (int): The x-coordinate of the noise effect on the screen. + y (int): The y-coordinate of the noise effect on the screen. + length (int): The length of the noise effect on the screen. + char_halt (int, optional): The halt of characters changing (frame_number % character_halt == 0). Defaults to 1. + color_halt (int, optional): The halt of colors changing (frame_number % color_halt == 0). Defaults to 1. + gradient_length (int, optional): Length of the gradient. Defaults to 1. + """ self.x = x self.y = y self.__gradient_length = gradient_length @@ -112,11 +139,23 @@ def __init__(self, x, y, length, char_halt=1, color_halt=1, gradient_length=1): ] # change the gradient - def update_gradient(self, gradient): + def update_gradient(self, gradient: list[int]): + """ + Updates the gradient of the noise. + + Args: + gradient (list[int]): The new gradient to use. + """ self.__gradient = [c for c in gradient for _ in range(self.__gradient_length)] return self def generate(self, frame_number: int): + """ + Generates the next frame of the noise. + + Args: + frame_number (int): The current frame number. + """ if self.done_generating: return # is it time to change the noise chars? @@ -152,6 +191,9 @@ def mark_done(self): class Loading: + """ + A class to handle the loading animation. + """ def __init__(self, animate_part: GradientNoise): self.animate_part = animate_part @@ -163,7 +205,20 @@ def mark_done(self): class StringStreamer: + """ + A class to handle the string streamer animation. + """ def __init__(self, x: int, y: int, text: str, start_frame: int, halt: int = 1): + """ + Initialize the StringStreamer class. + + Args: + x (int): The x position of the string streamer. + y (int): The y position of the string streamer. + text (str): The text to be displayed. + start_frame (int): The frame number to start the animation. + halt (int, optional): Halt value to delay the animation (frame_number & halt == 0). Defaults to 1. + """ self.x = x self.y = y self.text = text @@ -174,6 +229,12 @@ def __init__(self, x: int, y: int, text: str, start_frame: int, halt: int = 1): self.complete = False def generate(self, frame: int): + """ + Generate the string streamer animation for a given frame number. + + Args: + frame (int): The current frame number. + """ if self.complete or frame < self.__start_frame: return if frame % self.__halt == 0: @@ -183,12 +244,23 @@ def generate(self, frame: int): class OllamaApiCaller: + """ + A class to interact with the Ollama API. + """ def __init__( self, model: str, use_message_history: bool = False, message_history_cap: int = 5, ): + """ + Initialize the OllamaApiCaller class. + + Args: + model (str): The Ollama model to use. + use_message_history (bool, optional): Whether or not to use message history. Defaults to False. + message_history_cap (int, optional): How many messages should we use, sliding window. Defaults to 5. + """ self.model = model self.url = "http://127.0.0.1:11434/api/chat" self.busy = False @@ -201,6 +273,17 @@ def __init__( def chat( self, message: str, user: str | None, previous_messages: list[str] | None = None ) -> str: + """ + Send a chat message to the Ollama API and get a response. + + Args: + message (str): The message to send. + user (str | None): The user who sent the message. + previous_messages (list[str] | None, optional): Past sent messages. Defaults to None. + + Returns: + str: Response from ollama. + """ self.busy = True self.state = "running" payload = { @@ -230,6 +313,9 @@ def chat( class OpenAiCaller: + """ + Class to interact with the OpenAI API using the `openai` Python package. + """ def __init__( self, client: openai.OpenAI | openai.AzureOpenAI, @@ -237,6 +323,15 @@ def __init__( use_message_history: bool = False, message_history_cap: int = 5, ): + """ + Initialize the OpenAiCaller class. + + Args: + client (openai.OpenAI | openai.AzureOpenAI): The OpenAI client object. + model (str): The OpenAI model to be used. + use_message_history (bool, optional): Whether or not to use message history. Defaults to False. + message_history_cap (int, optional): Amount of messages from history to use, sliding window. Defaults to 5. + """ self.client = client self.model = model self.busy = False @@ -247,6 +342,16 @@ def __init__( self.message_history_cap = message_history_cap def chat(self, message: str, user: str | None) -> str: + """ + Send a chat message to the OpenAI API and get a response. + + Args: + message (str): The message to be sent to the OpenAI API. + user (str | None): The user who sent the message. + + Returns: + str: The response from the OpenAI API. + """ self.busy = True self.state = "running" response = self.client.chat.completions.create( @@ -277,7 +382,19 @@ def chat(self, message: str, user: str | None) -> str: class ChatbotEffect(BaseEffect): - def __init__(self, screen: Screen, buffer, back_buffer, background: str = " "): + """ + A class to create a chatbot effect. + """ + def __init__(self, screen: Screen, buffer: Buffer, back_buffer: Buffer, background: str = " "): + """ + Initialize the ChatbotEffect class. + + Args: + screen (Screen): Our instance of the terminal window + buffer (Buffer): Effect buffer to push updates to. + back_buffer (Buffer): The buffer to push the effect updates to. + background (str, optional): Character or string to use for the background. Defaults to " ". + """ super(ChatbotEffect, self).__init__(buffer, background) self.back_buffer = back_buffer self.screen = screen @@ -350,6 +467,16 @@ def __init__(self, screen: Screen, buffer, back_buffer, background: str = " "): self.avatar_placed = False def __expand_list(self, original_list: list[int|str], n: int, mul: int = 1): + """ + Expands a list by adding `n` elements to the end of it, each multiplied by `mul`. + + Args: + original_list (list[int | str]): The list to be expanded. + n (int): The number of elements to add to the end of the list. + mul (int, optional): The multiplier for each added element. Defaults to 1. + Returns: + _type_: _description_ + """ l = [] for val in original_list: for _ in range(mul): @@ -367,6 +494,20 @@ def set_chatbot_properties( use_message_history: bool = False, message_history_cap: int = 5, ): + """ + Sets the properties for the chatbot. + + Args: + interface (str | None): The interface type, e.g., "OpenAI" or "Azure OpenAI". + model (str): The name of the AI model to use. + user (str | None, optional): The name of the user. Defaults to None. + client (openai.OpenAI | openai.AzureOpenAI | None, optional): The client to use. Defaults to None. + use_message_history (bool, optional): Whether or not to use message history. Defaults to False. + message_history_cap (int, optional): How many messages from history to use, sliding window. Defaults to 5. + + Raises: + Exception: If the interface is not recognized, an exception will be raised. + """ if interface: self.interface = interface if user: @@ -391,14 +532,33 @@ def set_chatbot_properties( ) def set_second_effect(self, effect: str): + """ + Sets the second effect for the chatbot. + + Args: + effect (str): The effect to use + """ self.second_effect = effect def set_chatbot_print_halt(self, halt: int): + """ + Sets the chatbot print halt value to control how often it prints messages. + + Args: + halt (int): (frame_number % halt == 0) + """ self.chatbot_print_halt = halt def set_gradient_noise_halts( self, char_halt: int | None = None, color_halt: int | None = None ): + """ + Sets the gradient noise halts for character and color shifts. + + Args: + char_halt (int | None, optional): Sets the character halt for gradient noise. Defaults to None. + color_halt (int | None, optional): Sets the color halt for gradient noise. Defaults to None. + """ if char_halt: self.gradient_noise_char_halt = char_halt if color_halt: @@ -415,6 +575,19 @@ def set_chatbot_user_colors( user_avatar_color: int | str | None = None, user_avatar_text_color: int | str | None = None, ): + """ + Sets the colors for the chatbot and user messages. + + Args: + chatbot_text_color (int | str | None, optional): Color of chatbot output text. Defaults to None. + chatbot_background_color (int | str | None, optional): Background of chatbot output text. Defaults to None. + chatbot_avatar_color (int | str | None, optional): Text color of avatar logo. Defaults to None. + chatbot_avatar_text_color (int | str | None, optional): Background color of avatar logo. Defaults to None. + user_text_color (int | str | None, optional): Color of user text. Defaults to None. + user_background_color (int | str | None, optional): Background color of user text. Defaults to None. + user_avatar_color (int | str | None, optional): Text color of user avatar. Defaults to None. + user_avatar_text_color (int | str | None, optional): Background color of user avatar. Defaults to None. + """ if chatbot_text_color: self.chatbot_text_color = chatbot_text_color if chatbot_background_color: @@ -433,6 +606,12 @@ def set_chatbot_user_colors( self.user_avatar_text_color = user_avatar_text_color def set_avatar_properties(self, size: int): + """ + Set avatar properties for user and chatbot. + + Args: + size (int): Length of the avatars on left side of screen. + """ self.avatar_size = size self.user_cursor_x_idx = self.avatar_size for ydx in range(self.screen.height): @@ -442,24 +621,66 @@ def set_avatar_properties(self, size: int): ] def set_chatbot_stats(self, show: bool = False): + """ + Set chatbot stats on the right side of screen. + + Args: + show (bool, optional): Whether or not to show chatbot stats. Defaults to False. + """ self.show_stats = show def set_chatbot_blink_halt(self, halt: int): + """ + Set chatbot blink and halt properties. + + Args: + halt (int): (frame_number % halt == 0) + """ self.blink_halt = halt def set_divider_flag(self, divider: bool, divider_character: str = "-"): + """ + Set the divider flag and character for screen. + + Args: + divider (bool): Whether or not to show the divider. + divider_character (str, optional): Character to use for the divider. Defaults to "-". + """ self.divider = divider self.divider_character = divider_character def set_chatbot_cursor_colors(self, color_one: int | str, color_two: int | str): + """ + Set the colors for chatbot cursor. + + Args: + color_one (int | str): First color of cursor. + color_two (int | str): Second color of cursor. + """ self.blink_color_one = color_one self.blink_color_two = color_two def set_chatbot_text_gradient(self, gradient: list[int|str], mul: int): + """ + Set the text color for chatbot to use a gradient. + + Args: + gradient (list[int | str]): Gradient color to use for chatbot loading. + mul (int): Multiplier for the gradient effect. + """ self.gradient_text_color = gradient self.gradient_mul = mul - def __handle_keyboard_result(self, result): + def __handle_keyboard_result(self, result: int): + """ + Handle the keyboard input and return a result. + + Args: + result (int): Result from pressing down keyboard from win32 package. + + Returns: + bool: Something . . . + """ if result: if result == -300: # backspace if self.user_cursor_x_idx == self.avatar_size: @@ -533,6 +754,9 @@ def __handle_keyboard_result(self, result): return False def __scroll_up(self): + """ + Scroll up the display by one line. + """ first_key = min(self.all_keys.keys()) last_key = max(self.all_keys.keys()) if len(self.all_keys) == 0 or first_key == 0: @@ -549,6 +773,9 @@ def __scroll_up(self): self.current_bottom_y = self.current_bottom_y - 1 def __scroll_down(self): + """ + Scroll down the display by one line. + """ last_key = max(self.all_keys.keys()) self.all_keys[last_key + 1] = [ Key(" ", [ord(" ")], ord(" "), x=_, y=last_key + 1) @@ -564,9 +791,18 @@ def __scroll_down(self): self.all_keys = {i: self.all_keys[key] for i, key in enumerate(sorted(self.all_keys.keys()))} def scroll_keys(self, shift: int = 1): + """ + Scroll the keys up or down by one line + + Args: + shift (int, optional): How much to scroll. Defaults to 1. + """ self.__scroll_down() if shift == 1 else self.__scroll_up() def place_all_keys(self): + """ + Place all keys on to the buffer. + """ for idx, vals in self.all_keys.items(): if idx > self.current_bottom_y or idx < self.current_top_y: continue @@ -580,7 +816,13 @@ def place_all_keys(self): else: self.buffer.put_char(jdx + displacement, idx - self.current_top_y, key.character) - def render_frame(self, frame_number): + def render_frame(self, frame_number: int): + """ + Render the current state of the buffer to the terminal. + + Args: + frame_number (int): The frame number to render. + """ self.buffer.clear_buffer() if self.turn == 0: if not self.avatar_placed: diff --git a/bruhanimate/bruheffect/draw_lines_effect.py b/bruhanimate/bruheffect/draw_lines_effect.py index d343cab..d4d23df 100644 --- a/bruhanimate/bruheffect/draw_lines_effect.py +++ b/bruhanimate/bruheffect/draw_lines_effect.py @@ -15,10 +15,21 @@ """ from .base_effect import BaseEffect +from ..bruhutil import Buffer class Line: - def __init__(self, start_point, end_point): + """ + A class representing a line segment. + """ + def __init__(self, start_point: tuple[int], end_point: tuple[int]): + """ + Initializes a Line object with the given start and end points. + + Args: + start_point (tuple[int]): Start point of the line segment as a tuple (x, y). + end_point (tuple[int]): End point of the line segment as a tuple (x, y). + """ if start_point and end_point: self.start_point = (start_point[0] * 2, start_point[1] * 2) self.end_point = (end_point[0] * 2, end_point[1] * 2) @@ -26,25 +37,60 @@ def __init__(self, start_point, end_point): self.start_point = None self.end_point = None - def update_points(self, start_point, end_point): + def update_points(self, start_point: tuple[int], end_point: tuple[int]): + """ + Updates the points of the line segment with new values. + + Args: + start_point (tuple[int]): New start point of the line segment as a tuple (x, y). + end_point (tuple[int]): New end point of the line segment as a tuple (x, y). + """ self.start_point = (start_point[0], start_point[1]) self.end_point = (end_point[0], end_point[1]) def get_points(self): + """ + Returns the start and end points of the line segment. + + Returns: + tuple[tuple[int], tuple[int]]: The start and end points of the line. + """ return self.start_point, self.end_point class DrawLinesEffect(BaseEffect): - def __init__(self, buffer, background, char=None, thin=False): + def __init__(self, buffer: Buffer, background: str, char: str = None, thin: bool = False): + """ + Initializes the DrawLinesEffect class. + + Args: + buffer (Buffer): Effect buffer to push updates to. + background (str): Character or string to use as the background. + char (str, optional): Character to use for line drawing. Defaults to None. + thin (bool, optional): Whether or not the line should be thin. Defaults to False. + """ super(DrawLinesEffect, self).__init__(buffer, background) self.lines = [] self.char = char self.thin = thin - def add_line(self, start_point, end_point): + def add_line(self, start_point: tuple[int], end_point: tuple[int]): + """ + Adds a line to the effect. + + Args: + start_point (tuple[int]): Start point of the line as a tuple (x, y). + end_point (tuple[int]): End point of the line as a tuple (x, y). + """ self.lines.append(Line(start_point, end_point)) - def render_frame(self, frame_number): + def render_frame(self, frame_number: int): + """ + Renders the effect for a given frame number. + + Args: + frame_number (int): The current frame number. + """ if frame_number == 0 and len(self.lines) > 0: for y in range(self.buffer.height()): self.buffer.put_at(0, y, self.background * self.buffer.width()) diff --git a/bruhanimate/bruheffect/game_of_life_effect.py b/bruhanimate/bruheffect/game_of_life_effect.py index 0e20d61..98d9fe9 100644 --- a/bruhanimate/bruheffect/game_of_life_effect.py +++ b/bruhanimate/bruheffect/game_of_life_effect.py @@ -17,7 +17,7 @@ import random from bruhcolor import bruhcolored -from ..bruhutil import LIFE_COLORS, LIFE_SCALES +from ..bruhutil import LIFE_COLORS, LIFE_SCALES, Buffer from .base_effect import BaseEffect @@ -28,13 +28,24 @@ class GameOfLifeEffect(BaseEffect): def __init__( self, - buffer, - background, - decay=False, - color=False, - color_type=None, - scale="random", + buffer: Buffer, + background: str, + decay: bool = False, + color: bool = False, + color_type: str = None, + scale: str = "random", ): + """ + Initialize the Game of Life effect with a buffer and background color. + + Args: + buffer (Buffer): Effect buffer to push updates to. + background (str): Character of string to use as the background. + decay (bool, optional): Whether or not cells should decay. Defaults to False. + color (bool, optional): Whether or not the decay should use color. Defaults to False. + color_type (str, optional): Type of color scale to use. Defaults to None. + scale (str, optional): Type of gray scale to use. Defaults to "random". + """ super(GameOfLifeEffect, self).__init__(buffer, background) self.decay = decay self.scale = scale @@ -59,7 +70,7 @@ def __init__( def _set_attributes(self): """ - Function to set the attributes of the effect + Function to set the attributes of the effect. """ self.grey_scale = ( LIFE_SCALES[random.choice(list(LIFE_SCALES.keys()))] @@ -71,11 +82,14 @@ def _set_attributes(self): self.DEAD = 0 self.mappings = {i: self.grey_scale[i] for i in range(len(self.grey_scale))} - def update_decay(self, decay, color_type="GREYSCALE", scale="random"): + def update_decay(self, decay: bool, color_type: str = "GREYSCALE", scale: str = "random"): """ - Function to enable to decay and select the color map - :param decay: True / False - :param color_type: color map for the effect + Function to enable the decay and select the color map. + + Args: + decay (bool): Whether or not the cell should decay + color_type (str, optional): Type of color to use. Defaults to "GREYSCALE". + scale (str, optional): Type of scale to use. Defaults to "random". """ self.decay = decay self.scale = scale @@ -83,13 +97,23 @@ def update_decay(self, decay, color_type="GREYSCALE", scale="random"): self.color_type = color_type self._set_attributes() - def update_rules(self, life_rule, death_rule): + def update_rules(self, life_rule: list[int], death_rule: list[int]): + """ + Function to update the rules for life and death. + + Args: + life_rule (list[int]): Lower and upper bound for number of neighbors that lead to life. + death_rule (list[int]): Lower and upper bound for number of neighbors that lead to death. + """ self.rules["life"] = life_rule self.rules["death"] = death_rule - def render_frame(self, frame_number): + def render_frame(self, frame_number: int): """ - Function to render the next frame of the GOL effect + Function to render the next frame of the GOL effect. + + Args: + frame_number (int): The current frame number to render. """ if frame_number == 0: # INITIALIZE THE GAME for y in range(self.buffer.height()): diff --git a/bruhanimate/bruheffect/matrix_effect.py b/bruhanimate/bruheffect/matrix_effect.py index 062e6d8..05bb827 100644 --- a/bruhanimate/bruheffect/matrix_effect.py +++ b/bruhanimate/bruheffect/matrix_effect.py @@ -19,24 +19,38 @@ from bruhcolor import bruhcolored from .base_effect import BaseEffect +from ..bruhutil import Buffer class MatrixEffect(BaseEffect): """ - Effect to mimic the cliche coding backgroud with falling random characters + Effect to mimic the cliche coding backgroud with falling random characters. """ def __init__( self, - buffer, - background, - chracter_halt_range=(1, 2), - color_halt_range=(1, 2), - character_randomness_one=0.70, - character_randomness_two=0.60, - color_randomness=0.50, - gradient_length=1, + buffer: Buffer, + background: str, + chracter_halt_range: tuple[int] = (1, 2), + color_halt_range: tuple[int] = (1, 2), + character_randomness_one: float = 0.70, + character_randomness_two: float = 0.60, + color_randomness: float = 0.50, + gradient_length: int = 1, ): + """ + Initialize the MatrixEffect class. + + Args: + buffer (Buffer): Effect buffer to push changes to. + background (str): Character or string used for the background. + chracter_halt_range (tuple[int], optional): Halt range. Defaults to (1, 2). + color_halt_range (tuple[int], optional): Halt range. Defaults to (1, 2). + character_randomness_one (float, optional): Frequency to update a character. Defaults to 0.70. + character_randomness_two (float, optional): Frequency to update a character. Defaults to 0.60. + color_randomness (float, optional): Frequency to move the color gradient. Defaults to 0.50. + gradient_length (int, optional): Length of the color gradient. Defaults to 1. + """ super(MatrixEffect, self).__init__(buffer, background) self.__character_choices = ( string.ascii_letters + "1234567890!@#$%^&*()_+-=<>,.:\";'{}[]?/" @@ -97,13 +111,24 @@ def __init__( def set_matrix_properties( self, - chacter_halt_range=(1, 2), - color_halt_range=(1, 2), - character_randomness_one=0.70, - character_randomness_two=0.60, - color_randomness=0.50, - gradient_length=1, + chacter_halt_range: tuple[int] = (1, 2), + color_halt_range: tuple[int] = (1, 2), + character_randomness_one: float = 0.70, + character_randomness_two: float = 0.60, + color_randomness: float = 0.50, + gradient_length: int = 1, ): + """ + Set the matrix properties for the MatrixEffect. + + Args: + chracter_halt_range (tuple[int], optional): Halt range. Defaults to (1, 2). + color_halt_range (tuple[int], optional): Halt range. Defaults to (1, 2). + character_randomness_one (float, optional): Frequency to update a character. Defaults to 0.70. + character_randomness_two (float, optional): Frequency to update a character. Defaults to 0.60. + color_randomness (float, optional): Frequency to move the color gradient. Defaults to 0.50. + gradient_length (int, optional): Length of the color gradient. Defaults to 1. + """ self.__character_randomness_one = character_randomness_one self.__character_randomness_two = character_randomness_two self.__color_randomness = color_randomness @@ -126,7 +151,13 @@ def set_matrix_properties( for _ in range(self.buffer.height()) ] - def set_matrix_gradient(self, gradient): + def set_matrix_gradient(self, gradient: list[int]): + """ + Set the base gradient of the matrix. This will reset the current gradient and recreate it based on the new base gradient. + + Args: + gradient (list[int]): List of colors. + """ self.__base_gradient = gradient self.__gradient = [ color @@ -135,9 +166,18 @@ def set_matrix_gradient(self, gradient): ] def get_gradient(self): + """ + Get the current gradient. + + Returns: + list[int]: The current gradient. + """ return self.__base_gradient def __initialize_buffer(self): + """ + Initialize the buffer with characters and colors based on the current settings. + """ for y in range(self.buffer.height()): for x in range(self.buffer.width()): self.__buffer_characters[y][x] = random.choice(self.__character_choices) @@ -151,9 +191,12 @@ def __initialize_buffer(self): ).colored, ) - def render_frame(self, frame_number): + def render_frame(self, frame_number: int): """ - Renders the next frame for the Matrix effect into the effect buffer + Render a single frame of the matrix effect. + + Args: + frame_number (int): The current frame number. """ if frame_number == 0: self.__initialize_buffer()