# LeetCode Animation — Administrator & Developer Guide

## 1. Architecture Overview

LeetCode Animation is a static content archive of ~100 LeetCode algorithm problems, each presented as an animated GIF visualization, a Chinese markdown article, and optionally a Java reference implementation. There is no runtime service, no database, and no CI — the "architecture" is a folder-naming contract and a small Python scaffolding CLI.

### Content production pipeline

```text
┌─────────────────────────────────────────────────────────┐
│               CONTENT PRODUCTION PIPELINE               │
│                                                         │
│  1. Scaffold          2. Author         3. Publish      │
│     (anima CLI)          (human)           (git push)   │
│                                                         │
│  python anima.py  →  Article/*.md    →  git add + push  │
│  new <id> <title>    Animation/*.gif                    │
│       ↓              Code/*.java                        │
│  {id:04d}-{slug}/                                       │
│  ├─ Animation/                                          │
│  ├─ Article/                                            │
│  └─ Code/                                               │
└─────────────────────────────────────────────────────────┘
```

> [!NOTE]
> This is not a conventional software project. There is no build, no test suite, no deploy pipeline. The product is textual and media content; the only executable is a ~100-line Python scaffold tool. The correct mental model is a **flat content catalog governed by a folder-naming contract**.

### Component inventory

| Component | Path | Role |
|-----------|------|------|
| `anima.py` | Repository root | CLI entrypoint — `fire.Fire(anima.Anima())` |
| `anima/` package | `anima/__init__.py`, `base.py`, `create.py`, `model.py` | Scaffold logic: problem naming, directory creation, template copying |
| Article template | `template/template.md` | Blank markdown skeleton copied into each new article |
| Per-problem folders | `0001-Two-Sum/`, etc. (~108 folders) | The content itself |
| Notes directory | `notes/` (68 files) | Standalone Chinese article write-ups |
| READMEs | `Readme.md`, `README-En.md` | Catalog indexes (Chinese and English) |
| Contributing guide | `contributing.md` | Usage notes for `anima` CLI (Chinese) |
| Shared images | `Pictures/` | QR code, banners referenced by README |

### Technology stack

| Layer | Technology |
|-------|-----------|
| Content format | Markdown (GFM), GIF, MP4/M4V |
| Scaffold CLI | Python 3.6+, `fire` library |
| Version control | Git (default branch: `master`) |
| Hosting | GitHub (public repository) |

### What does NOT exist

- No web server, API, or service boundary
- No database, cache, or persistent state outside of git
- No test suite, no CI configuration
- No build system (`setup.py`, `pyproject.toml`, Makefile)
- No packaging metadata — `anima` cannot be `pip install`-ed
- No configuration files, no `.env`, no secrets
- No Docker or container configuration
- No internationalization framework

## 2. System Requirements

### For reading content

| Requirement | Details |
|-------------|---------|
| Git | Any version (to clone) |
| Disk space | ~300–500 MB (GIFs and video files dominate) |
| Markdown viewer | Any (VS Code, GitHub web, browser) |

### For using the scaffolding CLI

| Requirement | Details |
|-------------|---------|
| Python | 3.6+ (f-strings, `dataclasses`) |
| `fire` | Any version (unpinned in `requirements.txt`) |

### Dependencies

The `requirements.txt` contains a single entry:

```text
fire
```

`fire` transitively pulls `six` and `termcolor`. No other runtime dependencies exist.

> [!IMPORTANT]
> The `fire` version is unpinned, which means `pip install` will grab the latest release. For reproducibility, consider pinning: `fire==0.6.0` (or the latest stable at time of fork).

## 3. Configuration Reference

This project has no configuration files, environment variables, or CLI flags beyond the `anima.py new` command arguments.

| Parameter | Type | Description |
|-----------|------|-------------|
| `id` | `int` | LeetCode problem number |
| `title` | `str` | Problem title (spaces become hyphens in the folder name) |

The naming convention is hardcoded in `anima/model.py`:

```python
def title_slug(self):
    title_parts = re.split(r'\s+', self.title)
    return f'{self.id:04d}-' + '-'.join(title_parts)
```

> [!WARNING]
> The slug generator zero-pads to 4 digits via `f'{id:04d}'` but does **not** truncate. IDs like `1394` produce `1394-...` (4 digits), not `01394-...` (5 digits). The existing folder `01394-Find-out-the-lucky-number-in-the-array` was created manually with extra padding. Any tooling walking the catalog must handle both widths.

## 4. Operations

### Routine maintenance (if resurrecting the project)

- **Broken outbound links.** Articles reference external URLs that may go stale. Audit with any link checker (`lychee`, `muffet`).
- **CDN reachability.** README-embedded GIFs may reference external CDN URLs. Clone the repository for local copies as the reliable fallback.
- **Catalog-to-filesystem consistency.** The READMEs link to specific paths under `notes/` and `Article/` directories. There is no script verifying these links resolve.

> [!TIP]
> A simple link-verification script (walk every markdown link in the READMEs, `os.path.exists()` each local target) is a ~20-line task and would catch most breakage.

### Disk usage

The repository is a few hundred MB, dominated by:
- GIFs under `Animation/` (typically 500 KB – 3 MB each)
- M4V/MP4 source files (10–50 MB each when present)

> [!NOTE]
> Use sparse checkout to pull a subset of problems without downloading the full media collection (see User Guide, Common Tasks).

### Backup strategy

The GitHub repository is the durable copy. Anyone forking for preservation should `git clone` to capture in-repo GIF copies rather than relying on external CDN URLs referenced in the READMEs.

### No CI, no tests

This is intentional. Reintroducing automation would add value only if contributions resumed — at which point `anima` could grow a `--dry-run` mode, a lint target for article templates, and a link-checker workflow.

### Lifecycle state

The repository has not accepted commits since 2022-01-12. Issues #104, #126, #127, #134, #138, #139, #140, #141, #144, and #148 remain open and untriaged.

## 5. Security

There is almost no attack surface because there is no runtime service.

### CDN trust

If README-embedded animation URLs point to an external CDN, a compromise of that CDN would affect the rendered README. Forks should replace external URLs with `raw.githubusercontent.com` URLs pointing to in-repo copies.

> [!CAUTION]
> Do not assume externally hosted GIF URLs are stable or trustworthy long-term. Always prefer the in-repo `Animation/` copies as the authoritative source.

### `anima` CLI input sanitization

`anima` accepts free-form title strings and concatenates them into directory names. The current implementation uses `re.split(r'\s+', title)` to split on whitespace but does **not** sanitize path-dangerous characters:

- A title containing `/` or `..` would produce a slug with path separators
- Unicode control characters would be preserved verbatim

> [!WARNING]
> For a single-contributor use case this has never been a practical issue. A fork accepting community CLI input should validate titles against a safe character set (e.g., `[A-Za-z0-9 -]`) before calling `create_solution`.

### Python dependencies

`fire` is maintained by Google. It transitively depends on `six` and `termcolor`. Neither has known supply-chain issues, but pinning the version in `requirements.txt` would reduce risk.

## 6. Developer Internals

### Repository structure

```text
LeetCodeAnimation/
├── Readme.md                      Chinese catalog index
├── README-En.md                   English catalog with inline GIFs
├── contributing.md                anima CLI usage (Chinese)
├── requirements.txt               Python deps: fire
├── .gitattributes                 Git attributes
├── .gitignore                     Git ignore rules
├── anima.py                       CLI entrypoint
├── anima/
│   ├── __init__.py                Anima class (new() method)
│   ├── base.py                    Path helpers
│   ├── create.py                  create_solution() orchestration
│   └── model.py                   ProblemInfo + Solution dataclasses
├── template/
│   └── template.md                Article template
├── Pictures/                      Shared images (QR code, banners)
├── notes/                         68 Chinese article write-ups
├── 0001-Two-Sum/                  Per-problem folders (~108 total)
│   ├── Animation/
│   ├── Article/
│   └── Code/                      (optional)
├── ...
└── Interview053-I-Find-Number-In-Sort-Array-I/
```

### Module reference

#### `anima.py` (entrypoint)

```python
#!/usr/bin/env python3
import fire
import anima

if __name__ == '__main__':
    fire.Fire(anima.Anima())
```

Wires the `Anima` class to the CLI via Google Fire. All `Anima` public methods become subcommands.

#### `anima/__init__.py` — `Anima` class

| Method | Parameters | Description |
|--------|-----------|-------------|
| `new` | `id: str`, `title: str` | Delegates to `create_solution(id, title)` |

#### `anima/base.py` — Path helpers

| Function | Returns | Description |
|----------|---------|-------------|
| `get_project_path()` | `Path` | Resolves to the repository root (parent of `anima/`) |
| `get_md_template_path()` | `Path` | Returns `{project_root}/template/template.md` |

Path resolution uses `os.path.realpath(__file__)` to handle symlinks.

#### `anima/create.py` — Solution creation

| Function | Parameters | Description |
|----------|-----------|-------------|
| `create_solution` | `problem_id: int`, `problem_title: str` | Creates `ProblemInfo`, builds directory via `Solution.create()`, copies template |

Flow:
1. Build `ProblemInfo(problem_id, problem_title)`
2. Compute `solution_dir = project_root / problem.title_slug()`
3. If `solution_dir` exists → print error (Chinese) and `exit(1)`
4. `solution_dir.mkdir()` → `Solution.create()` → copy `template.md` to article path

#### `anima/model.py` — Data models

**`ProblemInfo` dataclass:**

| Field | Type | Description |
|-------|------|-------------|
| `id` | `int` | LeetCode problem number |
| `title` | `str` | Problem title |

| Method | Returns | Description |
|--------|---------|-------------|
| `title_slug()` | `str` | `f'{self.id:04d}-' + '-'.join(re.split(r'\s+', self.title))` |

**`Solution` dataclass:**

| Field | Type | Description |
|-------|------|-------------|
| `problem` | `ProblemInfo` | The associated problem |
| `path` | `Path` | Root directory of this solution |

| Method | Returns | Description |
|--------|---------|-------------|
| `create(problem, path)` | `Solution` | Class method; creates directory structure |
| `animation_path()` | `Path` | `self.path / 'Animation'` |
| `article_path()` | `Path` | `self.path / 'Article'` |
| `code_path()` | `Path` | `self.path / 'Code'` |
| `doc_path()` | `Path` | `article_path() / (title_slug + '.md')` |

The private `_create_dirs()` method creates `Animation/`, `Article/`, and `Code/` subdirectories, plus two zero-byte placeholder files: `Animation/Animation.m4v` and `Animation/Animation.gif`.

### Class hierarchy

```text
Anima                    (anima/__init__.py)
  └── new() → create_solution()

ProblemInfo              (anima/model.py)
  └── title_slug()

Solution                 (anima/model.py)
  ├── create()           (classmethod)
  ├── animation_path()
  ├── article_path()
  ├── doc_path()
  └── code_path()
```

### The problem folder contract

Every per-problem folder must follow this naming and structural convention:

**Naming rule:** `{ID:0>4}-{TitleWithHyphens}/`

**Directory shape:**

```text
{id-slug}/
├── Animation/                   ← the teaching GIF
│   ├── Animation.gif              (created by anima)
│   └── Animation.m4v              (created by anima, optional)
├── Article/                     ← written walkthrough
│   └── {id-slug}.md               (created from template)
└── Code/                        ← optional reference implementation
    └── 1.java                     (free-form naming)
```

### Article template structure

Every article starts from `template/template.md` with six sections:

| Section | Chinese | Purpose |
|---------|---------|---------|
| 1 | 题目描述 | Problem statement |
| 2 | 题目解析 | Analysis of the approach |
| 3 | 动画理解 | Narrated explanation of the animation |
| 4 | 参考代码 | Reference implementation |
| 5 | 复杂度分析 | Time and space complexity |

The relative image reference `../Animation/Animation.gif` in the template assumes the article lives at `{id-slug}/Article/{id-slug}.md`. Moving articles out of this path (e.g., into `notes/`) breaks the image reference.

### `notes/` vs. `Article/` distinction

| Path | Convention |
|------|-----------|
| `{id-slug}/Article/{id-slug}.md` | Per-problem folder, alongside Animation/ and Code/ |
| `notes/LeetCode第{id}号问题：{title}.md` | Flat directory, Chinese filenames (full-width colon `：`) |

A problem may have one, the other, or both. No automation enforces consistency between them.

> [!NOTE]
> The `notes/` filenames contain Chinese characters and full-width colons. On Windows systems with legacy encoding, use UTF-8-aware tooling (PowerShell 7+, Git Bash, WSL). Do not rename these files — other documents link to their exact Unicode filenames.

### Code solutions inventory

Problems with Java code solutions in `Code/` directories:

| Problem | File(s) | Language |
|---------|---------|----------|
| #4 Median of Two Sorted Arrays | `1.java` | Java |
| #34 Find First and Last Position | `1.java` | Java |
| #35 Search Insert Position | `1.java`, `2.java` | Java |
| #36 Valid Sudoku | `1.java` | Java |
| #155 Min Stack | `1.java` | Java |
| #215 Kth Largest Element | `1.cpp`, `1.java` | C++, Java |
| #290 Word Pattern | `1.java` | Java |
| #394 Decode String | `1.java` | Java |
| #771 Jewels and Stones | `1.java` | Java |
| #946 Validate Stack Sequences | `1.java` | Java |

> [!TIP]
> Java is the dominant code language. The single C++ file is Problem #215. Code files are standalone — they compile against the standard LeetCode class signature for each problem.

### Known limitations of `anima`

- **No rename or delete command.** Only creates. Use `git mv` to rename.
- **No validation of problem IDs.** Any integer is accepted.
- **No idempotency.** Re-running against an existing folder exits non-zero with no `--force` flag.
- **No `.mp4` placeholder.** Only `.m4v` is created by default.
- **Hard-coded template path.** Resolved relative to `anima/base.py`'s parent. Moving `anima/` breaks it.
- **Hard-coded zero-pad width of 4.** Problem IDs beyond 9999 will not pad to 5 digits.

### Potential improvements

1. **Pin `fire` version** in `requirements.txt` for reproducible installs
2. **Add input validation** to `create_solution` to reject path-unsafe characters in titles
3. **Add a `--force` flag** to overwrite existing problem directories
4. **Link verification script** to check that README table links resolve to real files
5. **Add a LICENSE file** — currently absent, which limits reuse rights under GitHub default ToS
6. **Support `.mp4` placeholders** alongside `.m4v` in the scaffold
7. **Automate README updates** when a new problem is scaffolded

### Contributing

1. Fork the repository
2. Create a virtual environment and install dependencies: `pip install -r requirements.txt`
3. Scaffold a new problem: `python anima.py new <id> "<title>"`
4. Fill in the article, create the animation, optionally add code
5. Update both `Readme.md` and `README-En.md` catalog tables
6. Submit a pull request

The repository's `contributing.md` describes the `anima` CLI invocation in Chinese.

> [!WARNING]
> Pull requests are not actively reviewed since the repository has been inactive since 2022-01-12. Community issues #104, #126, #127, #134, #138, #139, #140, #141, #144, and #148 remain open and untriaged.

---

_Generated May 2026 from MisterBooo/LeetCodeAnimation at fd42771. AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it. Unofficial; not affiliated with or reviewed by the project._
