|
|
--- |
|
|
title: Wrdler |
|
|
emoji: 🧩 |
|
|
colorFrom: blue |
|
|
colorTo: indigo |
|
|
sdk: streamlit |
|
|
sdk_version: 1.51.0 |
|
|
python_version: 3.12.8 |
|
|
app_port: 8501 |
|
|
app_file: app.py |
|
|
tags: |
|
|
- game |
|
|
- vocabulary |
|
|
- streamlit |
|
|
- education |
|
|
- ai |
|
|
short_description: Fast paced word guessing game with AI-generated word lists |
|
|
thumbnail: >- |
|
|
https://cdn-uploads.huggingface.co/production/uploads/6346595c9e5f0fe83fc60444/6rWS4AIaozoNMCbx9F5Rv.png |
|
|
--- |
|
|
|
|
|
# Wrdler |
|
|
|
|
|
> **Wrdler is a Python/Streamlit vocabulary puzzle game based on BattleWords, adapted for a simpler 8x6 grid, horizontal words only, and free letter guesses at the start.** |
|
|
|
|
|
Wrdler is a vocabulary learning game with a simplified grid and strategic letter guessing. The objective is to discover hidden words on a grid by making smart guesses before all letters are revealed. |
|
|
|
|
|
**Current Version:** v0.2.4 |
|
|
|
|
|
## Key Differences from BattleWords |
|
|
|
|
|
- **8x6 grid** (instead of 12x12) with **6 words total** (one per row) |
|
|
- **Horizontal words only** (no vertical placement) |
|
|
- **No scope/radar visualization** |
|
|
- **2 free letter guesses** at the start - choose letters to reveal all instances in the grid |
|
|
|
|
|
## Features |
|
|
|
|
|
### Core Gameplay |
|
|
- 8x6 grid with six hidden words (one per row, all horizontal) |
|
|
- **Word composition:** Each puzzle contains exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words |
|
|
- Game starts with 2 free letter guesses; all instances of chosen letters are revealed |
|
|
- Reveal grid cells and guess words for points |
|
|
- Scoring tiers: **Legendary (45+)**, Fantastic (42-44), Great (39-41), Good (35-38), Keep practicing (<35) |
|
|
- Game ends when all words are guessed or all word letters are revealed |
|
|
- Incorrect guess history with tooltip and optional display (enabled by default) |
|
|
- 10 incorrect guess limit per game |
|
|
- Two game modes: Classic (chain guesses) and Too Easy (single guess per reveal) |
|
|
|
|
|
### Audio & Visuals |
|
|
- Ocean-themed gradient background with wave animations |
|
|
- Background music system (toggleable with volume control) |
|
|
- Sound effects for hits, misses, correct/incorrect guesses |
|
|
- Responsive UI built with Streamlit |
|
|
|
|
|
### AI Word Generation |
|
|
- **Topic-based word lists**: Generate custom word lists using AI for any theme |
|
|
- **Intelligent word expansion**: New AI-generated words automatically saved to local files |
|
|
- Smart detection separates existing dictionary words from new AI words |
|
|
- Only saves new words to prevent duplicates |
|
|
- Automatic retry mechanism (up to 3 attempts) for insufficient word counts |
|
|
- 1000-word file size limit prevents bloat |
|
|
- Auto-sorted by length then alphabetically |
|
|
- **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 |
|
|
- **Fallback support**: Gracefully uses dictionary words if AI generation fails |
|
|
- **Guaranteed distribution**: Ensures exactly 25 words each of lengths 4, 5, and 6 |
|
|
|
|
|
### Customization |
|
|
- Multiple word lists (classic, fourth_grade, wordlist) |
|
|
- Wordlist sidebar controls (picker + one-click sort + filter) |
|
|
- Audio volume controls (music and effects separate) |
|
|
|
|
|
### ✅ Challenge Mode |
|
|
- **Shareable challenge links** via short URLs (`?game_id=<sid>`) |
|
|
- **Multi-user leaderboards** sorted by score and time |
|
|
- **Remote storage** via Hugging Face datasets |
|
|
- **Word list difficulty calculation** and display |
|
|
- **Submit results** to existing challenges or create new ones |
|
|
- **Top 5 leaderboard** display in Challenge Mode banner |
|
|
- **"Show Challenge Share Links" toggle** (default OFF) to control URL visibility |
|
|
- Each player gets different random words from the same wordlist |
|
|
|
|
|
### 🏆 Daily & Weekly Leaderboards (v0.2.1) ✅ |
|
|
**Comprehensive Leaderboard System:** |
|
|
- **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 settings creates a separate leaderboard |
|
|
- Settings include: game_mode, wordlist_source, show_incorrect_guesses, enable_free_letters, puzzle_options |
|
|
- You compete only with players using identical settings |
|
|
- **Sorting:** Scores sorted by: score (desc) → time (asc) → difficulty (desc) |
|
|
- **Qualification:** Only top 25 scores displayed per leaderboard (more can be stored) |
|
|
- **Storage:** Folder-based discovery in HuggingFace repo (no index.json) |
|
|
- Path: `games/leaderboards/{daily|weekly}/{period}/{file_id}/settings.json` |
|
|
- File ID format: `{wordlist_source}-{game_mode}-{sequence}` (e.g., `classic-classic-0`) |
|
|
- **Time Display:** |
|
|
- Leaderboard files store UTC dates/times for each period. |
|
|
- When viewing daily leaderboards, the app displays the UTC period as a PST date range: |
|
|
- For example, a UTC file date of `2025-12-08` covers `2025-12-08 00:00:00 UTC` to `2025-12-08 23:59:59 UTC`, which is displayed as `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]` |
|
|
- Daily leaderboards display the date range in PST for easier local time understanding. |
|
|
- Weekly leaderboards use ISO week dates (e.g., `2025-W49`) and are available every Monday. |
|
|
|
|
|
**Leaderboard Page Features:** |
|
|
- **Today Tab:** Current daily and weekly leaderboards side-by-side |
|
|
- Query param filtering: `?gidd={file_id}` and `?gidw={file_id}` |
|
|
- **Daily Tab:** Last 7 days of daily leaderboards with expandable date groups |
|
|
- **Weekly Tab:** Current ISO week leaderboard with all settings combinations |
|
|
- **History Tab:** Browse past leaderboards with date/week and settings selectors |
|
|
|
|
|
**Integration:** |
|
|
- Automatic submission after game completion (opt-in via game over popup) |
|
|
- 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) |
|
|
|
|
|
**Access:** 'Leaderboard' link in the footer navigation at the bottom of the page |
|
|
|
|
|
### Deployment & Technical |
|
|
- **Dockerfile-based deployment** supported for Hugging Face Spaces and other container platforms |
|
|
- **Environment variables** for Challenge Mode (HF_API_TOKEN, HF_REPO_ID, SPACE_NAME) |
|
|
- Works offline without HF credentials (Challenge Mode features disabled gracefully) |
|
|
|
|
|
### Progressive Web App (PWA) |
|
|
- Installable on desktop and mobile from your browser |
|
|
- Includes `service worker` and `manifest.json` with basic offline caching of static assets |
|
|
- See `INSTALL_GUIDE.md` for platform-specific steps |
|
|
|
|
|
### Planned/Upcoming |
|
|
- Move all game settings from sidebar to a dedicated settings page (`?page=settings`) requiring a logged in user (OAuth) |
|
|
- Local persistent storage for personal game history (future) |
|
|
- Personal high scores sidebar (future) |
|
|
- Player statistics tracking (future) |
|
|
- Deterministic seed UI for custom puzzles (future) |
|
|
|
|
|
## Challenge Mode & Leaderboard |
|
|
|
|
|
When playing a shared challenge (via a `game_id` link), the leaderboard displays all submitted results for that challenge. The leaderboard is **sorted by highest score (descending), then by fastest time (ascending)**. This means players with the most points appear at the top, and ties are broken by the shortest completion time. |
|
|
|
|
|
## Installation |
|
|
1. Clone the repository: |
|
|
``` |
|
|
git clone https://github.com/Oncorporation/Wrdler.git |
|
|
cd wrdler |
|
|
``` |
|
|
2. (Optional) Create and activate a virtual environment: |
|
|
``` |
|
|
python -m venv venv |
|
|
source venv/bin/activate # On Windows use `venv\Scripts\activate` |
|
|
``` |
|
|
3. Install dependencies: ( add --system if not using a virutal environment) |
|
|
``` |
|
|
uv pip install -r requirements.txt --link-mode=copy |
|
|
``` |
|
|
|
|
|
|
|
|
## Running Wrdler |
|
|
|
|
|
You can run the app locally using either [uv](https://github.com/astral-sh/uv) or Streamlit directly: |
|
|
|
|
|
``` |
|
|
uv run streamlit run app.py |
|
|
``` |
|
|
|
|
|
or |
|
|
``` |
|
|
streamlit run app.py |
|
|
``` |
|
|
|
|
|
### Dockerfile Deployment (Hugging Face Spaces and more) |
|
|
|
|
|
Wrdler supports containerized deployment using a `Dockerfile`. This is the recommended method for deploying to [Hugging Face Spaces](https://huggingface.co/docs/hub/spaces-sdks-docker) or any Docker-compatible environment. |
|
|
|
|
|
To deploy on Hugging Face Spaces: |
|
|
1. Add a `Dockerfile` to your repository root (see [Spaces Dockerfile guide](https://huggingface.co/docs/hub/spaces-sdks-docker)). |
|
|
2. Push your code to your Hugging Face Space. |
|
|
3. The platform will build and run your app automatically. |
|
|
|
|
|
For local Docker runs: |
|
|
```sh |
|
|
docker build -t wrdler . |
|
|
docker run -p8501:8501 wrdler |
|
|
``` |
|
|
|
|
|
### Environment Variables (for Challenge Mode) |
|
|
|
|
|
Challenge Mode requires a `.env` file in the project root with HuggingFace Hub credentials: |
|
|
|
|
|
```bash |
|
|
# Required for Challenge Mode |
|
|
HF_API_TOKEN=hf_xxxxxxxxxxxxxxxxxxxxx # or HF_TOKEN |
|
|
HF_REPO_ID=YourUsername/YourRepo # Target HF dataset repo |
|
|
SPACE_NAME=YourUsername/Wrdler # Your HF Space name |
|
|
|
|
|
# Optional |
|
|
CRYPTO_PK= # Reserved for future signing |
|
|
MAX_DISPLAY_ENTRIES=25 # Max leaderboard entries to display (default: 25) |
|
|
``` |
|
|
|
|
|
**How to get your HF_API_TOKEN:** |
|
|
1. Go to https://huggingface.co/settings/tokens |
|
|
2. Create a new token with `write` access |
|
|
3. Add to `.env` file as `HF_API_TOKEN=hf_...` |
|
|
|
|
|
**Note:** The app works without these variables, but Challenge Mode features (sharing, leaderboards) will be disabled. |
|
|
|
|
|
## Folder Structure |
|
|
|
|
|
- `app.py` – Streamlit entry point |
|
|
- `wrdler/` – Python package |
|
|
- `models.py` – data models and types |
|
|
- `word_loader.py` – word list loading and validation |
|
|
- `word_loader_ai.py` – AI word generation with retry logic |
|
|
- `generator.py` – word placement logic (8x6, horizontal only) |
|
|
- `logic.py` – game mechanics (reveal, guess, scoring, free letters) |
|
|
- `ui.py` – Streamlit UI composition |
|
|
- `oauth.py` – HuggingFace OAuth utilities (NEW) |
|
|
- `settings_page.py` – Settings page UI (IN PROGRESS) |
|
|
- `leaderboard.py` – Daily/weekly leaderboard system (v0.2.1) |
|
|
- `leaderboard_page.py` – Leaderboard UI page (v0.2.1) |
|
|
- `game_storage.py` – Hugging Face remote storage integration and challenge sharing |
|
|
- `local_storage.py` – local JSON storage for results and high scores |
|
|
- `modules/` – shared utilities (storage with folder listing, constants, file_utils) |
|
|
- `words/` – word list files (classic.txt, fourth_grade.txt, wordlist.txt) |
|
|
- `specs/` – documentation (`specs.md`, `requirements.md`, `leaderboard_spec.md`) |
|
|
- `tests/` – unit tests |
|
|
- `static/` – PWA assets (manifest.json, service-worker.js, icons) |
|
|
|
|
|
## Test File Location |
|
|
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. |
|
|
|
|
|
## How to Play |
|
|
|
|
|
1. **Start with 2 free letter guesses** - choose two letters to reveal all their instances in the grid. |
|
|
2. Click grid squares to reveal letters or empty spaces. |
|
|
3. After revealing a letter, enter a guess for a word in the text box. |
|
|
4. Earn points for correct guesses and bonus points for unrevealed letters. |
|
|
5. **The game ends when all six words are found or all word letters are revealed. Your score tier is displayed.** |
|
|
6. **To play a shared challenge, use a link with `?game_id=<sid>`. Your result will be added to the challenge leaderboard.** |
|
|
7. **Access leaderboards anytime using the 'Leaderboard' link in the footer navigation.** |
|
|
|
|
|
## Changelog |
|
|
|
|
|
### v0.2.4 (Current) ✅ |
|
|
**Word List Filtering** |
|
|
- ✅ Added "Filter Wordlist" button to sidebar |
|
|
- ✅ Filters words against `assets/filter.txt` blocklist |
|
|
- ✅ Displays dialog with count and list of removed words |
|
|
|
|
|
### v0.2.1 |
|
|
**Daily and Weekly Leaderboards Improved** |
|
|
- ✅ Settings-based leaderboard separation (unique leaderboards per settings combo) |
|
|
- ✅ Folder-based discovery system (no index.json) |
|
|
- ✅ Top 25 displayed entries per leaderboard |
|
|
- ✅ Four-tab leaderboard page (Today, Daily, Weekly, History) |
|
|
- ✅ Automatic score qualification and submission |
|
|
- ✅ Query parameter filtering for direct links (`?gidd=`, `?gidw=`) |
|
|
- ✅ Integration with challenge mode (source_challenge_id tracking) |
|
|
- ✅ Unified JSON format with entry_type field (daily/weekly/challenge) |
|
|
- ✅ Period-based organization: daily (YYYY-MM-DD), weekly (YYYY-Www) |
|
|
- ✅ Enhanced storage.py with folder listing capabilities |
|
|
- ✅ Updated scoring tiers with "Legendary" (45+) |
|
|
- ✅ Settings page planned (move from sidebar, OAuth login required) |
|
|
|
|
|
### v0.1.1 |
|
|
- ✅ Enhanced AI word generation with intelligent word saving |
|
|
- ✅ Automatic retry mechanism for insufficient word counts (up to 3 retries) |
|
|
- ✅ 1000-word file size limit to prevent dictionary bloat |
|
|
- ✅ Improved new word detection (separates existing vs. new words before saving) |
|
|
- ✅ Better HF Space API integration with graceful fallback to local models |
|
|
- ✅ Additional word generation when initial pass doesn't meet MIN_REQUIRED threshold |
|
|
- ✅ Enhanced logging for word generation pipeline visibility |
|
|
|
|
|
### v0.1.0 |
|
|
- ✅ AI word generation functionality added |
|
|
- ✅ Topic-based custom word list creation |
|
|
- ✅ Dual generation modes (HF Space API + local transformers) |
|
|
- ✅ Utility modules integration (storage, file_utils, constants) |
|
|
- ✅ Documentation synchronized across all files |
|
|
|
|
|
### v0.0.8 |
|
|
- remove background animation |
|
|
- add "easy" mode (single guess per reveal) |
|
|
|
|
|
### v0.0.7 |
|
|
- fix guess bug - allowing guesses only after word guessed or letter revealed |
|
|
|
|
|
### v0.0.2 (All Sprints Complete) 🎉 |
|
|
- **Sprint 1-3:** Core data models, generator refactor, radar removal |
|
|
- **Sprint 4:** Implemented free letter selection UI with circular green gradient buttons |
|
|
- **Sprint 5:** Updated grid UI rendering for 8×6 display |
|
|
- **Sprint 6:** Comprehensive integration testing (7/7 tests passing) |
|
|
- **Sprint 7:** Complete documentation update |
|
|
- Sound effects integration for free letter selection |
|
|
- Mobile-responsive free letter grid |
|
|
- Fixed duplicate rendering call bug |
|
|
- **All core Wrdler features complete and tested** |
|
|
|
|
|
### v0.0.1 (Initial Wrdler Release) |
|
|
- Project renamed from BattleWords to Wrdler |
|
|
- Grid resized from 12x12 to 8x6 |
|
|
- Changed to one word per row (6 total), horizontal only |
|
|
- Removed vertical word placement |
|
|
- Removed scope/radar visualization |
|
|
- Core data models updated for rectangular grid |
|
|
- Generator refactored for horizontal-only placement |
|
|
|
|
|
Note |
|
|
- `battlewords/storage.py` remains local-only storage; a separate HF integration wrapper is provided as `game_storage.py` for remote challenge mode. |
|
|
|
|
|
## Known Issues / TODO |
|
|
|
|
|
- Word list loading bug: the app may not select the proper word lists in some environments. Investigate `word_loader.get_wordlist_files()` / `load_word_list()` and sidebar selection persistence to ensure the chosen file is correctly used by the generator. |
|
|
|
|
|
## Development Phases |
|
|
|
|
|
- **Proof of Concept (0.1.0):** No overlaps, basic UI, single session. |
|
|
- **Beta (0.5.0):** Overlaps allowed on shared letters, responsive layout, keyboard support, deterministic seed. |
|
|
- **Full (1.0.0):** Enhanced UX, persistence, leaderboards, daily/practice modes, advanced features. |
|
|
|
|
|
See `specs/requirements.md` and `specs/specs.md` for full details and roadmap. |
|
|
|
|
|
## License |
|
|
|
|
|
Wrdler is based on BattleWords. BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner. |
|
|
|
|
|
## Hugging Face Spaces Configuration |
|
|
|
|
|
Wrdler is deployable as a Hugging Face Space. You can use either the YAML config block or a Dockerfile for advanced/custom deployments. |
|
|
|
|
|
To configure your Space with the YAML block, add it at the top of your `README.md`: |
|
|
|
|
|
```yaml |
|
|
--- |
|
|
title: Wrdler |
|
|
emoji: 🎲 |
|
|
colorFrom: blue |
|
|
colorTo: indigo |
|
|
sdk: streamlit |
|
|
sdk_version: 1.51.0 |
|
|
python_version: 3.12.8 |
|
|
app_file: app.py |
|
|
tags: |
|
|
- game |
|
|
- vocabulary |
|
|
- streamlit |
|
|
- education |
|
|
--- |
|
|
``` |
|
|
|
|
|
**Key parameters:** |
|
|
- `title`, `emoji`, `colorFrom`, `colorTo`: Visuals for your Space. |
|
|
- `sdk`: Use `streamlit` for Streamlit apps. |
|
|
- `sdk_version`: Latest supported Streamlit version. |
|
|
- `python_version`: Python version (default is3.10). |
|
|
- `app_file`: Entry point for your app. |
|
|
- `tags`: List of descriptive tags. |
|
|
|
|
|
**Dependencies:** |
|
|
Add a `requirements.txt` with your Python dependencies (e.g., `streamlit`, etc.). |
|
|
|
|
|
**Port:** |
|
|
Streamlit Spaces use port `8501` by default. |
|
|
|
|
|
**Embedding:** |
|
|
Spaces can be embedded in other sites using an `<iframe>`: |
|
|
|
|
|
```html |
|
|
<iframe src="https://[YourUsername]-Wrdler.hf.space?embed=true" title="Wrdler"></iframe> |
|
|
``` |
|
|
|
|
|
For full configuration options, see [Spaces Config Reference](https://huggingface.co/docs/hub/spaces-config-reference) and [Streamlit SDK Guide](https://huggingface.co/docs/hub/spaces-sdks-streamlit). |
|
|
|
|
|
# Assets Setup |
|
|
|
|
|
To fully experience Wrdler, especially the audio elements, ensure you set up the following assets: |
|
|
|
|
|
- Place your background music `.mp3` files in `wrdler/assets/audio/music/` to enable music. |
|
|
- Place your sound effect files (`.mp3` or `.wav`) in `wrdler/assets/audio/effects/` for sound effects. |
|
|
|
|
|
Refer to the documentation for guidance on compatible audio formats and common troubleshooting tips. |
|
|
|
|
|
# Sound Asset Generation |
|
|
|
|
|
To generate and save custom sound effects for Wrdler, you can use the `generate_sound_effect` function. |
|
|
|
|
|
## Function: `generate_sound_effect` |
|
|
|
|
|
```python |
|
|
def generate_sound_effect(effect: str, save_to_assets: bool = False, use_api: str = "huggingface") -> str: |
|
|
""" |
|
|
Generate a sound effect and save it as a file. |
|
|
|
|
|
Parameters: |
|
|
- `effect`: Name of the effect to generate. |
|
|
- `save_to_assets`: If `True`, saves the effect to the assets directory; |
|
|
if `False`, saves to a temporary location. Default is `False`. |
|
|
- `use_api`: API to use for generation. Options are "huggingface" or "replicate". Default is "huggingface". |
|
|
|
|
|
Returns: |
|
|
- File path to the saved sound effect. |
|
|
``` |
|
|
|
|
|
## Parameters |
|
|
|
|
|
- `effect`: The name of the sound effect you want to generate (e.g., "explosion", "powerup"). |
|
|
- `save_to_assets` (optional): Set to `True` to save the generated sound effect to the game's assets directory. If `False`, the effect is saved to a temporary location. Default is `False`. |
|
|
- `use_api` (optional): The API to use for generating the sound. Options are `"huggingface"` or `"replicate"`. Default is `"huggingface"`. |
|
|
|
|
|
## Returns |
|
|
|
|
|
- The function returns the file path to the saved sound effect, whether it's in the assets directory or a temporary location. |
|
|
|
|
|
## Usage Example |
|
|
|
|
|
To generate a sound effect and save it to the assets directory: |
|
|
|
|
|
```python |
|
|
generate_sound_effect("your_effect_name", save_to_assets=True) |
|
|
``` |
|
|
|
|
|
To generate a sound effect and keep it in a temporary location: |
|
|
|
|
|
```python |
|
|
temp_path = generate_sound_effect("your_effect_name", save_to_assets=False) |
|
|
``` |
|
|
|
|
|
## Note |
|
|
|
|
|
Ensure you have the necessary permissions and API access (if required) to use the sound generation service. Generated sounds are subject to the terms of use of the respective API. |
|
|
|
|
|
For any issues or enhancements, please refer to the project documentation or contact the project maintainer. |
|
|
|
|
|
Happy gaming and sound designing! |