first commit
This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
# Crossword Puzzle Generator for Amazon KDP
|
||||
|
||||
## Overview
|
||||
|
||||
A Python CLI tool that reads words and clues from CSV files, generates crossword puzzle grids, and outputs print-ready PDF books formatted for Amazon KDP upload.
|
||||
|
||||
---
|
||||
|
||||
## How It Works (High Level)
|
||||
|
||||
1. **Read** a CSV file containing words and their clues
|
||||
2. **Generate** crossword grids by placing words on a grid so they interlock at shared letters
|
||||
3. **Render** each puzzle and its solution as pages in a print-ready PDF
|
||||
4. **Format** the PDF to meet KDP's trim size, margin, and bleed requirements
|
||||
|
||||
---
|
||||
|
||||
## Input Format
|
||||
|
||||
A CSV file with at minimum two columns:
|
||||
|
||||
```csv
|
||||
word,clue
|
||||
PYTHON,"A large snake, or a programming language"
|
||||
GRID,"A network of lines that cross each other"
|
||||
PUZZLE,"A game or problem that tests ingenuity"
|
||||
```
|
||||
|
||||
Optional columns:
|
||||
- `difficulty` — to group words into easy/medium/hard puzzles
|
||||
- `category` — to generate themed puzzles (e.g., "Animals", "Science")
|
||||
|
||||
---
|
||||
|
||||
## Core Components
|
||||
|
||||
### 1. CSV Parser (`csv_reader.py`)
|
||||
|
||||
- Read and validate the CSV (reject duplicates, too-short words, non-alpha characters)
|
||||
- Normalize words to uppercase
|
||||
- Group words by category/difficulty if those columns exist
|
||||
- Return a list of `(word, clue)` tuples ready for the generator
|
||||
|
||||
### 2. Crossword Generator (`generator.py`)
|
||||
|
||||
This is the core algorithm. It places words onto a 2D grid so they intersect at shared letters.
|
||||
|
||||
**Algorithm (backtracking with heuristics):**
|
||||
|
||||
1. Sort words longest-first (longer words are harder to place, so do them early)
|
||||
2. Place the first word horizontally in the center of the grid
|
||||
3. For each remaining word:
|
||||
a. Find all candidate positions where it intersects an already-placed word at a shared letter
|
||||
b. Score each candidate (prefer positions that keep the grid compact and balanced)
|
||||
c. Place the word at the best valid position (no collisions, no unintended adjacencies)
|
||||
d. If no valid position exists, skip the word (or backtrack)
|
||||
4. Number the cells (across and down) in reading order (left-to-right, top-to-bottom)
|
||||
5. Return the grid, placed words with their positions/directions, and numbered clue lists
|
||||
|
||||
**Grid rules to enforce:**
|
||||
- Words cannot run parallel and adjacent (would create unintended mini-words)
|
||||
- Every letter in the grid must belong to a placed word
|
||||
- Minimum grid density target to avoid sparse-looking puzzles
|
||||
- Configurable grid size (e.g., 15x15 for standard, 10x10 for easy)
|
||||
|
||||
**Output of this step:** a `Crossword` object containing:
|
||||
- The letter grid (2D array)
|
||||
- List of placed words with start position, direction, and clue number
|
||||
- Across clues list (numbered)
|
||||
- Down clues list (numbered)
|
||||
|
||||
### 3. PDF Renderer (`renderer.py`)
|
||||
|
||||
Uses **ReportLab** to generate print-ready PDFs.
|
||||
|
||||
**Each puzzle produces two pages:**
|
||||
|
||||
1. **Puzzle page:**
|
||||
- Title (e.g., "Puzzle 1" or a category name)
|
||||
- The empty grid with numbered cells and black squares
|
||||
- Across clues listed below or beside the grid
|
||||
- Down clues listed below or beside the grid
|
||||
|
||||
2. **Solution page:**
|
||||
- The filled grid with all letters visible
|
||||
- Labeled "Solution to Puzzle N"
|
||||
|
||||
**Page layout considerations:**
|
||||
- Grid cells should be large enough to write in (~0.3–0.4 inches per cell)
|
||||
- Clue text should be readable (10–12pt font)
|
||||
- Clean, professional look (black borders, light grid lines)
|
||||
|
||||
### 4. KDP Formatter (`kdp_format.py`)
|
||||
|
||||
Handles KDP-specific requirements:
|
||||
|
||||
- **Trim sizes:** Support common KDP sizes (8.5"x11", 6"x9", 8"x10")
|
||||
- **Margins:** KDP requires minimum margins that vary by page count (typically 0.5" outside, 0.75"+ gutter/inside)
|
||||
- **Page count:** Must be between 24–828 pages
|
||||
- **Bleed:** Not needed for puzzle books (no content to edge)
|
||||
- **Front matter:** Generate a title page, copyright page, and optional instructions page
|
||||
- **Page numbering:** Footer with page numbers
|
||||
- **Table of contents:** Optional, mapping puzzle numbers to pages
|
||||
|
||||
### 5. CLI Interface (`main.py`)
|
||||
|
||||
```
|
||||
python main.py --input words.csv \
|
||||
--output crossword_book.pdf \
|
||||
--puzzles 50 \
|
||||
--grid-size 15 \
|
||||
--trim-size 8.5x11 \
|
||||
--title "The Ultimate Crossword Book" \
|
||||
--author "Your Name"
|
||||
```
|
||||
|
||||
**Arguments:**
|
||||
| Flag | Description | Default |
|
||||
|------|-------------|---------|
|
||||
| `--input` | Path to CSV file | required |
|
||||
| `--output` | Output PDF path | `output.pdf` |
|
||||
| `--puzzles` | Number of puzzles to generate | `20` |
|
||||
| `--grid-size` | Grid dimensions (e.g., 15 for 15x15) | `13` |
|
||||
| `--trim-size` | KDP page size | `8.5x11` |
|
||||
| `--title` | Book title for the cover page | `"Crossword Puzzles"` |
|
||||
| `--author` | Author name | `""` |
|
||||
| `--words-per-puzzle` | Target words per puzzle | `20` |
|
||||
| `--solutions-at-end` | Group all solutions at the back | `false` |
|
||||
| `--seed` | Random seed for reproducibility | none |
|
||||
|
||||
---
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
crossword-kdp-generator/
|
||||
├── main.py # CLI entry point
|
||||
├── csv_reader.py # CSV parsing and validation
|
||||
├── generator.py # Crossword grid generation algorithm
|
||||
├── renderer.py # PDF rendering (grids, clues, layout)
|
||||
├── kdp_format.py # KDP trim sizes, margins, front matter
|
||||
├── models.py # Data classes (Crossword, PlacedWord, Cell, etc.)
|
||||
├── requirements.txt # Dependencies
|
||||
├── sample_words.csv # Example input file
|
||||
└── README.md # Usage instructions
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
| Package | Purpose |
|
||||
|---------|---------|
|
||||
| `reportlab` | PDF generation |
|
||||
| `click` | CLI argument parsing |
|
||||
|
||||
No heavy dependencies needed — the crossword algorithm is pure Python, and ReportLab handles all the PDF work.
|
||||
|
||||
---
|
||||
|
||||
## Generation Strategy for a Full Book
|
||||
|
||||
A single CSV might have hundreds of words, but each puzzle only uses ~15–25 of them. The tool will:
|
||||
|
||||
1. Shuffle the word list (using the optional seed for reproducibility)
|
||||
2. Pull a batch of N words for each puzzle
|
||||
3. Attempt to generate a crossword grid from that batch
|
||||
4. If the grid doesn't meet a minimum quality threshold (too few intersections, too sparse), retry with a different subset
|
||||
5. Repeat until the requested number of puzzles is generated
|
||||
6. Assemble all puzzles into the final PDF with front matter and optional solutions section at the back
|
||||
|
||||
---
|
||||
|
||||
## Edge Cases to Handle
|
||||
|
||||
- **Too few words in CSV** — error out with a clear message
|
||||
- **Words that can't interlock** — skip them, log a warning
|
||||
- **Grid overflow** — if words don't fit the requested grid size, increase grid or reduce words per puzzle
|
||||
- **Duplicate words across puzzles** — allow (different puzzles can reuse words) but avoid within a single puzzle
|
||||
- **Non-ASCII characters** — strip accents or reject, since crosswords are typically A-Z only
|
||||
- **Very long words** — warn if a word exceeds grid size
|
||||
|
||||
---
|
||||
|
||||
## Stretch Goals (Post-MVP)
|
||||
|
||||
- **Cover page PDF** — generate a separate KDP-compliant cover
|
||||
- **Multiple difficulty levels** in one book (easy section, medium, hard)
|
||||
- **Themed sections** based on CSV category column
|
||||
- **Word search mode** — reuse the same CSV to generate word search puzzles too
|
||||
- **Web UI** — a simple local web interface instead of CLI
|
||||
- **ISBN barcode** placement on back cover
|
||||
|
||||
---
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. ~~`models.py` — define data structures~~ ✅
|
||||
2. ~~`csv_reader.py` — parse and validate input~~ ✅
|
||||
3. ~~`generator.py` — crossword algorithm (the hard part)~~ ✅
|
||||
4. ~~`renderer.py` — PDF grid and clue rendering~~ ✅
|
||||
5. ~~`kdp_format.py` — page layout and front matter~~ ✅
|
||||
6. ~~`main.py` — wire it all together with CLI~~ ✅
|
||||
7. ~~Test with sample data and iterate on grid quality~~ ✅
|
||||
Reference in New Issue
Block a user