Files
python-tdd/src/apps/epic/utils.py

64 lines
2.4 KiB
Python
Raw Normal View History

from django.db.models import Q
from apps.epic.models import Room, RoomInvite
# ── Game-wide constants ────────────────────────────────────────────────────
# Reversal probability applied to any card pulled from a stack, anywhere in
# the game (PICK SEA initially; future phases — gameplay draws etc. — will
# share this single source of truth). Stub for a future per-user profile
# override: callers MUST go through stack_reversal_probability(user, room)
# rather than referencing the constant directly so the user-config hookup is
# a one-line change inside the helper.
STACK_REVERSAL_PROBABILITY = 0.25
def stack_reversal_probability(user=None, room=None):
"""Reversal probability for a draw stack in this user's context.
Current behavior: returns the module default for everyone. Plumbing point
for a forthcoming per-user setting when that lands, swap the body to
something like `return getattr(user.profile, 'reversal_rate', STACK_REVERSAL_PROBABILITY)`
and every call site picks up the per-user value automatically.
"""
return STACK_REVERSAL_PROBABILITY
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()