# Matrix Rain Plugin Specification

## Overview

The Matrix Rain Plugin creates the iconic "digital rain" effect from The Matrix movie. It demonstrates full-screen plugin capabilities with falling green characters, providing an immersive visual experience.

**Location:** `plugins/fullscreen/matrix_plugin.py`

**Version:** 1.0.0

## Features

### Visual Effects

- **Falling characters**: Green characters cascading down the screen
- **Column tracking**: Independent columns with varying speeds
- **Random gaps**: Gaps between falling streams
- **Trail effect**: Characters fade as they fall
- **Random reset**: Columns randomly reset to top

### Performance

- **Optimized rendering**: Uses pre-compiled character sets
- **Efficient state management**: Column-based state tracking
- **Configurable speed**: Adjustable fall speed
- **Color customization**: Customizable color scheme

## Architecture

### Plugin Structure

```python
class MatrixRainPlugin(FullScreenPlugin):
    - initialize(renderer) -> bool
    - on_start() -> None
    - render_frame(delta_time: float) -> bool
    - handle_key(key_press: KeyPress) -> None
    - on_end() -> None
```

### Component System

Uses `MatrixRenderer` from `core.fullscreen.components.matrix_components`:

```python
class MatrixRenderer:
    - __init__(width: int, height: int)
    - reset() -> None
    - update(delta_time: float) -> None
    - render() -> str
    - _get_next_char() -> str
    - _should_reset_column(col: int) -> bool
```

## Configuration

### Configuration Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `character_set` | string | `"katakana"` | Character set (katakana, binary, mixed) |
| `fall_speed` | float | `1.0` | Base fall speed multiplier |
| `column_speed_variance` | float | `0.5` | Speed variance per column (0.0-1.0) |
| `trail_length` | int | `20` | Trail length for each column |
| `reset_probability` | float | `0.02` | Probability of column reset per frame |
| `color_mode` | string | `"classic"` | Color scheme (classic, green, cyan, rainbow) |

### Configuration File

Edit `~/.kollabor-cli/config.json`:

```json
{
  "plugins": {
    "matrix_rain": {
      "character_set": "katakana",
      "fall_speed": 1.0,
      "column_speed_variance": 0.5,
      "trail_length": 20,
      "reset_probability": 0.02,
      "color_mode": "classic"
    }
  }
}
```

## Character Sets

### Katakana (Default)

Japanese Katakana characters:

```
ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ タ チ ツ テ ト ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ マ ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ヰ ヱ ヲ ン
```

### Binary

Binary digits:

```
0 1
```

### Mixed

Katakana + binary + latin:

```
ア イ ウ エ オ 0 1 A B C D E F 0 1
```

## Color Modes

### Classic (Default)

Bright green on black:

```
Foreground: \033[92m (bright green)
Background: \033[40m (black)
```

### Green

Standard green on black:

```
Foreground: \033[32m (green)
Background: \033[40m (black)
```

### Cyan

Cyan on black:

```
Foreground: \033[36m (cyan)
Background: \033[40m (black)
```

### Rainbow

Cycling colors:

```
Foreground: \033[91m through \033[96m (red through cyan)
Background: \033[40m (black)
```

## Algorithm

### Column State

```python
@dataclass
class ColumnState:
    position: float           # Current vertical position (pixels)
    speed: float             # Fall speed
    trail: List[str]         # Trail characters
    head_char: str           # Character at head of stream
```

### Update Logic

```python
def update(delta_time: float):
    for col in range(width):
        # Update position
        column_states[col].position += column_states[col].speed * delta_time
        
        # Randomly reset column
        if self._should_reset_column(col):
            column_states[col].position = 0
            column_states[col].trail = []
            column_states[col].head_char = self._get_next_char()
        
        # Update trail
        if column_states[col].position >= 1.0:
            column_states[col].trail.append(column_states[col].head_char)
            if len(column_states[col].trail) > trail_length:
                column_states[col].trail.pop(0)
            column_states[col].position -= 1.0
            column_states[col].head_char = self._get_next_char()
```

### Render Logic

```python
def render() -> str:
    output = []
    
    for row in range(height):
        line = []
        for col in range(width):
            # Determine character for this cell
            char = self._get_char_at(col, row)
            line.append(char)
        output.append(''.join(line))
    
    return '\n'.join(output)

def _get_char_at(col: int, row: int) -> str:
    column = column_states[col]
    
    # Calculate if this row is in the trail
    trail_row = height - row - 1
    trail_index = len(column.trail) - trail_row - 1
    
    if trail_index >= 0 and trail_index < len(column.trail):
        # Trail character
        char = column.trail[trail_index]
        # Fade based on distance from head
        intensity = 1.0 - (trail_index / len(column.trail))
        return self._apply_color(char, intensity)
    elif trail_index == -1:
        # Head character
        return self._apply_color(column.head_char, 1.0)
    else:
        # Empty
        return ' '
```

## Keyboard Controls

| Key | Action |
|-----|--------|
| `Esc` | Exit plugin |
| `Space` | Pause/resume |
| `+` / `=` | Increase speed |
| `-` / `_` | Decrease speed |
| `c` | Cycle color mode |
| `s` | Cycle character set |
| `r` | Reset animation |
| `q` | Quick exit |

## Implementation Details

### Initialization

```python
async def initialize(self, renderer) -> bool:
    if not await super().initialize(renderer):
        return False
    
    # Get terminal dimensions
    width, height = renderer.get_terminal_size()
    
    # Create matrix renderer
    self.matrix_renderer = MatrixRenderer(width, height)
    
    return True
```

### Frame Rendering

```python
async def render_frame(self, delta_time: float) -> bool:
    # Update matrix state
    self.matrix_renderer.update(delta_time)
    
    # Get rendered output
    output = self.matrix_renderer.render()
    
    # Display
    self.renderer.clear()
    self.renderer.write(output)
    
    return True
```

### Character Generation

```python
CHARACTER_SETS = {
    "katakana": [
        'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ',
        # ... full katakana set
    ],
    "binary": ['0', '1'],
    "mixed": [
        'ア', 'イ', 'ウ', 'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ',
        '0', '1', 'A', 'B', 'C', 'D', 'E', 'F'
    ]
}

def _get_next_char(self) -> str:
    char_set = CHARACTER_SETS[self.character_set]
    return random.choice(char_set)
```

## Performance Considerations

### Optimization Techniques

- **Pre-compiled character sets**: Character sets defined as lists (constant time access)
- **Minimal state updates**: Only update columns that change
- **Efficient string building**: Use list comprehension for each line
- **Delta time usage**: Frame-independent animation

### Memory Usage

- **Column state**: O(width) memory (one state per column)
- **Trail storage**: O(width * trail_length) for trail characters
- **Render buffer**: O(width * height) for final output

Typical usage for 80x24 terminal:
- Column state: ~1KB
- Trail storage: ~40KB (assuming trail_length=20)
- Render buffer: ~2KB

## Implementation Checklist

### Core Functionality
- [x] Column-based state management
- [x] Falling character animation
- [x] Random reset logic
- [x] Trail effect
- [x] Color application

### Configuration
- [x] Character set selection
- [x] Speed control
- [x] Trail length
- [x] Reset probability
- [x] Color mode

### Keyboard Controls
- [x] Exit
- [x] Pause/resume
- [x] Speed adjustment
- [x] Color cycling
- [x] Character set cycling
- [x] Reset

## Usage Examples

### Start Matrix Effect

```bash
# Via slash command (if implemented)
/matrix

# Via full-screen menu
Press F9 -> Select "Matrix Rain"
```

### Adjust Speed

While running:
- Press `+` to increase speed
- Press `-` to decrease speed

### Change Color

While running:
- Press `c` to cycle color modes
- Modes: classic → green → cyan → rainbow → classic

### Change Character Set

While running:
- Press `s` to cycle character sets
- Sets: katakana → binary → mixed → katakana

## Best Practices

### Performance

- **Terminal size**: Works best on larger terminals (80x24 or larger)
- **Trail length**: Default 20 provides good visual without high CPU
- **Fall speed**: 1.0 provides classic movie speed
- **Reset probability**: 0.02 creates natural random gaps

### Visual Appeal

- **Classic mode**: Bright green on black for authentic look
- **Katakana characters**: Most authentic to movie
- **Moderate speed**: Not too fast to read, not too slow to be boring

## Related Documentation

- /docs/reference/fullscreen-framework.md - Full-screen plugin framework
- /docs/reference/drawing-primitives.md - Drawing primitives
- /docs/reference/color-system.md - Color system

## Future Enhancements

### Planned Features

- [ ] Custom character set input
- [ ] Matrix rain in specified color
- [ ] Interactive mouse support (ripple effect)
- [ ] Background image with rain overlay
- [ ] Sound effects (digital drops)
- [ ] Text message in rain (reveal characters)

### Visual Variations

- [ ] Binary rain only
- [ ] Numbers instead of characters
- [ ] Glitch effects
- [ ] Flash effect on column reset

## Troubleshooting

### Animation Too Slow

1. Check terminal size (smaller = fewer columns = faster)
2. Increase `fall_speed` configuration
3. Decrease `trail_length` for less drawing
4. Check system CPU usage

### Animation Too Fast

1. Decrease `fall_speed` configuration
2. Increase `trail_length` for slower visual feedback
3. Check if delta_time is being calculated correctly

### Characters Not Visible

1. Verify terminal supports Unicode
2. Check character set is correct
3. Verify color mode is compatible with terminal
4. Check if terminal background is black

## Extension Points

### Custom Character Sets

Add custom character sets:

```python
CHARACTER_SETS["custom"] = [
    # Your custom characters
    '★', '☆', '✦', '✧', '◉', '◎', '●', '○'
]
```

### Custom Color Modes

Add custom color modes:

```python
def _apply_color_custom(self, char: str, intensity: float) -> str:
    # Custom color logic
    if intensity > 0.8:
        return f"\033[95m{char}\033[0m"  # Magenta
    elif intensity > 0.5:
        return f"\033[94m{char}\033[0m"  # Blue
    else:
        return f"\033[90m{char}\033[0m"  # Gray
```

### Custom Fall Patterns

Modify column reset logic:

```python
def _should_reset_column(self, col: int) -> bool:
    # Custom reset pattern (e.g., wave pattern)
    wave_offset = math.sin(col * 0.1 + time.time()) * 0.5 + 0.5
    return random.random() < self.reset_probability * wave_offset
```
