diff --git a/src/apps/epic/views.py b/src/apps/epic/views.py index 17e80e6..2c1ba63 100644 --- a/src/apps/epic/views.py +++ b/src/apps/epic/views.py @@ -803,7 +803,48 @@ def sig_ready(request, room_id): @login_required def sig_confirm(request, room_id): - """No-op: polarity confirmation is now driven server-side by threading.Timer in tasks.py.""" + """Finalise polarity group once the countdown fires. + POST body: polarity=levity|gravity + """ + if request.method != "POST": + return HttpResponse(status=405) + room = Room.objects.get(id=room_id) + if room.table_status != Room.SIG_SELECT: + return HttpResponse(status=400) + user_seat = _canonical_user_seat(room, request.user) + if user_seat is None: + return HttpResponse(status=403) + + polarity = request.POST.get("polarity", SigReservation.LEVITY) + polarity_roles = _LEVITY_ROLES if polarity == SigReservation.LEVITY else _GRAVITY_ROLES + + # Idempotency: seats already have significators + if not room.table_seats.filter(role__in=polarity_roles, significator__isnull=True).exists(): + return HttpResponse(status=200) + + # All three in the polarity group must be ready + ready_count = SigReservation.objects.filter(room=room, polarity=polarity, ready=True).count() + if ready_count < 3: + return HttpResponse(status=400) + + # Assign significators from reservations + reservations = list( + SigReservation.objects.filter(room=room, polarity=polarity, ready=True) + .select_related('seat', 'card') + ) + for res in reservations: + if res.seat: + res.seat.significator = res.card + res.seat.save(update_fields=['significator']) + SigReservation.objects.filter(room=room, polarity=polarity).update(countdown_remaining=None) + + _notify_polarity_room_done(room_id, polarity) + + # If both polarities are now done, advance to SKY_SELECT + if not room.table_seats.filter(significator__isnull=True).exists(): + Room.objects.filter(id=room_id).update(table_status=Room.SKY_SELECT) + _notify_pick_sky_available(room_id) + return HttpResponse(status=200)