feat(domain-clash-royale): first non-transport domain — 121 cards#67
Merged
Conversation
scripts/ingest/build_clash_royale_dataset.py — stdlib-only Python. Pulls from two sources: - Supercell official /v1/cards for the canonical card list + iconUrls + rarity + elixirCost. Key read from ~/.config/kalidoku/clash_royale_api_key (mode 600, outside the repo). - RoyaleAPI cards_stats.json for the combat stats Supercell doesn't expose (damage, hit_speed, range, speed, hitpoints, attacks_air, attacks_ground, flying_height, unlock_arena). Match by normalised name (lowercase + ASCII + strip non-alphanumerics). Troops/buildings expose a summon_character pointer into the characters table where the real combat stats live. 50/121 cards land with partial stats — RoyaleAPI uses internal names that differ from Supercell's public names (Bandit -> Assassin, Executioner -> AxeMan) and doesn't publish entries for public spells (Fireball, Rocket, Arrows, Mirror, The Log, etc.). They still ingest with dps=0, hitpoints=0, type=Unknown; only the rarity/elixir/name_* predicates operate on them. Acceptable for v1 — list tracked in the wiki under [[kalidoku-domain-clash-royale]]. fame_score is rarity-driven (common=100, rare=80, epic=50, legendary=20, champion=5). No Wikipedia pageviews — they're not meaningful per-card for game data. NOTE: icon_url from Supercell is intentionally not stored on the entity in this PR — entity-schema.json forbids extra top-level keys. PR B (card images) will either extend the schema or stash the URLs in a sibling icons.json.
Bootstrap of the clash-royale domain pack via the new ingest script. First non-transport domain in kalidoku, validates that the engine is truly domain-agnostic. domains/clash-royale/entities.json (121 cards) - Pulled from Supercell /v1/cards + RoyaleAPI cr-api-data join. - Attributes: rarity (str), type (str: Troop/Building/Spell/Unknown), elixir, dps (computed: damage * 1000 / hit_speed), hitpoints, range, speed, attacks_air, attacks_ground, flies, arena (parsed from TrainingCamp/ArenaN). - fame_score directly maps rarity (common=100 .. champion=5). - 50/121 entries have partial stats (dps=0, type=Unknown) — known upstream-data limitation, see [[kalidoku-domain-clash-royale]]. domains/clash-royale/predicates.json (33 predicates) Spans every usable axis given the partial data: - rarity: 5 (one predicate per tier) - type: 3 (Troop / Building / Spell) - elixir: 4 (<=2, =3, =4, >=6 — bucketed to keep coverage > 8) - target/movement: attacks_air, flies - combat: dps >= 100 / 200, hitpoints >= 1000 / 2000, range >= 5000 / <= 1200 (melee), speed >= 90 (fast) / <= 60 (slow) - progression: arena >= 7 - letters/words: starts_with G/S, ends_with R/N, contains Y/K, word_count = 1/2, name_length <= 6 / >= 12 Predicates with coverage < 8 on the dataset were intentionally dropped to keep the CSP solver healthy (100/100 seed test at max_attempts=1000).
server: - main.rs declares clash-royale in active_domains. Same shape as paris-metro/rer entries. The Dockerfile already COPYs domains/ into the image, worker auto-discovers — once this lands the next nightly cron publishes a clash-royale daily grid automatically. web: - src/lib/domains.ts: new entry in DOMAINS so the /domain picker and the /[domain]/* getStaticPaths route a new set of pages (/clash-royale/, /clash-royale/play, /clash-royale/leaderboard, /clash-royale/archives). - grid_domain_clash_royale i18n key (fr + en), wired into Grid's domainLabel switch.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
PR A of the Clash Royale arc. Adds the clash-royale domain pack alongside paris-metro + rer. First non-transport domain in kalidoku — validates that the engine is truly domain-agnostic.
max_attempts=1000No card images yet — PR B will surface them inside CellButton + AutocompleteModal. This PR is text-only.
Why
phase 3 of the roadmap originally listed
rer / transilien / sncf-grandes-lignes / world-airports. We're skipping the rest of the transport packs and jumping straight to a "fun" domain (phase 5) to prove the moteur isn't quietly coupled to lines/stations/geography. Clash Royale is also a recognisable brand that gives kalidoku something more sharable than yet-another-metro grid.How
Two layers, three commits.
3157b2f feat(scripts): ingest tooling for clash-royalescripts/ingest/build_clash_royale_dataset.py— stdlib-only Python. Joins two sources by normalised name:/v1/cards— canonical list + rarity + elixirCost + iconUrls. JWT read from~/.config/kalidoku/clash_royale_api_key(mode 600, outside the repo).cards_stats.json— combat stats (damage, hit_speed, range, speed, hitpoints, attacks_air, attacks_ground, flying_height, unlock_arena) via thetroop/building/spell/characterstables. Troops followsummon_characterinto the characters table to get the actual unit stats.fame_scoreis rarity-driven (common=100 .. champion=5). No Wikipedia pageviews — they're not meaningful per-card for game data.ceda44e feat(domain-clash-royale): seed packThe artefacts the script produces, committed as-is:
entities.json— 121 cards, sorted by id, withrarity / type / elixir / dps / hitpoints / range / speed / attacks_air / attacks_ground / flies / arena.predicates.json— 33 predicates curated to keep coverage > 8 entities on each (CSP-solver-friendly).metadata.json— version 0.1.0, both ingestion sources tracked.9979964 feat(server,web): register clash-royale + i18n + domain listserver/src/main.rsdeclares clash-royale; `bootstrap::upsert_active_domains` auto-inserts the row.web/src/lib/domains.tsadds the entry; `getStaticPaths` bakes `/clash-royale/` and its sub-pages.grid_domain_clash_royalei18n key in fr + en, wired into Grid's domainLabel switch.Known data gaps
50/121 cards have partial stats (dps=0, type=Unknown). Tracked in the wiki under [[kalidoku-domain-clash-royale]]. Causes:
These cards still match the rarity / elixir / name_* predicates. Enrichment path: `domains/clash-royale/manual_stats.json` à la `fame_overrides.json`, populated from the Fandom wiki. Out of scope for this PR.
Checklist
Test plan