File size: 8,570 Bytes
a16932a
 
09427c9
a16932a
09427c9
f0df64e
4f625d4
 
a6975b2
4f625d4
6829252
 
4f625d4
a6975b2
4f625d4
 
 
 
 
 
 
 
 
 
5f8a848
4f625d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d786c85
 
 
 
 
4f625d4
 
6829252
 
 
 
 
 
 
 
 
 
09427c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
950b0bb
 
09427c9
950b0bb
 
 
 
 
09427c9
 
 
6829252
 
09427c9
 
 
 
 
 
6829252
583f150
d786c85
 
 
09427c9
 
d786c85
 
 
 
 
 
 
082223e
d786c85
 
 
 
 
 
f0df64e
d786c85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38961b4
b7b95df
 
 
 
 
 
 
 
 
 
 
6829252
09427c9
4f625d4
 
 
 
 
09427c9
f0df64e
 
 
 
09427c9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# Wrdler Specifications

**Version:** 0.2.9

**Status:** Production Ready - Leaderboards & Enhanced Settings Page Implemented
**Last Updated:** 2025-12-09

## Overview
Wrdler is a Python/Streamlit 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.

**Current Status:** All 7 sprints complete, 100% tested, fully documented

## Key Differences from BattleWords
- **Python project** (Streamlit, Python 3.12.8)
- **8x6 grid** (instead of 12x12)
- **One word per row** (instead of 6 words placed anywhere)
- **Horizontal words only** (no vertical placement)
- **No scope/radar visualization**
- **2 free letter guesses at game start** (all instances of chosen letters are revealed)

## Game Board
- 8 x 6 grid
- Six hidden words:
  - One word per row (row 0-5)
  - **Word composition:** Exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words
  - All placed horizontally (left-right)
  - No vertical placement
  - No diagonal placement
  - Words do not overlap
- Entry point is `app.py`
- **Supports Dockerfile-based deployment for Hugging Face Spaces and other container platforms**

## Gameplay (Core)
- Players start by choosing 2 letters; all instances of those letters are revealed in the grid
- Players click grid squares to reveal letters or empty spaces
- Empty revealed squares are styled with CSS class `empty`
- After any reveal, the app immediately reruns (`st.rerun`) to show the change
- After revealing a letter, players may guess a word by entering it in a text box
- Guess submission triggers an immediate rerun to reflect results
- Only one guess per letter reveal; must uncover another letter before guessing again
- In the default mode, a correct guess allows chaining an additional guess without another reveal
- **The game ends when all six words are guessed or all word letters are revealed**

## Scoring
- Each correct word guess awards points:
  - 1 point per letter in the word
  - Bonus points for each hidden letter at the time of guessing
- Score tiers:
  - **Legendary:** 45+ points
  - **Fantastic:** 42-44 points
  - **Great:** 39-41 points
  - **Good:** 35-38 points
  - **Keep practicing:** <35 points
- **Game over is triggered by either all words being guessed or all word letters being revealed**

## Core Rules (v0.0.2 - Implemented)
- βœ… 8x6 grid with one word per row
- βœ… Horizontal words only; no vertical placement
- βœ… No overlaps: words do not overlap or share letters
- βœ… No radar/scope visualization (removed in Sprint 3)
- βœ… 2 free letter guesses at game start (implemented in Sprint 4)
- βœ… Incorrect guess history with optional display
- βœ… 10 incorrect guess limit per game
- βœ… Two game modes: Classic (chain guesses) and Too Easy (single guess per reveal)

## Implemented Features (v0.2.9)

### Settings Management (v0.2.9)
- Enhanced settings management: create, update, rename, and delete settings files
- Split "Save Settings" into "Create Settings" and "Update Settings" actions
- Improved settings loading and user feedback
- Default sound effects enabled in settings
- New default configuration: `classic-classic-full_sound_free_letters.json`
- Deprecated configuration removed: `classic-classic-2.json`
- Footer navigation updated to prevent reloading active pages

### Word List Management
- **Filter Wordlist:** Remove words found in `assets/filter.txt` from the selected word list
- **Sort Wordlist:** Sort words by length and alphabetically
- **Feedback:** Dialog showing count and list of removed words

### AI Word Generation
- **Topic-Based Generation:** Create custom word lists for any theme using AI
- **Dual Generation Modes:**
  - HF Space API (primary): Uses Hugging Face Space when `USE_HF_WORDS=true`
  - Local transformers (fallback): Falls back to local models if HF unavailable
- **Intelligent Word Management:**
  - Smart detection separates existing dictionary words from new AI-generated words
  - Only saves new words to prevent duplicates in word files
  - Automatic retry mechanism (up to 3 attempts) if insufficient words generated
  - 1000-word file size limit prevents dictionary bloat
  - Auto-sorted by length then alphabetically
- **Guaranteed Distribution:** Ensures exactly 25 words each of lengths 4, 5, and 6
- **Graceful Fallback:** Uses dictionary words if AI generation fails
- **Enhanced Logging:** Detailed pipeline visibility for debugging

### Challenge Mode
- **Game ID Sharing:** Each puzzle generates a shareable link with `?game_id=<sid>` to challenge others with the same word list
- **Remote Storage:** Game results and leaderboards stored in Hugging Face dataset repos
- **Leaderboards:** Multi-user leaderboards sorted by score (descending) then time (ascending)
- **Word List Difficulty:** Calculated and displayed for each challenge
- **Top 5 Display:** Leaderboard banner shows top 5 players
- **Optional Sharing:** "Show Challenge Share Links" toggle (default OFF) controls URL visibility

### Leaderboard System (v0.2.1) βœ… IMPLEMENTED
Wrdler features a comprehensive daily and weekly leaderboard system:

**Core Features:**
- **Daily Leaderboards:** Top 25 scores for each day (resets UTC midnight)
- **Weekly Leaderboards:** Top 25 scores for each ISO week (resets Monday UTC 00:00)
- **Settings-Based Separation:** Each unique combination of game-affecting settings creates a separate leaderboard:
  - `game_mode` (classic, easy, too easy)
  - `wordlist_source` (classic.txt, fourth_grade.txt, etc.)
  - `show_incorrect_guesses` (boolean)
  - `enable_free_letters` (boolean)
  - `puzzle_options` (spacer, may_overlap)
- **Sorting:** Scores sorted by: score (desc) β†’ time (asc) β†’ difficulty (desc)
- **Qualification:** Only top 25 (configurable) scores displayed per leaderboard (more can be stored)

**Storage Structure:**
```
HF_REPO_ID/games/
β”œβ”€β”€ leaderboards/
β”‚   β”œβ”€β”€ daily/{YYYY-MM-DD}/{file_id}/settings.json
β”‚   └── weekly/{YYYY-Wwww}/{file_id}/settings.json
└── {challenge_id}/settings.json
```

**File ID Format:** `{wordlist_source}-{game_mode}-{sequence}`
- Example: `classic-classic-0`, `easy-too_easy-1`
- Sanitized (no .txt, lowercase, underscores for spaces)

**Leaderboard Page UI:**
- **Today Tab:** Current daily and weekly leaderboards
  - Query params: `?gidd={file_id}` and `?gidw={file_id}` for filtering
  - Side-by-side display in two columns
- **Daily Tab:** Last 7 days of daily leaderboards
  - Expandable groups per date
  - All settings combinations shown
- **Weekly Tab:** Current ISO week leaderboard
  - All settings combinations displayed
- **History Tab:** Historical leaderboard browser
  - Dropdown selectors for period and settings
  - Separate daily and weekly columns

**Integration:**
- Automatic submission after game completion (opt-in)
- Challenge scores also contribute to daily/weekly leaderboards
- Source tracking via `source_challenge_id` field
- Unified JSON format with `entry_type` field (daily/weekly/challenge)

**Discovery:** Folder-based (no index.json)
- Scans period folders for date/week IDs
- Filters by file_id prefix for matching settings
- Loads and verifies full settings match

**Date Display Updates:**
- All leaderboard files use UTC for period boundaries.
- When displaying daily leaderboards, show the UTC period as a PST date range.
- Example: For UTC file date 2025-12-08, display:
  2025-12-08 00:00:00 UTC to 2025-12-08 23:59:59 UTC
  and
  2025-12-07 16:00:00 PST to 2025-12-08 15:59:59 PST
  The leaderboard expander label should show: `Mon, Dec 08, 2025 4:00 PM PST – Tue, Dec 09, 2025 3:59:59 PM PST [settings badge]`

**Access:** 'Leaderboard' link in the footer navigation at the bottom of the page

### PWA Support
- **PWA Installation:** App is installable as a Progressive Web App on desktop and mobile
  - Added `service worker` and `manifest.json`
  - Basic offline caching of static assets
  - INSTALL_GUIDE.md added with platform-specific install steps
  - No gameplay logic changes

### Settings Page (v0.2.8+)
 - All game settings moved from sidebar to a dedicated settings page (`?page=settings`)
 - Accessible via the footer navigation (`βš™οΈ Settings` link)
 - Controls game mode, word list selection, grid options (spacer, grid ticks), and audio (music and sound effects)
 - Settings are persisted to JSON files in `wrdler/settings/` and the latest settings are loaded on app startup
 - Enhanced management: create, update, rename, delete settings files