Spaces:
Running
Running
File size: 21,602 Bytes
1dcc163 2de3d96 0b81bf2 1dcc163 0b81bf2 2de3d96 0b81bf2 1dcc163 2de3d96 9ecb8cf 0b81bf2 2de3d96 0b81bf2 1dcc163 1b1b6cc 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 507acad 1dcc163 507acad 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 0b81bf2 9ecb8cf 0b81bf2 9ecb8cf 0b81bf2 9ecb8cf 0b81bf2 9ecb8cf 0b81bf2 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 0b81bf2 9ecb8cf 1dcc163 0b81bf2 507acad 0b81bf2 507acad 0b81bf2 507acad 0b81bf2 507acad 0b81bf2 9ecb8cf 1dcc163 0b81bf2 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf 1dcc163 9ecb8cf f969c4d 507acad |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 |
# BattleWords - Project Context
## Project Overview
BattleWords is a vocabulary learning game inspired by Battleship mechanics, built with Streamlit and Python 3.12. Players reveal cells on a 12x12 grid to discover hidden words and earn points for strategic guessing.
**Current Version:** 0.2.28 (Stable - PWA, Challenge Mode & Remote Storage)
**Next Version:** 0.3.0 (In Development - Local Player History & Statistics)
**Repository:** https://github.com/Oncorporation/BattleWords.git
**Live Demo:** https://huggingface.co/spaces/Surn/BattleWords
## Recent Changes & Branch Status
**Latest (v0.2.28):**
- Progressive Web App (PWA) support
- Added `service worker` and `manifest.json`
- Basic offline caching of static assets
- INSTALL_GUIDE.md added with install steps
- No gameplay logic changes
**Previous (v0.2.27):**
- New setting: "Show Challenge Share Links" (default OFF)
- Header Challenge Mode banner hides the "Share this challenge" link when disabled
- Game Over dialog still lets you submit or create a challenge, but hides the generated share URL when disabled (shows a success message instead)
- Setting is stored in Streamlit session state and preserved across "New Game"
- No changes to `logic.py` or `game_storage.py`; this is a UI-only visibility feature
## Core Gameplay
- 12x12 grid with 6 hidden words (2Γ4-letter, 2Γ5-letter, 2Γ6-letter)
- Words placed horizontally or vertically, no overlaps
- Players click cells to reveal letters or empty spaces
- After revealing a letter, players can guess words
- Scoring: word length + bonus for unrevealed letters
- Game ends when all words are guessed or all word letters are revealed
- Incorrect guess history with optional display (enabled by default)
- 10 incorrect guess limit per game
- **β
IMPLEMENTED (v0.2.20+):** Challenge Mode with game sharing via short URLs
- **β
IMPLEMENTED (v0.2.20+):** Remote storage via Hugging Face datasets for challenges and leaderboards
- **β
IMPLEMENTED (v0.2.28):** PWA install support
- **PLANNED (v0.3.0):** Local persistent storage for individual player results and high scores
### Scoring Tiers
- **Fantastic:** 42+ points
- **Great:** 38-41 points
- **Good:** 34-37 points
- **Keep practicing:** < 34 points
## Technical Architecture
### Technology Stack
- **Framework:** Streamlit 1.51.0
- **Language:** Python 3.12.8
- **Visualization:** Matplotlib, NumPy
- **Data Processing:** Pandas, Altair
- **Storage:** JSON-based local persistence
- **Testing:** Pytest
- **Code Quality:** Flake8, MyPy
- **Package Manager:** UV (modern Python package manager)
### Project Structure
```
battlewords/
βββ app.py # Streamlit entry point
βββ battlewords/ # Main package
β βββ __init__.py # Version: 0.2.17
β βββ models.py # Data models (Coord, Word, Puzzle, GameState)
β βββ generator.py # Puzzle generation with deterministic seeding
β βββ logic.py # Game mechanics (reveal, guess, scoring)
β βββ ui.py # Streamlit UI (~1800 lines)
β βββ word_loader.py # Word list management
β βββ audio.py # Background music system
β βββ sounds.py # Sound effects management
β βββ generate_sounds.py # Sound generation utilities
β βββ game_storage.py # HF game storage wrapper (v0.1.0)
β βββ version_info.py # Version display
β βββ modules/ # Shared utility modules (from OpenBadge)
β β βββ __init__.py # Module exports
β β βββ storage.py # HuggingFace storage & URL shortener (v0.1.5)
β β βββ storage.md # Storage module documentation
β β βββ constants.py # Storage-related constants (trimmed)
β β βββ file_utils.py # File utility functions
β βββ words/ # Word list files
β βββ classic.txt # Default word list
β βββ fourth_grade.txt # Elementary word list
β βββ wordlist.txt # Full word list
βββ tests/ # Unit tests
βββ specs/ # Documentation
β βββ specs.md # Game specifications
β βββ requirements.md # Implementation requirements
β βββ history.md # Game history
βββ .env # Environment variables
βββ pyproject.toml # Project metadata
βββ requirements.txt # Dependencies
βββ uv.lock # UV lock file
βββ Dockerfile # Container deployment
βββ CLAUDE.md # This file - project context for Claude
```
## Key Features
### Game Modes
1. **Classic Mode:** Allows consecutive guessing after correct answers
2. **Too Easy Mode:** Single guess per reveal
### Audio & Visual Effects
- **Background Music:** Toggleable ocean-themed background music with volume control
- **Sound Effects:** Hit/miss/correct/incorrect guess sounds with volume control
- **Animated Radar:** Pulsing rings showing word boundaries (last letter locations)
- **Ocean Theme:** Gradient animated background with wave effects
- **Incorrect Guess History:** Visual display of wrong guesses (toggleable in settings)
### β
Challenge Mode & Remote Storage (v0.2.20+)
- **Game ID System:** Short URL-based challenge sharing
- Format: `?game_id=<sid>` in URL (shortened URL reference)
- Each player gets different random words from the same wordlist
- Enables fair challenges between players
- Stored in Hugging Face dataset repository
- **Remote Storage via HuggingFace Hub:**
- Per-game settings JSON in `games/{uid}/settings.json`
- Shortened URL mapping in `shortener.json`
- Multi-user leaderboards with score, time, and difficulty tracking
- Results sorted by: highest score β fastest time β highest difficulty
- **Challenge Features:**
- Submit results to existing challenges
- Create new challenges from any completed game
- Top 5 leaderboard display in Challenge Mode banner
- Optional player names (defaults to "Anonymous")
- Word list difficulty calculation and display
- "Show Challenge Share Links" toggle (default OFF) to control URL visibility
### PLANNED: Local Player Storage (v0.3.0)
- **Local Storage:**
- Location: `~/.battlewords/data/`
- Files: `game_results.json`, `highscores.json`
- Privacy-first: no cloud dependency, offline-capable
- **Personal High Scores:**
- Top 100 scores tracked automatically on local machine
- Filterable by wordlist and game mode
- High score sidebar expander display
- **Player Statistics:**
- Games played, average score, best score
- Fastest completion time
- Per-player history on local device
### Puzzle Generation
- Deterministic seeding support for reproducible puzzles
- Configurable word spacing (spacer: 0-2)
- 0: Words may touch
- 1: At least 1 blank cell between words (default)
- 2: At least 2 blank cells between words
- Validation ensures no overlaps, proper bounds, correct word distribution
### UI Components (Current)
- **Radar Visualization:** Animated matplotlib GIF showing word boundaries
- Displays pulsing rings at last letter of each word
- Hides rings for guessed words
- Three-layer composition: gradient background, scope image, animated rings
- Cached per-puzzle with signature matching
- **Game Grid:** Interactive 12x12 button grid with responsive layout
- **Score Panel:** Real-time scoring with client-side JavaScript timer
- **Settings Sidebar:**
- Word list picker (classic, fourth_grade, wordlist)
- Game mode selector
- Word spacing configuration (0-2)
- Audio volume controls (music and effects separate)
- Toggle for incorrect guess history display
- **Theme System:** Ocean gradient background with CSS animations
- **Game Over Dialog:** Final score display with tier ranking
- **Incorrect Guess Display:** Shows history of wrong guesses with count
- **β
Challenge Mode UI (v0.2.20+):**
- Challenge Mode banner with leaderboard (top 5 players)
- Share challenge button in game over dialog
- Submit result or create new challenge options
- Word list difficulty display
- Conditional share URL visibility toggle
- **PLANNED (v0.3.0):** Local high scores expander in sidebar
- **PLANNED (v0.3.0):** Personal statistics display
### Recent Changes & Branch Status
**Branch:** cc-01 (Storage and sharing features - v0.3.0 development)
**Latest (v0.2.17):**
- Documentation updates and corrections
- Updated CLAUDE.md with accurate feature status
- Clarified v0.3.0 planned features vs current implementation
- Added comprehensive project structure details
- Improved version tracking and roadmap clarity
**Previously Fixed (v0.2.16):**
- Replace question marks with underscores in score panel
- Add toggle for incorrect guess history display (enabled by default)
- Game over popup positioning improvements
- Music playback after game end
- Sound effect and music volume issues
- Radar alignment inconsistencies
- Added `fig.subplots_adjust(left=0, right=0.9, top=0.9, bottom=0)`
- Set `fig.patch.set_alpha(0.0)` for transparent background
- Maintains 2% margin for tick visibility while ensuring consistent layer alignment
**Completed (v0.2.20-0.2.27 - Challenge Mode):**
- β
Imported storage modules from OpenBadge project:
- `battlewords/modules/storage.py` (v0.1.5) - HuggingFace storage & URL shortener
- `battlewords/modules/constants.py` (trimmed) - Storage-related constants
- `battlewords/modules/file_utils.py` - File utility functions
- `battlewords/modules/storage.md` - Documentation
- β
Created `battlewords/game_storage.py` (v0.1.0) - BattleWords storage wrapper:
- `save_game_to_hf()` - Save game to HF repo and generate short URL
- `load_game_from_sid()` - Load game from short ID
- `generate_uid()` - Generate unique game identifiers
- `serialize_game_settings()` - Convert game data to JSON
- `get_shareable_url()` - Generate shareable URLs
- `add_user_result_to_game()` - Append results to existing challenges
- β
UI integration complete (`battlewords/ui.py`):
- Query parameter parsing for `?game_id=<sid>` on app load
- Load shared game settings into session state
- Challenge Mode banner with leaderboard (top 5)
- Share button in game over dialog with "Generate Share Link" or "Submit Result"
- Conditional share URL display based on settings toggle
- Automatic save to HuggingFace on game completion
- Word list difficulty calculation and display
- β
Generator updates (`battlewords/generator.py`):
- Added `target_words` parameter for loading specific words
- Added `may_overlap` parameter (for future crossword mode)
- Support for shared game replay with randomized word positions
**In Progress (v0.3.0 - Local Player History):**
- β³ Local storage module (`battlewords/local_storage.py`)
- β³ Personal high score tracking (local JSON files)
- β³ High score sidebar UI display
- β³ Player statistics tracking and display
## Data Models
### Core Classes
```python
@dataclass
class Coord:
x: int # row, 0-based
y: int # col, 0-based
@dataclass
class Word:
text: str
start: Coord
direction: Direction # "H" or "V"
cells: List[Coord]
@dataclass
class Puzzle:
words: List[Word]
radar: List[Coord]
may_overlap: bool
spacer: int
uid: str # Unique identifier for caching
@dataclass
class GameState:
grid_size: int
puzzle: Puzzle
revealed: Set[Coord]
guessed: Set[str]
score: int
last_action: str
can_guess: bool
game_mode: str
points_by_word: Dict[str, int]
start_time: Optional[datetime]
end_time: Optional[datetime]
```
## Development Workflow
### Running Locally
```bash
# Install dependencies
uv pip install -r requirements.txt --link-mode=copy
# Run app
uv run streamlit run app.py
# or
streamlit run app.py
```
### Docker Deployment
```bash
docker build -t battlewords .
docker run -p 8501:8501 battlewords
```
### Testing
```bash
pytest tests/
```
### Environment Variables (for Challenge Mode)
Challenge Mode requires HuggingFace Hub access for remote storage. Create a `.env` file in the project root:
```bash
# Required for Challenge Mode
HF_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxx # or HF_TOKEN
HF_REPO_ID=YourUsername/YourRepo # Target HF dataset repo
SPACE_NAME=YourUsername/BattleWords # Your HF Space name
# Optional
CRYPTO_PK= # Reserved for future signing
```
**How to get your HF_API_TOKEN:**
1. Go to https://huggingface.co/settings/tokens
2. Create a new token with `write` access
3. Add to `.env` file as `HF_API_TOKEN=hf_...`
**HF_REPO_ID Structure:**
The dataset repository will contain:
- `shortener.json` - Short URL mappings
- `games/{uid}/settings.json` - Per-game challenge data
- `games/{uid}/result.json` - Optional detailed results
**Note:** The app will work without these variables but Challenge Mode features (sharing, leaderboards) will be disabled.
## Git Configuration & Deployment
**Current Branch:** cc-01
**Purpose:** Storage and sharing features (v0.3.0 development)
**Main Branch:** main (not specified in git config, but typical convention)
### Remotes
- **ONCORP (origin):** https://github.com/Oncorporation/BattleWords.git (main repository)
- **Hugging:** https://huggingface.co/spaces/Surn/BattleWords (live deployment)
## Known Issues
- Word list loading bug: App may not select proper word lists in some environments
- Investigation needed in `word_loader.get_wordlist_files()` and `load_word_list()`
- Sidebar selection persistence needs verification
## v0.3.0 Development Status (cc-01 branch)
### Completed β
- `battlewords/storage.py` module created with:
- `GameStorage` class for JSON-based local storage
- `GameResult` and `HighScoreEntry` dataclasses
- Functions: `generate_game_id_from_words()`, `parse_game_id_from_url()`, `create_shareable_url()`
- Storage location: `~/.battlewords/data/` (game_results.json, highscores.json)
- Documentation updated in specs/ folder
### In Progress β³
- Puzzle model integration for game_id field
- Generator updates for `target_words` parameter (replay from game_id)
- UI integration:
- Storage calls on game completion
- High score display in sidebar
- Share button in game over dialog
- Query parameter parsing for game_id
- Player name input in sidebar
### Planned π
- Unit tests for storage module
- Integration tests for complete storage flow
- Game replay from shared ID functionality
- Player statistics display
- Share results text generation
## Future Roadmap
### Phase 1.5 (v0.3.0) - Current Focus β³
- β
Storage module with local JSON persistence (backend complete)
- β
Game ID generation system (backend complete)
- β³ High score tracking and display (backend complete, UI pending)
- β³ Share challenge functionality (UI integration pending)
- β³ Game replay from shared IDs (generator updates needed)
- β³ Player name input and statistics
### Beta (v0.5.0)
- Word overlaps on shared letters (crossword-style gameplay)
- Enhanced responsive layout for mobile/tablet
- Keyboard navigation and guessing
- Deterministic seed UI for custom puzzles
- Improved accessibility features
### Full (v1.0.0)
- Optional cloud storage backend (FastAPI)
- Daily puzzle mode with global leaderboards
- Practice mode with hints
- Enhanced UX features (animations, themes)
- Multiple difficulty levels
- Internationalization (i18n) support
## Deployment Targets
- **Hugging Face Spaces:** Primary deployment platform
- **Docker:** Containerized deployment for any platform
- **Local:** Development and testing
### Privacy & Data
- All storage is local (no telemetry)
- Player names optional
- No data leaves user's machine
- Easy to delete: just remove `~/.battlewords/data/`
## Notes for Claude
- Project uses modern Python features (3.12+)
- Heavy use of Streamlit session state for game state management
- Matplotlib figures are converted to PIL images and animated GIFs
- Client-side JavaScript for timer updates without page refresh
- CSS heavily customized for game aesthetics
- All file paths should be absolute when working in WSL environment
- Current working directory: `/mnt/d/Projects/Battlewords`
- Storage features are backward-compatible (game works without storage)
- Game IDs are deterministic for consistent sharing
- JSON storage chosen for simplicity and privacy
### WSL Environment Python Versions
The development environment is WSL (Windows Subsystem for Linux) with access to both native Linux and Windows Python installations:
**Native WSL (Linux):**
- `python3` β Python 3.10.12 (`/usr/bin/python3`)
- `python3.10` β Python 3.10.12
**Windows Python (accessible via WSL):**
- `python311.exe` β Python 3.11.9 (`/mnt/c/Users/cfettinger/AppData/Local/Programs/Python/Python311/`)
- `python3.13.exe` β Python 3.13.1 (`/mnt/c/ProgramData/chocolatey/bin/`)
**Note:** Windows Python executables (`.exe`) can be invoked directly from WSL and are useful for testing compatibility across Python versions. The project targets Python 3.12+ but can run on 3.10+.
## v0.2.20: Remote Storage game_id via Shortened URL
Overview
- Use a storage server (Hugging Face Hub repo) to persist:
- Per-game settings JSON (word_list, score, time, game_mode, grid_size, puzzle options)
- High scores JSON (top scores)
- Each completed game writes JSON to repo under a unique `uid` folder.
- A shortened URL (sid) referencing the settings JSON is generated and used as `game_id` in the query string.
- On load, if `?game_id=<sid>` exists, resolve sid to the full JSON URL, fetch it, and apply settings for the session.
Modules to leverage (from OpenBadge/modules)
- `modules/storage.py`
- `upload_files_to_repo(files, repo_id, folder_name, repo_type="dataset")`
- `gen_full_url(short_url=None, full_url=None, repo_id=None, json_file="shortener.json")`
- `modules/constants.py` (env + defaults)
- Uses HF token from env (expects `HF_TOKEN`, we will also document `HF_API_TOKEN`)
- `HF_REPO_ID`, `SPACE_NAME`, `SHORTENER_JSON_FILE`
- `modules/file_utils.py` (helpers)
Environment variables (.env)
- HF_API_TOKEN or HF_TOKEN: Hugging Face access token (Bearer)
- CRYPTO_PK: optional, reserved for future signing
- HF_REPO_ID: target repo, e.g., Surn/Storage
- SPACE_NAME: e.g., Surn/BattleWords
Repository structure (dataset repo)
- shortener.json # sid -> full URL mapping
- games/{uid}/settings.json # per-game settings payload (primary)
- games/{uid}/result.json # finalized game result (optional)
- highscores/highscores.json # global/top scores JSON
Game settings JSON (example)
{
"uid": "20250101T120001Z-ABC123",
"word_list": ["APPLE","TRAIN","..."],
"score": 40,
"time": 173,
"game_mode": "classic",
"grid_size": 12,
"puzzle_options": { "spacer": 1, "may_overlap": false }
}
Flow
1) On game completion
- Build unique `uid` (timestamp + random suffix).
- Write settings.json (and optional result.json) to games/{uid}/
- Create full URL to settings.json, call `gen_full_url(full_url=...)` to obtain `sid`
- Share link: https://<space>/?game_id=<sid>
2) On load with `?game_id=<sid>`
- Call `gen_full_url(short_url=sid)` to get full URL
- Fetch settings.json, apply session: word_list, game_mode, grid_size, puzzle options; ignore score/time for gameplay
3) Highscores
- Maintain highscores/highscores.json in repo; append/update with best entries
Security/Privacy
- Only game configuration and scores are stored; no PII required
- sid is a reference; shortener.json can be in the same repo
- Consider private repo for write access; dataset can be public for read
Notes
- We will keep `battlewords/storage.py` as local-only storage (JSON on disk) and introduce a new integration wrapper in a later PR (e.g., `battlewords/hf_storage.py`) to avoid confusion with the generic modules. If needed, rename `battlewords/storage.py` to `local_storage.py` in a future pass.
- Add dependencies: `huggingface_hub`, `python-dotenv`
## Documentation Structure
This file (CLAUDE.md) serves as a **living context document** for AI-assisted development. It complements the formal specification documents:
- **[specs/specs.md](specs/specs.md)** - Game rules, requirements, and feature specifications
- **[specs/requirements.md](specs/requirements.md)** - Implementation phases, acceptance criteria, and technical tasks
- **[README.md](README.md)** - User-facing documentation, installation guide, and changelog
**When to use each:**
- **specs.md** - Understanding game rules, scoring, and player experience
- **requirements.md** - Planning implementation work, tracking phases, and defining done criteria
- **CLAUDE.md** - Quick reference for codebase structure, recent changes, and development context
- **README.md** - Public-facing information, setup instructions, and feature announcements
**Synchronization:**
Changes to game mechanics should update specs.md β requirements.md β CLAUDE.md β README.md in that order
## Challenge Mode & Remote Storage
- The app supports a Challenge Mode where games can be shared via a short link (`?game_id=<sid>`).
- Results are stored in a Hugging Face dataset repo using `game_storage.py`.
- The leaderboard for a challenge is sorted by highest score (descending), then by fastest time (ascending).
- Each user result is appended to the challenge's `users` array in the remote JSON.
|