refactor: extract apply_applet_toggle, rooms_for_user & natus helpers to utils; DRY toggle views
- epic/utils.py (new): _planet_house, _compute_distinctions, rooms_for_user - applets/utils.py: apply_applet_toggle replaces 5 copy-pasted toggle loops - dashboard/views.py: use apply_applet_toggle; fix double free_tokens/tithe_tokens query in wallet(); promote _compute_distinctions import to module level - gameboard/views.py: use apply_applet_toggle & rooms_for_user; fix double free_tokens query in toggle_game_applets - billboard/views.py: use apply_applet_toggle & rooms_for_user - SCSS: %tt-token-fields placeholder in _tooltips.scss; _gameboard & _game-kit @extend it - epic/tests/unit/test_utils.py (new): coverage for _planet_house fallback path Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
41
src/apps/epic/utils.py
Normal file
41
src/apps/epic/utils.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from django.db.models import Q
|
||||
|
||||
from apps.epic.models import Room, RoomInvite
|
||||
|
||||
|
||||
def _planet_house(degree, cusps):
|
||||
"""Return 1-based house number for a planet at ecliptic degree.
|
||||
|
||||
cusps is the 12-element list from PySwiss where cusps[i] is the start of
|
||||
house i+1. Handles the wrap-around case where a cusp crosses 0°/360°.
|
||||
"""
|
||||
degree = degree % 360
|
||||
for i in range(12):
|
||||
start = cusps[i] % 360
|
||||
end = cusps[(i + 1) % 12] % 360
|
||||
if start < end:
|
||||
if start <= degree < end:
|
||||
return i + 1
|
||||
else: # wrap-around: e.g. cusp at 350° → next at 10°
|
||||
if degree >= start or degree < end:
|
||||
return i + 1
|
||||
return 1
|
||||
|
||||
|
||||
def _compute_distinctions(planets, houses):
|
||||
"""Return dict {house_number_str: planet_count} for all 12 houses."""
|
||||
cusps = houses['cusps']
|
||||
counts = {str(i): 0 for i in range(1, 13)}
|
||||
for planet_data in planets.values():
|
||||
h = _planet_house(planet_data['degree'], cusps)
|
||||
counts[str(h)] += 1
|
||||
return counts
|
||||
|
||||
|
||||
def rooms_for_user(user):
|
||||
"""Return a queryset of rooms the user owns, has a gate slot in, or is invited to."""
|
||||
return Room.objects.filter(
|
||||
Q(owner=user) |
|
||||
Q(gate_slots__gamer=user) |
|
||||
Q(invites__invitee_email=user.email, invites__status=RoomInvite.PENDING)
|
||||
).distinct()
|
||||
Reference in New Issue
Block a user