Surn commited on
Commit
d786c85
Β·
1 Parent(s): 07fc9c2

0.2.1 Documentation Update

Browse files
Files changed (5) hide show
  1. CLAUDE.md +205 -15
  2. README.md +88 -28
  3. specs/leaderboard_spec.md +172 -51
  4. specs/requirements.md +104 -31
  5. 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.1.1
11
  **Repository:** https://github.com/Oncorporation/Wrdler.git
12
  **Live Demo:** [DEPLOYMENT_URL_HERE]
13
 
14
  ## Recent Changes
15
 
16
- **v0.1.1 (Current):**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- - **Fantastic:** 42+ points
66
- - **Great:** 38-41 points
67
- - **Good:** 34-37 points
68
- - **Keep practicing:** < 34 points
 
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.1.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
- β”‚ └── test_sprint6_integration.py # Comprehensive integration tests
 
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.1.1 (Complete)
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: Good (34–37), Great (38–41), Fantastic (42+)
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
- - **Daily Leaderboards:** Top 20 scores for each day (UTC midnight reset)
85
- - **Weekly Leaderboards:** Top 20 scores for each ISO week (resets Monday UTC)
86
- - **Settings-Based:** Each unique combination of game-affecting settings (game mode, wordlist, free letters, etc.) has its own leaderboard. You compete only with players using the same settings.
87
- - **Qualification:** Only the top 20 scores (sorted by score, then time, then difficulty) are displayed for each leaderboard. All submissions are stored, but only the best are shown.
88
- - **Automatic Submission:** After each game, you can submit your score to the leaderboards from the game over popup. Challenge submissions also submit to leaderboards.
89
- - **Leaderboard Page:** Access the Leaderboards from the footer navigation to view daily, weekly, and historical results, filtered by your current settings.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- - `words/wordlist.txt` – candidate words
190
- - `specs/` – documentation (`specs.md`, `requirements.md`)
 
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.1.1 (Current)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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.20-0.2.27: Challenge Mode 🎯
380
-
381
- ### Remote Challenge Sharing πŸ”—
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  - Share challenges with friends via short URLs (`?game_id=<sid>`)
383
- - Each player gets different random words from the same wordlist
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.3.1
4
- **Target Project Version:** 0.2.0
5
- **Author:** GitHub Copilot
6
- **Date:** 2025-01-27
7
- **Status:** Draft
8
 
9
  ---
10
 
@@ -28,16 +28,18 @@
28
 
29
  ## 1. Executive Summary
30
 
31
- This specification describes the implementation of a **Daily and Weekly Leaderboard System** for Wrdler. The system will:
32
 
33
- - Track top 20 scores for daily leaderboards (reset at UTC midnight)
34
- - Track top 20 scores for weekly leaderboards (reset at UTC Monday 00:00)
35
- - **Create separate leaderboards for each unique combination of game-affecting settings**
36
- - Automatically add qualifying scores from any game completion (including challenge mode)
37
- - Provide a dedicated leaderboard page with historical lookup capabilities
38
- - Store leaderboard data in HuggingFace repository using existing storage infrastructure
39
- - **Use folder-based discovery (no index.json) with descriptive folder names**
40
- - **Use a unified JSON format consistent with existing challenge settings.json files**
 
 
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 | Effort |
352
  |------|------|-------|--------|
353
- | 1.1 | Create `wrdler/leaderboard.py` with `GameSettings` and data models | NEW | 2h |
354
- | 1.2 | Implement folder listing in storage.py | storage.py | 1h |
355
- | 1.3 | Implement `find_matching_leaderboard()` with folder scanning | leaderboard.py | 1.5h |
356
- | 1.4 | Implement `check_qualification()` and sorting | leaderboard.py | 1h |
357
- | 1.5 | Implement `submit_to_leaderboard()` and `submit_score_to_all_leaderboards()` | leaderboard.py | 1h |
358
- | 1.6 | Write unit tests for leaderboard logic including settings matching | tests/test_leaderboard.py | 2h |
359
 
360
- ### Phase 2: UI Integration (v0.2.0-beta)
361
 
362
- | Step | Task | Files | Effort |
363
  |------|------|-------|--------|
364
- | 2.1 | Create `wrdler/leaderboard_page.py` with settings filtering | NEW | 3h |
365
- | 2.2 | Add leaderboard navigation to `ui.py` sidebar | ui.py | 1h |
366
- | 2.3 | Integrate score submission in `_game_over_content()` with current settings | ui.py | 2h |
367
- | 2.4 | Add leaderboard results display in game over dialog | ui.py | 1h |
368
- | 2.5 | Style leaderboard tables to match ocean theme | leaderboard_page.py | 1h |
369
 
370
- ### Phase 3: Challenge Format Migration (v0.2.0-beta)
371
 
372
- | Step | Task | Files | Effort |
373
  |------|------|-------|--------|
374
- | 3.1 | Add `entry_type` field to existing challenge saves | game_storage.py | 1h |
375
- | 3.2 | Update challenge loading to handle `entry_type` | game_storage.py | 0.5h |
376
- | 3.3 | Test backward compatibility with old challenges | Manual | 1h |
377
 
378
- ### Phase 4: Testing & Polish (v0.2.0-rc)
379
 
380
- | Step | Task | Files | Effort |
381
  |------|------|-------|--------|
382
- | 4.1 | Integration testing with HuggingFace | Manual | 2h |
383
- | 4.2 | Add caching for leaderboard data | leaderboard.py | 1h |
384
- | 4.3 | Add error handling and retry logic | leaderboard.py | 1h |
385
- | 4.4 | Update documentation | README.md, specs/ | 1h |
386
- | 4.5 | Version bump and release notes | pyproject.toml, __init__.py | 0.5h |
387
 
388
  ---
389
 
@@ -648,9 +650,128 @@ class TestDateIds:
648
 
649
  ---
650
 
651
- ## 13. Operational Considerations
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
652
 
653
- ### 13.1 Concurrency and Consistency
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
- ### 13.2 Caching and Discovery Performance
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
- ### 13.3 Error Handling and Observability
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
- ### 13.4 Security and Abuse Controls
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
- ### 13.5 Data Lifecycle and Retention
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
- ### 13.6 Time and Period Boundaries
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
- ### 13.7 UI Reliability and UX
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
- ### 13.8 Ranking and Tie-Breaks (Operational Clarification)
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
- ### 13.9 Commit and Retry Strategy (HF)
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.1.1
3
- **Status:** Production Ready - AI Enhanced
4
- **Last Updated:** 2025-01-31
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.1.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
- - **Daily and Weekly Leaderboards:**
190
- - Top 20 scores for each day (UTC midnight reset) and week (ISO week, resets Monday UTC)
191
- - Each unique combination of game-affecting settings (game mode, wordlist, free letters, etc.) has its own leaderboard
192
- - Scores are sorted by: score (descending), time (ascending), difficulty (descending)
193
- - Only the top 20 scores are displayed per leaderboard, but all submissions are stored
194
- - After each game, players can submit their score to the leaderboards from the game over popup
195
- - Challenge submissions also submit to daily/weekly leaderboards
196
- - Leaderboard navigation is available in the sidebar ("πŸ† Leaderboards")
197
- - Leaderboard page allows browsing daily, weekly, and historical leaderboards, filtered by current settings
198
-
199
- - **Challenge Mode (Updated):**
200
- - Submitting a result to a challenge also submits to the appropriate daily/weekly leaderboards
201
- - Challenge leaderboards remain for each challenge, but global leaderboards are now settings-based
202
-
203
- - **Data Privacy:**
204
- - Only player name (optional), score, and game settings are stored in the leaderboard
205
- - All leaderboard data is stored in the Hugging Face repository
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
 
207
- - **UI Integration:**
208
- - Game over popup displays leaderboard submission status and rank if qualified
209
- - Sidebar navigation for leaderboard page
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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-01-31
260
- **Version:** 0.1.1
261
- **Status:** Production Ready - AI Enhanced πŸš€
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.1.1
3
- **Status:** Production Ready - AI Enhanced
4
- **Last Updated:** 2025-01-31
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
- - Good: 34-37
47
- - Great: 38-41
48
- - Fantastic: 42+
 
 
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 now features a daily and weekly leaderboard system:
88
- - **Daily Leaderboards:** Top 20 scores for each day (UTC midnight reset)
89
- - **Weekly Leaderboards:** Top 20 scores for each ISO week (resets Monday UTC)
90
- - **Settings-Based:** Each unique combination of game-affecting settings (game mode, wordlist, free letters, etc.) has its own leaderboard. You compete only with players using the same settings.
91
- - **Qualification:** Only the top 20 scores (sorted by score, then time, then difficulty) are displayed for each leaderboard. All submissions are stored, but only the best are shown.
92
- - **Automatic Submission:** After each game, you can submit your score to the leaderboards from the game over popup. Challenge submissions also submit to leaderboards.
93
- - **Leaderboard Page:** Access the Leaderboards from the sidebar to view daily, weekly, and historical results, filtered by your current settings.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- └── {uid}/
185
- └── settings.json # Challenge data with users array
 
 
 
 
 
 
 
 
 
186
  ```
187
 
188
  **Data Privacy:**
@@ -199,28 +253,37 @@ HF_REPO_ID/
199
 
200
  ## Development Status
201
 
202
- **Current Version:** 0.1.1 (Production Ready - AI Enhanced)
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