#!/usr/bin/env python3 """One-shot migration: split a per-theme audio.json into the subscription- pattern triple used everywhere else in the codebase. Before: public/games//data/audio.json {schema_version, sfx: {...}, music: {tracks: [...], victory_pool, defeat_pool, default_track_id, crossfade_seconds}} After: public/resources/audio/library.json # shared catalogue {schema_version, sfx: {...}, music: {tracks: [...]}} public/games//data/audio/manifest.json # subscription {source: "resources/audio", includes: true, overrides: {}} public/games//data/audio/pools.json # per-game routing {default_track_id, crossfade_seconds, victory_pool, defeat_pool} The migration assumes the current single audio.json IS the only library — i.e. all entries are subscribed by Game 1. Future games author their own manifest.json with `includes: [whitelist]` or overrides. """ from __future__ import annotations import json from pathlib import Path REPO = Path(__file__).resolve().parent.parent THEME = "age-of-dwarves" SRC = REPO / "public" / "games" / THEME / "data" / "audio.json" LIBRARY = REPO / "public" / "resources" / "audio" / "library.json" DEST_DIR = REPO / "public" / "games" / THEME / "data" / "audio" MANIFEST = DEST_DIR / "manifest.json" POOLS = DEST_DIR / "pools.json" def main() -> None: with open(SRC) as f: old = json.load(f) sfx: dict = old["sfx"] music: dict = old["music"] tracks: list = music.get("tracks", []) # Library: schema_version + sfx + music tracks (no per-theme routing). library = { "schema_version": int(old.get("schema_version", 2)), "sfx": sfx, "music": {"tracks": tracks}, } # Manifest: subscription. Game 1 takes everything. manifest = { "source": "resources/audio", "includes": True, "overrides": {}, } # Pools: per-theme routing. Pull every per-game-only field out of # the music block. pools: dict = {} for k in ("default_track_id", "crossfade_seconds", "victory_pool", "defeat_pool"): if k in music: pools[k] = music[k] DEST_DIR.mkdir(parents=True, exist_ok=True) LIBRARY.parent.mkdir(parents=True, exist_ok=True) LIBRARY.write_text(json.dumps(library, indent=2) + "\n") MANIFEST.write_text(json.dumps(manifest, indent=2) + "\n") POOLS.write_text(json.dumps(pools, indent=2) + "\n") SRC.unlink() print(f"library: {LIBRARY} ({len(sfx)} sfx, {len(tracks)} tracks)") print(f"manifest: {MANIFEST}") print(f"pools: {POOLS}") print(f"removed: {SRC}") if __name__ == "__main__": main()