diff --git a/src/apps/epic/models.py b/src/apps/epic/models.py index a2f1883..039cdfe 100644 --- a/src/apps/epic/models.py +++ b/src/apps/epic/models.py @@ -421,6 +421,19 @@ class SigReservation(models.Model): # ── Significator deck helpers ───────────────────────────────────────────────── +def _room_deck_variant(room): + """Return the DeckVariant in use for this room. + + Looks up the deck committed to any TableSeat in the room (all seats share the + same deck per game). Falls back to the room owner's equipped_deck for rooms + created before deck contribution was wired. + """ + seat = room.table_seats.filter(deck_variant__isnull=False).first() + if seat: + return seat.deck_variant + return room.owner.equipped_deck + + def sig_deck_cards(room): """Return 36 TarotCard objects forming the Significator deck (18 unique × 2). @@ -429,7 +442,7 @@ def sig_deck_cards(room): NC/EC pair → MAJOR arcana numbers 0 and 1: 2 unique Total: 18 unique × 2 (levity + gravity piles) = 36 cards. """ - deck_variant = room.owner.equipped_deck + deck_variant = _room_deck_variant(room) if deck_variant is None: return [] wands_crowns = list(TarotCard.objects.filter( @@ -455,7 +468,7 @@ def sig_deck_cards(room): def _sig_unique_cards(room): """Return the 18 unique TarotCard objects that form one sig pile.""" - deck_variant = room.owner.equipped_deck + deck_variant = _room_deck_variant(room) if deck_variant is None: return [] wands_crowns = list(TarotCard.objects.filter( diff --git a/src/functional_tests/management/commands/setup_sig_session.py b/src/functional_tests/management/commands/setup_sig_session.py index 8c5ecbe..634f1f7 100644 --- a/src/functional_tests/management/commands/setup_sig_session.py +++ b/src/functional_tests/management/commands/setup_sig_session.py @@ -2,8 +2,13 @@ Management command for manual multi-user sig-select testing. Creates (or reuses) a room with all 6 gate slots filled, roles assigned, -and table_status=SIG_SELECT. Prints one pre-auth URL per gamer so you can -paste them into 6 Firefox Multi-Account Container tabs. +deck contributions wired, and table_status=SIG_SELECT. Prints one pre-auth +URL per gamer so you can paste them into 6 Firefox Multi-Account Container tabs. + +Deck contribution by role pair (same segment, levity vs gravity pole): + PC & BC → Brands + Crowns (levity / gravity) + SC & AC → Blades + Grails (levity / gravity) + NC & EC → Trumps (levity / gravity) Usage: python src/manage.py setup_sig_session @@ -15,7 +20,7 @@ from django.contrib.auth import BACKEND_SESSION_KEY, HASH_SESSION_KEY, SESSION_K from django.contrib.sessions.backends.db import SessionStore from django.core.management.base import BaseCommand -from apps.epic.models import DeckVariant, GateSlot, Room, TableSeat, TarotCard +from apps.epic.models import DeckVariant, GateSlot, Room, TableSeat from apps.lyric.models import User @@ -31,28 +36,6 @@ GAMERS = [ ROLES = ["PC", "NC", "EC", "SC", "AC", "BC"] -def _ensure_earthman(): - """Return (or create) the Earthman DeckVariant with enough sig-deck cards seeded.""" - earthman, _ = DeckVariant.objects.get_or_create( - slug="earthman", - defaults={"name": "Earthman Deck", "card_count": 108, "is_default": True}, - ) - _NAME = {11: "Maid", 12: "Jack", 13: "Queen", 14: "King"} - for suit in ("WANDS", "PENTACLES", "SWORDS", "CUPS"): - for number in (11, 12, 13, 14): - TarotCard.objects.get_or_create( - deck_variant=earthman, - slug=f"{_NAME[number].lower()}-of-{suit.lower()}-em", - defaults={ - "arcana": "MINOR", - "suit": suit, - "number": number, - "name": f"{_NAME[number]} of {suit.capitalize()}", - }, - ) - return earthman - - def _make_session(user): session = SessionStore() session[SESSION_KEY] = str(user.pk) @@ -71,7 +54,7 @@ class Command(BaseCommand): def handle(self, *args, **options): base_url = options["base_url"].rstrip("/") - earthman = _ensure_earthman() + earthman = DeckVariant.objects.get(slug="earthman") # ── Users ──────────────────────────────────────────────────────────── users = [] @@ -79,9 +62,11 @@ class Command(BaseCommand): user, _ = User.objects.get_or_create(email=email) user.is_staff = True user.is_superuser = True - if not user.equipped_deck: - user.equipped_deck = earthman + # Deck will be assigned to seat below; ensure it's in unlocked_decks + # but leave equipped_deck=None (seat assignment owns it) + user.equipped_deck = None user.save() + user.unlocked_decks.add(earthman) users.append(user) # ── Room ───────────────────────────────────────────────────────────── @@ -104,11 +89,21 @@ class Command(BaseCommand): room.gate_status = Room.OPEN room.save() - # ── Table seats + roles ────────────────────────────────────────────── + # ── Table seats + roles + deck contributions ───────────────────────── + # PC/NC/SC → levity pole; BC/EC/AC → gravity pole. + # Each role pair shares a deck segment: + # PC & BC → Brands + Crowns + # SC & AC → Blades + Grails + # NC & EC → Trumps for i, (user, role) in enumerate(zip(users, ROLES), start=1): TableSeat.objects.update_or_create( room=room, slot_number=i, - defaults={"gamer": user, "role": role, "role_revealed": True}, + defaults={ + "gamer": user, + "role": role, + "role_revealed": True, + "deck_variant": earthman, + }, ) room.table_status = Room.SIG_SELECT