Surn commited on
Commit
f969c4d
·
1 Parent(s): 7606f52

- Fix music and sound effect volume issues
- Update documentation for proposed new features

.gitignore CHANGED
@@ -490,3 +490,4 @@ secrets.*
490
  /battlewords/__pycache__/__init__.cpython-311.pyc
491
  /package.json
492
  /package-lock.json
 
 
490
  /battlewords/__pycache__/__init__.cpython-311.pyc
491
  /package.json
492
  /package-lock.json
493
+ /.claude
README.md CHANGED
@@ -112,6 +112,33 @@ docker run -p8501:8501 battlewords
112
  - High Scores: local leaderboard tracking top scores by wordlist and game mode.
113
  - Persistent Storage: all game results saved locally for personal statistics without accounts.
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  -0.2.18
116
  - Fix sound effect volume wiring and apply volume to all effects (hit/miss/correct/incorrect)
117
  - Respect "Enable music" and "Volume" when playing congratulations music and when resuming background music (uses selected track)
 
112
  - High Scores: local leaderboard tracking top scores by wordlist and game mode.
113
  - Persistent Storage: all game results saved locally for personal statistics without accounts.
114
 
115
+ -0.2.20 (development)
116
+ - Remote Storage game_id:
117
+ - Per-game JSON settings uploaded to a storage server (Hugging Face repo) under unique `games/{uid}/settings.json`
118
+ - A shortened URL id (sid) is generated; shareable link: `?game_id=<sid>`
119
+ - On load with `game_id`, the app resolves sid to the JSON and applies word_list, game_mode, grid_size, puzzle options
120
+ - High Scores: add remote `highscores/highscores.json` (repo) alongside local highscores
121
+ - Dependencies: add `huggingface_hub` and `python-dotenv`
122
+ - Env: `.env` should include `HF_API_TOKEN` (or `HF_TOKEN`), `CRYPTO_PK`, `HF_REPO_ID`, `SPACE_NAME`
123
+
124
+ ### Environment Variables
125
+ - HF_API_TOKEN or HF_TOKEN: HF Hub access token
126
+ - CRYPTO_PK: reserved for signing (optional)
127
+ - HF_REPO_ID: e.g., Surn/Storage
128
+ - SPACE_NAME: e.g., Surn/BattleWords
129
+
130
+ ### Remote Storage Structure
131
+ - shortener.json
132
+ - games/{uid}/settings.json
133
+ - highscores/highscores.json
134
+
135
+ Note
136
+ - `battlewords/storage.py` remains local-only storage; a separate HF integration wrapper will be added in a later PR to avoid confusion with generic modules
137
+
138
+ -0.2.19
139
+ - Fix music and sound effect volume issues
140
+ - Update documentation for proposed new features
141
+
142
  -0.2.18
143
  - Fix sound effect volume wiring and apply volume to all effects (hit/miss/correct/incorrect)
144
  - Respect "Enable music" and "Volume" when playing congratulations music and when resuming background music (uses selected track)
battlewords/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
- __version__ = "0.2.18"
2
  __all__ = ["models", "generator", "logic", "ui"]
 
1
+ __version__ = "0.2.19"
2
  __all__ = ["models", "generator", "logic", "ui"]
battlewords/storage.py CHANGED
@@ -1,4 +1,4 @@
1
- // file: battlewords/storage.py
2
  """
3
  Storage module for BattleWords game.
4
 
 
1
+ # file: battlewords/storage.py
2
  """
3
  Storage module for BattleWords game.
4
 
claude.md CHANGED
@@ -309,3 +309,96 @@ pytest tests/
309
  - Storage features are backward-compatible (game works without storage)
310
  - Game IDs are deterministic for consistent sharing
311
  - JSON storage chosen for simplicity and privacy
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  - Storage features are backward-compatible (game works without storage)
310
  - Game IDs are deterministic for consistent sharing
311
  - JSON storage chosen for simplicity and privacy
312
+
313
+ ### WSL Environment Python Versions
314
+ The development environment is WSL (Windows Subsystem for Linux) with access to both native Linux and Windows Python installations:
315
+
316
+ **Native WSL (Linux):**
317
+ - `python3` → Python 3.10.12 (`/usr/bin/python3`)
318
+ - `python3.10` → Python 3.10.12
319
+
320
+ **Windows Python (accessible via WSL):**
321
+ - `python311.exe` → Python 3.11.9 (`/mnt/c/Users/cfettinger/AppData/Local/Programs/Python/Python311/`)
322
+ - `python3.13.exe` → Python 3.13.1 (`/mnt/c/ProgramData/chocolatey/bin/`)
323
+
324
+ **Note:** Windows Python executables (`.exe`) can be invoked directly from WSL and are useful for testing compatibility across Python versions. The project targets Python 3.12+ but can run on 3.10+.
325
+
326
+ ## v0.2.20: Remote Storage game_id via Shortened URL
327
+
328
+ Overview
329
+ - Use a storage server (Hugging Face Hub repo) to persist:
330
+ - Per-game settings JSON (word_list, score, time, game_mode, grid_size, puzzle options)
331
+ - High scores JSON (top scores)
332
+ - Each completed game writes JSON to repo under a unique `uid` folder.
333
+ - A shortened URL (sid) referencing the settings JSON is generated and used as `game_id` in the query string.
334
+ - On load, if `?game_id=<sid>` exists, resolve sid to the full JSON URL, fetch it, and apply settings for the session.
335
+
336
+ Modules to leverage (from OpenBadge/modules)
337
+ - `modules/storage.py`
338
+ - `upload_files_to_repo(files, repo_id, folder_name, repo_type="dataset")`
339
+ - `gen_full_url(short_url=None, full_url=None, repo_id=None, json_file="shortener.json")`
340
+ - `modules/constants.py` (env + defaults)
341
+ - Uses HF token from env (expects `HF_TOKEN`, we will also document `HF_API_TOKEN`)
342
+ - `HF_REPO_ID`, `SPACE_NAME`, `SHORTENER_JSON_FILE`
343
+ - `modules/file_utils.py` (helpers)
344
+
345
+ Environment variables (.env)
346
+ - HF_API_TOKEN or HF_TOKEN: Hugging Face access token (Bearer)
347
+ - CRYPTO_PK: optional, reserved for future signing
348
+ - HF_REPO_ID: target repo, e.g., Surn/Storage
349
+ - SPACE_NAME: e.g., Surn/BattleWords
350
+
351
+ Repository structure (dataset repo)
352
+ - shortener.json # sid -> full URL mapping
353
+ - games/{uid}/settings.json # per-game settings payload (primary)
354
+ - games/{uid}/result.json # finalized game result (optional)
355
+ - highscores/highscores.json # global/top scores JSON
356
+
357
+ Game settings JSON (example)
358
+ {
359
+ "uid": "20250101T120001Z-ABC123",
360
+ "word_list": ["APPLE","TRAIN","..."],
361
+ "score": 40,
362
+ "time": 173,
363
+ "game_mode": "classic",
364
+ "grid_size": 12,
365
+ "puzzle_options": { "spacer": 1, "may_overlap": false }
366
+ }
367
+
368
+ Flow
369
+ 1) On game completion
370
+ - Build unique `uid` (timestamp + random suffix).
371
+ - Write settings.json (and optional result.json) to games/{uid}/
372
+ - Create full URL to settings.json, call `gen_full_url(full_url=...)` to obtain `sid`
373
+ - Share link: https://<space>/?game_id=<sid>
374
+ 2) On load with `?game_id=<sid>`
375
+ - Call `gen_full_url(short_url=sid)` to get full URL
376
+ - Fetch settings.json, apply session: word_list, game_mode, grid_size, puzzle options; ignore score/time for gameplay
377
+ 3) Highscores
378
+ - Maintain highscores/highscores.json in repo; append/update with best entries
379
+
380
+ Security/Privacy
381
+ - Only game configuration and scores are stored; no PII required
382
+ - sid is a reference; shortener.json can be in the same repo
383
+ - Consider private repo for write access; dataset can be public for read
384
+
385
+ Notes
386
+ - We will keep `battlewords/storage.py` as local-only storage (JSON on disk) and introduce a new integration wrapper in a later PR (e.g., `battlewords/hf_storage.py`) to avoid confusion with the generic modules. If needed, rename `battlewords/storage.py` to `local_storage.py` in a future pass.
387
+ - Add dependencies: `huggingface_hub`, `python-dotenv`
388
+
389
+ ## Documentation Structure
390
+
391
+ This file (CLAUDE.md) serves as a **living context document** for AI-assisted development. It complements the formal specification documents:
392
+
393
+ - **[specs/specs.md](specs/specs.md)** - Game rules, requirements, and feature specifications
394
+ - **[specs/requirements.md](specs/requirements.md)** - Implementation phases, acceptance criteria, and technical tasks
395
+ - **[README.md](README.md)** - User-facing documentation, installation guide, and changelog
396
+
397
+ **When to use each:**
398
+ - **specs.md** - Understanding game rules, scoring, and player experience
399
+ - **requirements.md** - Planning implementation work, tracking phases, and defining done criteria
400
+ - **CLAUDE.md** - Quick reference for codebase structure, recent changes, and development context
401
+ - **README.md** - Public-facing information, setup instructions, and feature announcements
402
+
403
+ **Synchronization:**
404
+ Changes to game mechanics should update specs.md → requirements.md → CLAUDE.md → README.md in that order
pyproject.toml CHANGED
@@ -1,7 +1,7 @@
1
  [project]
2
  name = "battlewords"
3
- version = "0.2.18"
4
- description = "BattleWords vocabulary game"
5
  readme = "README.md"
6
  requires-python = ">=3.12,<3.13"
7
  dependencies = [
 
1
  [project]
2
  name = "battlewords"
3
+ version = "0.2.20"
4
+ description = "BattleWords vocabulary game with game sharing via shortened game_id URL referencing server-side JSON settings"
5
  readme = "README.md"
6
  requires-python = ">=3.12,<3.13"
7
  dependencies = [
requirements.txt CHANGED
@@ -7,4 +7,6 @@ Pillow
7
  pytest
8
  flake8
9
  mypy
10
- requests
 
 
 
7
  pytest
8
  flake8
9
  mypy
10
+ requests
11
+ huggingface_hub
12
+ python-dotenv
specs/requirements.md CHANGED
@@ -192,3 +192,58 @@ Definitions of Done (per task)
192
  - Code merged with tests and docs updated.
193
  - No regressions in existing tests; coverage maintained or improved for core logic.
194
  - Manual playthrough validates rules: reveal/guess gating, scoring, radar pulses, end state and tiers.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  - Code merged with tests and docs updated.
193
  - No regressions in existing tests; coverage maintained or improved for core logic.
194
  - Manual playthrough validates rules: reveal/guess gating, scoring, radar pulses, end state and tiers.
195
+
196
+ ## v0.2.20 Update: Game Sharing with Shortened game_id URL
197
+
198
+ ### Game Sharing Feature
199
+ - On game completion, save a JSON file to the storage server named by a unique `uid`.
200
+ - The JSON file contains: word_list, score, time, game_mode, grid_size, and puzzle options.
201
+ - Generate a shortened URL for this file; use it as the `game_id` in the shareable link.
202
+ - When a user loads a game with a `game_id` query string, fetch the JSON file and apply all settings for the session.
203
+
204
+ ### Implementation Notes
205
+ - The game_id is a shortened URL referencing the JSON file.
206
+ - The app applies all settings from the file for a true replay.
207
+ - No direct encoding of game data in the query string; only the reference is shared.
208
+
209
+ ## Phase 1.6: Remote Storage & Sharing (0.2.20)
210
+
211
+ Goal
212
+ - Persist per-game settings and highscores on a storage server (Hugging Face Hub repo).
213
+ - Use a shortened `game_id` (sid) that resolves to settings.json for replay/sharing.
214
+
215
+ A) Storage Server Integration
216
+ - Use modules from OpenBadge `modules/storage.py`:
217
+ - `upload_files_to_repo(...)` to write JSON to `HF_REPO_ID`
218
+ - `gen_full_url(...)` for shortener lookups/creation backed by `shortener.json`
219
+ - Create per-game folder `games/{uid}/` and write:
220
+ - `settings.json` with: word_list, score, time, game_mode, grid_size, puzzle options
221
+ - (optional) `result.json` with additional details for analytics
222
+ - Maintain `highscores/highscores.json` for top scores
223
+ - Env vars (.env): `HF_API_TOKEN` (or `HF_TOKEN`), `CRYPTO_PK`, `HF_REPO_ID`, `SPACE_NAME`
224
+
225
+ B) Sharing Link (game_id)
226
+ - After upload of `settings.json`, call `gen_full_url(full_url=...)` to obtain a short id (sid)
227
+ - Shareable link: `https://<SPACE_NAME>/?game_id=<sid>`
228
+ - On app load with `game_id`, call `gen_full_url(short_url=sid)`, fetch JSON, apply settings
229
+
230
+ C) App Behavior
231
+ - When `game_id` exists:
232
+ - Apply `game_mode`, `grid_size`, `puzzle_options` directly
233
+ - Load `word_list` as the target set; positions remain randomized unless later extended
234
+ - Ignore `score`/`time` for gameplay; those are metadata only
235
+ - Continue to support local JSON storage for users without HF credentials
236
+
237
+ D) Dependencies
238
+ - Add `huggingface_hub` and `python-dotenv` to requirements
239
+ - Ensure `requests` remains present for HTTP fetch fallback if needed
240
+
241
+ E) Acceptance
242
+ - A completed game produces a working share link with `game_id` sid
243
+ - Visiting the link reconstructs the session settings from storage server JSON
244
+ - Highscores JSON updates in the repo
245
+ - Documentation updated with env vars, repo structure, and flows
246
+
247
+ F) Implementation Notes
248
+ - Do not replace `battlewords/storage.py` now; introduce a separate integration wrapper (e.g., `battlewords/hf_storage.py`) in the next PR
249
+ - Consider a private repo for write access; shortener JSON and settings JSONs can be public read
specs/specs.md CHANGED
@@ -88,3 +88,28 @@ Battlewords is inspired by the classic Battleship game, but uses words instead o
88
 
89
  ## Copyright
90
  BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  ## Copyright
90
  BattlewordsTM. All Rights Reserved. All content, trademarks and logos are copyrighted by the owner.
91
+
92
+ ## v0.2.20: Remote Storage and Shortened game_id URL
93
+
94
+ Game Sharing
95
+ - Each puzzle can be shared via a link containing a `game_id` querystring (short id / sid)
96
+ - `game_id` resolves to a settings JSON on the storage server (HF repo)
97
+ - JSON fields:
98
+ - word_list (list of 6 uppercase words)
99
+ - score (int), time (int seconds) [metadata only]
100
+ - game_mode (e.g., classic, too easy)
101
+ - grid_size (e.g., 12)
102
+ - puzzle_options (e.g., { spacer, may_overlap })
103
+ - On load with `game_id`, fetch and apply: word_list, game_mode, grid_size, puzzle_options
104
+
105
+ High Scores
106
+ - Repository maintains `highscores/highscores.json` for top scores
107
+ - Local highscores remain supported for offline use
108
+
109
+ UI/UX
110
+ - Show the current `game_id` (sid) and a �Share Challenge� link
111
+ - When loading with a `game_id`, indicate the puzzle is a shared challenge
112
+
113
+ Security/Privacy
114
+ - Only game configuration and scores are stored; no personal data is required
115
+ - `game_id` is a short reference; full URL is stored in a repo JSON shortener index