Django Channels role-select sprint: turn_changed, roles_revealed, role_select_start consumer handlers; WS URL changed from room_slug to room_id UUID; TableSeat model - room, gamer, slot_number, role, role_revealed, seat_position fields; Room.table_status field with ROLE_SELECT, SIG_SELECT, IN_GAME choices; migration 0006_table_status_and_table_seat; pick_roles and select_role views; _role_select_context helper; _notify_turn_changed, _notify_roles_revealed, _notify_role_select_start notifiers; all gate-mutation views now call _notify_gate_update; ChannelsFunctionalTest base class with serve_static, screenshot, dump helpers; SQLite TEST NAME set to file path for ChannelsLiveServerTestCase; InMemoryChannelLayer added to test CHANNEL_LAYERS settings; FT 5 and FT 6 now passing - active seat arc and turn advance via WS, no page refresh; room.js, gatekeeper.js, role-select.js added to apps/epic/static; applets.js, game-kit.js, dashboard.js, wallet.js relocated to app-scoped static dirs; room.html: hex table, table-seat arcs, card-stack, inventory panel, role-card hand, WS scripts; _room.scss: room-shell flex layout, .table-hex polygon clip-path, .table-seat and .seat-card-arc, .card-stack eligible/ineligible states, .card flip animation, .inv-role-card stacked hand, .role-select-backdrop; gear btn and room menu always position: fixed; 375 tests, 0 skipped
This commit is contained in:
@@ -29,6 +29,15 @@ class Room(models.Model):
|
||||
(INVITE_ONLY, "Invite Only"),
|
||||
]
|
||||
|
||||
ROLE_SELECT = "ROLE_SELECT"
|
||||
SIG_SELECT = "SIG_SELECT"
|
||||
IN_GAME = "IN_GAME"
|
||||
TABLE_STATUS_CHOICES = [
|
||||
(ROLE_SELECT, "Role Select"),
|
||||
(SIG_SELECT, "Significator Select"),
|
||||
(IN_GAME, "In Game"),
|
||||
]
|
||||
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
name = models.CharField(max_length=200)
|
||||
owner = models.ForeignKey(
|
||||
@@ -36,6 +45,9 @@ class Room(models.Model):
|
||||
)
|
||||
visibility = models.CharField(max_length=20, choices=VISIBILITY_CHOICES, default=PRIVATE)
|
||||
gate_status = models.CharField(max_length=20, choices=GATE_STATUS_CHOICES, default=GATHERING)
|
||||
table_status = models.CharField(
|
||||
max_length=20, choices=TABLE_STATUS_CHOICES, null=True, blank=True
|
||||
)
|
||||
renewal_period = models.DurationField(null=True, blank=True, default=timedelta(days=7))
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
board_state = models.JSONField(default=dict)
|
||||
@@ -133,3 +145,31 @@ def debit_token(user, slot, token):
|
||||
if not room.gate_slots.filter(status=GateSlot.EMPTY).exists():
|
||||
room.gate_status = Room.OPEN
|
||||
room.save()
|
||||
|
||||
|
||||
class TableSeat(models.Model):
|
||||
PC = "PC"
|
||||
BC = "BC"
|
||||
SC = "SC"
|
||||
AC = "AC"
|
||||
NC = "NC"
|
||||
EC = "EC"
|
||||
ROLE_CHOICES = [
|
||||
(PC, "Player"),
|
||||
(BC, "Builder"),
|
||||
(SC, "Shepherd"),
|
||||
(AC, "Alchemist"),
|
||||
(NC, "Narrator"),
|
||||
(EC, "Economist"),
|
||||
]
|
||||
PARTNER_MAP = {PC: BC, BC: PC, SC: AC, AC: SC, NC: EC, EC: NC}
|
||||
|
||||
room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name="table_seats")
|
||||
gamer = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, null=True, blank=True,
|
||||
on_delete=models.SET_NULL, related_name="table_seats"
|
||||
)
|
||||
slot_number = models.IntegerField()
|
||||
role = models.CharField(max_length=2, choices=ROLE_CHOICES, null=True, blank=True)
|
||||
role_revealed = models.BooleanField(default=False)
|
||||
seat_position = models.IntegerField(null=True, blank=True)
|
||||
|
||||
Reference in New Issue
Block a user