sea select scroll log: publish a Role<->Celtic-position affinity on the completing draw; redact + relinquish on DEL; re-publish on re-draw — TDD
The gameroom DRAW SEA phase now writes drama provenance, mirroring sig/sky. When a gamer's 6-card Celtic Cross COMPLETES, a SEA_DRAWN Scroll log publishes their affinity with the card sitting in their Role-correlated position.
- epic/views.py: ROLE_POSITION_MAP — the user's sixfold index (PC->crown, NC->leave, EC->loom, SC->cover, AC->cross, BC->lay; roles rotate each round, so a seat's CURRENT role drives it) + SEA_POSITION_LABELS (each spread's display label for a position KEY; Waite-Smith's Behind/Before/Beneath + Escape-Velocity's Leave/Loom/Lay both key to the same index). sea_save publishes SEA_DRAWN on the <6->6 completing transition only (a reload that re-POSTs the full hand can't double-publish); a re-draw first redacts the standing relinquishment, then publishes anew. sea_delete redacts the published affinity (the strikethrough) + records SEA_RELINQUISHED in its wake (the redact-pair). _sea_affinity_for mirrors SIG_READY's polarity-qualified name_title + corner abbrev; _redact_standing_sea_event tests 'not retracted' in PYTHON (the SQLite JSONField exclude-NULL trap).
- drama/models.py: SEA_DRAWN + SEA_RELINQUISHED verbs + to_prose ('draws {poss} Celtic Cross, finding affinity with the {card}{abbrev} in the {Position}.' / 'relinquishes {poss} affinity with the {card}.'); 'The ' stripped so a levity/gravity qualifier butts the proper name. The generic struck/retracted property renders the strikethrough + data-label=redact in _scroll.html unchanged.
TDD: 4 drama prose ITs (affinity statement, spread-label passthrough, relinquishment, struck-when-retracted) + 7 epic ITs (publish-on-complete, position=crown for PC, none-before-complete, no-double-publish-on-reload, DEL redacts+relinquishes, re-draw redacts-the-relinquishment+republishes, DEL-noop-when-nothing-published). 459 drama + epic-view ITs green.
- bundled (parallel work): rootvars.scss --sixUser/--sepUser/--octUser slot reassignments across the forest/khaki/blade palettes (tuning the new reelhouse h2 bgs) + a new --terMrb.
[[project-sea-select-scroll-provenance]] [[feedback-jsonfield-exclude-sqlite-null]]
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,12 @@ class GameEvent(models.Model):
|
||||
SIG_UNREADY = "sig_unready"
|
||||
# Sky Select phase
|
||||
SKY_SAVED = "sky_saved"
|
||||
# Sea Select phase — Role↔Celtic-position affinity provenance. SEA_DRAWN
|
||||
# publishes on hand-complete; SEA_RELINQUISHED is the let-go entry left in
|
||||
# the redact-pair's wake when the spread is DELeted (the SEA_DRAWN gets
|
||||
# `retracted` + a re-draw later retracts the relinquishment in turn).
|
||||
SEA_DRAWN = "sea_drawn"
|
||||
SEA_RELINQUISHED = "sea_relinquished"
|
||||
|
||||
VERB_CHOICES = [
|
||||
(ROOM_CREATED, "Room created"),
|
||||
@@ -40,6 +46,8 @@ class GameEvent(models.Model):
|
||||
(SIG_READY, "Sig claim staked"),
|
||||
(SIG_UNREADY, "Sig claim withdrawn"),
|
||||
(SKY_SAVED, "Sky saved"),
|
||||
(SEA_DRAWN, "Sea drawn"),
|
||||
(SEA_RELINQUISHED, "Sea relinquished"),
|
||||
]
|
||||
|
||||
room = models.ForeignKey(
|
||||
@@ -154,6 +162,31 @@ class GameEvent(models.Model):
|
||||
f"beholds the skyscape of {poss} birth, "
|
||||
f"which yields {obj} equal {joined} capacities."
|
||||
)
|
||||
if self.verb == self.SEA_DRAWN:
|
||||
# Affinity statement: the card drawn into the gamer's Role-correlated
|
||||
# Celtic position. `card_name`/`corner_rank`/`suit_icon` mirror
|
||||
# SIG_READY (qualifier-prefixed name + abbrev, "The " stripped so a
|
||||
# qualifier butts the proper name); `position_label` is the
|
||||
# spread-specific label for the role's position key.
|
||||
card_name = d.get("card_name", "a card")
|
||||
corner_rank = d.get("corner_rank", "")
|
||||
suit_icon = d.get("suit_icon", "")
|
||||
position_label = d.get("position_label", "spread")
|
||||
if corner_rank:
|
||||
icon_html = f' <i class="fa-solid {suit_icon}"></i>' if suit_icon else ""
|
||||
abbrev = f" ({corner_rank}{icon_html})"
|
||||
else:
|
||||
abbrev = ""
|
||||
card_name = card_name.replace("The ", "", 1)
|
||||
_, _, poss = _actor_pronouns(self.actor)
|
||||
return (
|
||||
f"draws {poss} Celtic Cross, finding affinity with "
|
||||
f"the {card_name}{abbrev} in the {position_label}."
|
||||
)
|
||||
if self.verb == self.SEA_RELINQUISHED:
|
||||
card_name = d.get("card_name", "a card").replace("The ", "", 1)
|
||||
_, _, poss = _actor_pronouns(self.actor)
|
||||
return f"relinquishes {poss} affinity with the {card_name}."
|
||||
return self.verb
|
||||
|
||||
@property
|
||||
|
||||
Reference in New Issue
Block a user