42_ft_transcendence/tournament/models.py

116 lines
3.7 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)