- migration 0016: card 49 gravity_reversal All-Bestowing → Bestowing - migration 0017: implicit virtues (trumps 6–9) Sublimating/Sedimentary qualifiers + shared reversals (Indulged Folly / Indulgent Doing / Self-Indulgence / Indulging Personal History); explicit virtues (trumps 19–21) full-string emanation/reversal overrides (The Hunter's/Sleeper's/Quarry's etc.); canonicalize trump 7 name "Not Doing" → "Not-Doing" - migrations 0018+0019: TarotCard.italic_word field; populated for trumps 19–21 (Stalking / Dreaming / Intent) - _tarot_fan.html: data-italic-word + |italicize:card.italic_word filter applied to all rendered title slots - new templatetags/tarot_filters.py: italicize(text, word) — escape-safe <em> wrapping - StageCard JS: parse data-italic-word; new _escape / _italicize / _setTitle helpers wrap matching word in <em> via innerHTML when present (textContent otherwise) - views.py _card_dict: include polarity-split overrides + italic_word so Sea Select stage gets them via fetch JSON - _sig_select_overlay.html: emit the five new data-* attrs on sig-card markup so Sig Select stage picks them up via StageCard.fromDataset Code architected by Disco DeDisco <discodedisco@outlook.com> Git commit message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
115 lines
4.0 KiB
Python
115 lines
4.0 KiB
Python
"""Populate the seven Castanedan Virtues — trumps 6–9 (Implicit) + 19–21 (Explicit).
|
||
|
||
Implicit Virtues (6–9): emanation qualifier differs by polarity (Sublimating /
|
||
Sedimentary), name is shared. Reversal is a single full string shared across
|
||
both polarities (the agency word — Controlled / Not / Losing / Erasing —
|
||
flips to Indulged / Indulgent / Self-Indulgence / Indulging). We fill the
|
||
standard `levity_qualifier` / `gravity_qualifier` slots so the major-arcana
|
||
upright renders "Controlled Folly,\nSublimating" via the existing template
|
||
branch; we fill BOTH `levity_reversal` + `gravity_reversal` with the same
|
||
string so a FLIP'd reversal still picks up the override (an empty side falls
|
||
through to the default major-arcana rendering).
|
||
|
||
Explicit Virtues (19–21): emanation is shared across polarities (e.g. "The
|
||
Hunter's Stalking" — no qualifier + stem decomposition), reversal differs by
|
||
polarity. All four polarity-split title fields filled.
|
||
|
||
Also canonicalizes trump 7's name from "Not Doing" to "Not-Doing" per the spec
|
||
doc (slug "not-doing" already correct).
|
||
"""
|
||
from django.db import migrations
|
||
|
||
|
||
IMPLICIT = [
|
||
# (number, levity_qualifier, gravity_qualifier, reversal_title)
|
||
(6, "Sublimating", "Sedimentary", "Indulged Folly"),
|
||
(7, "Sublimating", "Sedimentary", "Indulgent Doing"),
|
||
(8, "Sublimating", "Sedimentary", "Self-Indulgence"),
|
||
(9, "Sublimating", "Sedimentary", "Indulging Personal History"),
|
||
]
|
||
|
||
EXPLICIT = [
|
||
# (number, levity_emanation, gravity_emanation, levity_reversal, gravity_reversal)
|
||
(19, "The Hunter's Stalking", "The Hunter's Stalking", "The Sleeper's Stalking", "The Quarry's Stalking"),
|
||
(20, "The Dreamer's Dreaming", "The Dreamer's Dreaming", "The Sleeper's Dreaming", "The Dreamed's Dreaming"),
|
||
(21, "The Warrior's Intent", "The Warrior's Intent", "The Sleeper's Intent", "The Predator's Intent"),
|
||
]
|
||
|
||
|
||
def forward(apps, schema_editor):
|
||
TarotCard = apps.get_model("epic", "TarotCard")
|
||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||
try:
|
||
earthman = DeckVariant.objects.get(slug="earthman")
|
||
except DeckVariant.DoesNotExist:
|
||
return
|
||
|
||
# Trump 7 name canonicalization
|
||
TarotCard.objects.filter(
|
||
deck_variant=earthman, arcana="MAJOR", number=7,
|
||
).update(name="Not-Doing")
|
||
|
||
for number, lvty, grav, rev in IMPLICIT:
|
||
TarotCard.objects.filter(
|
||
deck_variant=earthman, arcana="MAJOR", number=number,
|
||
).update(
|
||
levity_qualifier=lvty,
|
||
gravity_qualifier=grav,
|
||
levity_reversal=rev,
|
||
gravity_reversal=rev,
|
||
)
|
||
|
||
for number, le, ge, lr, gr in EXPLICIT:
|
||
TarotCard.objects.filter(
|
||
deck_variant=earthman, arcana="MAJOR", number=number,
|
||
).update(
|
||
levity_emanation=le,
|
||
gravity_emanation=ge,
|
||
levity_reversal=lr,
|
||
gravity_reversal=gr,
|
||
)
|
||
|
||
|
||
def reverse(apps, schema_editor):
|
||
TarotCard = apps.get_model("epic", "TarotCard")
|
||
DeckVariant = apps.get_model("epic", "DeckVariant")
|
||
try:
|
||
earthman = DeckVariant.objects.get(slug="earthman")
|
||
except DeckVariant.DoesNotExist:
|
||
return
|
||
|
||
TarotCard.objects.filter(
|
||
deck_variant=earthman, arcana="MAJOR", number=7,
|
||
).update(name="Not Doing")
|
||
|
||
for number, _lvty, _grav, _rev in IMPLICIT:
|
||
TarotCard.objects.filter(
|
||
deck_variant=earthman, arcana="MAJOR", number=number,
|
||
).update(
|
||
levity_qualifier="",
|
||
gravity_qualifier="",
|
||
levity_reversal="",
|
||
gravity_reversal="",
|
||
)
|
||
|
||
for number, _le, _ge, _lr, _gr in EXPLICIT:
|
||
TarotCard.objects.filter(
|
||
deck_variant=earthman, arcana="MAJOR", number=number,
|
||
).update(
|
||
levity_emanation="",
|
||
gravity_emanation="",
|
||
levity_reversal="",
|
||
gravity_reversal="",
|
||
)
|
||
|
||
|
||
class Migration(migrations.Migration):
|
||
|
||
dependencies = [
|
||
("epic", "0016_card49_bestowing_eagle"),
|
||
]
|
||
|
||
operations = [
|
||
migrations.RunPython(forward, reverse_code=reverse),
|
||
]
|