116 lines
3.8 KiB
Python
116 lines
3.8 KiB
Python
from __future__ import annotations
|
|
from typing import Any
|
|
|
|
from games.models import GameModel
|
|
|
|
from django.contrib.auth.models import User
|
|
from django.db.models import CASCADE
|
|
from django.db import models
|
|
|
|
|
|
class TournamentModel(models.Model):
|
|
|
|
name = models.CharField(max_length = 100)
|
|
nb_participants = models.IntegerField()
|
|
round = models.IntegerField()
|
|
started = models.BooleanField(default = False)
|
|
finished = models.BooleanField(default = False)
|
|
winner = models.ForeignKey(User, on_delete=CASCADE, blank=True, null=True)
|
|
|
|
def _register_participant(self, participant: User) -> None:
|
|
TournamentParticipantModel(participant=participant, tournament=self).save()
|
|
|
|
def create_round(self, participants: set[User], round: int) -> set[GameModel]:
|
|
|
|
game_list: set[GameModel] = set()
|
|
|
|
for i, (participant1, participant2) in enumerate(zip(participants[0::2], participants[1::2])):
|
|
game: GameModel = self.create_game([participant1, participant2], round, i)
|
|
game_list.add(game)
|
|
|
|
return game_list
|
|
|
|
def start(self, participant_list: set[User]) -> None:
|
|
|
|
self.started = True
|
|
self.round = 1
|
|
|
|
for participant in participant_list:
|
|
self._register_participant(participant)
|
|
|
|
self.save()
|
|
|
|
def finish(self, winner: User):
|
|
|
|
self.finished = True
|
|
|
|
self.winner = winner
|
|
|
|
self.save()
|
|
|
|
def create_game(self, participants: set[User], round: int, pos: int) -> GameModel:
|
|
|
|
if (self.started == False):
|
|
return None
|
|
|
|
if (len(participants) != 2):
|
|
return None
|
|
|
|
from games.models import GameModel
|
|
|
|
game: GameModel = GameModel().create(participants)
|
|
|
|
TournamentGameModel(tournament=self, game=game, round=round, pos=pos).save()
|
|
|
|
return game
|
|
|
|
def get_games(self) -> set[GameModel]:
|
|
return [{games for games in self.get_games_by_round(i)} for i in range(1, self.round)]
|
|
|
|
def get_games_by_round(self, round: int) -> set[GameModel]:
|
|
return {tournament_game for tournament_game in TournamentGameModel.objects.filter(tournament=self, round=round)}
|
|
|
|
def get_participants_by_round(self, round: int) -> set[User]:
|
|
if round == 1:
|
|
return self.get_participants()
|
|
return {game.winner for game in self.get_games_by_round(round - 1)}
|
|
|
|
def get_winners_by_round(self, round: int) -> set[User]:
|
|
return {game.winner for game in self.get_games_by_round(round)}
|
|
|
|
def get_participants(self) -> set[User]:
|
|
return {tournament_participant.participant for tournament_participant in TournamentParticipantModel.objects.filter(tournament=self.pk)}
|
|
|
|
def get_state(self) -> str:
|
|
return ("waiting to start", "in progress", "finish")[self.started + self.finished]
|
|
|
|
def is_participating(self, profile: User) -> bool:
|
|
return TournamentParticipantModel.objects.filter(participant=profile, tournament=self).exists()
|
|
|
|
class TournamentParticipantModel(models.Model):
|
|
participant = models.ForeignKey(User, on_delete=CASCADE)
|
|
tournament = models.ForeignKey(TournamentModel, on_delete=CASCADE)
|
|
|
|
class TournamentGameModel(GameModel):
|
|
|
|
tournament = models.ForeignKey(TournamentModel, on_delete=CASCADE, null=True, blank=True)
|
|
round = models.IntegerField()
|
|
pos = models.IntegerField()
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
super().__init__(*args, **kwargs)
|
|
|
|
from .consumers import tournament_manager
|
|
self.room = tournament_manager.get(self.tournament)
|
|
|
|
|
|
def start(self):
|
|
super().start()
|
|
|
|
self.room.set_game_as_started(self)
|
|
|
|
|
|
def finish(self, winner_id):
|
|
super().finish(winner_id)
|
|
|
|
self.room.set_game_as_finished(self) |