| import gradio as gr |
| import time |
| import random |
|
|
| from algorithms.bubble_sort import bubble_sort_steps |
| from algorithms.insertion_sort import insertion_sort_steps |
| from algorithms.selection_sort import selection_sort_steps |
| from algorithms.binary_search import binary_search_steps |
|
|
| from utils.visualizer import render_single_step_html |
|
|
| |
| |
| |
| is_paused = False |
|
|
| def pause_sort(): |
| global is_paused |
| is_paused = True |
|
|
| def resume_sort(): |
| global is_paused |
| is_paused = False |
|
|
| |
| |
| |
| def parse_array(text: str): |
| if not text: |
| raise ValueError("Input array is empty.") |
| parts = [p.strip() for p in text.split(",")] |
| arr = [] |
| for p in parts: |
| if p == "": |
| continue |
| try: |
| arr.append(float(p) if "." in p else int(p)) |
| except: |
| raise ValueError(f"Invalid number: {p}") |
| if len(arr) == 0: |
| raise ValueError("No valid numbers found.") |
| return arr |
|
|
| def generate_random_array(n): |
| return [random.randint(1, 99) for _ in range(n)] |
|
|
| |
| |
| |
| def stream_sort(algo, array_text, speed_ms, search_target, use_random, random_size): |
| global is_paused |
| is_paused = False |
|
|
| |
| if use_random: |
| arr = generate_random_array(random_size) |
| else: |
| try: |
| arr = parse_array(array_text) |
| except Exception as e: |
| yield f"<div style='color:red;'>Error: {e}</div>" |
| return |
|
|
| delay = speed_ms / 1000.0 |
|
|
| |
| if algo == "Bubble Sort": |
| steps = bubble_sort_steps(arr) |
| elif algo == "Insertion Sort": |
| steps = insertion_sort_steps(arr) |
| elif algo == "Selection Sort": |
| steps = selection_sort_steps(arr) |
| elif algo == "Binary Search": |
| if search_target is None: |
| yield "<div style='color:red;'>Binary Search needs a target.</div>" |
| return |
| arr_sorted = sorted(arr) |
| steps = binary_search_steps(arr_sorted, search_target) |
| else: |
| yield "<div style='color:red;'>Unknown algorithm.</div>" |
| return |
|
|
| |
| for i, step in enumerate(steps): |
| while is_paused: |
| time.sleep(0.05) |
| yield render_single_step_html(step, i) |
| time.sleep(delay) |
|
|
| |
| |
| |
| with gr.Blocks(title="Sorting/Searching Visualization") as demo: |
|
|
| gr.Markdown("# 🔍 Algorithm Visualizer (Real-Time + Adjustable Speed)") |
| gr.Markdown("Choose an algorithm, enter an array, and watch it animate step by step.") |
|
|
| with gr.Row(): |
| algo_dd = gr.Dropdown( |
| label="Algorithm", |
| choices=["Bubble Sort", "Insertion Sort", "Selection Sort", "Binary Search"], |
| value="Bubble Sort" |
| ) |
| use_random = gr.Checkbox(label="Use random array", value=False) |
| random_size = gr.Slider(label="Random array size", minimum=3, maximum=50, step=1, value=10) |
| array_input = gr.Textbox( |
| label="Input Array", |
| value="8, 3, 7, 4, 9, 1", |
| interactive=True |
| ) |
| speed = gr.Slider( |
| label="Speed (ms per step)", |
| minimum=10, |
| maximum=1500, |
| step=10, |
| value=300 |
| ) |
|
|
| search_target = gr.Number( |
| label="Binary Search Target", |
| value=4, |
| interactive=True, |
| visible=False |
| ) |
|
|
| |
| def update_array(use_random_val, size, current_value): |
| if use_random_val: |
| arr = generate_random_array(size) |
| return gr.update(value=", ".join(str(x) for x in arr)) |
| return gr.update(value=current_value) |
|
|
| use_random.change(update_array, inputs=[use_random, random_size, array_input], outputs=[array_input]) |
| random_size.change(update_array, inputs=[use_random, random_size, array_input], outputs=[array_input]) |
|
|
| |
| def toggle_target(algo_value): |
| return gr.update(visible=(algo_value == "Binary Search")) |
|
|
| algo_dd.change(toggle_target, inputs=[algo_dd], outputs=[search_target]) |
|
|
| run_btn = gr.Button("Run Visualization") |
|
|
| with gr.Row(): |
| pause_btn = gr.Button("Pause") |
| resume_btn = gr.Button("Resume") |
|
|
| pause_btn.click(pause_sort, inputs=None, outputs=None) |
| resume_btn.click(resume_sort, inputs=None, outputs=None) |
|
|
| output = gr.HTML(label="Visualization") |
|
|
| run_btn.click( |
| stream_sort, |
| inputs=[algo_dd, array_input, speed, search_target, use_random, random_size], |
| outputs=[output] |
| ) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch(server_name="0.0.0.0", server_port=None) |
|
|