SEED MAP shared wheel rim: the table's OWN sky (planets-only, canonical signs) rings the tessellation — one frame for all six gamers — TDD
The Voronoi felt gains a stripped sky-wheel rim drawn from the ROOM's own sky
(Room.sky_chart) — identical for every gamer, updating toward the shared map —
with the tessellation sized into the wheel's freed hub. Roadmap step 21, Step
2's coordinate frame.
- Room.convened_at + Room.sky_chart (migration 0019); pick_roles stamps
convened_at at gate-close (stamp only — no HTTP on the transition)
- epic.table_sky: lazy planets-only chart via PySwiss at the null location
(geocentric longitudes need only the convened TIME; houses/ASC/MC need a
birth LOCATION a virtual table lacks → omitted), cached on Room.sky_chart;
legacy rooms key off created_at; seated-gamer gated, 502 on PySwiss down
- SkyWheel.drawRim(svg, data): pure static renderer — canonical asc=0 frame,
signs ring + planet glyphs only, NO element ring / centre disc / houses /
axes / aspects / tooltips; never writes the interactive wheel's singleton
state; returns {size, cx, cy, r, hubR} so the felt sizes the map into the hub
- _seed_map_overlay.html: rim draws on open; map svg shrinks to 2×hubR +
.voronoi-map--rimmed clip; lazy table-sky fetch on open; preload-then-repaint
so a cold-cache open doesn't strand the zodiac glyphs; ResizeObserver on the
col (not the self-sized map svg)
- _sky.scss: stacked centred svgs in .seed-map-col; .seed-wheel pointer-events
none; circle clip on the rimmed map
- room_sky_json ctx in _role_select_context; rootvars: --sixUser/--octUser
nudged within the Trs ramp (parallel palette tune)
- drawRim Jasmine suite (R1–R6: signs+planets, strip, hub geometry, static
placement, singleton untouched, signs-only fallback) in both spec copies;
epic TableSkyViewTest + convened_at stamp + seed-overlay rim ITs; FT rim
assertions (12 signs, 3 planets, no stripped/located layers, hub sizing)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
"""Functional test for the SEED MAP felt — Voronoi map, roadmap step 21, Step 1.
|
||||
"""Functional test for the SEED MAP felt — Voronoi map, roadmap step 21.
|
||||
|
||||
The SEED MAP felt is the inline --duoUser sibling of the CAST SKY / DRAW SEA
|
||||
felts: once the seat's Celtic-Cross hand is complete (hand_complete), SEED MAP
|
||||
@@ -7,6 +7,13 @@ d3-delaunay DUAL GRAPH — a Voronoi cell layer (territory) + a Delaunay edge
|
||||
layer (adjacency). STEP 1 is placeholder-seeded (card-driven seeding is Step 2),
|
||||
so we assert only that the dual graph renders both layers.
|
||||
|
||||
Step 2's first piece — the SHARED WHEEL RIM: the stripped sky wheel (signs ring
|
||||
at canonical orientation + planet glyphs; NO element ring, centre disc, houses
|
||||
or axes — a virtual table has a convened TIME but no birth LOCATION) rings the
|
||||
tessellation, drawn from the ROOM'S OWN sky (Room.sky_chart, identical for all
|
||||
six gamers). The map svg shrinks into the wheel's freed hub. The fixture
|
||||
pre-stores Room.sky_chart so the lazy PySwiss compute path never fires HTTP.
|
||||
|
||||
Plain FunctionalTest (NOT @tag("channels")): the felt-open is pure client-side.
|
||||
We seed a CONFIRMED Character with a complete hand directly in the DB, so there
|
||||
is no WebSocket sky-confirm flow to drive — unlike the sky/sea FTs.
|
||||
@@ -25,6 +32,17 @@ from .test_game_room_select_sea import _make_sky_confirmed_room
|
||||
|
||||
_HAND_POSITIONS = ["cover", "cross", "crown", "lay", "leave", "loom"]
|
||||
|
||||
# The room's own sky — planets only (location-independent), mirroring the
|
||||
# Jasmine ROOM_SKY fixture. Mercury retrograde exercises the ℞ badge.
|
||||
_ROOM_SKY = {
|
||||
"planets": {
|
||||
"Sun": {"sign": "Pisces", "degree": 338.4, "retrograde": False},
|
||||
"Moon": {"sign": "Capricorn", "degree": 295.1, "retrograde": False},
|
||||
"Mercury": {"sign": "Aquarius", "degree": 312.8, "retrograde": True},
|
||||
},
|
||||
"aspects": [],
|
||||
}
|
||||
|
||||
|
||||
class SeedMapFeltTest(FunctionalTest):
|
||||
def setUp(self):
|
||||
@@ -53,6 +71,10 @@ class SeedMapFeltTest(FunctionalTest):
|
||||
celtic_cross holds `hand_len` placed cards. hand_len>=6 => hand_complete
|
||||
=> SEED MAP is the live phase btn + the felt renders."""
|
||||
room, seat = _make_sky_confirmed_room(self.live_server_url, self.gamer, self.earthman)
|
||||
# Pre-store the table's own sky so the rim renders without the lazy
|
||||
# PySwiss compute (no live HTTP from FTs).
|
||||
room.sky_chart = _ROOM_SKY
|
||||
room.save(update_fields=["sky_chart"])
|
||||
hand = [
|
||||
{"position": p, "card_id": self.card.id, "reversed": False, "polarity": "gravity"}
|
||||
for p in _HAND_POSITIONS[:hand_len]
|
||||
@@ -67,8 +89,8 @@ class SeedMapFeltTest(FunctionalTest):
|
||||
def _room_url(self, room):
|
||||
return self.live_server_url + reverse("epic:room", kwargs={"room_id": room.id})
|
||||
|
||||
def test_seed_map_felt_opens_and_paints_dual_graph(self):
|
||||
room = self._seed_room(hand_len=6)
|
||||
def _open_seed_felt(self, room):
|
||||
"""Load the room, wait for SEED MAP to go live, click it open."""
|
||||
self.create_pre_authenticated_session("founder@test.io")
|
||||
self.browser.get(self._room_url(room))
|
||||
|
||||
@@ -88,6 +110,10 @@ class SeedMapFeltTest(FunctionalTest):
|
||||
))
|
||||
self.wait_for(_click_and_assert_open)
|
||||
|
||||
def test_seed_map_felt_opens_and_paints_dual_graph(self):
|
||||
room = self._seed_room(hand_len=6)
|
||||
self._open_seed_felt(room)
|
||||
|
||||
self.assertTrue(
|
||||
self.browser.find_element(By.ID, "id_seed_map_overlay").is_displayed()
|
||||
)
|
||||
@@ -105,6 +131,58 @@ class SeedMapFeltTest(FunctionalTest):
|
||||
), 1,
|
||||
)
|
||||
|
||||
def test_seed_map_felt_rings_tessellation_with_room_sky_rim(self):
|
||||
"""Step 2's shared frame: the stripped sky wheel — canonical signs ring +
|
||||
the ROOM's own planets, NOTHING location-bound (no houses/axes) and none
|
||||
of the stripped chrome (element ring / centre disc / aspect web) — rings
|
||||
the tessellation, which shrinks into the wheel's freed hub."""
|
||||
room = self._seed_room(hand_len=6)
|
||||
self._open_seed_felt(room)
|
||||
|
||||
# The rim paints: 12 canonical sign slices + the room sky's 3 planets.
|
||||
self.wait_for(lambda: self.assertEqual(
|
||||
self.browser.execute_script(
|
||||
"return document.querySelectorAll('#id_seed_wheel_svg .nw-sign-group').length"
|
||||
), 12,
|
||||
))
|
||||
self.assertEqual(
|
||||
self.browser.execute_script(
|
||||
"return document.querySelectorAll('#id_seed_wheel_svg .nw-planet-group').length"
|
||||
), 3,
|
||||
)
|
||||
|
||||
# The strip: no element ring / centre disc / aspect web, and no
|
||||
# location-bound layers (houses, ASC/MC axes) on a shared rim.
|
||||
for cls in ["nw-elements", "nw-inner-disc", "nw-aspects", "nw-houses", "nw-axes"]:
|
||||
self.assertEqual(
|
||||
self.browser.execute_script(
|
||||
f"return document.querySelectorAll('#id_seed_wheel_svg .{cls}').length"
|
||||
), 0, f"expected no .{cls} on the shared rim",
|
||||
)
|
||||
|
||||
# The tessellation sits INSIDE the rim: the map svg is shrunk square
|
||||
# into the wheel's hub (2 × hubR = 2 × 0.52 × 0.46 × wheel span) and
|
||||
# carries the rimmed clip class.
|
||||
map_w, map_h, col_w, col_h = self.browser.execute_script(
|
||||
"const m = document.getElementById('id_seed_map_svg'),"
|
||||
" c = m.closest('.seed-map-col');"
|
||||
"return [m.clientWidth, m.clientHeight, c.clientWidth, c.clientHeight];"
|
||||
)
|
||||
self.assertEqual(map_w, map_h) # square
|
||||
self.assertLess(map_w, min(col_w, col_h)) # inside the wheel
|
||||
self.assertAlmostEqual( # = the freed hub
|
||||
map_w, 2 * 0.52 * 0.46 * min(col_w, col_h), delta=2,
|
||||
)
|
||||
self.assertIn("voronoi-map--rimmed",
|
||||
self.browser.find_element(By.ID, "id_seed_map_svg").get_attribute("class"))
|
||||
|
||||
# And the dual graph still paints inside the hub.
|
||||
self.assertGreaterEqual(
|
||||
self.browser.execute_script(
|
||||
"return document.querySelectorAll('#id_seed_map_svg .voronoi-cell').length"
|
||||
), 1,
|
||||
)
|
||||
|
||||
def test_seed_map_felt_absent_until_hand_complete(self):
|
||||
room = self._seed_room(hand_len=5) # only 5 placed → NOT hand_complete
|
||||
self.create_pre_authenticated_session("founder@test.io")
|
||||
|
||||
Reference in New Issue
Block a user