2026-03-13 00:31:17 -04:00
|
|
|
{% extends "core/base.html" %}
|
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
2026-03-17 00:24:23 -04:00
|
|
|
{% load static %}
|
2026-03-13 00:31:17 -04:00
|
|
|
|
2026-03-14 00:10:40 -04:00
|
|
|
{% block title_text %}Gameboard{% endblock title_text %}
|
|
|
|
|
{% block header_text %}<span>Game</span>room{% endblock header_text %}
|
|
|
|
|
|
2026-03-13 00:31:17 -04:00
|
|
|
{% block content %}
|
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
2026-03-17 00:24:23 -04:00
|
|
|
<div class="room-page" data-room-id="{{ room.id }}"
|
|
|
|
|
{% if room.table_status %}data-select-role-url="{% url 'epic:select_role' room.id %}"{% endif %}>
|
2026-04-06 00:48:25 -04:00
|
|
|
<div id="id_aperture_fill"></div>
|
2026-03-13 00:31:17 -04:00
|
|
|
<div class="room-shell">
|
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
2026-03-17 00:24:23 -04:00
|
|
|
<div id="id_game_table" class="room-table">
|
2026-04-04 14:51:49 -04:00
|
|
|
{% if room.table_status == "ROLE_SELECT" %}
|
|
|
|
|
<div id="id_pick_sigs_wrap"{% if starter_roles|length < 6 %} style="display:none"{% endif %}>
|
|
|
|
|
<form method="POST" action="{% url 'epic:pick_sigs' room.id %}">
|
|
|
|
|
{% csrf_token %}
|
2026-04-06 03:02:37 -04:00
|
|
|
<button id="id_pick_sigs_btn" type="submit" class="btn btn-primary">PICK<br>SIGS</button>
|
2026-04-04 14:51:49 -04:00
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
2026-04-01 23:24:17 -04:00
|
|
|
<div class="room-table-scene">
|
|
|
|
|
<div class="table-hex-border">
|
|
|
|
|
<div class="table-hex">
|
|
|
|
|
<div class="table-center">
|
2026-04-04 14:33:35 -04:00
|
|
|
{% if room.table_status == "ROLE_SELECT" %}
|
2026-04-04 14:51:49 -04:00
|
|
|
{% if card_stack_state %}
|
2026-04-04 14:33:35 -04:00
|
|
|
<div class="card-stack" data-state="{{ card_stack_state }}"
|
|
|
|
|
data-starter-roles="{{ starter_roles|join:',' }}"
|
|
|
|
|
data-user-slots="{{ user_slots|join:',' }}"
|
|
|
|
|
data-active-slot="{{ active_slot }}">
|
|
|
|
|
{% if card_stack_state == "ineligible" %}
|
|
|
|
|
<i class="fa-solid fa-ban"></i>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
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
2026-03-17 00:24:23 -04:00
|
|
|
{% endif %}
|
2026-04-09 01:17:24 -04:00
|
|
|
{% if room.table_status == "SKY_SELECT" %}
|
|
|
|
|
<button id="id_pick_sky_btn" class="btn btn-primary">PICK<br>SKY</button>
|
2026-04-13 00:34:05 -04:00
|
|
|
{% elif room.table_status == "SIG_SELECT" %}
|
|
|
|
|
<button id="id_pick_sky_btn" class="btn btn-primary" style="display:none">PICK<br>SKY</button>
|
|
|
|
|
{% if polarity_done %}
|
|
|
|
|
<p id="id_hex_waiting_msg">{% if user_polarity == "levity" %}Gravity settling . . .{% else %}Levity appraising . . .{% endif %}</p>
|
|
|
|
|
{% endif %}
|
2026-04-09 01:17:24 -04:00
|
|
|
{% endif %}
|
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
2026-03-17 00:24:23 -04:00
|
|
|
</div>
|
2026-04-01 23:24:17 -04:00
|
|
|
</div>
|
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
2026-03-17 00:24:23 -04:00
|
|
|
</div>
|
2026-04-05 22:01:23 -04:00
|
|
|
{# Seats — fa-chair layout persists from ROLE_SELECT through SIG_SELECT #}
|
2026-03-31 00:01:04 -04:00
|
|
|
{% for pos in gate_positions %}
|
|
|
|
|
<div class="table-seat{% if pos.role_label in starter_roles %} role-confirmed{% endif %}"
|
|
|
|
|
data-slot="{{ pos.slot.slot_number }}" data-role="{{ pos.role_label }}">
|
|
|
|
|
<i class="fa-solid fa-chair"></i>
|
|
|
|
|
<span class="seat-role-label">{{ pos.role_label }}</span>
|
|
|
|
|
{% if pos.role_label in starter_roles %}
|
|
|
|
|
<i class="position-status-icon fa-solid fa-circle-check"></i>
|
|
|
|
|
{% else %}
|
|
|
|
|
<i class="position-status-icon fa-solid fa-ban"></i>
|
|
|
|
|
{% endif %}
|
2026-03-25 01:50:06 -04:00
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
2026-04-01 23:24:17 -04:00
|
|
|
</div>
|
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
2026-03-17 00:24:23 -04:00
|
|
|
</div>
|
2026-03-13 00:31:17 -04:00
|
|
|
</div>
|
|
|
|
|
|
2026-04-13 00:34:05 -04:00
|
|
|
{# Sig Select overlay — suppressed once this gamer's polarity sigs are assigned #}
|
|
|
|
|
{% if room.table_status == "SIG_SELECT" and user_polarity and not polarity_done %}
|
2026-04-05 22:01:23 -04:00
|
|
|
{% include "apps/gameboard/_partials/_sig_select_overlay.html" %}
|
2026-03-25 01:50:06 -04:00
|
|
|
{% endif %}
|
|
|
|
|
|
PICK SKY overlay: D3 natal wheel, Character model, PySwiss aspects+tz
PySwiss:
- calculate_aspects() in calc.py (conjunction/sextile/square/trine/opposition with orbs)
- /api/tz/ endpoint (timezonefinder lat/lon → IANA timezone)
- aspects included in /api/chart/ response
- timezonefinder==8.2.2 added to requirements
- 14 new unit tests (test_calc.py) + 12 new integration tests (TimezoneApiTest, aspect fields)
Main app:
- Sign, Planet, AspectType, HouseLabel reference models + seeded migrations (0032–0033)
- Character model with birth_dt/lat/lon/place, house_system, chart_data, celtic_cross,
confirmed_at/retired_at lifecycle (migration 0034)
- natus_preview proxy view: calls PySwiss /api/chart/ + optional /api/tz/ auto-resolution,
computes planet-in-house distinctions, returns enriched JSON
- natus_save view: find-or-create draft Character, confirmed_at on action='confirm'
- natus-wheel.js: D3 v7 SVG natal wheel (elements pie, signs, houses, planets, aspects,
ASC/MC axes); NatusWheel.draw() / redraw() / clear()
- _natus_overlay.html: Nominatim place autocomplete (debounced 400ms), geolocation button
with reverse-geocode city name, live chart preview (debounced 300ms), tz auto-fill,
NVM / SAVE SKY footer; html.natus-open class toggle pattern
- _natus.scss: Gaussian backdrop+modal, two-column form|wheel layout, suggestion dropdown,
portrait collapse at 600px, landscape sidebar z-index sink
- room.html: include overlay when table_status == SKY_SELECT
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 02:09:26 -04:00
|
|
|
{# Natus (Pick Sky) overlay — natal chart entry #}
|
|
|
|
|
{% if room.table_status == "SKY_SELECT" %}
|
|
|
|
|
{% include "apps/gameboard/_partials/_natus_overlay.html" %}
|
|
|
|
|
{% endif %}
|
|
|
|
|
|
2026-03-31 00:01:04 -04:00
|
|
|
{% if room.gate_status != "RENEWAL_DUE" and room.table_status != "SIG_SELECT" %}
|
|
|
|
|
{% include "apps/gameboard/_partials/_table_positions.html" %}
|
|
|
|
|
{% endif %}
|
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
2026-03-17 00:24:23 -04:00
|
|
|
{% if not room.table_status and room.gate_status != "RENEWAL_DUE" %}
|
2026-03-14 00:34:07 -04:00
|
|
|
{% include "apps/gameboard/_partials/_gatekeeper.html" %}
|
|
|
|
|
{% endif %}
|
2026-03-31 00:01:04 -04:00
|
|
|
{% if room.table_status %}
|
2026-04-05 01:14:31 -04:00
|
|
|
<div id="id_tray_wrap"{% if room.table_status == "ROLE_SELECT" and starter_roles|length < 6 %} class="role-select-phase"{% endif %}>
|
2026-03-28 18:52:46 -04:00
|
|
|
<div id="id_tray_handle">
|
|
|
|
|
<div id="id_tray_grip"></div>
|
|
|
|
|
<button id="id_tray_btn" aria-label="Open seat tray">
|
|
|
|
|
<i class="fa-solid fa-dice-d20"></i>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
2026-04-09 01:17:24 -04:00
|
|
|
<div id="id_tray" style="display:none"><div id="id_tray_grid" data-role-icons-url="{% static 'apps/epic/icons/cards-roles/' %}">{% if my_tray_role %}<div class="tray-cell tray-role-card" data-role="{{ my_tray_role }}"><img src="{% static my_tray_scrawl_static_path %}" alt="{{ my_tray_role }}"></div>{% else %}<div class="tray-cell"></div>{% endif %}{% if my_tray_sig %}<div class="tray-cell tray-sig-card"><img src="{% static 'apps/epic/icons/cards-sigs/Blank.svg' %}" alt="{{ my_tray_sig.name }}"></div>{% else %}<div class="tray-cell"></div>{% endif %}{% for i in "345678" %}<div class="tray-cell"></div>{% endfor %}</div></div>
|
2026-03-28 18:52:46 -04:00
|
|
|
</div>
|
2026-03-31 00:01:04 -04:00
|
|
|
{% endif %}
|
2026-03-14 00:10:40 -04:00
|
|
|
{% include "apps/gameboard/_partials/_room_gear.html" %}
|
2026-03-13 00:31:17 -04:00
|
|
|
</div>
|
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
2026-03-17 00:24:23 -04:00
|
|
|
{% endblock content %}
|
|
|
|
|
|
|
|
|
|
{% block scripts %}
|
|
|
|
|
<script src="{% static 'apps/epic/room.js' %}"></script>
|
|
|
|
|
<script src="{% static 'apps/epic/gatekeeper.js' %}"></script>
|
|
|
|
|
<script src="{% static 'apps/epic/role-select.js' %}"></script>
|
2026-03-25 11:03:53 -04:00
|
|
|
<script src="{% static 'apps/epic/sig-select.js' %}"></script>
|
2026-03-28 18:52:46 -04:00
|
|
|
<script src="{% static 'apps/epic/tray.js' %}"></script>
|
2026-04-05 22:01:23 -04:00
|
|
|
{% endblock scripts %}
|