anagrams-with-friends/models.py
2022-08-28 02:52:52 -07:00

141 lines
5.2 KiB
Python

import random
import string
from django.db import models, transaction
from django.utils import timezone
def generate_code(length):
return "".join([random.choice(string.ascii_lowercase)
for i in range(length)])
class Game(models.Model):
ACCESS_CODE_LENGTH = 6
access_code = models.CharField(db_index=True, unique=True,
max_length=ACCESS_CODE_LENGTH)
GAME_PHASE_LOBBY = 0
GAME_PHASE_PROPOSE = 1
GAME_PHASE_CLUE = 2
GAME_PHASE_SOLVE = 3
GAME_PHASE_END = 4
game_phase = models.IntegerField(default=GAME_PHASE_LOBBY)
default_cards_per_player = models.IntegerField()
num_initial_free_clues = models.IntegerField()
num_unlock_clues_per_player = models.IntegerField()
num_unlockable_clues = models.IntegerField()
remaining_deck_order = models.CharField(max_length=64)
created = models.DateTimeField()
ended = models.DateTimeField(null=True, default=None)
next_game = models.OneToOneField('self', null=True, default=None,
related_name='previous_game')
# from http://stackoverflow.com/a/11821832
def save(self, *args, **kwargs):
# object is being created, thus no primary key field yet
if not self.pk:
# Make sure access_code is unique before using it.
access_code = generate_code(Game.ACCESS_CODE_LENGTH)
while Game.objects.filter(access_code=access_code).exists():
access_code = generate_code(Game.ACCESS_CODE_LENGTH)
self.access_code = access_code
self.created = timezone.now()
if self.ended is None and self.game_phase == Game.GAME_PHASE_END:
self.ended = timezone.now()
super(Game, self).save(*args, **kwargs)
_game_phase_strings = {
GAME_PHASE_LOBBY: 'lobby',
GAME_PHASE_PROPOSE: 'propose',
GAME_PHASE_CLUE: 'clue',
GAME_PHASE_SOLVE: 'solve',
GAME_PHASE_END: 'end',
}
def game_phase_string(self):
return Game._game_phase_strings[self.game_phase]
def num_players(self):
return self.player_set.filter(is_player=True).count()
def num_non_player_stands(self):
return self.player_set.filter(is_player=False).count()
@transaction.atomic
def create_or_get_next_game(self):
if self.next_game is None and self.game_phase == self.GAME_PHASE_END:
self.next_game = Game.objects.create()
self.save()
return self.next_game
class Player(models.Model):
game = models.ForeignKey(Game, on_delete=models.CASCADE, db_index=True)
SECRET_ID_LENGTH = 8
secret_id = models.CharField(db_index=True, max_length=SECRET_ID_LENGTH)
name = models.CharField(max_length=80)
player_num = models.IntegerField()
is_player = models.BooleanField() # as opposed to non-player stack
ready = models.BooleanField(default=False)
# num_cards is redundant with cards, but used during setup.
num_cards = models.IntegerField()
cards = models.CharField(max_length=16)
ready = models.BooleanField(default=False)
joined = models.DateTimeField()
last_accessed = models.DateTimeField()
# names are unique in a game
unique_together = (("game", "name"), ("game", "secret_id"))
class Turn(models.Model):
game = models.ForeignKey(Game, on_delete=models.CASCADE, db_index=True)
turn_num = models.IntegerField()
visible_cards = models.CharField(max_length=64)
clue = models.OneToOneField('ClueProposal', null=True)
class ClueProposal(models.Model):
turn = models.ForeignKey(Turn, on_delete=models.CASCADE, db_index=True)
player = models.ForeignKey(Player, on_delete=models.CASCADE, db_index=True)
card_indexes = models.CharField(max_length=80)
class ClueProposalVote(models.Model):
turn = models.ForeignKey(Turn, on_delete=models.CASCADE, db_index=True)
player = models.ForeignKey(Player,
on_delete=models.CASCADE,
db_index=True)
clue_proposal = models.OneToOneField(ClueProposal)
class AdvanceDecision(models.Model):
turn = models.ForeignKey(Turn, on_delete=models.CASCADE, db_index=True)
player = models.ForeignKey(Player,
on_delete=models.CASCADE,
db_index=True)
advance_card = models.BooleanField(null=True)
guess = models.CharField(null=True, max_length=1)
class BonusCardGuess(models.Model):
turn = models.ForeignKey(Turn, on_delete=models.CASCADE, db_index=True)
player = models.ForeignKey(Player,
on_delete=models.CASCADE,
db_index=True)
guess = models.CharField(null=True, max_length=1)
class Notes(models.Model):
turn = models.ForeignKey(Turn, on_delete=models.CASCADE, db_index=True)
player = models.ForeignKey(Player,
on_delete=models.CASCADE,
db_index=True)
notes = models.CharField(max_length=80)
class Solve(models.Model):
player = models.ForeignKey(Player,
on_delete=models.CASCADE,
db_index=True)
card_indexes = models.CharField(max_length=80)