RuslanKain
init
d19858a
"""
╔══════════════════════════════════════════════════════════════════════════════╗
β•‘ Models: step.py β•‘
β•‘ Classes for representing algorithm execution steps β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
This module contains:
β€’ StepType (Enum) - Types of operations (compare, swap, merge, etc.)
β€’ Step (dataclass) - A single step in algorithm execution
πŸ“š WHY RECORD STEPS?
To visualize algorithms step-by-step, we need to RECORD what happens.
Each Step captures:
- WHAT operation occurred (compare, swap, etc.)
- WHERE it happened (which indices)
- WHEN in the process (depth for recursive algorithms)
- Additional context (metadata)
This is the "data" that visualization will render.
"""
from dataclasses import dataclass, field
from enum import Enum, auto
from typing import List, TYPE_CHECKING
# Avoid circular import - only import for type checking
if TYPE_CHECKING:
from oop_sorting_teaching.models.gesture import GestureImage
# ==============================================================================
# ENUM: StepType
# ==============================================================================
#
# πŸ“š CONCEPT: Enums for Type Safety
#
# Instead of using strings like "compare" or "swap", we use an Enum.
# This prevents bugs from typos:
# - String: if step_type == "comprae" # Typo! No error, silent bug
# - Enum: if step_type == StepType.COMPRAE # Python error! Bug caught
# ==============================================================================
class StepType(Enum):
"""
Types of algorithm steps that can be visualized.
Each step in our sorting/searching algorithms will have a type
that determines how it's displayed in the visualization.
πŸ“š CONCEPT: auto()
The auto() function automatically assigns incrementing values.
We don't care what the actual numbers are - we just need
unique identifiers for each step type.
"""
# Comparison operations
COMPARE = auto() # Comparing two elements
# Movement operations
SWAP = auto() # Swapping two elements (in-place algorithms)
MOVE = auto() # Moving an element to a new position
# Merge sort specific
SPLIT = auto() # Splitting array into subarrays
MERGE = auto() # Merging sorted subarrays
# Quick sort specific
PIVOT_SELECT = auto() # Selecting a pivot element
PARTITION = auto() # Partitioning around pivot
# Binary search specific
SEARCH_RANGE = auto() # Showing current search range
NARROW_LEFT = auto() # Target is in left half
NARROW_RIGHT = auto() # Target is in right half
FOUND = auto() # Target element found
NOT_FOUND = auto() # Target element not in array
# General
PASS_COMPLETE = auto() # One pass through the data complete (Bubble Sort)
COMPLETE = auto() # Algorithm finished
MARK_SORTED = auto() # Mark element(s) as in final position
# Stability detection
INSTABILITY = auto() # Stability violation detected!
INSTABILITY_WARNING = auto() # Warning for potential instability
# ==============================================================================
# DATACLASS: Step
# ==============================================================================
#
# πŸ“š CONCEPT: Recording Algorithm Execution
#
# When an algorithm runs, we want to show EVERY step:
# 1. What operation happened (StepType)
# 2. Which elements were involved (indices)
# 3. What the array looks like now (array_state)
# 4. Any additional info (metadata)
#
# By recording steps, we can:
# - Play back the algorithm visually
# - Step forward and backward
# - Analyze algorithm behavior
# ==============================================================================
@dataclass
class Step:
"""
Represents a single step in an algorithm's execution.
This is used to record what the algorithm is doing at each point,
so we can visualize it step by step.
Think of it like frames in a movie:
- Each Step is one frame
- Together they tell the story of the algorithm
Attributes:
step_type: What kind of operation (compare, swap, merge, etc.)
indices: Which array positions are involved
description: Human-readable explanation
depth: Recursion depth (for merge sort / quick sort)
array_state: Copy of the array at this step
highlight_indices: Extra indices to highlight (e.g., sorted region)
metadata: Additional algorithm-specific data
Example:
step = Step(
step_type=StepType.COMPARE,
indices=[3, 4],
description="Comparing elements at positions 3 and 4",
depth=0,
array_state=[...],
metadata={"comparison_count": 5}
)
"""
step_type: StepType
indices: List[int]
description: str
depth: int = 0
array_state: List['GestureImage'] = field(default_factory=list)
highlight_indices: List[int] = field(default_factory=list)
metadata: dict = field(default_factory=dict)
@property
def type(self) -> StepType:
"""
Alias for step_type for cleaner access in renderers.
This allows: step.type instead of step.step_type
Makes the code more readable in visualization code.
"""
return self.step_type
def __str__(self) -> str:
"""Human-readable string for debugging."""
indices_str = ', '.join(str(i) for i in self.indices)
return f"[{self.step_type.name}] indices=[{indices_str}] depth={self.depth}: {self.description}"