import uuid from datetime import timedelta from django.db import models from django.db.models.signals import post_save from django.dispatch import receiver from django.conf import settings from django.utils import timezone from apps.lyric.models import Token class Room(models.Model): GATHERING = "GATHERING" OPEN = "OPEN" RENEWAL_DUE = "RENEWAL_DUE" GATE_STATUS_CHOICES = [ (GATHERING, "GATHERING GAMERS"), (OPEN, "Open"), (RENEWAL_DUE, "Renewal Due"), ] PRIVATE = "PRIVATE" PUBLIC = "PUBLIC" INVITE_ONLY = "INVITE ONLY" VISIBILITY_CHOICES = [ (PRIVATE, "Private"), (PUBLIC, "Public"), (INVITE_ONLY, "Invite Only"), ] id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=200) owner = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="owned_rooms" ) visibility = models.CharField(max_length=20, choices=VISIBILITY_CHOICES, default=PRIVATE) gate_status = models.CharField(max_length=20, choices=GATE_STATUS_CHOICES, default=GATHERING) renewal_period = models.DurationField(null=True, blank=True, default=timedelta(days=7)) created_at = models.DateTimeField(auto_now_add=True) board_state = models.JSONField(default=dict) seed_count = models.IntegerField(default=12) class GateSlot(models.Model): EMPTY = "EMPTY" RESERVED = "RESERVED" FILLED = "FILLED" STATUS_CHOICES = [ (EMPTY, "Empty"), (RESERVED, "Reserved"), (FILLED, "Filled"), ] room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name="gate_slots") slot_number = models.IntegerField() gamer = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="gate_slots" ) funded_by = models.ForeignKey( settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL, related_name="funded_slots" ) status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=EMPTY) reserved_at = models.DateTimeField(null=True, blank=True) filled_at = models.DateTimeField(null=True, blank=True) debited_token_type = models.CharField(max_length=8, null=True, blank=True) debited_token_expires_at = models.DateTimeField(null=True, blank=True) class RoomInvite(models.Model): PENDING = "PENDING" ACCEPTED = "ACCEPTED" DECLINED = "DECLINED" STATUS_CHOICES = [ (PENDING, "Pending"), (ACCEPTED, "Accepted"), (DECLINED, "Declined"), ] room = models.ForeignKey(Room, on_delete=models.CASCADE, related_name="invites") inviter = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="sent_invites" ) invitee_email = models.EmailField() status = models.CharField(max_length=10, choices=STATUS_CHOICES, default=PENDING) created_at = models.DateTimeField(auto_now_add=True) @receiver(post_save, sender=Room) def create_gate_slots(sender, instance, created, **kwargs): if created: for i in range(1, 7): GateSlot.objects.create(room=instance, slot_number=i) def select_token(user): if user.is_staff: pass_token = user.tokens.filter(token_type=Token.PASS).first() if pass_token: return pass_token coin = user.tokens.filter(token_type=Token.COIN, current_room__isnull=True).first() if coin: return coin free = user.tokens.filter( token_type=Token.FREE, expires_at__gt=timezone.now(), ).order_by("expires_at").first() if free: return free return user.tokens.filter(token_type=Token.TITHE).first() def debit_token(user, slot, token): slot.debited_token_type = token.token_type if token.token_type == Token.COIN: token.current_room = slot.room period = slot.room.renewal_period or timedelta(days=7) token.next_ready_at = timezone.now() + period token.save() elif token.token_type != Token.PASS: slot.debited_token_expires_at = token.expires_at token.delete() slot.gamer = user slot.status = GateSlot.FILLED slot.filled_at = timezone.now() slot.save() room = slot.room if not room.gate_slots.filter(status=GateSlot.EMPTY).exists(): room.gate_status = Room.OPEN room.save()