wrdler / specs /requirements.md
Surn's picture
Add Gradio UI and AI Topic Generation Features
0860b52

A newer version of the Gradio SDK is available: 6.1.0

Upgrade

# Wrdler: Implementation Requirements Version: 0.1.1 Status: Production Ready - AI Enhanced Last Updated: 2025-01-31

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.

Current Status: ✅ All Phase 1 requirements complete, 100% tested (25/25 tests passing), AI word generation enhanced in v0.1.1

Key Differences from BattleWords

  • 8x6 grid instead of 12x12
  • One word per row (6 total) instead of flexible placement
  • Horizontal words only (no vertical)
  • No radar/scope visualization
  • 2 free letter guesses at game start

Implementation Details (v0.1.1)

  • Tech Stack: Python 3.12.8, Streamlit 1.51.0, Gradio 5.50, numpy, matplotlib, transformers, gradio_client
  • Architecture: Single-player, local state in Streamlit session state or Gradio gr.State
  • Grid: 8 columns × 6 rows (48 cells) with exactly six words
  • Word Placement: Horizontal-only, one word per row, no overlaps
  • AI Generation: Topic-based word lists with intelligent saving and retry logic
  • Entry Points:
    • Streamlit: app.py
    • Gradio: wrdler/gradio_ui.py or python -m wrdler.gradio_ui
  • Testing: pytest with 25/25 tests passing (100%)
  • Development Time: ~12.75 hours across 7 sprints (Phase 1) + AI enhancements
  • Gradio Implementation: Modern API compatible with Gradio 5.50+
    • Reference: Gradio 6 Migration Guide
    • Uses gr.State for game persistence
    • Event handlers with modern .click(), .change(), .submit() methods
    • Custom CSS styling via external file

Streamlit Components (Implemented in v0.0.2)

  • State & caching ✅

    • st.session_state for puzzle, grid_rows, grid_cols, revealed, guessed, score, last_action, can_guess
    • st.session_state.points_by_word for per-word score breakdown
    • st.session_state.letter_map derived from puzzle
    • st.session_state.selected_wordlist for sidebar picker
    • st.session_state.show_incorrect_guesses toggle
    • st.session_state.show_challenge_share_links toggle (default OFF)
    • st.session_state.free_letters and free_letters_used for free letter tracking
  • Layout & structure ✅

    • st.title, st.subheader, st.markdown for headers
    • st.columns(8) to render the 8×6 grid (6 rows)
    • st.sidebar for secondary controls
    • st.expander for high scores and stats
  • Widgets (interaction) ✅

    • st.button for each grid cell (48 total) with unique key
    • Circular green gradient free letter choice buttons (2 at game start)
    • st.form + st.text_input + st.form_submit_button("OK") for word guessing
    • st.button("New Game") to reset state
    • Sidebar selectbox for wordlist selection (classic, fourth_grade, wordlist)
  • Visualization ✅

    • Ocean-themed gradient background
    • No animated radar (removed in Sprint 3)
    • Responsive 8×6 grid layout
    • Cell state indicators (unrevealed, letter, empty, completed)
  • Control flow ✅

    • App reruns on interaction using st.rerun()
    • Game over dialog with final score and tier display

Gradio Components (Implemented in v0.1.1)

  • State management ✅

    • gr.State(value=create_new_game_state) for game persistence
    • State updates use copy.deepcopy() to trigger reactivity
    • Serializable state dict (no complex objects in state)
  • Layout & structure ✅

    • gr.Blocks() with custom theme (theme="Surn/beeuty")
    • gr.Tabs() for Game and Settings sections
    • gr.Row() and gr.Column() for responsive layout
    • gr.Modal() for share challenge dialog
  • Widgets (interaction) ✅

    • 48 gr.Button components for grid cells with dynamic updates
    • 26 gr.Button components for letter selection (only puzzle letters visible)
    • gr.Textbox for word guessing with .submit() handler
    • gr.Button for actions (New Game, Guess, Share Challenge)
    • gr.Dropdown for settings (wordlist, game mode)
    • gr.Checkbox for toggles (audio, display options)
    • gr.Slider for volume controls
  • Visualization ✅

    • gr.HTML() for score panel with custom styling
    • gr.HTML() for audio player (sound effects)
    • gr.HTML() for game over display
    • Custom CSS via style_wrdler.css file
    • Responsive grid layout with CSS Grid
  • Control flow ✅

    • Event handlers return component update tuples
    • .click(), .change(), .submit() for events
    • gr.update() for conditional component updates
    • State mutations trigger UI updates
  • Reference ✅

Folder Structure (Implemented)

  • app.py – Streamlit entry point ✅
  • wrdler/ – Python package ✅
    • __init__.py (version 0.1.0)
    • models.py – data models and types (rectangular grid support)
    • word_loader.py – load/validate/cached word lists
    • generator.py – word placement (8x6, horizontal only, one per row)
    • logic.py – game mechanics (reveal, guess, scoring, tiers, free letters)
    • ui.py – Streamlit UI composition (8×6 grid rendering)
    • audio.py – background music system
    • sounds.py – sound effects management
    • game_storage.py – HF storage wrapper for Challenge Mode
    • modules/ – shared utilities (storage, constants, file_utils)
    • words/ – word list files (classic.txt, fourth_grade.txt, wordlist.txt)
  • specs/ – documentation (specs.md, requirements.md, sprint reports)
  • tests/ – unit tests (test_sprint6_integration.py with 7 comprehensive tests)
  • static/ – PWA assets (manifest.json, service-worker.js, icons)

Phase 1: Wrdler v0.0.2 (Complete) ✅

Goal: A playable 8x6 grid game with free letter guesses, horizontal-only words, and Challenge Mode support.

Status: ✅ All requirements complete, 7/7 sprints finished, 100% test pass rate

1) Data Models ✅ (Sprint 1)

  • Coord(x:int, y:int) with in_bounds_rect() for rectangular grid validation
  • Word(text:str, start:Coord, direction:str{"H"}, cells:list[Coord]) (H only)
  • Puzzle(words:list[Word], grid_rows:int, grid_cols:int, uid:str)
  • GameState(grid_rows:int, grid_cols:int, puzzle:Puzzle, revealed:set[Coord], guessed:set[str], score:int, free_letters:set[str], free_letters_used:int, ...)

Acceptance: ✅ Types implemented and fully integrated (13/13 tests passing)

2) Word List Management ✅ (Sprint 1, Enhanced in v0.1.0-0.1.1)

  • ✅ English word list filtered to alphabetic uppercase, lengths in {4,5,6}
  • ✅ Loader centralized in word_loader.py with caching
  • ✅ Three word lists: classic, fourth_grade, wordlist
  • AI word generation support via word_loader_ai.py:
    • Generates 75 words per topic (25 each of lengths 4, 5, 6)
    • Dual generation modes (v0.1.0+):
      • 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 saving (v0.1.1):
      • Smart detection separates existing dictionary words from new AI-generated words
      • Only saves new words to prevent duplicates
      • 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
    • Additional word generation: Automatically generates more words when MIN_REQUIRED threshold not met
    • Enhanced logging: Detailed pipeline visibility for debugging
  • ✅ Unified loader (load_word_list_or_ai) routes between file-based and AI-generated words
  • ✅ Saves new AI-generated words to local files for expansion

Acceptance: ✅ Loading function returns lists by length with >= 25 words per length; AI generation produces valid words with intelligent saving and retry logic

3) Puzzle Generation (8x6 Horizontal) ✅ (Sprint 2)

  • ✅ Randomly place 6 words on 8x6 grid, one per row
  • Word length requirement: Each puzzle must have exactly 2 four-letter words, 2 five-letter words, and 2 six-letter words
  • ✅ Constraints:
    • Horizontal (left→right) only
    • One word per row (no stacking)
    • No overlapping letters
  • ✅ Retry strategy with max attempts
  • ✅ Deterministic seeding support

Acceptance: ✅ Generator returns valid Puzzle with 6 words, no collisions, in-bounds (5/5 tests passing)

4) Free Letter Guesses ✅ (Sprint 4)

  • ✅ At game start, show 2 circular green gradient buttons for letter selection
  • ✅ On selection, reveal all instances of that letter in the grid
  • ✅ Mark as used; disable buttons after 2 uses
  • ✅ Sound effects play on reveal (hit/miss)
  • ✅ Set can_guess=True after revealing letters

Acceptance: ✅ Both free letters properly reveal all matching cells; buttons disabled appropriately; UI renders correctly

5) Game Mechanics ✅ (Sprint 1, 6)

  • ✅ Reveal: Click a covered cell to reveal letter or mark empty
  • ✅ Guess: After revealing, guess word (4-6 letters)
  • ✅ Scoring: Base + bonus for unrevealed cells
  • ✅ End: All words guessed or all word letters revealed
  • ✅ Incorrect guess limit: 10 per game
  • ✅ Auto-mark completed words when all letters revealed

Acceptance: ✅ Unit tests cover reveal, guess gating, scoring, tiers, auto-completion (7/7 integration tests passing)

6) UI (Streamlit) ✅ (Sprint 5)

  • ✅ Layout:
    • Title and instructions
    • Left: 8×6 grid using st.columns(8) with 6 rows
    • Right: Score panel, guess form, incorrect guess history
    • Sidebar: New Game, wordlist select, game mode, settings
  • ✅ Visuals:
    • Ocean gradient background
    • Covered vs revealed cell styles (40px buttons)
    • Completed word highlighting
    • Free letter selection UI with circular buttons

Acceptance: ✅ Users can play end-to-end; all features functional; responsive design

7) Challenge Mode ✅ (Inherited from BattleWords)

  • ✅ Parse game_id from query params
  • ✅ Load game settings from HF repo
  • ✅ Share button generates shareable URL
  • ✅ Display top 5 leaderboard in Challenge Mode banner
  • ✅ "Show Challenge Share Links" toggle (default OFF)

Acceptance: ✅ URL with game_id loads correctly; share button works; leaderboard displays properly

8) Utility Modules ✅ (Sprint 1)

  • ✅ Shared utility modules from OpenBadge project
  • modules/__init__.py exports storage, constants, file_utils
  • ✅ HuggingFace storage & URL shortener
  • ✅ File handling and utility functions

Acceptance: ✅ Modules integrated and functional for Challenge Mode storage

9) Comprehensive Tests ✅ (Sprint 6)

  • ✅ Placement validity (bounds, no overlaps, correct counts)
  • ✅ Scoring logic and bonuses
  • ✅ Free letter reveal behavior (2-letter limit)
  • ✅ Guess gating and word validation
  • ✅ Game completion detection
  • ✅ Auto-mark completed words
  • ✅ State consistency validation

Test Results: ✅ 25/25 tests passing (100%)

Sprint Completion Summary (v0.0.2)

Sprint Description Time Tests Status
Sprint 1 Core Data Models 3h 13/13 ✅ Complete
Sprint 2 Puzzle Generator 3h 5/5 ✅ Complete
Sprint 3 Remove Radar 0.5h N/A Complete
Sprint 4 Free Letters UI 2h Manual ✅ Complete
Sprint 5 Grid UI Updates 1.25h Syntax ✅ Complete
Sprint 6 Integration Testing 2h 7/7 ✅ Complete
Sprint 7 Documentation 1h N/A Complete
Total All Features 12.75h 25/25 Complete ✅

All known issues resolved. All TODO items completed.

Future Roadmap

v0.3.0 (Next Phase)

  • 📋 Local persistent storage in ~/.wrdler/data/
  • 📋 High score tracking and display
  • 📋 Player statistics
  • 📋 Enhanced UI animations

v0.4.0 (AI Expansion)

  • 📋 AI difficulty tuning based on player performance
  • 📋 Custom topic suggestions
  • 📋 Multi-language word generation
  • 📋 Word difficulty analysis and visualization

v1.0.0 (Long Term)

  • 📋 Multiple difficulty levels
  • 📋 Daily puzzle mode
  • 📋 Internationalization (i18n)
  • 📋 Performance optimizations

Deployment Targets ✅

Supported Platforms (v0.0.2)

  • Hugging Face Spaces (primary) - Dockerfile deployment
  • Docker - Containerization with provided Dockerfile
  • Local Development - Run with streamlit run app.py
  • PWA - Installable as Progressive Web App on desktop and mobile

Deployment Status

Ready for production deployment! All features tested and documented.


Last Updated: 2025-01-31 Version: 0.1.1 Status: Production Ready - AI Enhanced 🚀

AI Word Generation Pipeline (v0.1.1)

Architecture

User Input (Topic)
    ↓
Check USE_HF_WORDS flag
    ↓
┌─────────────────────────────────────┐
│ HF Space API (Primary)              │
│ - gradio_client integration         │
│ - Temperature: 0.95                 │
│ - Max tokens: 512                   │
└─────────────────────────────────────┘
    ↓ (if fails or USE_HF_WORDS=false)
┌─────────────────────────────────────┐
│ Local Transformers (Fallback)       │
│ - Auto model selection              │
│ - Device auto-detection             │
│ - Temperature: 0.7                  │
└─────────────────────────────────────┘
    ↓
Parse & Filter Words
    ↓
Identify New vs Existing
    ↓
Check MIN_REQUIRED threshold
    ↓ (if insufficient)
Generate Additional Words (up to 3 retries)
    ↓
Save New Words to File
    ↓
Validate & Sort File
    ↓
Return 75 Words for Game

Word Saving Strategy

  1. Detection Phase: Separate new AI words from existing dictionary words
  2. Validation Phase: Check if file meets MIN_REQUIRED (25 words per length)
  3. Retry Phase: If insufficient, generate additional words (up to 3 attempts)
  4. Save Phase: Write only new words to topic-based file
  5. Sort Phase: Auto-sort by length then alphabetically
  6. Limit Phase: Stop adding if file reaches 1000 words

Error Handling

  • HF Space API failure: Graceful fallback to local model
  • Model loading failure: Try multiple models in priority order
  • Device compatibility: Retry pipeline without device parameter on error 422
  • Insufficient words: Automatic retry with targeted prompts
  • File operations: Detailed logging and error recovery

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.

Gradio 5.50 Implementation Reference

Migration from Gradio 4.x to 5.x

The Gradio UI implementation follows modern Gradio 5.50+ patterns, compatible with the upcoming Gradio 6 release:

Official Reference: Gradio 6 Migration Guide

Key Gradio Patterns Used

  1. State Management

    game_state = gr.State(value=create_new_game_state)
    # Updates use deep copy to trigger reactivity
    new_state = copy.deepcopy(state)
    new_state["score"] = 42
    return new_state
    
  2. Component Updates

    # Dynamic button updates
    gr.Button(value="X", variant="primary", interactive=True)
    # Conditional visibility
    gr.update(visible=True)
    
  3. Event Handlers

    button.click(
        fn=handler_function,
        inputs=[input1, input2, state],
        outputs=[output1, output2, state]
    )
    
  4. Modal Dialogs

    with gr.Modal(visible=False, elem_id="modal-id") as modal:
        gr.Markdown("Modal content")
    
  5. Custom CSS

    with gr.Blocks(css=css_content, theme="Surn/beeuty") as demo:
        # Components
    

Component Compatibility

  • gr.Button - Modern button API with variant, size, interactive params
  • gr.Textbox - Text input with submit handler support
  • gr.HTML - Custom HTML rendering for score panels and audio
  • gr.State - Serializable state management
  • gr.Dropdown - Selection widgets for settings
  • gr.Checkbox - Boolean toggles
  • gr.Slider - Numeric value controls
  • gr.Tabs - Multi-section layout
  • gr.Modal - Dialog overlays
  • gr.Row / gr.Column - Responsive layout containers

Best Practices

  1. State must be JSON-serializable - Use dicts/lists, not complex objects
  2. Deep copy for updates - copy.deepcopy(state) triggers reactivity
  3. Return tuples matching outputs - Order matters for component updates
  4. Use elem_id for CSS targeting - Consistent IDs for custom styling
  5. Handle None/undefined gracefully - Check state initialization
  6. Batch updates efficiently - Return all component changes together

File Structure

  • wrdler/gradio_ui.py - Main Gradio interface implementation
  • style_wrdler.css - Custom CSS for Gradio components
  • Both files use Gradio 5.50+ compatible patterns