Files
python-tdd/src/apps/epic
Disco DeDisco a4ac25605d A.1 seed Minchiate Fiorentine 1860-1890 deck (97 cards) — TDD. Sprint A.1 follow-up to [[project-image-based-deck-face-rendering]]. Creates the actual Minchiate Fiorentine DeckVariant (separate from the renamed-from-fiorentine-minchiate RWS Tarot now living at tarot-rider-waite-smith per A.0). Slug minchiate-fiorentine-1860-1890 matches the asset dir committed in 0add163 (98 PNGs at src/apps/epic/static/apps/epic/images/cards-faces/minchiate-fiorentine-1860-1890/); Sprint A.2's image_filename property will use deck.slug to point at those images. Schema fields set: family='italian' (drives display + filename slug mapping per [[reference-card-image-naming-convention]] — BRANDS→batons, CROWNS→coins, GRAILS→cups, BLADES→swords), has_card_images=True (first deck w. images shipped), is_polarized=False (Earthman remains the only polarized deck), is_default=False (Earthman is default), card_count=97. 97 TarotCard rows seeded: 41 trumps (Il Matto at rank 0 per the unnumbered-Fool-gets-sortable-position convention from [[reference-card-image-naming-convention]]; then 40 numbered 1-40) + 56 minors (4 suits × 14 cards = pip 1-10 + page=11 + knight=12 + queen=13 + king=14 per the v2 convention's number-prefixed-courts decision). Trump names are Italian (Papa Uno / Papa Due / La Temperanza / La Forza / La Giustizia / La Ruota della Fortuna / Il Carro / Il Gobbo / L'Impiccato / La Morte / Il Diavolo / La Casa del Diavolo / La Speranza / La Prudenza / La Fede / La Carita / Il Fuoco / L'Acqua / La Terra / L'Aria + 12 zodiac signs + La Stella / La Luna / Il Sole / Il Mondo / Le Trombe). Card-suit canonical enum stays BRANDS/CROWNS/GRAILS/BLADES per A.0's lock; minor card NAMES use Italian-family display vocab ("Page of Batons" not "Page of Brands") since names are the user-facing label whereas suit is the structural identity. 16 trumps carry a correspondence field pointing to their RWS Tarot equivalent (Il Matto→The Fool, Il Carro→The Chariot, Il Gobbo→The Hermit, L'Impiccato→The Hanged Man, La Morte→Death, Il Diavolo→The Devil, La Casa del Diavolo→The Tower, La Temperanza→Temperance, La Forza→Strength, La Giustizia→Justice, La Ruota della Fortuna→Wheel of Fortune, La Stella→The Star, La Luna→The Moon, Il Sole→The Sun, Il Mondo→The World, Le Trombe→Judgement); the 25 Minchiate-only trumps (5 popes + 4 theological/cardinal virtues + 4 elements + 12 zodiac) have no RWS parallel → empty correspondence. keywords_upright / keywords_reversed intentionally left empty []: those are interpretive content the user owns; admin form (Sprint B) will enrich via UI rather than have them committed as code in a migration. Five trumps in the v2 filename convention have elided-apostrophe slugs restored (l-impiccato, l-acqua, l-aria, l-ariete, l-acquario); DB slug field matches (no apostrophe, but with the leading l- prefix). 17 new ITs in MinchiateFiorentine1860SeedTest cover the deck attributes (name + family + has_card_images + is_polarized + card_count) + total row count (97) + arcana breakdown (41 trumps + 56 minors + 0 middle) + specific cards (Il Matto at rank 0 + Il Gobbo at rank 11 w. correspondence "The Hermit" + Le Trombe at rank 40 + 5 popes are MAJOR ranks 1-5 + Page of Batons + King of Coins) + canonical-suit-only check (no WANDS/CUPS/SWORDS/PENTACLES in DB) + court rank range (11-14 per suit). Tests: 17 new green; 1272/1272 IT+UT total green (64s; +17 from A.0's 1255). Out of scope: A.2 adds the TarotCard.image_filename + display_suit_name properties consuming deck.family for per-family translation; A.3 wires my_sign.html's first render branch
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 23:32:19 -04:00
..
A.1 seed Minchiate Fiorentine 1860-1890 deck (97 cards) — TDD. Sprint A.1 follow-up to [[project-image-based-deck-face-rendering]]. Creates the actual Minchiate Fiorentine DeckVariant (separate from the renamed-from-fiorentine-minchiate RWS Tarot now living at tarot-rider-waite-smith per A.0). Slug minchiate-fiorentine-1860-1890 matches the asset dir committed in 0add163 (98 PNGs at src/apps/epic/static/apps/epic/images/cards-faces/minchiate-fiorentine-1860-1890/); Sprint A.2's image_filename property will use deck.slug to point at those images. Schema fields set: family='italian' (drives display + filename slug mapping per [[reference-card-image-naming-convention]] — BRANDS→batons, CROWNS→coins, GRAILS→cups, BLADES→swords), has_card_images=True (first deck w. images shipped), is_polarized=False (Earthman remains the only polarized deck), is_default=False (Earthman is default), card_count=97. 97 TarotCard rows seeded: 41 trumps (Il Matto at rank 0 per the unnumbered-Fool-gets-sortable-position convention from [[reference-card-image-naming-convention]]; then 40 numbered 1-40) + 56 minors (4 suits × 14 cards = pip 1-10 + page=11 + knight=12 + queen=13 + king=14 per the v2 convention's number-prefixed-courts decision). Trump names are Italian (Papa Uno / Papa Due / La Temperanza / La Forza / La Giustizia / La Ruota della Fortuna / Il Carro / Il Gobbo / L'Impiccato / La Morte / Il Diavolo / La Casa del Diavolo / La Speranza / La Prudenza / La Fede / La Carita / Il Fuoco / L'Acqua / La Terra / L'Aria + 12 zodiac signs + La Stella / La Luna / Il Sole / Il Mondo / Le Trombe). Card-suit canonical enum stays BRANDS/CROWNS/GRAILS/BLADES per A.0's lock; minor card NAMES use Italian-family display vocab ("Page of Batons" not "Page of Brands") since names are the user-facing label whereas suit is the structural identity. 16 trumps carry a correspondence field pointing to their RWS Tarot equivalent (Il Matto→The Fool, Il Carro→The Chariot, Il Gobbo→The Hermit, L'Impiccato→The Hanged Man, La Morte→Death, Il Diavolo→The Devil, La Casa del Diavolo→The Tower, La Temperanza→Temperance, La Forza→Strength, La Giustizia→Justice, La Ruota della Fortuna→Wheel of Fortune, La Stella→The Star, La Luna→The Moon, Il Sole→The Sun, Il Mondo→The World, Le Trombe→Judgement); the 25 Minchiate-only trumps (5 popes + 4 theological/cardinal virtues + 4 elements + 12 zodiac) have no RWS parallel → empty correspondence. keywords_upright / keywords_reversed intentionally left empty []: those are interpretive content the user owns; admin form (Sprint B) will enrich via UI rather than have them committed as code in a migration. Five trumps in the v2 filename convention have elided-apostrophe slugs restored (l-impiccato, l-acqua, l-aria, l-ariete, l-acquario); DB slug field matches (no apostrophe, but with the leading l- prefix). 17 new ITs in MinchiateFiorentine1860SeedTest cover the deck attributes (name + family + has_card_images + is_polarized + card_count) + total row count (97) + arcana breakdown (41 trumps + 56 minors + 0 middle) + specific cards (Il Matto at rank 0 + Il Gobbo at rank 11 w. correspondence "The Hermit" + Le Trombe at rank 40 + 5 popes are MAJOR ranks 1-5 + Page of Batons + King of Coins) + canonical-suit-only check (no WANDS/CUPS/SWORDS/PENTACLES in DB) + court rank range (11-14 per suit). Tests: 17 new green; 1272/1272 IT+UT total green (64s; +17 from A.0's 1255). Out of scope: A.2 adds the TarotCard.image_filename + display_suit_name properties consuming deck.family for per-family translation; A.3 wires my_sign.html's first render branch
2026-05-24 23:32:19 -04:00
feat: import Minchiate Fiorentine 1860-1890 deck assets (98 PNGs, alpha-channel transparent bg) + naming convention v2 + pngquant optimization tooling. Public-domain 1860-1890 lithograph scans sourced from Wikimedia (single download series + trump 11 Il Gobbo individually-sourced from same era series); user removed white backgrounds in Photoshop to leave irregular card-shape with transparent canvas. Filenames v2-conformant per [[reference-card-image-naming-convention]] (revised from v1 of 2026-05-24): deck slug carries -1860-1890 publication-year suffix so future Minchiate Fiorentine variants from different publishers/eras coexist cleanly; courts use rank-number-prefix (batons-11-page not batons-page) for linear sort key; trumps carry both numeric rank AND italian-name suffix (trumps-01-papa-uno, trumps-11-il-gobbo) for forensic identification across variant decks the user plans to sell. Il Matto (unnumbered Fool in Minchiate tradition) assigned rank 00 to give it a sortable position. Five trump filenames had elided-apostrophe slugs restored from the download source (-lacqua-l-acqua etc.). Card-back at <deck-slug>-back.png sorts alphabetically before all suit categories — no separate card-back/ subdir needed. pngquant 2.17.0 installed at C:\Users\adamc\AppData\Local\Programs\pngquant\, added to user PATH (effective next session) for future deck imports; ran with --quality=65-85 --speed=1 --strip --skip-if-larger for 57.6% size reduction (86.6 MB → 36.7 MB total, 935 KB → 383 KB avg). Second pass at --quality=40-65 hit pngquant's floor (only 0.5% further reduction — re-quantizing an already-quantized image has little headroom). Il Gobbo from Wikimedia was a dimensional outlier (1426x2366 vs siblings ~620x1024) — resized via System.Drawing HighQualityBicubic to 620x1029 before optimization. Format32bppArgb alpha channel verified intact across samples after optimization pass. Visually validated by user: cards must fill entire screen before any pixelization visible. Sprint A precursor — DeckVariant.has_card_images toggle + image-rendering template branch per [[project-image-based-deck-face-rendering]] follows in subsequent commits, will consume these assets in 6 surfaces (my_sign, my_sea, both billboard applets, room, game_kit). Asset set also unblocks downstream Sprint C+B [[project-deck-segment-model]] (admin form will require image upload + enforce naming convention) and Sprint D [[project-card-deck-icon]] (uses -back.png as the deck-stack icon's repeating card-face). Future: when Sprint B's admin form ships, wire pngquant into an optimize_card_images management command so admin uploads auto-optimize on save. Gitignore line src/apps/epic/static/apps/epic/images/cards-faces/minchiate-fiorentine/ dropped — v1 staging dir deleted (was only ever the rename-staging set; superseded by v2-named optimized set). Total disk delta: +36.7 MB binary content. No code changes — pure asset + convention import
2026-05-24 22:39:21 -04:00
A.1 seed Minchiate Fiorentine 1860-1890 deck (97 cards) — TDD. Sprint A.1 follow-up to [[project-image-based-deck-face-rendering]]. Creates the actual Minchiate Fiorentine DeckVariant (separate from the renamed-from-fiorentine-minchiate RWS Tarot now living at tarot-rider-waite-smith per A.0). Slug minchiate-fiorentine-1860-1890 matches the asset dir committed in 0add163 (98 PNGs at src/apps/epic/static/apps/epic/images/cards-faces/minchiate-fiorentine-1860-1890/); Sprint A.2's image_filename property will use deck.slug to point at those images. Schema fields set: family='italian' (drives display + filename slug mapping per [[reference-card-image-naming-convention]] — BRANDS→batons, CROWNS→coins, GRAILS→cups, BLADES→swords), has_card_images=True (first deck w. images shipped), is_polarized=False (Earthman remains the only polarized deck), is_default=False (Earthman is default), card_count=97. 97 TarotCard rows seeded: 41 trumps (Il Matto at rank 0 per the unnumbered-Fool-gets-sortable-position convention from [[reference-card-image-naming-convention]]; then 40 numbered 1-40) + 56 minors (4 suits × 14 cards = pip 1-10 + page=11 + knight=12 + queen=13 + king=14 per the v2 convention's number-prefixed-courts decision). Trump names are Italian (Papa Uno / Papa Due / La Temperanza / La Forza / La Giustizia / La Ruota della Fortuna / Il Carro / Il Gobbo / L'Impiccato / La Morte / Il Diavolo / La Casa del Diavolo / La Speranza / La Prudenza / La Fede / La Carita / Il Fuoco / L'Acqua / La Terra / L'Aria + 12 zodiac signs + La Stella / La Luna / Il Sole / Il Mondo / Le Trombe). Card-suit canonical enum stays BRANDS/CROWNS/GRAILS/BLADES per A.0's lock; minor card NAMES use Italian-family display vocab ("Page of Batons" not "Page of Brands") since names are the user-facing label whereas suit is the structural identity. 16 trumps carry a correspondence field pointing to their RWS Tarot equivalent (Il Matto→The Fool, Il Carro→The Chariot, Il Gobbo→The Hermit, L'Impiccato→The Hanged Man, La Morte→Death, Il Diavolo→The Devil, La Casa del Diavolo→The Tower, La Temperanza→Temperance, La Forza→Strength, La Giustizia→Justice, La Ruota della Fortuna→Wheel of Fortune, La Stella→The Star, La Luna→The Moon, Il Sole→The Sun, Il Mondo→The World, Le Trombe→Judgement); the 25 Minchiate-only trumps (5 popes + 4 theological/cardinal virtues + 4 elements + 12 zodiac) have no RWS parallel → empty correspondence. keywords_upright / keywords_reversed intentionally left empty []: those are interpretive content the user owns; admin form (Sprint B) will enrich via UI rather than have them committed as code in a migration. Five trumps in the v2 filename convention have elided-apostrophe slugs restored (l-impiccato, l-acqua, l-aria, l-ariete, l-acquario); DB slug field matches (no apostrophe, but with the leading l- prefix). 17 new ITs in MinchiateFiorentine1860SeedTest cover the deck attributes (name + family + has_card_images + is_polarized + card_count) + total row count (97) + arcana breakdown (41 trumps + 56 minors + 0 middle) + specific cards (Il Matto at rank 0 + Il Gobbo at rank 11 w. correspondence "The Hermit" + Le Trombe at rank 40 + 5 popes are MAJOR ranks 1-5 + Page of Batons + King of Coins) + canonical-suit-only check (no WANDS/CUPS/SWORDS/PENTACLES in DB) + court rank range (11-14 per suit). Tests: 17 new green; 1272/1272 IT+UT total green (64s; +17 from A.0's 1255). Out of scope: A.2 adds the TarotCard.image_filename + display_suit_name properties consuming deck.family for per-family translation; A.3 wires my_sign.html's first render branch
2026-05-24 23:32:19 -04:00
A.0 image-rendering schema + RWS rename + canonical-Earthman suit collapse — TDD. Sprint A.0 of [[project-image-based-deck-face-rendering]]. Adds three DeckVariant fields: has_card_images (BooleanField default=True — Earthman keeps False until its artwork ships, every new deck defaults True), family (CharField choices=[earthman, italian, english, playing] default=earthman — drives per-family display + filename slug mapping per [[reference-card-image-naming-convention]]), is_polarized (BooleanField default=False — Earthman is True today; Sprint A.4 game_kit applet will render "(×2)" in --terUser for polarized decks; Sprint C+B segment model uses it for segment-count logic). TarotCard.SUIT_CHOICES collapses from 8 values to 4 canonical Earthman values (BRANDS / CROWNS / GRAILS / BLADES); WANDS / CUPS / SWORDS / PENTACLES dropped — they were duplicative at the structural level since sig_deck_cards + levity/gravity_sig_cards already treated [WANDS, BRANDS, CROWNS] as one segment and [SWORDS, BLADES, CUPS, GRAILS] as another (so the project already *functionally* equated them; the lock just makes that explicit). Per-family display vocab (batons for Italian, wands for English, clubs for Playing) lives in Sprint A.2's display_suit_name property, not in the enum. Audit 2026-05-25 revealed the existing fiorentine-minchiate DeckVariant is actually 78-card RWS Tarot in disguise (22 majors numbered 0-21 w. RWS names: The Fool / The Magician / ... / The World; 56 minors in 4 suits × 14 cards) — NOT Minchiate (which has 40 trumps + 1 Il Matto + 56 minors = 97 cards). Migration 0012 renames the slug → tarot-rider-waite-smith, name → "Tarot (Rider-Waite-Smith)", sets family='english', has_card_images=False, is_polarized=False — and revocabs its 56 minor cards' suits in-place (WANDS→BRANDS, CUPS→GRAILS, SWORDS→BLADES, PENTACLES→CROWNS) so they match the new canonical enum. FKs (User.equipped_deck, User.unlocked_decks, TableSeat.deck_variant, etc.) survive untouched — slug-only changes don't break referential integrity. Earthman fields set explicitly in 0012 too (family=earthman, has_card_images=False, is_polarized=True). Companion code simplifications: sig_deck_cards + _sig_unique_cards_for_deck queries shrink from suit__in=[3 values] and [4 values] to [2 values] each (one per segment); TarotCard.suit_icon mapping shrinks from 8 entries to 4; gameboard.views.tarot_fan._suit_order shrinks from 8 keys to 4. Existing test files updated: test_game_room_tray.py (largest update — self.fiorentineself.rws, id_kit_fiorentine_deckid_kit_tarot_deck (template-id derives from deck.short_key = first slug segment), assertion "Fiorentine" → "Rider-Waite-Smith"); test_game_room_deck_contrib.py (same pattern, smaller); lyric/test_models.py + gameboard/test_views.py (slug literal swaps only); epic/test_models.py _make_sig_card test fixtures: "WANDS"→"BRANDS", "CUPS"→"GRAILS". 14 new ITs in DeckSchemaA0Test cover the schema additions + migration outcomes (field existence + choice values + earthman has all three fields set correctly + RWS rename verified + RWS cards use canonical suits + dropped enum values absent from SUIT_CHOICES). Tests: 14 new green; 1255/1255 IT+UT total green (38s); no regressions. Out of scope: Sprint A.1 will seed the actual Minchiate Fiorentine 1860-1890 (97-card) DeckVariant + TarotCard rows w. family='italian', has_card_images=True; A.2 adds the image_filename + display_suit_name properties that consume the new family field; A.3+ wires the render branches across 6 surfaces
2026-05-24 23:25:26 -04:00
btn-primary label renames + stage-card polarity color refinements — two interleaved threads from one session, committing together since both touch sig + sea stage cards ; LABEL RENAMES: PICK SIGS → SCAN SIGS (room.html #id_pick_sigs_btn), PICK SKY → CAST SKY (room.html #id_pick_sky_btn × 2), PICK SEA → DRAW SEA (room.html #id_pick_sea_btn), TAKE SIG → SAVE SIG (sig-select.js _takeSigBtn.textContent × 2 callsites + section comment) — Element IDs (id_pick_sky_btn etc.), URL names (epic:pick_sigs, epic:pick_sky), and Python state enums (TableStatus.PICK_SKY, PICK_SEA, SIG_SELECT) intentionally retained as stable identifiers; the renamed text is purely the .btn-primary user-facing label ; FT + IT mentions of the old labels swept in test_game_room_select_{sig,sky,sea,role}.py, test_billboard.py, setup_sea_session.py mgmt cmd, apps/epic/{views,utils,models,tasks,tests/integrated/test_views}.py, SigSelectSpec.js, sky_overlay/sea_overlay/dashboard/sky.html, _card-deck.scss, _sky.scss — all docstring/comment references updated for cascade-grep cleanliness ; STAGE-CARD COLOR + CLASS REFINEMENTS (earlier in session): sig-stage card text colour split per polarity — gravity gets --terUser on .fan-card-name + .fan-card-reversal-{name,qualifier} + .sig-qualifier-{above,below}, levity gets --quiUser on the same five slots; all selectors prefixed w. .sig-stage-card to match the 0,4,0 specificity of the default .sig-stage .sig-stage-card .fan-card-face .sig-qualifier-* rule (without the prefix the polarity overrides lose the cascade — .sig-qualifier-below was visibly stuck on the default --quiUser) ; .stat-face-label gets polarity-inverse colours — gravity stat-block bg is --secUser (opposite of card's --priUser) so the label takes --quiUser to stay legible; levity is the symmetric flip (label = --terUser on --priUser stat-block bg) ; levity card title/qualifier drop-shadow swapped from rgba(0,0,0,…) → rgba(255,255,255,…) — dark drop reads as harsh smudge against the inverted-frame levity --secUser bg; applied to both sig-overlay[data-polarity="levity"] stage card AND sea-stage--levity via $_sea-title-shadow-levity (former shared $_sea-title-shadow split into per-polarity {levity,gravity} variants) ; reversal-face class/content alignment so each .fan-card-reversal-* class always carries its semantic content — DOM order per arcana type controls visual layout after the 180° SPIN (DOM-second appears visually on top): Major → title in .fan-card-reversal-name @ DOM-second (visually top after spin), qualifier in .fan-card-reversal-qualifier @ DOM-first; Non-major → title in .fan-card-reversal-name @ DOM-first (visually bottom after spin), qualifier in .fan-card-reversal-qualifier @ DOM-second (preserves the original "qualifier word reads first after spin" layout for Middle/Minor arcana — e.g. "Relieving / Eight of Crowns" not "Eight of Crowns / Relieving") ; _tarot_fan.html renders per-arcana DOM order directly (Django template branches handle both layouts); sig + sea overlays render a fixed two-<p> skeleton (one DOM order) so stage-card.js's populator dynamically rewrites the two <p>s' className per arcana — Major/override branch flips DOM-second to .fan-card-reversal-name + content, DOM-first to .fan-card-reversal-qualifier; non-major branch keeps DOM-first as .fan-card-reversal-name + title, DOM-second as .fan-card-reversal-qualifier + reversalQualifier-or-polarity-fallback ; SigSelectSpec.js + SeaDealSpec.js fixtures + Major reversed-face assertion updated for the new semantic — TDD
2026-05-18 00:25:10 -04:00