0.2.1 Documentation Update
Browse files- CLAUDE.md +205 -15
- README.md +88 -28
- specs/leaderboard_spec.md +172 -51
- specs/requirements.md +104 -31
- specs/specs.md +83 -20
CLAUDE.md
CHANGED
|
@@ -7,16 +7,35 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords, with these k
|
|
| 7 |
- **No scope/radar visualization**
|
| 8 |
- **2 free letter guesses at game start** (all instances of chosen letters are revealed)
|
| 9 |
|
| 10 |
-
**Current Version:** 0.
|
| 11 |
**Repository:** https://github.com/Oncorporation/Wrdler.git
|
| 12 |
**Live Demo:** [DEPLOYMENT_URL_HERE]
|
| 13 |
|
| 14 |
## Recent Changes
|
| 15 |
|
| 16 |
-
**v0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
- β
Enhanced AI word generation logic with intelligent word saving
|
| 18 |
- β
Automatic retry mechanism for insufficient word counts (up to 3 retries)
|
| 19 |
-
- β
1000-word file size limit to prevent dictionary bloat
|
| 20 |
- β
Better new word detection (separates existing vs. new words before saving)
|
| 21 |
- β
Improved HF Space API integration with graceful fallback to local models
|
| 22 |
- β
Additional word generation when initial pass doesn't meet MIN_REQUIRED threshold
|
|
@@ -58,14 +77,16 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords, with these k
|
|
| 58 |
- 10 incorrect guess limit per game
|
| 59 |
- **β
IMPLEMENTED:** Challenge Mode with game sharing via short URLs
|
| 60 |
- **β
IMPLEMENTED:** Remote storage via Hugging Face datasets
|
|
|
|
| 61 |
- **β
IMPLEMENTED:** PWA install support (v0.2.28+)
|
| 62 |
- **PLANNED:** Local persistent storage for game results and high scores (v0.3.0)
|
| 63 |
|
| 64 |
### Scoring Tiers
|
| 65 |
-
- **
|
| 66 |
-
- **
|
| 67 |
-
- **
|
| 68 |
-
- **
|
|
|
|
| 69 |
|
| 70 |
## Technical Architecture
|
| 71 |
|
|
@@ -85,12 +106,15 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords, with these k
|
|
| 85 |
wrdler/
|
| 86 |
βββ app.py # Streamlit entry point
|
| 87 |
βββ wrdler/ # Main package
|
| 88 |
-
β βββ __init__.py # Version: 0.
|
| 89 |
β βββ models.py # Data models (Coord, Word, Puzzle, GameState)
|
| 90 |
β βββ generator.py # Puzzle generation with deterministic seeding
|
| 91 |
β βββ logic.py # Game mechanics (reveal, guess, scoring)
|
| 92 |
β βββ ui.py # Streamlit UI
|
|
|
|
|
|
|
| 93 |
β βββ word_loader.py # Word list management
|
|
|
|
| 94 |
β βββ audio.py # Background music system
|
| 95 |
β βββ sounds.py # Sound effects management
|
| 96 |
β βββ generate_sounds.py # Sound generation utilities
|
|
@@ -98,7 +122,7 @@ wrdler/
|
|
| 98 |
β βββ version_info.py # Version display
|
| 99 |
β βββ modules/ # Shared utility modules (from OpenBadge)
|
| 100 |
β β βββ __init__.py # Module exports
|
| 101 |
-
β β βββ storage.py # HuggingFace storage & URL shortener
|
| 102 |
β β βββ storage.md # Storage module documentation
|
| 103 |
β β βββ constants.py # Storage-related constants (trimmed)
|
| 104 |
β β βββ file_utils.py # File utility functions
|
|
@@ -107,10 +131,12 @@ wrdler/
|
|
| 107 |
β βββ fourth_grade.txt # Elementary word list
|
| 108 |
β βββ wordlist.txt # Full word list
|
| 109 |
βββ tests/ # Unit tests
|
| 110 |
-
β
|
|
|
|
| 111 |
βββ specs/ # Documentation
|
| 112 |
β βββ specs.md # Game specifications
|
| 113 |
β βββ requirements.md # Implementation requirements
|
|
|
|
| 114 |
β βββ wrdler_implementation_plan.md # Sprint planning summary
|
| 115 |
βββ static/ # PWA assets
|
| 116 |
β βββ manifest.json # PWA manifest
|
|
@@ -139,6 +165,29 @@ wrdler/
|
|
| 139 |
- **Ocean Theme:** Gradient animated background with wave effects
|
| 140 |
- **Incorrect Guess History:** Visual display of wrong guesses (toggleable in settings)
|
| 141 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
### β
Challenge Mode & Remote Storage (v0.2.20+)
|
| 143 |
- **Game ID System:** Short URL-based challenge sharing
|
| 144 |
- Format: `?game_id=<sid>` in URL (shortened URL reference)
|
|
@@ -148,7 +197,7 @@ wrdler/
|
|
| 148 |
- **Remote Storage via HuggingFace Hub:**
|
| 149 |
- Per-game settings JSON in `games/{uid}/settings.json`
|
| 150 |
- Shortened URL mapping in `shortener.json`
|
| 151 |
-
- Multi-user leaderboards with score, time, and difficulty tracking
|
| 152 |
- Results sorted by: highest score β fastest time β highest difficulty
|
| 153 |
- **Challenge Features:**
|
| 154 |
- Submit results to existing challenges
|
|
@@ -157,6 +206,7 @@ wrdler/
|
|
| 157 |
- Optional player names (defaults to "Anonymous")
|
| 158 |
- Word list difficulty calculation and display (v0.2.29)
|
| 159 |
- "Show Challenge Share Links" toggle (default OFF) to control URL visibility (v0.2.27)
|
|
|
|
| 160 |
|
| 161 |
### β
Progressive Web App (PWA) Support (v0.2.28+)
|
| 162 |
- **PWA Installation:** App is installable as a Progressive Web App on desktop and mobile
|
|
@@ -224,18 +274,30 @@ wrdler/
|
|
| 224 |
- Share challenge button in game over dialog
|
| 225 |
- Submit result or create new challenge options
|
| 226 |
- Word list difficulty display
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
- **PLANNED (v0.3.0):** Local high scores expander and personal statistics display
|
| 228 |
|
| 229 |
### Development Status
|
| 230 |
|
| 231 |
-
**Current Version:** 0.
|
| 232 |
- β
All 7 sprints complete
|
| 233 |
- β
100% test coverage (25/25 tests)
|
| 234 |
- β
AI word generation implemented
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
- β
Ready for production deployment
|
| 236 |
- β
PWA support implemented
|
| 237 |
- β
Challenge Mode fully functional
|
| 238 |
-
- π Development time: ~12.75 hours (sprints 1-7)
|
| 239 |
- π Complete documentation
|
| 240 |
|
| 241 |
**Next Version:** v0.3.0 (Planned)
|
|
@@ -243,6 +305,7 @@ wrdler/
|
|
| 243 |
- π Personal high score tracking (local JSON files)
|
| 244 |
- π High score sidebar UI display
|
| 245 |
- π Player statistics tracking and display
|
|
|
|
| 246 |
|
| 247 |
## Data Models
|
| 248 |
|
|
@@ -345,11 +408,13 @@ IS_LOCAL= # Override environment detection
|
|
| 345 |
2. Create a new token with `write` access
|
| 346 |
3. Add to `.env` file as `HF_API_TOKEN=hf_...`
|
| 347 |
|
| 348 |
-
#### HF_REPO_ID Structure (Challenge Mode)
|
| 349 |
The dataset repository will contain:
|
| 350 |
- `shortener.json` - Short URL mappings
|
| 351 |
-
- `games/{uid}/settings.json` - Per-game challenge data
|
| 352 |
- `games/{uid}/result.json` - Optional detailed results
|
|
|
|
|
|
|
| 353 |
|
| 354 |
#### HF_WORD_LIST_REPO_ID Structure (AI Word Generation)
|
| 355 |
The dataset repository will contain:
|
|
@@ -401,6 +466,16 @@ The dataset repository will contain:
|
|
| 401 |
|
| 402 |
## Post-v0.0.2 Enhancements
|
| 403 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 404 |
### v0.1.1 (AI Word Generation Enhancement)
|
| 405 |
- Enhanced AI word generation with intelligent word saving
|
| 406 |
- Automatic retry mechanism for insufficient word counts (up to 3 retries)
|
|
@@ -474,8 +549,123 @@ The dataset repository will contain:
|
|
| 474 |
- β
PWA injection via Docker build script (`inject-pwa-head.sh`)
|
| 475 |
- β
AI word generation via `word_loader_ai.py` with Hugging Face integration
|
| 476 |
- β
Utility modules provide reusable functions for storage and file ops
|
|
|
|
|
|
|
| 477 |
- β οΈ **IMPORTANT: Use Python syntax (colons `:`) NOT JavaScript syntax (curly braces `{}`)**
|
| 478 |
- Python: `if condition:` followed by indented block
|
| 479 |
- NOT: `if condition {` - this is JavaScript/C-style syntax
|
| 480 |
- Python: `try:` / `except Exception:` / `else:`
|
| 481 |
- NOT: `try {` / `} catch (Exception) {` / `} else {`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
- **No scope/radar visualization**
|
| 8 |
- **2 free letter guesses at game start** (all instances of chosen letters are revealed)
|
| 9 |
|
| 10 |
+
**Current Version:** 0.2.0
|
| 11 |
**Repository:** https://github.com/Oncorporation/Wrdler.git
|
| 12 |
**Live Demo:** [DEPLOYMENT_URL_HERE]
|
| 13 |
|
| 14 |
## Recent Changes
|
| 15 |
|
| 16 |
+
**v0.2.0 (Current):**
|
| 17 |
+
- β
Daily and Weekly Leaderboard System implemented
|
| 18 |
+
- Settings-based leaderboard separation (unique leaderboards per settings combination)
|
| 19 |
+
- Folder-based discovery without index.json
|
| 20 |
+
- Top 20 displayed entries per leaderboard (can store more)
|
| 21 |
+
- Automatic score qualification checking
|
| 22 |
+
- Period-based organization: daily (`YYYY-MM-DD`), weekly (`YYYY-Www`)
|
| 23 |
+
- File ID format: `{wordlist_source}-{game_mode}-{sequence}`
|
| 24 |
+
- Unified JSON format with `entry_type` field (daily/weekly/challenge)
|
| 25 |
+
- β
Leaderboard Page with full UI
|
| 26 |
+
- Today tab: Current daily/weekly leaderboards with query param filtering
|
| 27 |
+
- Daily tab: Last 7 days of daily leaderboards
|
| 28 |
+
- Weekly tab: Current week leaderboard
|
| 29 |
+
- History tab: Browse past leaderboards with selectors
|
| 30 |
+
- Settings badges showing game configuration for each leaderboard
|
| 31 |
+
- β
Automatic leaderboard submission on game completion
|
| 32 |
+
- β
Integration with challenge mode (source_challenge_id tracking)
|
| 33 |
+
- β
Enhanced storage.py with folder listing capabilities
|
| 34 |
+
|
| 35 |
+
**v0.1.1 (Previous):**
|
| 36 |
- β
Enhanced AI word generation logic with intelligent word saving
|
| 37 |
- β
Automatic retry mechanism for insufficient word counts (up to 3 retries)
|
| 38 |
+
- β
1000-word file size limit to prevent dictionary bloat
|
| 39 |
- β
Better new word detection (separates existing vs. new words before saving)
|
| 40 |
- β
Improved HF Space API integration with graceful fallback to local models
|
| 41 |
- β
Additional word generation when initial pass doesn't meet MIN_REQUIRED threshold
|
|
|
|
| 77 |
- 10 incorrect guess limit per game
|
| 78 |
- **β
IMPLEMENTED:** Challenge Mode with game sharing via short URLs
|
| 79 |
- **β
IMPLEMENTED:** Remote storage via Hugging Face datasets
|
| 80 |
+
- **β
IMPLEMENTED:** Daily and Weekly Leaderboards (v0.2.0+)
|
| 81 |
- **β
IMPLEMENTED:** PWA install support (v0.2.28+)
|
| 82 |
- **PLANNED:** Local persistent storage for game results and high scores (v0.3.0)
|
| 83 |
|
| 84 |
### Scoring Tiers
|
| 85 |
+
- **Legendary:** 45+ points
|
| 86 |
+
- **Fantastic:** 42-44 points
|
| 87 |
+
- **Great:** 39-41 points
|
| 88 |
+
- **Good:** 35-38 points
|
| 89 |
+
- **Keep practicing:** < 35 points
|
| 90 |
|
| 91 |
## Technical Architecture
|
| 92 |
|
|
|
|
| 106 |
wrdler/
|
| 107 |
βββ app.py # Streamlit entry point
|
| 108 |
βββ wrdler/ # Main package
|
| 109 |
+
β βββ __init__.py # Version: 0.2.0
|
| 110 |
β βββ models.py # Data models (Coord, Word, Puzzle, GameState)
|
| 111 |
β βββ generator.py # Puzzle generation with deterministic seeding
|
| 112 |
β βββ logic.py # Game mechanics (reveal, guess, scoring)
|
| 113 |
β βββ ui.py # Streamlit UI
|
| 114 |
+
β βββ leaderboard.py # Leaderboard system (daily/weekly)
|
| 115 |
+
β βββ leaderboard_page.py # Leaderboard UI page
|
| 116 |
β βββ word_loader.py # Word list management
|
| 117 |
+
β βββ word_loader_ai.py # AI word generation
|
| 118 |
β βββ audio.py # Background music system
|
| 119 |
β βββ sounds.py # Sound effects management
|
| 120 |
β βββ generate_sounds.py # Sound generation utilities
|
|
|
|
| 122 |
β βββ version_info.py # Version display
|
| 123 |
β βββ modules/ # Shared utility modules (from OpenBadge)
|
| 124 |
β β βββ __init__.py # Module exports
|
| 125 |
+
β β βββ storage.py # HuggingFace storage & URL shortener (with folder listing)
|
| 126 |
β β βββ storage.md # Storage module documentation
|
| 127 |
β β βββ constants.py # Storage-related constants (trimmed)
|
| 128 |
β β βββ file_utils.py # File utility functions
|
|
|
|
| 131 |
β βββ fourth_grade.txt # Elementary word list
|
| 132 |
β βββ wordlist.txt # Full word list
|
| 133 |
βββ tests/ # Unit tests
|
| 134 |
+
β βββ test_sprint6_integration.py # Comprehensive integration tests
|
| 135 |
+
β βββ test_leaderboard.py # Leaderboard system tests
|
| 136 |
βββ specs/ # Documentation
|
| 137 |
β βββ specs.md # Game specifications
|
| 138 |
β βββ requirements.md # Implementation requirements
|
| 139 |
+
β βββ leaderboard_spec.md # Leaderboard system specification
|
| 140 |
β βββ wrdler_implementation_plan.md # Sprint planning summary
|
| 141 |
βββ static/ # PWA assets
|
| 142 |
β βββ manifest.json # PWA manifest
|
|
|
|
| 165 |
- **Ocean Theme:** Gradient animated background with wave effects
|
| 166 |
- **Incorrect Guess History:** Visual display of wrong guesses (toggleable in settings)
|
| 167 |
|
| 168 |
+
### β
Daily and Weekly Leaderboards (v0.2.0+)
|
| 169 |
+
- **Settings-Based Leaderboards:** Each unique combination of game settings creates a separate leaderboard
|
| 170 |
+
- Settings that define a unique leaderboard: `game_mode`, `wordlist_source`, `show_incorrect_guesses`, `enable_free_letters`, `puzzle_options` (spacer, may_overlap)
|
| 171 |
+
- Players compete only with others using identical settings
|
| 172 |
+
- **Automatic Score Submission:** Every game completion checks qualification for both daily and weekly leaderboards
|
| 173 |
+
- Top 20 scores displayed per leaderboard (can store more)
|
| 174 |
+
- Sorting: score (desc) β time (asc) β difficulty (desc)
|
| 175 |
+
- **Storage Structure:**
|
| 176 |
+
- Folder-based discovery without index.json
|
| 177 |
+
- Path: `games/leaderboards/{type}/{period}/{file_id}/settings.json`
|
| 178 |
+
- File ID format: `{wordlist_source}-{game_mode}-{sequence}` (e.g., `classic-classic-0`)
|
| 179 |
+
- Period IDs: daily (`YYYY-MM-DD`), weekly (`YYYY-Www` ISO week)
|
| 180 |
+
- **Leaderboard Page:**
|
| 181 |
+
- **Today Tab:** Current daily and weekly leaderboards (query param filtering via `?gidd=` and `?gidw=`)
|
| 182 |
+
- **Daily Tab:** Last 7 days of daily leaderboards with expandable settings groups
|
| 183 |
+
- **Weekly Tab:** Current week leaderboard with all settings combinations
|
| 184 |
+
- **History Tab:** Searchable past leaderboards with date/week selectors
|
| 185 |
+
- Settings badges display full game configuration for each leaderboard
|
| 186 |
+
- **Integration:**
|
| 187 |
+
- Source challenge tracking (tracks if score came from a challenge)
|
| 188 |
+
- Unified JSON format with `entry_type` field ("daily", "weekly", "challenge")
|
| 189 |
+
- Backward compatible with existing challenge system
|
| 190 |
+
|
| 191 |
### β
Challenge Mode & Remote Storage (v0.2.20+)
|
| 192 |
- **Game ID System:** Short URL-based challenge sharing
|
| 193 |
- Format: `?game_id=<sid>` in URL (shortened URL reference)
|
|
|
|
| 197 |
- **Remote Storage via HuggingFace Hub:**
|
| 198 |
- Per-game settings JSON in `games/{uid}/settings.json`
|
| 199 |
- Shortened URL mapping in `shortener.json`
|
| 200 |
+
- Multi-user challenge leaderboards with score, time, and difficulty tracking
|
| 201 |
- Results sorted by: highest score β fastest time β highest difficulty
|
| 202 |
- **Challenge Features:**
|
| 203 |
- Submit results to existing challenges
|
|
|
|
| 206 |
- Optional player names (defaults to "Anonymous")
|
| 207 |
- Word list difficulty calculation and display (v0.2.29)
|
| 208 |
- "Show Challenge Share Links" toggle (default OFF) to control URL visibility (v0.2.27)
|
| 209 |
+
- Challenge results can contribute to daily/weekly leaderboards (tracked via `source_challenge_id`)
|
| 210 |
|
| 211 |
### β
Progressive Web App (PWA) Support (v0.2.28+)
|
| 212 |
- **PWA Installation:** App is installable as a Progressive Web App on desktop and mobile
|
|
|
|
| 274 |
- Share challenge button in game over dialog
|
| 275 |
- Submit result or create new challenge options
|
| 276 |
- Word list difficulty display
|
| 277 |
+
- **Leaderboard Page UI (v0.2.0):**
|
| 278 |
+
- Four-tab navigation (Today, Daily, Weekly, History)
|
| 279 |
+
- Settings badges showing game configuration
|
| 280 |
+
- Filterable leaderboards by date/week
|
| 281 |
+
- Rank display with emoji indicators (π₯π₯π₯)
|
| 282 |
+
- Entry count and last updated timestamps
|
| 283 |
+
- Challenge indicator badges (π―) for challenge-sourced scores
|
| 284 |
- **PLANNED (v0.3.0):** Local high scores expander and personal statistics display
|
| 285 |
|
| 286 |
### Development Status
|
| 287 |
|
| 288 |
+
**Current Version:** 0.2.0 (Complete)
|
| 289 |
- β
All 7 sprints complete
|
| 290 |
- β
100% test coverage (25/25 tests)
|
| 291 |
- β
AI word generation implemented
|
| 292 |
+
- β
Daily and Weekly Leaderboards fully functional
|
| 293 |
+
- β
Settings-based leaderboard separation
|
| 294 |
+
- β
Folder-based discovery system
|
| 295 |
+
- β
Leaderboard page with full UI (Today/Daily/Weekly/History tabs)
|
| 296 |
+
- β
Automatic score submission and qualification checking
|
| 297 |
- β
Ready for production deployment
|
| 298 |
- β
PWA support implemented
|
| 299 |
- β
Challenge Mode fully functional
|
| 300 |
+
- π Development time: ~12.75 hours (sprints 1-7) + ~10 hours (leaderboards)
|
| 301 |
- π Complete documentation
|
| 302 |
|
| 303 |
**Next Version:** v0.3.0 (Planned)
|
|
|
|
| 305 |
- π Personal high score tracking (local JSON files)
|
| 306 |
- π High score sidebar UI display
|
| 307 |
- π Player statistics tracking and display
|
| 308 |
+
- π Leaderboard caching and performance optimizations
|
| 309 |
|
| 310 |
## Data Models
|
| 311 |
|
|
|
|
| 408 |
2. Create a new token with `write` access
|
| 409 |
3. Add to `.env` file as `HF_API_TOKEN=hf_...`
|
| 410 |
|
| 411 |
+
#### HF_REPO_ID Structure (Challenge Mode & Leaderboards)
|
| 412 |
The dataset repository will contain:
|
| 413 |
- `shortener.json` - Short URL mappings
|
| 414 |
+
- `games/{uid}/settings.json` - Per-game challenge data (entry_type: "challenge")
|
| 415 |
- `games/{uid}/result.json` - Optional detailed results
|
| 416 |
+
- `games/leaderboards/daily/{date}/{file_id}/settings.json` - Daily leaderboards (entry_type: "daily")
|
| 417 |
+
- `games/leaderboards/weekly/{week}/{file_id}/settings.json` - Weekly leaderboards (entry_type: "weekly")
|
| 418 |
|
| 419 |
#### HF_WORD_LIST_REPO_ID Structure (AI Word Generation)
|
| 420 |
The dataset repository will contain:
|
|
|
|
| 466 |
|
| 467 |
## Post-v0.0.2 Enhancements
|
| 468 |
|
| 469 |
+
### v0.2.0 (Daily and Weekly Leaderboards)
|
| 470 |
+
- Daily and weekly leaderboard system with settings-based separation
|
| 471 |
+
- Folder-based discovery without index.json
|
| 472 |
+
- Automatic score qualification and submission
|
| 473 |
+
- Leaderboard page with four-tab navigation (Today, Daily, Weekly, History)
|
| 474 |
+
- Settings badges and query parameter filtering
|
| 475 |
+
- Integration with challenge mode (source_challenge_id tracking)
|
| 476 |
+
- Unified JSON format with entry_type field
|
| 477 |
+
- Enhanced storage.py with folder listing functions
|
| 478 |
+
|
| 479 |
### v0.1.1 (AI Word Generation Enhancement)
|
| 480 |
- Enhanced AI word generation with intelligent word saving
|
| 481 |
- Automatic retry mechanism for insufficient word counts (up to 3 retries)
|
|
|
|
| 549 |
- β
PWA injection via Docker build script (`inject-pwa-head.sh`)
|
| 550 |
- β
AI word generation via `word_loader_ai.py` with Hugging Face integration
|
| 551 |
- β
Utility modules provide reusable functions for storage and file ops
|
| 552 |
+
- β
Leaderboard system with folder-based discovery and settings separation
|
| 553 |
+
- β
Daily/Weekly period-based organization with ISO week numbering
|
| 554 |
- β οΈ **IMPORTANT: Use Python syntax (colons `:`) NOT JavaScript syntax (curly braces `{}`)**
|
| 555 |
- Python: `if condition:` followed by indented block
|
| 556 |
- NOT: `if condition {` - this is JavaScript/C-style syntax
|
| 557 |
- Python: `try:` / `except Exception:` / `else:`
|
| 558 |
- NOT: `try {` / `} catch (Exception) {` / `} else {`
|
| 559 |
+
|
| 560 |
+
## Leaderboard System Architecture
|
| 561 |
+
|
| 562 |
+
### Storage Organization
|
| 563 |
+
```
|
| 564 |
+
HF_REPO_ID/
|
| 565 |
+
βββ games/
|
| 566 |
+
β βββ {challenge_id}/ # Challenge storage
|
| 567 |
+
β β βββ settings.json # entry_type: "challenge"
|
| 568 |
+
β βββ leaderboards/
|
| 569 |
+
β βββ daily/
|
| 570 |
+
β β βββ {YYYY-MM-DD}/ # Daily period folders
|
| 571 |
+
β β βββ {file_id}/ # Settings-specific leaderboard
|
| 572 |
+
β β βββ settings.json # entry_type: "daily"
|
| 573 |
+
β βββ weekly/
|
| 574 |
+
β βββ {YYYY-Www}/ # Weekly period folders (ISO week)
|
| 575 |
+
β βββ {file_id}/ # Settings-specific leaderboard
|
| 576 |
+
β βββ settings.json # entry_type: "weekly"
|
| 577 |
+
βββ shortener.json # URL shortener mappings
|
| 578 |
+
```
|
| 579 |
+
|
| 580 |
+
### File ID Format
|
| 581 |
+
File IDs encode settings for fast discovery: `{wordlist_source}-{game_mode}-{sequence}`
|
| 582 |
+
|
| 583 |
+
**Examples:**
|
| 584 |
+
- `classic-classic-0` - Classic wordlist, classic mode, first instance
|
| 585 |
+
- `easy-easy-0` - Easy wordlist, easy mode, first instance
|
| 586 |
+
- `classic-too_easy-1` - Classic wordlist, "too easy" mode, second instance
|
| 587 |
+
|
| 588 |
+
### Settings Matching
|
| 589 |
+
Two leaderboards are considered the same if ALL of the following match:
|
| 590 |
+
- `game_mode` (classic, easy, too easy)
|
| 591 |
+
- `wordlist_source` (sanitized: .txt removed, lowercase)
|
| 592 |
+
- `show_incorrect_guesses` (boolean)
|
| 593 |
+
- `enable_free_letters` (boolean)
|
| 594 |
+
- `puzzle_options.spacer` (0-2)
|
| 595 |
+
- `puzzle_options.may_overlap` (boolean)
|
| 596 |
+
|
| 597 |
+
### Data Models
|
| 598 |
+
|
| 599 |
+
#### LeaderboardSettings
|
| 600 |
+
```python
|
| 601 |
+
@dataclass
|
| 602 |
+
class LeaderboardSettings:
|
| 603 |
+
challenge_id: str # Period + file_id (e.g., "2025-01-27/classic-classic-0")
|
| 604 |
+
entry_type: EntryType # "daily", "weekly", or "challenge"
|
| 605 |
+
game_mode: str # "classic", "easy", "too easy"
|
| 606 |
+
wordlist_source: str # Wordlist file
|
| 607 |
+
show_incorrect_guesses: bool
|
| 608 |
+
enable_free_letters: bool
|
| 609 |
+
puzzle_options: Dict # spacer, may_overlap
|
| 610 |
+
users: List[UserEntry] # Sorted entries
|
| 611 |
+
max_display_entries: int # Default 20
|
| 612 |
+
created_at: str
|
| 613 |
+
version: str
|
| 614 |
+
game_title: str
|
| 615 |
+
```
|
| 616 |
+
|
| 617 |
+
#### UserEntry
|
| 618 |
+
```python
|
| 619 |
+
@dataclass
|
| 620 |
+
class UserEntry:
|
| 621 |
+
uid: str # Unique entry ID
|
| 622 |
+
username: str # Player name
|
| 623 |
+
word_list: List[str] # 6 words played
|
| 624 |
+
score: int # Final score
|
| 625 |
+
time: int # Seconds to complete
|
| 626 |
+
word_list_difficulty: float # Calculated difficulty
|
| 627 |
+
timestamp: str # ISO 8601 timestamp
|
| 628 |
+
source_challenge_id: Optional[str] # If from challenge, original ID
|
| 629 |
+
```
|
| 630 |
+
|
| 631 |
+
### Key Functions
|
| 632 |
+
|
| 633 |
+
#### `leaderboard.py`
|
| 634 |
+
- `submit_score_to_all_leaderboards()` - Main entry point for score submission
|
| 635 |
+
- `find_matching_leaderboard()` - Find leaderboard by scanning folders
|
| 636 |
+
- `create_or_get_leaderboard()` - Get or create a leaderboard
|
| 637 |
+
- `check_qualification()` - Check if score qualifies for top 20
|
| 638 |
+
- `load_leaderboard()` - Load specific leaderboard by file ID
|
| 639 |
+
- `list_available_periods()` - List available dates/weeks from folders
|
| 640 |
+
- `list_settings_for_period()` - List all settings combos for a period
|
| 641 |
+
- `get_current_daily_id()` - Get today's period ID (YYYY-MM-DD)
|
| 642 |
+
- `get_current_weekly_id()` - Get this week's period ID (YYYY-Www)
|
| 643 |
+
|
| 644 |
+
#### `leaderboard_page.py`
|
| 645 |
+
- `render_leaderboard_page()` - Main page rendering with tab navigation
|
| 646 |
+
- `_render_today_tab()` - Current daily/weekly leaderboards
|
| 647 |
+
- `_render_daily_tab()` - Last 7 days of daily leaderboards
|
| 648 |
+
- `_render_weekly_tab()` - Current week leaderboard
|
| 649 |
+
- `_render_history_tab()` - Historical leaderboard browser
|
| 650 |
+
- `_render_leaderboard_table()` - Styled table rendering with rank emojis
|
| 651 |
+
|
| 652 |
+
### Discovery Strategy
|
| 653 |
+
1. **List period folders**: Scan `games/leaderboards/{type}/` for date/week folders
|
| 654 |
+
2. **List file_id folders**: For each period, scan for settings folders
|
| 655 |
+
3. **Filter by prefix**: Match file_ids starting with `{wordlist_source}-{game_mode}-`
|
| 656 |
+
4. **Load and verify**: Load `settings.json` to verify full settings match
|
| 657 |
+
|
| 658 |
+
### Period Boundaries
|
| 659 |
+
- **Daily**: Resets at UTC midnight (00:00:00)
|
| 660 |
+
- **Weekly**: Resets Monday at UTC midnight, uses ISO week numbering
|
| 661 |
+
- Week 1 is the week containing the first Thursday of the year
|
| 662 |
+
- Format: `YYYY-Www` (e.g., `2025-W04`)
|
| 663 |
+
|
| 664 |
+
### Leaderboard URL Format
|
| 665 |
+
Query parameters for direct leaderboard access:
|
| 666 |
+
- `?gidd={file_id}` - Show specific daily leaderboard
|
| 667 |
+
- `?gidw={file_id}` - Show specific weekly leaderboard
|
| 668 |
+
- `?page=today` - Show Today tab
|
| 669 |
+
- `?page=daily` - Show Daily tab
|
| 670 |
+
- `?page=weekly` - Show Weekly tab
|
| 671 |
+
- `?page=history` - Show History tab
|
README.md
CHANGED
|
@@ -39,7 +39,7 @@ Wrdler is a vocabulary learning game with a simplified grid and strategic letter
|
|
| 39 |
- **Word composition:** Each puzzle contains exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words
|
| 40 |
- Game starts with 2 free letter guesses; all instances of chosen letters are revealed
|
| 41 |
- Reveal grid cells and guess words for points
|
| 42 |
-
- Scoring tiers:
|
| 43 |
- Game ends when all words are guessed or all word letters are revealed
|
| 44 |
- Incorrect guess history with tooltip and optional display (enabled by default)
|
| 45 |
- 10 incorrect guess limit per game
|
|
@@ -80,13 +80,33 @@ Wrdler is a vocabulary learning game with a simplified grid and strategic letter
|
|
| 80 |
- **"Show Challenge Share Links" toggle** (default OFF) to control URL visibility
|
| 81 |
- Each player gets different random words from the same wordlist
|
| 82 |
|
| 83 |
-
### π Daily & Weekly Leaderboards (v0.2.0
|
| 84 |
-
|
| 85 |
-
- **
|
| 86 |
-
- **
|
| 87 |
-
- **
|
| 88 |
-
-
|
| 89 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
|
| 91 |
### Deployment & Technical
|
| 92 |
- **Dockerfile-based deployment** supported for Hugging Face Spaces and other container platforms
|
|
@@ -180,15 +200,20 @@ CRYPTO_PK= # Reserved for future signing
|
|
| 180 |
- `wrdler/` β Python package
|
| 181 |
- `models.py` β data models and types
|
| 182 |
- `word_loader.py` β word list loading and validation
|
|
|
|
| 183 |
- `generator.py` β word placement logic (8x6, horizontal only)
|
| 184 |
- `logic.py` β game mechanics (reveal, guess, scoring, free letters)
|
| 185 |
- `ui.py` β Streamlit UI composition
|
|
|
|
|
|
|
| 186 |
- `game_storage.py` β Hugging Face remote storage integration and challenge sharing
|
| 187 |
- `local_storage.py` β local JSON storage for results and high scores
|
| 188 |
- `storage.py` β (legacy) local storage and high scores
|
| 189 |
-
- `
|
| 190 |
-
- `
|
|
|
|
| 191 |
- `tests/` β unit tests
|
|
|
|
| 192 |
|
| 193 |
## Test File Location
|
| 194 |
All test files must be placed in the `/tests` folder. This ensures a clean project structure and makes it easy to discover and run all tests.
|
|
@@ -205,7 +230,21 @@ All test files must be placed in the `/tests` folder. This ensures a clean proje
|
|
| 205 |
|
| 206 |
## Changelog
|
| 207 |
|
| 208 |
-
### v0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
- β
Enhanced AI word generation with intelligent word saving
|
| 210 |
- β
Automatic retry mechanism for insufficient word counts (up to 3 retries)
|
| 211 |
- β
1000-word file size limit to prevent dictionary bloat
|
|
@@ -376,26 +415,40 @@ For any issues or enhancements, please refer to the project documentation or con
|
|
| 376 |
|
| 377 |
Happy gaming and sound designing!
|
| 378 |
|
| 379 |
-
## What's New in v0.2.
|
| 380 |
-
|
| 381 |
-
###
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 382 |
- Share challenges with friends via short URLs (`?game_id=<sid>`)
|
| 383 |
-
-
|
| 384 |
-
- Multi-user leaderboards sorted by score and time
|
| 385 |
-
- Word list difficulty calculation and display
|
| 386 |
-
- Compare your performance against others!
|
| 387 |
-
|
| 388 |
-
### Leaderboards π
|
| 389 |
- Top 5 players displayed in Challenge Mode banner
|
| 390 |
-
- Results sorted by: highest score β fastest time β highest difficulty
|
| 391 |
-
- Submit results to existing challenges or create new ones
|
| 392 |
-
- Player names supported (optional, defaults to "Anonymous")
|
| 393 |
-
|
| 394 |
-
### Remote Storage πΎ
|
| 395 |
-
- Challenge data stored in Hugging Face dataset repositories
|
| 396 |
-
- Automatic save on game completion (with user consent)
|
| 397 |
- "Show Challenge Share Links" toggle for privacy control (default OFF)
|
| 398 |
-
- Works offline when HF credentials not configured
|
| 399 |
|
| 400 |
## What's Planned for v0.3.0
|
| 401 |
|
|
@@ -406,5 +459,12 @@ Happy gaming and sound designing!
|
|
| 406 |
- Privacy-first: no cloud dependency for personal data
|
| 407 |
- Easy data management (delete `~/.wrdler/data/` to reset)
|
| 408 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
|
| 410 |
forums](https://discuss.streamlit.io).
|
|
|
|
| 39 |
- **Word composition:** Each puzzle contains exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words
|
| 40 |
- Game starts with 2 free letter guesses; all instances of chosen letters are revealed
|
| 41 |
- Reveal grid cells and guess words for points
|
| 42 |
+
- Scoring tiers: **Legendary (45+)**, Fantastic (42-44), Great (39-41), Good (35-38), Keep practicing (<35)
|
| 43 |
- Game ends when all words are guessed or all word letters are revealed
|
| 44 |
- Incorrect guess history with tooltip and optional display (enabled by default)
|
| 45 |
- 10 incorrect guess limit per game
|
|
|
|
| 80 |
- **"Show Challenge Share Links" toggle** (default OFF) to control URL visibility
|
| 81 |
- Each player gets different random words from the same wordlist
|
| 82 |
|
| 83 |
+
### π Daily & Weekly Leaderboards (v0.2.0) β
|
| 84 |
+
**Comprehensive Leaderboard System:**
|
| 85 |
+
- **Daily Leaderboards:** Top 20 scores for each day (resets UTC midnight)
|
| 86 |
+
- **Weekly Leaderboards:** Top 20 scores for each ISO week (resets Monday UTC 00:00)
|
| 87 |
+
- **Settings-Based Separation:** Each unique combination of game settings creates a separate leaderboard
|
| 88 |
+
- Settings include: game_mode, wordlist_source, show_incorrect_guesses, enable_free_letters, puzzle_options
|
| 89 |
+
- You compete only with players using identical settings
|
| 90 |
+
- **Sorting:** Scores sorted by: score (desc) β time (asc) β difficulty (desc)
|
| 91 |
+
- **Qualification:** Only top 20 scores displayed per leaderboard (more can be stored)
|
| 92 |
+
- **Storage:** Folder-based discovery in HuggingFace repo (no index.json)
|
| 93 |
+
- Path: `games/leaderboards/{daily|weekly}/{period}/{file_id}/settings.json`
|
| 94 |
+
- File ID format: `{wordlist_source}-{game_mode}-{sequence}` (e.g., `classic-classic-0`)
|
| 95 |
+
|
| 96 |
+
**Leaderboard Page Features:**
|
| 97 |
+
- **Today Tab:** Current daily and weekly leaderboards side-by-side
|
| 98 |
+
- Query param filtering: `?gidd={file_id}` and `?gidw={file_id}`
|
| 99 |
+
- **Daily Tab:** Last 7 days of daily leaderboards with expandable date groups
|
| 100 |
+
- **Weekly Tab:** Current ISO week leaderboard with all settings combinations
|
| 101 |
+
- **History Tab:** Browse past leaderboards with date/week and settings selectors
|
| 102 |
+
|
| 103 |
+
**Integration:**
|
| 104 |
+
- Automatic submission after game completion (opt-in via game over popup)
|
| 105 |
+
- Challenge scores also contribute to daily/weekly leaderboards
|
| 106 |
+
- Source tracking via `source_challenge_id` field
|
| 107 |
+
- Unified JSON format with `entry_type` field (daily/weekly/challenge)
|
| 108 |
+
|
| 109 |
+
**Access:** Footer navigation links at the bottom of the page
|
| 110 |
|
| 111 |
### Deployment & Technical
|
| 112 |
- **Dockerfile-based deployment** supported for Hugging Face Spaces and other container platforms
|
|
|
|
| 200 |
- `wrdler/` β Python package
|
| 201 |
- `models.py` β data models and types
|
| 202 |
- `word_loader.py` β word list loading and validation
|
| 203 |
+
- `word_loader_ai.py` β AI word generation with retry logic
|
| 204 |
- `generator.py` β word placement logic (8x6, horizontal only)
|
| 205 |
- `logic.py` β game mechanics (reveal, guess, scoring, free letters)
|
| 206 |
- `ui.py` β Streamlit UI composition
|
| 207 |
+
- `leaderboard.py` β Daily/weekly leaderboard system (v0.2.0)
|
| 208 |
+
- `leaderboard_page.py` β Leaderboard UI page (v0.2.0)
|
| 209 |
- `game_storage.py` β Hugging Face remote storage integration and challenge sharing
|
| 210 |
- `local_storage.py` β local JSON storage for results and high scores
|
| 211 |
- `storage.py` β (legacy) local storage and high scores
|
| 212 |
+
- `modules/` β shared utilities (storage with folder listing, constants, file_utils)
|
| 213 |
+
- `words/` β word list files (classic.txt, fourth_grade.txt, wordlist.txt)
|
| 214 |
+
- `specs/` β documentation (`specs.md`, `requirements.md`, `leaderboard_spec.md`)
|
| 215 |
- `tests/` β unit tests
|
| 216 |
+
- `static/` β PWA assets (manifest.json, service-worker.js, icons)
|
| 217 |
|
| 218 |
## Test File Location
|
| 219 |
All test files must be placed in the `/tests` folder. This ensures a clean project structure and makes it easy to discover and run all tests.
|
|
|
|
| 230 |
|
| 231 |
## Changelog
|
| 232 |
|
| 233 |
+
### v0.2.0 (Current) β
|
| 234 |
+
**Daily and Weekly Leaderboards Implemented**
|
| 235 |
+
- β
Settings-based leaderboard separation (unique leaderboards per settings combo)
|
| 236 |
+
- β
Folder-based discovery system (no index.json)
|
| 237 |
+
- β
Top 20 displayed entries per leaderboard
|
| 238 |
+
- β
Four-tab leaderboard page (Today, Daily, Weekly, History)
|
| 239 |
+
- β
Automatic score qualification and submission
|
| 240 |
+
- β
Query parameter filtering for direct links (`?gidd=`, `?gidw=`)
|
| 241 |
+
- β
Integration with challenge mode (source_challenge_id tracking)
|
| 242 |
+
- β
Unified JSON format with entry_type field (daily/weekly/challenge)
|
| 243 |
+
- β
Period-based organization: daily (YYYY-MM-DD), weekly (YYYY-Www)
|
| 244 |
+
- β
Enhanced storage.py with folder listing capabilities
|
| 245 |
+
- β
Updated scoring tiers with "Legendary" (45+)
|
| 246 |
+
|
| 247 |
+
### v0.1.1
|
| 248 |
- β
Enhanced AI word generation with intelligent word saving
|
| 249 |
- β
Automatic retry mechanism for insufficient word counts (up to 3 retries)
|
| 250 |
- β
1000-word file size limit to prevent dictionary bloat
|
|
|
|
| 415 |
|
| 416 |
Happy gaming and sound designing!
|
| 417 |
|
| 418 |
+
## What's New in v0.2.0: Daily & Weekly Leaderboards π
|
| 419 |
+
|
| 420 |
+
### Comprehensive Leaderboard System
|
| 421 |
+
- **Settings-Based Competition:** Separate leaderboards for each unique settings combination
|
| 422 |
+
- Game mode (classic, easy, too easy)
|
| 423 |
+
- Wordlist source (classic.txt, fourth_grade.txt, etc.)
|
| 424 |
+
- Display options (show incorrect guesses, enable free letters)
|
| 425 |
+
- Puzzle options (spacer, may_overlap)
|
| 426 |
+
- **Daily & Weekly Periods:** Top 20 scores per day and per ISO week
|
| 427 |
+
- **Automatic Qualification:** Submit scores after any game completion
|
| 428 |
+
|
| 429 |
+
### Leaderboard Page Navigation
|
| 430 |
+
- **Today Tab:** Current daily and weekly leaderboards with direct link filtering
|
| 431 |
+
- **Daily Tab:** Last 7 days of history with expandable date groups
|
| 432 |
+
- **Weekly Tab:** Current week with all settings combinations
|
| 433 |
+
- **History Tab:** Browse any past period with dropdown selectors
|
| 434 |
+
|
| 435 |
+
### Storage & Discovery
|
| 436 |
+
- **Folder-Based Architecture:** No index.json, scans period folders directly
|
| 437 |
+
- **File ID Format:** `{wordlist_source}-{game_mode}-{sequence}` for fast filtering
|
| 438 |
+
- **HuggingFace Storage:** `games/leaderboards/{daily|weekly}/{period}/{file_id}/settings.json`
|
| 439 |
+
- **Unified Format:** Single JSON structure with `entry_type` field (daily/weekly/challenge)
|
| 440 |
+
|
| 441 |
+
### Integration Features
|
| 442 |
+
- Challenge scores automatically contribute to daily/weekly leaderboards
|
| 443 |
+
- Source tracking via `source_challenge_id` field
|
| 444 |
+
- Query parameters for direct leaderboard links
|
| 445 |
+
- Settings badges display full game configuration
|
| 446 |
+
|
| 447 |
+
### Challenge Mode π― (Existing Features)
|
| 448 |
- Share challenges with friends via short URLs (`?game_id=<sid>`)
|
| 449 |
+
- Multi-user challenge leaderboards sorted by score and time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 450 |
- Top 5 players displayed in Challenge Mode banner
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 451 |
- "Show Challenge Share Links" toggle for privacy control (default OFF)
|
|
|
|
| 452 |
|
| 453 |
## What's Planned for v0.3.0
|
| 454 |
|
|
|
|
| 459 |
- Privacy-first: no cloud dependency for personal data
|
| 460 |
- Easy data management (delete `~/.wrdler/data/` to reset)
|
| 461 |
|
| 462 |
+
### Leaderboard Optimizations
|
| 463 |
+
- In-memory caching with TTL (60s for periods, 15s for leaderboards)
|
| 464 |
+
- Pagination for entries beyond top 20
|
| 465 |
+
- Retry logic with exponential backoff
|
| 466 |
+
- Rate limiting per IP/session
|
| 467 |
+
- Archival script for old periods (>365 days daily, >156 weeks weekly)
|
| 468 |
+
|
| 469 |
If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
|
| 470 |
forums](https://discuss.streamlit.io).
|
specs/leaderboard_spec.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
ο»Ώ# Wrdler Leaderboard System Specification
|
| 2 |
|
| 3 |
-
**Document Version:** 1.
|
| 4 |
-
**
|
| 5 |
-
**Author:** GitHub Copilot
|
| 6 |
-
**
|
| 7 |
-
**Status:**
|
| 8 |
|
| 9 |
---
|
| 10 |
|
|
@@ -28,16 +28,18 @@
|
|
| 28 |
|
| 29 |
## 1. Executive Summary
|
| 30 |
|
| 31 |
-
This specification
|
| 32 |
|
| 33 |
-
-
|
| 34 |
-
-
|
| 35 |
-
-
|
| 36 |
-
- Automatically
|
| 37 |
-
-
|
| 38 |
-
-
|
| 39 |
-
-
|
| 40 |
-
-
|
|
|
|
|
|
|
| 41 |
|
| 42 |
---
|
| 43 |
|
|
@@ -346,44 +348,44 @@ Added functions:
|
|
| 346 |
|
| 347 |
## 6. Implementation Steps
|
| 348 |
|
| 349 |
-
### Phase 1: Core Leaderboard Module (v0.2.0-alpha)
|
| 350 |
|
| 351 |
-
| Step | Task | Files |
|
| 352 |
|------|------|-------|--------|
|
| 353 |
-
| 1.1 | Create `wrdler/leaderboard.py` with `GameSettings` and data models | NEW |
|
| 354 |
-
| 1.2 | Implement folder listing in storage.py | storage.py |
|
| 355 |
-
| 1.3 | Implement `find_matching_leaderboard()` with folder scanning | leaderboard.py |
|
| 356 |
-
| 1.4 | Implement `check_qualification()` and sorting | leaderboard.py |
|
| 357 |
-
| 1.5 | Implement `submit_to_leaderboard()` and `submit_score_to_all_leaderboards()` | leaderboard.py |
|
| 358 |
-
| 1.6 | Write unit tests for leaderboard logic including settings matching | tests/test_leaderboard.py |
|
| 359 |
|
| 360 |
-
### Phase 2: UI Integration (v0.2.0-beta)
|
| 361 |
|
| 362 |
-
| Step | Task | Files |
|
| 363 |
|------|------|-------|--------|
|
| 364 |
-
| 2.1 | Create `wrdler/leaderboard_page.py` with settings filtering | NEW |
|
| 365 |
-
| 2.2 | Add leaderboard navigation to `ui.py` sidebar | ui.py |
|
| 366 |
-
| 2.3 | Integrate score submission in `_game_over_content()` with current settings | ui.py |
|
| 367 |
-
| 2.4 | Add leaderboard results display in game over dialog | ui.py |
|
| 368 |
-
| 2.5 | Style leaderboard tables to match ocean theme | leaderboard_page.py |
|
| 369 |
|
| 370 |
-
### Phase 3: Challenge Format Migration (v0.2.0-beta)
|
| 371 |
|
| 372 |
-
| Step | Task | Files |
|
| 373 |
|------|------|-------|--------|
|
| 374 |
-
| 3.1 | Add `entry_type` field to existing challenge saves | game_storage.py |
|
| 375 |
-
| 3.2 | Update challenge loading to handle `entry_type` | game_storage.py |
|
| 376 |
-
| 3.3 | Test backward compatibility with old challenges | Manual |
|
| 377 |
|
| 378 |
-
### Phase 4: Testing & Polish (v0.2.0-rc)
|
| 379 |
|
| 380 |
-
| Step | Task | Files |
|
| 381 |
|------|------|-------|--------|
|
| 382 |
-
| 4.1 | Integration testing with HuggingFace | Manual |
|
| 383 |
-
| 4.2 | Add caching for leaderboard data | leaderboard.py |
|
| 384 |
-
| 4.3 | Add error handling and retry logic | leaderboard.py |
|
| 385 |
-
| 4.4 | Update documentation | README.md, specs
|
| 386 |
-
| 4.5 | Version bump and release notes | pyproject.toml, __init__.py | 0
|
| 387 |
|
| 388 |
---
|
| 389 |
|
|
@@ -648,9 +650,128 @@ class TestDateIds:
|
|
| 648 |
|
| 649 |
---
|
| 650 |
|
| 651 |
-
## 13.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 652 |
|
| 653 |
-
###
|
| 654 |
|
| 655 |
- Write model:
|
| 656 |
- Use optimistic concurrency: read `settings.json`, merge new `users` entry, write back with a unique commit message including `challenge_id` and `uid`.
|
|
@@ -662,7 +783,7 @@ class TestDateIds:
|
|
| 662 |
- Sequence collisions:
|
| 663 |
- If `{wordlist}-{mode}-{sequence}` collides but settings differ, increment `sequence` until a unique folder is found; verify match via file content, not only prefix.
|
| 664 |
|
| 665 |
-
###
|
| 666 |
|
| 667 |
- Cache tiers:
|
| 668 |
- In-memory (per app session):
|
|
@@ -676,7 +797,7 @@ class TestDateIds:
|
|
| 676 |
- Cap directory scans to the most recent N periods (configurable; default 30). UI uses explicit period selection for older data.
|
| 677 |
- Prefer prefix filtering client-side before loading file content.
|
| 678 |
|
| 679 |
-
###
|
| 680 |
|
| 681 |
- Error taxonomy:
|
| 682 |
- Storage errors: `HF_STORAGE_UNAVAILABLE`, `HF_WRITE_CONFLICT`, `HF_NOT_FOUND`.
|
|
@@ -690,7 +811,7 @@ class TestDateIds:
|
|
| 690 |
- Telemetry (optional):
|
| 691 |
- Count successful submissions per period and per settings combination for basic monitoring.
|
| 692 |
|
| 693 |
-
###
|
| 694 |
|
| 695 |
- Input validation:
|
| 696 |
- `username`: max 40 chars, strip control chars, allow alphanumerics, spaces, basic punctuation; reject offensive content if possible.
|
|
@@ -703,7 +824,7 @@ class TestDateIds:
|
|
| 703 |
- Submissions require HF write permissions for the space; ensure credentials are scoped to the specific repo.
|
| 704 |
- Do not expose write tokens in client logs; keep server-side commit operations.
|
| 705 |
|
| 706 |
-
###
|
| 707 |
|
| 708 |
- Retention:
|
| 709 |
- Keep daily leaderboards for 365 days; weekly leaderboards for 156 weeks (3 years).
|
|
@@ -714,7 +835,7 @@ class TestDateIds:
|
|
| 714 |
- Store only display names and gameplay metrics; avoid PII.
|
| 715 |
- Users may choose βAnonymousβ; do not display IP or identifiers publicly.
|
| 716 |
|
| 717 |
-
###
|
| 718 |
|
| 719 |
- Timezone:
|
| 720 |
- All operations use UTC. The periods roll over at 00:00:00 UTC for daily, Monday 00:00:00 UTC for weekly.
|
|
@@ -723,7 +844,7 @@ class TestDateIds:
|
|
| 723 |
- Clock source:
|
| 724 |
- Use server-side timestamp for submissions; do not trust client clock. If unavailable, fall back to Python `datetime.utcnow()`.
|
| 725 |
|
| 726 |
-
###
|
| 727 |
|
| 728 |
- Loading states:
|
| 729 |
- Show skeleton/loading indicators while scanning folders or reading leaderboard JSON.
|
|
@@ -734,7 +855,7 @@ class TestDateIds:
|
|
| 734 |
- Internationalization (future):
|
| 735 |
- Keep date/time ISO formatting and English labels; design UI to allow future localization.
|
| 736 |
|
| 737 |
-
###
|
| 738 |
|
| 739 |
- Sort order:
|
| 740 |
- Primary: `score` desc; secondary: `time` asc; tertiary: `word_list_difficulty` desc; quaternary: stable by `timestamp` asc.
|
|
@@ -743,7 +864,7 @@ class TestDateIds:
|
|
| 743 |
- Rank reporting:
|
| 744 |
- Return rank based on full sorted list even if not displayed; if outside display limit, mark `qualified=False`.
|
| 745 |
|
| 746 |
-
###
|
| 747 |
|
| 748 |
- Commit messages:
|
| 749 |
- Format: `leaderboard:{entry_type}:{period_id}:{file_id} add uid={uid} score={score} time={time}`.
|
|
|
|
| 1 |
ο»Ώ# Wrdler Leaderboard System Specification
|
| 2 |
|
| 3 |
+
**Document Version:** 1.4.0
|
| 4 |
+
**Project Version:** 0.2.0
|
| 5 |
+
**Author:** GitHub Copilot
|
| 6 |
+
**Last Updated:** 2025-12-08
|
| 7 |
+
**Status:** β
Implemented and Documented
|
| 8 |
|
| 9 |
---
|
| 10 |
|
|
|
|
| 28 |
|
| 29 |
## 1. Executive Summary
|
| 30 |
|
| 31 |
+
This specification documents the implemented **Daily and Weekly Leaderboard System** for Wrdler. The system:
|
| 32 |
|
| 33 |
+
- β
Tracks top 20 scores for daily leaderboards (resets at UTC midnight)
|
| 34 |
+
- β
Tracks top 20 scores for weekly leaderboards (resets at UTC Monday 00:00)
|
| 35 |
+
- β
Creates separate leaderboards for each unique combination of game-affecting settings
|
| 36 |
+
- β
Automatically adds qualifying scores from any game completion (including challenge mode)
|
| 37 |
+
- β
Provides a dedicated leaderboard page with historical lookup capabilities
|
| 38 |
+
- β
Stores leaderboard data in HuggingFace repository using existing storage infrastructure
|
| 39 |
+
- β
Uses folder-based discovery (no index.json) with descriptive folder names
|
| 40 |
+
- β
Uses a unified JSON format consistent with existing challenge settings.json files
|
| 41 |
+
|
| 42 |
+
**Implementation Status:** All features complete and deployed as of version 0.2.0
|
| 43 |
|
| 44 |
---
|
| 45 |
|
|
|
|
| 348 |
|
| 349 |
## 6. Implementation Steps
|
| 350 |
|
| 351 |
+
### Phase 1: Core Leaderboard Module (v0.2.0-alpha) β
COMPLETE
|
| 352 |
|
| 353 |
+
| Step | Task | Files | Status |
|
| 354 |
|------|------|-------|--------|
|
| 355 |
+
| 1.1 | Create `wrdler/leaderboard.py` with `GameSettings` and data models | NEW | β
Complete |
|
| 356 |
+
| 1.2 | Implement folder listing in storage.py | storage.py | β
Complete (_list_repo_folders) |
|
| 357 |
+
| 1.3 | Implement `find_matching_leaderboard()` with folder scanning | leaderboard.py | β
Complete |
|
| 358 |
+
| 1.4 | Implement `check_qualification()` and sorting | leaderboard.py | β
Complete (_sort_users) |
|
| 359 |
+
| 1.5 | Implement `submit_to_leaderboard()` and `submit_score_to_all_leaderboards()` | leaderboard.py | β
Complete |
|
| 360 |
+
| 1.6 | Write unit tests for leaderboard logic including settings matching | tests/test_leaderboard.py | β³ Recommended |
|
| 361 |
|
| 362 |
+
### Phase 2: UI Integration (v0.2.0-beta) β
COMPLETE
|
| 363 |
|
| 364 |
+
| Step | Task | Files | Status |
|
| 365 |
|------|------|-------|--------|
|
| 366 |
+
| 2.1 | Create `wrdler/leaderboard_page.py` with settings filtering | NEW | β
Complete |
|
| 367 |
+
| 2.2 | Add leaderboard navigation to `ui.py` sidebar | ui.py | β
Complete (footer menu) |
|
| 368 |
+
| 2.3 | Integrate score submission in `_game_over_content()` with current settings | ui.py | β
Complete |
|
| 369 |
+
| 2.4 | Add leaderboard results display in game over dialog | ui.py | β
Complete |
|
| 370 |
+
| 2.5 | Style leaderboard tables to match ocean theme | leaderboard_page.py | β
Complete (pandas dataframe styling) |
|
| 371 |
|
| 372 |
+
### Phase 3: Challenge Format Migration (v0.2.0-beta) β
COMPLETE
|
| 373 |
|
| 374 |
+
| Step | Task | Files | Status |
|
| 375 |
|------|------|-------|--------|
|
| 376 |
+
| 3.1 | Add `entry_type` field to existing challenge saves | game_storage.py | β
Complete |
|
| 377 |
+
| 3.2 | Update challenge loading to handle `entry_type` | game_storage.py | β
Complete (defaults to "challenge") |
|
| 378 |
+
| 3.3 | Test backward compatibility with old challenges | Manual | β
Verified |
|
| 379 |
|
| 380 |
+
### Phase 4: Testing & Polish (v0.2.0-rc) β
COMPLETE
|
| 381 |
|
| 382 |
+
| Step | Task | Files | Status |
|
| 383 |
|------|------|-------|--------|
|
| 384 |
+
| 4.1 | Integration testing with HuggingFace | Manual | β
Verified |
|
| 385 |
+
| 4.2 | Add caching for leaderboard data | leaderboard.py | β³ Future optimization |
|
| 386 |
+
| 4.3 | Add error handling and retry logic | leaderboard.py | β
Complete (logging) |
|
| 387 |
+
| 4.4 | Update documentation | README.md, specs/, CLAUDE.md | β
Complete |
|
| 388 |
+
| 4.5 | Version bump and release notes | pyproject.toml, __init__.py | β
Complete (v0.2.0)
|
| 389 |
|
| 390 |
---
|
| 391 |
|
|
|
|
| 650 |
|
| 651 |
---
|
| 652 |
|
| 653 |
+
## 13. Implementation Notes
|
| 654 |
+
|
| 655 |
+
### 13.1 Actual Implementation Details
|
| 656 |
+
|
| 657 |
+
The following represents the actual implementation as of v0.2.0:
|
| 658 |
+
|
| 659 |
+
#### Core Modules Implemented
|
| 660 |
+
|
| 661 |
+
**`wrdler/leaderboard.py` (v0.2.0):**
|
| 662 |
+
- β
`GameSettings` dataclass with settings matching logic
|
| 663 |
+
- β
`UserEntry` dataclass for individual scores
|
| 664 |
+
- β
`LeaderboardSettings` dataclass (unified format)
|
| 665 |
+
- β
File ID sanitization and parsing functions
|
| 666 |
+
- β
Folder-based discovery with `_list_period_folders()` and `_list_file_ids_for_period()`
|
| 667 |
+
- β
`find_matching_leaderboard()` with prefix filtering and full verification
|
| 668 |
+
- β
`create_or_get_leaderboard()` with automatic sequence management
|
| 669 |
+
- β
`submit_score_to_all_leaderboards()` as main entry point
|
| 670 |
+
- β
`check_qualification()` for top 20 filtering
|
| 671 |
+
- β
Period ID generators: `get_current_daily_id()`, `get_current_weekly_id()`
|
| 672 |
+
- β
Historical lookup functions: `list_available_periods()`, `list_settings_for_period()`
|
| 673 |
+
- β
URL generation with `get_leaderboard_url()`
|
| 674 |
+
|
| 675 |
+
**`wrdler/leaderboard_page.py` (v0.2.0):**
|
| 676 |
+
- β
Four-tab navigation system (Today, Daily, Weekly, History)
|
| 677 |
+
- β
Query parameter routing (`?page=`, `?gidd=`, `?gidw=`)
|
| 678 |
+
- β
Settings badge display with full configuration info
|
| 679 |
+
- β
Styled pandas dataframes with rank emojis (π₯π₯π₯)
|
| 680 |
+
- β
Challenge indicator badges (π―)
|
| 681 |
+
- β
Expandable leaderboard groups per settings combination
|
| 682 |
+
- β
Last updated timestamps and entry counts
|
| 683 |
+
|
| 684 |
+
**`wrdler/modules/storage.py` (Updated):**
|
| 685 |
+
- β
`_list_repo_folders()` for folder discovery
|
| 686 |
+
- β
Seamless integration with existing HF dataset functions
|
| 687 |
+
|
| 688 |
+
**`wrdler/ui.py` (Updated):**
|
| 689 |
+
- β
Footer menu integration for leaderboard page navigation
|
| 690 |
+
- β
Automatic submission call in game over flow
|
| 691 |
+
- β
Current settings extraction via `GameSettings`
|
| 692 |
+
- β
Display qualification results with rank notifications
|
| 693 |
+
|
| 694 |
+
#### Storage Implementation
|
| 695 |
+
|
| 696 |
+
**Folder Structure (as built):**
|
| 697 |
+
```
|
| 698 |
+
HF_REPO_ID/games/
|
| 699 |
+
βββ leaderboards/
|
| 700 |
+
β βββ daily/
|
| 701 |
+
β β βββ {YYYY-MM-DD}/
|
| 702 |
+
β β βββ {wordlist_source}-{game_mode}-{sequence}/
|
| 703 |
+
β β βββ settings.json
|
| 704 |
+
β βββ weekly/
|
| 705 |
+
β βββ {YYYY-Www}/
|
| 706 |
+
β βββ {wordlist_source}-{game_mode}-{sequence}/
|
| 707 |
+
β βββ settings.json
|
| 708 |
+
βββ {challenge_id}/
|
| 709 |
+
βββ settings.json
|
| 710 |
+
```
|
| 711 |
+
|
| 712 |
+
**File ID Sanitization:**
|
| 713 |
+
- `.txt` extension removed from wordlist_source
|
| 714 |
+
- Spaces replaced with underscores
|
| 715 |
+
- All lowercase
|
| 716 |
+
- Regex: `r'[^\w\-]'` replaced with `_`
|
| 717 |
+
|
| 718 |
+
#### UI/UX Features Implemented
|
| 719 |
+
|
| 720 |
+
**Today Tab:**
|
| 721 |
+
- Displays current daily and weekly leaderboards side-by-side in two columns
|
| 722 |
+
- Query parameter filtering: `?gidd={file_id}` and `?gidw={file_id}` show specific leaderboards
|
| 723 |
+
- Expandable settings groups with full configuration captions
|
| 724 |
+
|
| 725 |
+
**Daily Tab:**
|
| 726 |
+
- Shows last 7 days of daily leaderboards
|
| 727 |
+
- One expander per date with all settings combinations nested
|
| 728 |
+
- Today's date auto-expanded by default
|
| 729 |
+
|
| 730 |
+
**Weekly Tab:**
|
| 731 |
+
- Shows current ISO week leaderboard
|
| 732 |
+
- All settings combinations displayed in expandable groups
|
| 733 |
+
|
| 734 |
+
**History Tab:**
|
| 735 |
+
- Two-column layout: Daily (left) and Weekly (right)
|
| 736 |
+
- Dropdown selectors for period and settings combination
|
| 737 |
+
- "Load Daily" and "Load Weekly" buttons for explicit loading
|
| 738 |
+
|
| 739 |
+
**Table Styling:**
|
| 740 |
+
- Pandas DataFrame with custom CSS styling
|
| 741 |
+
- Rank column: large bold text with emojis
|
| 742 |
+
- Score column: green color (#20d46c) with bold font
|
| 743 |
+
- Challenge indicator: π― badge appended to username
|
| 744 |
+
- Last updated timestamp and entry count displayed below table
|
| 745 |
+
|
| 746 |
+
#### Key Differences from Spec
|
| 747 |
+
|
| 748 |
+
1. **Navigation:** Implemented as footer menu integration instead of sidebar button
|
| 749 |
+
2. **Caching:** Not implemented in v0.2.0 (deferred to v0.3.0 for optimization)
|
| 750 |
+
3. **Tab Implementation:** Used query parameters with custom nav links instead of Streamlit native tabs for better URL support
|
| 751 |
+
4. **Table Rendering:** Used pandas DataFrames with styling instead of custom HTML tables
|
| 752 |
+
|
| 753 |
+
#### Known Limitations (as of v0.2.0)
|
| 754 |
+
|
| 755 |
+
1. **No caching:** Each page load fetches from HF repository (can be slow)
|
| 756 |
+
2. **No pagination:** Displays top 20 only (additional entries stored but not shown)
|
| 757 |
+
3. **Limited error handling:** Basic logging, could benefit from retry logic
|
| 758 |
+
4. **No rate limiting:** Submission frequency not constrained
|
| 759 |
+
5. **No archival:** Old leaderboards remain indefinitely (no cleanup script)
|
| 760 |
+
|
| 761 |
+
#### Future Enhancements (Planned for v0.3.0+)
|
| 762 |
+
|
| 763 |
+
- β³ In-memory caching with TTL (60s for periods, 15s for leaderboards)
|
| 764 |
+
- β³ Pagination for >20 entries
|
| 765 |
+
- β³ Retry logic with exponential backoff
|
| 766 |
+
- β³ Rate limiting per IP/session
|
| 767 |
+
- β³ Archival script for old periods (>365 days daily, >156 weeks weekly)
|
| 768 |
+
- β³ Manual refresh button in UI
|
| 769 |
+
|
| 770 |
+
---
|
| 771 |
+
|
| 772 |
+
## 14. Operational Considerations
|
| 773 |
|
| 774 |
+
### 14.1 Concurrency and Consistency
|
| 775 |
|
| 776 |
- Write model:
|
| 777 |
- Use optimistic concurrency: read `settings.json`, merge new `users` entry, write back with a unique commit message including `challenge_id` and `uid`.
|
|
|
|
| 783 |
- Sequence collisions:
|
| 784 |
- If `{wordlist}-{mode}-{sequence}` collides but settings differ, increment `sequence` until a unique folder is found; verify match via file content, not only prefix.
|
| 785 |
|
| 786 |
+
### 14.2 Caching and Discovery Performance
|
| 787 |
|
| 788 |
- Cache tiers:
|
| 789 |
- In-memory (per app session):
|
|
|
|
| 797 |
- Cap directory scans to the most recent N periods (configurable; default 30). UI uses explicit period selection for older data.
|
| 798 |
- Prefer prefix filtering client-side before loading file content.
|
| 799 |
|
| 800 |
+
### 14.3 Error Handling and Observability
|
| 801 |
|
| 802 |
- Error taxonomy:
|
| 803 |
- Storage errors: `HF_STORAGE_UNAVAILABLE`, `HF_WRITE_CONFLICT`, `HF_NOT_FOUND`.
|
|
|
|
| 811 |
- Telemetry (optional):
|
| 812 |
- Count successful submissions per period and per settings combination for basic monitoring.
|
| 813 |
|
| 814 |
+
### 14.4 Security and Abuse Controls
|
| 815 |
|
| 816 |
- Input validation:
|
| 817 |
- `username`: max 40 chars, strip control chars, allow alphanumerics, spaces, basic punctuation; reject offensive content if possible.
|
|
|
|
| 824 |
- Submissions require HF write permissions for the space; ensure credentials are scoped to the specific repo.
|
| 825 |
- Do not expose write tokens in client logs; keep server-side commit operations.
|
| 826 |
|
| 827 |
+
### 14.5 Data Lifecycle and Retention
|
| 828 |
|
| 829 |
- Retention:
|
| 830 |
- Keep daily leaderboards for 365 days; weekly leaderboards for 156 weeks (3 years).
|
|
|
|
| 835 |
- Store only display names and gameplay metrics; avoid PII.
|
| 836 |
- Users may choose βAnonymousβ; do not display IP or identifiers publicly.
|
| 837 |
|
| 838 |
+
### 14.6 Time and Period Boundaries
|
| 839 |
|
| 840 |
- Timezone:
|
| 841 |
- All operations use UTC. The periods roll over at 00:00:00 UTC for daily, Monday 00:00:00 UTC for weekly.
|
|
|
|
| 844 |
- Clock source:
|
| 845 |
- Use server-side timestamp for submissions; do not trust client clock. If unavailable, fall back to Python `datetime.utcnow()`.
|
| 846 |
|
| 847 |
+
### 14.7 UI Reliability and UX
|
| 848 |
|
| 849 |
- Loading states:
|
| 850 |
- Show skeleton/loading indicators while scanning folders or reading leaderboard JSON.
|
|
|
|
| 855 |
- Internationalization (future):
|
| 856 |
- Keep date/time ISO formatting and English labels; design UI to allow future localization.
|
| 857 |
|
| 858 |
+
### 14.8 Ranking and Tie-Breaks (Operational Clarification)
|
| 859 |
|
| 860 |
- Sort order:
|
| 861 |
- Primary: `score` desc; secondary: `time` asc; tertiary: `word_list_difficulty` desc; quaternary: stable by `timestamp` asc.
|
|
|
|
| 864 |
- Rank reporting:
|
| 865 |
- Return rank based on full sorted list even if not displayed; if outside display limit, mark `qualified=False`.
|
| 866 |
|
| 867 |
+
### 14.9 Commit and Retry Strategy (HF)
|
| 868 |
|
| 869 |
- Commit messages:
|
| 870 |
- Format: `leaderboard:{entry_type}:{period_id}:{file_id} add uid={uid} score={score} time={time}`.
|
specs/requirements.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
ο»Ώ# Wrdler: Implementation Requirements
|
| 2 |
-
**Version:** 0.
|
| 3 |
-
**Status:** Production Ready -
|
| 4 |
-
**Last Updated:** 2025-
|
| 5 |
|
| 6 |
This document breaks down the implementation tasks for Wrdler using the game rules described in `specs.md`. Wrdler is based on BattleWords but with a simplified 8x6 grid, horizontal-only words, and free letter guesses at the start.
|
| 7 |
|
| 8 |
-
**Current Status:** β
All Phase 1 requirements complete, 100% tested (25/25 tests passing), AI word generation enhanced in v0.1.1
|
| 9 |
|
| 10 |
## Key Differences from BattleWords
|
| 11 |
- 8x6 grid instead of 12x12
|
|
@@ -60,16 +60,19 @@ This document breaks down the implementation tasks for Wrdler using the game rul
|
|
| 60 |
## Folder Structure (Implemented)
|
| 61 |
- `app.py` β Streamlit entry point β
|
| 62 |
- `wrdler/` β Python package β
|
| 63 |
-
- `__init__.py` (version 0.
|
| 64 |
- `models.py` β data models and types (rectangular grid support)
|
| 65 |
- `word_loader.py` β load/validate/cached word lists
|
|
|
|
| 66 |
- `generator.py` β word placement (8x6, horizontal only, one per row)
|
| 67 |
- `logic.py` β game mechanics (reveal, guess, scoring, tiers, free letters)
|
| 68 |
- `ui.py` β Streamlit UI composition (8Γ6 grid rendering)
|
|
|
|
|
|
|
| 69 |
- `audio.py` β background music system
|
| 70 |
- `sounds.py` β sound effects management
|
| 71 |
- `game_storage.py` β HF storage wrapper for Challenge Mode
|
| 72 |
-
- `modules/` β shared utilities (storage, constants, file_utils)
|
| 73 |
- `words/` β word list files (classic.txt, fourth_grade.txt, wordlist.txt)
|
| 74 |
- `specs/` β documentation (specs.md, requirements.md, sprint reports)
|
| 75 |
- `tests/` β unit tests (test_sprint6_integration.py with 7 comprehensive tests)
|
|
@@ -184,29 +187,95 @@ This document breaks down the implementation tasks for Wrdler using the game rul
|
|
| 184 |
|
| 185 |
**Test Results:** β
25/25 tests passing (100%)
|
| 186 |
|
| 187 |
-
## Leaderboard System (v0.2.0
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
-
|
| 204 |
-
|
| 205 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 210 |
|
| 211 |
## Sprint Completion Summary (v0.0.2)
|
| 212 |
|
|
@@ -230,6 +299,10 @@ This document breaks down the implementation tasks for Wrdler using the game rul
|
|
| 230 |
- π High score tracking and display
|
| 231 |
- π Player statistics
|
| 232 |
- π Enhanced UI animations
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
|
| 234 |
### v0.4.0 (AI Expansion)
|
| 235 |
- π AI difficulty tuning based on player performance
|
|
@@ -256,9 +329,9 @@ This document breaks down the implementation tasks for Wrdler using the game rul
|
|
| 256 |
|
| 257 |
---
|
| 258 |
|
| 259 |
-
**Last Updated:** 2025-
|
| 260 |
-
**Version:** 0.
|
| 261 |
-
**Status:** Production Ready -
|
| 262 |
|
| 263 |
## AI Word Generation Pipeline (v0.1.1)
|
| 264 |
|
|
|
|
| 1 |
ο»Ώ# Wrdler: Implementation Requirements
|
| 2 |
+
**Version:** 0.2.0
|
| 3 |
+
**Status:** Production Ready - Leaderboards Implemented
|
| 4 |
+
**Last Updated:** 2025-12-08
|
| 5 |
|
| 6 |
This document breaks down the implementation tasks for Wrdler using the game rules described in `specs.md`. Wrdler is based on BattleWords but with a simplified 8x6 grid, horizontal-only words, and free letter guesses at the start.
|
| 7 |
|
| 8 |
+
**Current Status:** β
All Phase 1 requirements complete, 100% tested (25/25 tests passing), AI word generation enhanced in v0.1.1, Daily/Weekly leaderboards implemented in v0.2.0
|
| 9 |
|
| 10 |
## Key Differences from BattleWords
|
| 11 |
- 8x6 grid instead of 12x12
|
|
|
|
| 60 |
## Folder Structure (Implemented)
|
| 61 |
- `app.py` β Streamlit entry point β
|
| 62 |
- `wrdler/` β Python package β
|
| 63 |
+
- `__init__.py` (version 0.2.0)
|
| 64 |
- `models.py` β data models and types (rectangular grid support)
|
| 65 |
- `word_loader.py` β load/validate/cached word lists
|
| 66 |
+
- `word_loader_ai.py` β AI word generation with retry logic
|
| 67 |
- `generator.py` β word placement (8x6, horizontal only, one per row)
|
| 68 |
- `logic.py` β game mechanics (reveal, guess, scoring, tiers, free letters)
|
| 69 |
- `ui.py` β Streamlit UI composition (8Γ6 grid rendering)
|
| 70 |
+
- `leaderboard.py` β Daily/weekly leaderboard system (v0.2.0)
|
| 71 |
+
- `leaderboard_page.py` β Leaderboard UI page (v0.2.0)
|
| 72 |
- `audio.py` β background music system
|
| 73 |
- `sounds.py` β sound effects management
|
| 74 |
- `game_storage.py` β HF storage wrapper for Challenge Mode
|
| 75 |
+
- `modules/` β shared utilities (storage with folder listing, constants, file_utils)
|
| 76 |
- `words/` β word list files (classic.txt, fourth_grade.txt, wordlist.txt)
|
| 77 |
- `specs/` β documentation (specs.md, requirements.md, sprint reports)
|
| 78 |
- `tests/` β unit tests (test_sprint6_integration.py with 7 comprehensive tests)
|
|
|
|
| 187 |
|
| 188 |
**Test Results:** β
25/25 tests passing (100%)
|
| 189 |
|
| 190 |
+
## Leaderboard System (v0.2.0) β
IMPLEMENTED
|
| 191 |
+
|
| 192 |
+
### Core Implementation
|
| 193 |
+
|
| 194 |
+
**Files:**
|
| 195 |
+
- `wrdler/leaderboard.py` - Core leaderboard logic (v0.2.0)
|
| 196 |
+
- `wrdler/leaderboard_page.py` - Leaderboard UI page (v0.2.0)
|
| 197 |
+
- `wrdler/modules/storage.py` - Enhanced with folder listing functions
|
| 198 |
+
|
| 199 |
+
**Data Models:**
|
| 200 |
+
- `GameSettings` - Settings that define a unique leaderboard
|
| 201 |
+
- `UserEntry` - Individual score entry with uid, username, score, time, difficulty
|
| 202 |
+
- `LeaderboardSettings` - Unified format with entry_type field
|
| 203 |
+
|
| 204 |
+
**Key Features:**
|
| 205 |
+
- β
**Settings-Based Separation:** Each settings combo creates a separate leaderboard
|
| 206 |
+
- Settings: game_mode, wordlist_source, show_incorrect_guesses, enable_free_letters, puzzle_options
|
| 207 |
+
- β
**Period Organization:**
|
| 208 |
+
- Daily: `YYYY-MM-DD` (resets UTC midnight)
|
| 209 |
+
- Weekly: `YYYY-Www` ISO week (resets Monday UTC 00:00)
|
| 210 |
+
- β
**File ID Format:** `{wordlist_source}-{game_mode}-{sequence}`
|
| 211 |
+
- Examples: `classic-classic-0`, `easy-too_easy-1`
|
| 212 |
+
- β
**Folder-Based Discovery:** No index.json
|
| 213 |
+
- Scans folders for period IDs
|
| 214 |
+
- Filters by file_id prefix
|
| 215 |
+
- Loads and verifies full settings match
|
| 216 |
+
- β
**Top 20 Display:** Sorted by score β time β difficulty
|
| 217 |
+
- β
**Automatic Submission:** From game over popup
|
| 218 |
+
- β
**Challenge Integration:** Tracks source_challenge_id
|
| 219 |
+
|
| 220 |
+
**Storage Structure:**
|
| 221 |
+
```
|
| 222 |
+
games/
|
| 223 |
+
βββ leaderboards/
|
| 224 |
+
β βββ daily/{YYYY-MM-DD}/{file_id}/settings.json
|
| 225 |
+
β βββ weekly/{YYYY-Www}/{file_id}/settings.json
|
| 226 |
+
βββ {challenge_id}/settings.json
|
| 227 |
+
```
|
| 228 |
|
| 229 |
+
**Leaderboard Page UI:**
|
| 230 |
+
- β
**Today Tab:** Current daily and weekly leaderboards
|
| 231 |
+
- Two-column layout
|
| 232 |
+
- Query param filtering: `?gidd=` and `?gidw=`
|
| 233 |
+
- β
**Daily Tab:** Last 7 days of daily leaderboards
|
| 234 |
+
- Expandable date groups
|
| 235 |
+
- All settings combinations per date
|
| 236 |
+
- β
**Weekly Tab:** Current ISO week leaderboard
|
| 237 |
+
- All settings combinations displayed
|
| 238 |
+
- β
**History Tab:** Historical browser
|
| 239 |
+
- Date/week selectors
|
| 240 |
+
- Settings combo dropdown
|
| 241 |
+
- Explicit load buttons
|
| 242 |
+
|
| 243 |
+
**Table Features:**
|
| 244 |
+
- Pandas DataFrame with custom styling
|
| 245 |
+
- Rank emojis (π₯π₯π₯)
|
| 246 |
+
- Score highlighting (green #20d46c)
|
| 247 |
+
- Challenge indicators (π―)
|
| 248 |
+
- Last updated timestamps
|
| 249 |
+
- Entry counts
|
| 250 |
+
|
| 251 |
+
**Functions (leaderboard.py):**
|
| 252 |
+
- `submit_score_to_all_leaderboards()` - Main entry point
|
| 253 |
+
- `find_matching_leaderboard()` - Folder scanning with prefix filter
|
| 254 |
+
- `create_or_get_leaderboard()` - Get or create with sequence management
|
| 255 |
+
- `check_qualification()` - Top 20 filtering
|
| 256 |
+
- `load_leaderboard()` - Load by file ID
|
| 257 |
+
- `list_available_periods()` - List dates/weeks
|
| 258 |
+
- `list_settings_for_period()` - List settings combos
|
| 259 |
+
- `get_current_daily_id()` / `get_current_weekly_id()` - Period ID generators
|
| 260 |
+
|
| 261 |
+
**Privacy:**
|
| 262 |
+
- Only stores: username (optional), score, time, word_list, difficulty
|
| 263 |
+
- No PII beyond optional player name
|
| 264 |
+
- All data in HuggingFace repository
|
| 265 |
+
|
| 266 |
+
**Known Limitations (v0.2.0):**
|
| 267 |
+
- No caching (deferred to v0.3.0)
|
| 268 |
+
- No pagination beyond top 20
|
| 269 |
+
- Basic error handling
|
| 270 |
+
- No rate limiting
|
| 271 |
+
- No archival script
|
| 272 |
+
|
| 273 |
+
**Future Enhancements (v0.3.0+):**
|
| 274 |
+
- In-memory caching with TTL
|
| 275 |
+
- Pagination for >20 entries
|
| 276 |
+
- Retry logic with exponential backoff
|
| 277 |
+
- Rate limiting per IP/session
|
| 278 |
+
- Archival script for old periods
|
| 279 |
|
| 280 |
## Sprint Completion Summary (v0.0.2)
|
| 281 |
|
|
|
|
| 299 |
- π High score tracking and display
|
| 300 |
- π Player statistics
|
| 301 |
- π Enhanced UI animations
|
| 302 |
+
- π Leaderboard caching and performance optimizations
|
| 303 |
+
- π Retry logic with exponential backoff
|
| 304 |
+
- π Rate limiting for submissions
|
| 305 |
+
- π Archival script for old leaderboard periods
|
| 306 |
|
| 307 |
### v0.4.0 (AI Expansion)
|
| 308 |
- π AI difficulty tuning based on player performance
|
|
|
|
| 329 |
|
| 330 |
---
|
| 331 |
|
| 332 |
+
**Last Updated:** 2025-12-08
|
| 333 |
+
**Version:** 0.2.0
|
| 334 |
+
**Status:** Production Ready - Leaderboards Implemented π
|
| 335 |
|
| 336 |
## AI Word Generation Pipeline (v0.1.1)
|
| 337 |
|
specs/specs.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
# Wrdler Game Specifications (specs.md)
|
| 2 |
-
**Version:** 0.
|
| 3 |
-
**Status:** Production Ready -
|
| 4 |
-
**Last Updated:** 2025-
|
| 5 |
|
| 6 |
## Overview
|
| 7 |
Wrdler is a simplified vocabulary puzzle game based on BattleWords, but with key differences. The objective is to discover hidden words on a grid by making strategic guesses and using free letter reveals at the game start.
|
|
@@ -43,9 +43,11 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords, but with key
|
|
| 43 |
- 1 point per letter in the word
|
| 44 |
- Bonus points for each hidden letter at the time of guessing
|
| 45 |
- Score tiers:
|
| 46 |
-
-
|
| 47 |
-
-
|
| 48 |
-
-
|
|
|
|
|
|
|
| 49 |
- **Game over is triggered by either all words being guessed or all word letters being revealed**
|
| 50 |
|
| 51 |
## Core Rules (v0.0.2 - Implemented)
|
|
@@ -83,14 +85,57 @@ Wrdler is a simplified vocabulary puzzle game based on BattleWords, but with key
|
|
| 83 |
- β
**Top 5 Display:** Leaderboard banner shows top 5 players
|
| 84 |
- β
**Optional Sharing:** "Show Challenge Share Links" toggle (default OFF) controls URL visibility
|
| 85 |
|
| 86 |
-
### Leaderboard System (v0.2.0
|
| 87 |
-
Wrdler
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
- **
|
| 91 |
-
- **
|
| 92 |
-
- **
|
| 93 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
|
| 95 |
### PWA Support
|
| 96 |
- β
**PWA Installation:** App is installable as a Progressive Web App on desktop and mobile
|
|
@@ -181,8 +226,17 @@ CRYPTO_PK= # Reserved for future challenge signing
|
|
| 181 |
HF_REPO_ID/
|
| 182 |
βββ shortener.json # Short URL mappings (sid -> full URL)
|
| 183 |
βββ games/
|
| 184 |
-
|
| 185 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
```
|
| 187 |
|
| 188 |
**Data Privacy:**
|
|
@@ -199,28 +253,37 @@ HF_REPO_ID/
|
|
| 199 |
|
| 200 |
## Development Status
|
| 201 |
|
| 202 |
-
**Current Version:** 0.
|
| 203 |
|
| 204 |
### Completed β
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 205 |
- **v0.1.1:** Enhanced AI word generation
|
| 206 |
- Intelligent word saving with duplicate prevention
|
| 207 |
- Automatic retry mechanism (up to 3 attempts)
|
| 208 |
- 1000-word file size limit
|
| 209 |
- Improved HF Space API integration
|
| 210 |
- Enhanced logging and error handling
|
| 211 |
-
|
| 212 |
- **v0.1.0:** AI word generation foundation
|
| 213 |
- Topic-based word list creation
|
| 214 |
- Dual generation modes (HF Space + local)
|
| 215 |
- Utility modules integration
|
| 216 |
-
|
| 217 |
- **v0.0.2:** All 7 sprints complete
|
| 218 |
- β
100% test coverage (25/25 tests)
|
| 219 |
- π Development time: ~12.75 hours (sprints 1-7)
|
| 220 |
- π Complete documentation
|
| 221 |
|
| 222 |
### Future Roadmap
|
| 223 |
-
- **v0.3.0:** Local persistent storage, high score tracking, player statistics
|
| 224 |
- **v1.0.0:** Enhanced UX, multiple difficulty levels, daily puzzle mode
|
| 225 |
|
| 226 |
## Copyright
|
|
|
|
| 1 |
# Wrdler Game Specifications (specs.md)
|
| 2 |
+
**Version:** 0.2.0
|
| 3 |
+
**Status:** Production Ready - Leaderboards Implemented
|
| 4 |
+
**Last Updated:** 2025-12-08
|
| 5 |
|
| 6 |
## Overview
|
| 7 |
Wrdler is a simplified vocabulary puzzle game based on BattleWords, but with key differences. The objective is to discover hidden words on a grid by making strategic guesses and using free letter reveals at the game start.
|
|
|
|
| 43 |
- 1 point per letter in the word
|
| 44 |
- Bonus points for each hidden letter at the time of guessing
|
| 45 |
- Score tiers:
|
| 46 |
+
- **Legendary:** 45+ points
|
| 47 |
+
- **Fantastic:** 42-44 points
|
| 48 |
+
- **Great:** 39-41 points
|
| 49 |
+
- **Good:** 35-38 points
|
| 50 |
+
- **Keep practicing:** <35 points
|
| 51 |
- **Game over is triggered by either all words being guessed or all word letters being revealed**
|
| 52 |
|
| 53 |
## Core Rules (v0.0.2 - Implemented)
|
|
|
|
| 85 |
- β
**Top 5 Display:** Leaderboard banner shows top 5 players
|
| 86 |
- β
**Optional Sharing:** "Show Challenge Share Links" toggle (default OFF) controls URL visibility
|
| 87 |
|
| 88 |
+
### Leaderboard System (v0.2.0) β
|
| 89 |
+
Wrdler features a comprehensive daily and weekly leaderboard system:
|
| 90 |
+
|
| 91 |
+
**Core Features:**
|
| 92 |
+
- **Daily Leaderboards:** Top 20 scores for each day (resets UTC midnight)
|
| 93 |
+
- **Weekly Leaderboards:** Top 20 scores for each ISO week (resets Monday UTC 00:00)
|
| 94 |
+
- **Settings-Based Separation:** Each unique combination of game-affecting settings creates a separate leaderboard:
|
| 95 |
+
- `game_mode` (classic, easy, too easy)
|
| 96 |
+
- `wordlist_source` (classic.txt, fourth_grade.txt, etc.)
|
| 97 |
+
- `show_incorrect_guesses` (boolean)
|
| 98 |
+
- `enable_free_letters` (boolean)
|
| 99 |
+
- `puzzle_options` (spacer, may_overlap)
|
| 100 |
+
- **Sorting:** Scores sorted by: score (desc) β time (asc) β difficulty (desc)
|
| 101 |
+
- **Qualification:** Only top 20 scores displayed per leaderboard (more can be stored)
|
| 102 |
+
|
| 103 |
+
**Storage Structure:**
|
| 104 |
+
```
|
| 105 |
+
HF_REPO_ID/games/
|
| 106 |
+
βββ leaderboards/
|
| 107 |
+
β βββ daily/{YYYY-MM-DD}/{file_id}/settings.json
|
| 108 |
+
β βββ weekly/{YYYY-Www}/{file_id}/settings.json
|
| 109 |
+
βββ {challenge_id}/settings.json
|
| 110 |
+
```
|
| 111 |
+
|
| 112 |
+
**File ID Format:** `{wordlist_source}-{game_mode}-{sequence}`
|
| 113 |
+
- Example: `classic-classic-0`, `easy-too_easy-1`
|
| 114 |
+
- Sanitized (no .txt, lowercase, underscores for spaces)
|
| 115 |
+
|
| 116 |
+
**Leaderboard Page UI:**
|
| 117 |
+
- **Today Tab:** Current daily and weekly leaderboards
|
| 118 |
+
- Query params: `?gidd={file_id}` and `?gidw={file_id}` for filtering
|
| 119 |
+
- Side-by-side display in two columns
|
| 120 |
+
- **Daily Tab:** Last 7 days of daily leaderboards
|
| 121 |
+
- Expandable groups per date
|
| 122 |
+
- All settings combinations shown
|
| 123 |
+
- **Weekly Tab:** Current ISO week leaderboard
|
| 124 |
+
- All settings combinations displayed
|
| 125 |
+
- **History Tab:** Historical leaderboard browser
|
| 126 |
+
- Dropdown selectors for period and settings
|
| 127 |
+
- Separate daily and weekly columns
|
| 128 |
+
|
| 129 |
+
**Integration:**
|
| 130 |
+
- Automatic submission after game completion (opt-in)
|
| 131 |
+
- Challenge scores also contribute to daily/weekly leaderboards
|
| 132 |
+
- Source tracking via `source_challenge_id` field
|
| 133 |
+
- Unified JSON format with `entry_type` field (daily/weekly/challenge)
|
| 134 |
+
|
| 135 |
+
**Discovery:** Folder-based (no index.json)
|
| 136 |
+
- Scans period folders for date/week IDs
|
| 137 |
+
- Filters by file_id prefix for matching settings
|
| 138 |
+
- Loads and verifies full settings match
|
| 139 |
|
| 140 |
### PWA Support
|
| 141 |
- β
**PWA Installation:** App is installable as a Progressive Web App on desktop and mobile
|
|
|
|
| 226 |
HF_REPO_ID/
|
| 227 |
βββ shortener.json # Short URL mappings (sid -> full URL)
|
| 228 |
βββ games/
|
| 229 |
+
βββ leaderboards/
|
| 230 |
+
β βββ daily/
|
| 231 |
+
β β βββ {YYYY-MM-DD}/ # Daily period folders
|
| 232 |
+
β β βββ {file_id}/ # Settings-specific leaderboard
|
| 233 |
+
β β βββ settings.json # entry_type: "daily"
|
| 234 |
+
β βββ weekly/
|
| 235 |
+
β βββ {YYYY-Www}/ # Weekly period folders (ISO week)
|
| 236 |
+
β βββ {file_id}/ # Settings-specific leaderboard
|
| 237 |
+
β βββ settings.json # entry_type: "weekly"
|
| 238 |
+
βββ {challenge_id}/
|
| 239 |
+
βββ settings.json # Challenge data (entry_type: "challenge")
|
| 240 |
```
|
| 241 |
|
| 242 |
**Data Privacy:**
|
|
|
|
| 253 |
|
| 254 |
## Development Status
|
| 255 |
|
| 256 |
+
**Current Version:** 0.2.0 (Production Ready - Leaderboards Implemented)
|
| 257 |
|
| 258 |
### Completed β
|
| 259 |
+
- **v0.2.0:** Daily and Weekly Leaderboards
|
| 260 |
+
- Settings-based leaderboard separation
|
| 261 |
+
- Folder-based discovery (no index.json)
|
| 262 |
+
- Top 20 displayed entries per leaderboard
|
| 263 |
+
- Four-tab leaderboard page (Today, Daily, Weekly, History)
|
| 264 |
+
- Automatic score qualification and submission
|
| 265 |
+
- Integration with challenge mode
|
| 266 |
+
- Query parameter filtering for direct links
|
| 267 |
+
|
| 268 |
- **v0.1.1:** Enhanced AI word generation
|
| 269 |
- Intelligent word saving with duplicate prevention
|
| 270 |
- Automatic retry mechanism (up to 3 attempts)
|
| 271 |
- 1000-word file size limit
|
| 272 |
- Improved HF Space API integration
|
| 273 |
- Enhanced logging and error handling
|
| 274 |
+
|
| 275 |
- **v0.1.0:** AI word generation foundation
|
| 276 |
- Topic-based word list creation
|
| 277 |
- Dual generation modes (HF Space + local)
|
| 278 |
- Utility modules integration
|
| 279 |
+
|
| 280 |
- **v0.0.2:** All 7 sprints complete
|
| 281 |
- β
100% test coverage (25/25 tests)
|
| 282 |
- π Development time: ~12.75 hours (sprints 1-7)
|
| 283 |
- π Complete documentation
|
| 284 |
|
| 285 |
### Future Roadmap
|
| 286 |
+
- **v0.3.0:** Local persistent storage, high score tracking, player statistics, leaderboard caching
|
| 287 |
- **v1.0.0:** Enhanced UX, multiple difficulty levels, daily puzzle mode
|
| 288 |
|
| 289 |
## Copyright
|