core: tournament

This commit is contained in:
starnakin 2024-04-16 19:13:18 +02:00
parent 14886c8ac9
commit 630ef709ab
10 changed files with 160 additions and 216 deletions

View File

@ -9,13 +9,13 @@ class Tourmanent
* @param {Number} name * @param {Number} name
* @param {Number} nb_players * @param {Number} nb_players
* @param {Number} nb_players_by_game * @param {Number} nb_players_by_game
* @param {Number} level * @param {Number} round
* @param {Boolean} started * @param {Boolean} started
* @param {Boolean} finished * @param {Boolean} finished
* @param {[]} levels * @param {[]} rounds
* @param {String} state * @param {String} state
*/ */
constructor(client, id, name = undefined, nb_players = undefined, nb_players_by_game = undefined, level = undefined, started = undefined, finished = undefined, levels = undefined, state = undefined) constructor(client, id, name = undefined, nb_players = undefined, round = undefined, started = undefined, finished = undefined, rounds = undefined, state = undefined)
{ {
/** /**
* @type {Client} * @type {Client}
@ -31,16 +31,11 @@ class Tourmanent
* @type {Number} * @type {Number}
*/ */
this.nb_players = nb_players; this.nb_players = nb_players;
/**
* @type {Number}
*/
this.nb_players_by_game = nb_players_by_game;
/** /**
* @type {Number} * @type {Number}
*/ */
this.level = level; this.round = round;
/** /**
* @type {Number} * @type {Number}
@ -55,7 +50,7 @@ class Tourmanent
/** /**
* @type {[]} * @type {[]}
*/ */
this.levels = levels; this.rounds = rounds;
/** /**
* @type {String} must be "finished", or "started", or "waiting". Any other return all elements * @type {String} must be "finished", or "started", or "waiting". Any other return all elements
@ -86,13 +81,12 @@ class Tourmanent
let response_data = await response.json(); let response_data = await response.json();
this.name = response_data.name || `${response_data.nb_players_by_game}x1, ${response_data.nb_players} players`; this.name = response_data.name || `${response_data.nb_players} players tournament`;
this.nb_players = response_data.nb_players; this.nb_players = response_data.nb_players;
this.nb_players_by_game = response_data.nb_players_by_game; this.round = response_data.round;
this.level = response_data.level;
this.started = response_data.started; this.started = response_data.started;
this.finished = response_data.finished; this.finished = response_data.finished;
this.levels = response_data.levels; this.rounds = response_data.rounds;
this.state = response_data.state; this.state = response_data.state;
} }
@ -112,11 +106,11 @@ class Tourmanent
this._socket.send(JSON.stringify({participate: ""})); this._socket.send(JSON.stringify({participate: ""}));
} }
async onParticipantsUpdate(data) async onPlayersUpdate(data)
{ {
oldParticipantList = this.par oldPlayerList = this.par
await this.participantsUpdateHandler(); await this.playersUpdateHandler();
} }
async onError(data) async onError(data)
@ -134,18 +128,18 @@ class Tourmanent
if (data?.detail === "error") if (data?.detail === "error")
this.onError(data); this.onError(data);
else if (data?.detail === "participants_update") else if (data?.detail === "players_update")
this.onParticipantsUpdate(data); this.onPlayersUpdate(data);
} }
/** /**
* Join the tournament Websocket * Join the tournament Websocket
* @param {CallableFunction} errorHandler * @param {CallableFunction} errorHandler
* @param {CallableFunction} participantsUpdateHandler * @param {CallableFunction} playersUpdateHandler
* @param {CallableFunction} disconnectHandler * @param {CallableFunction} disconnectHandler
* @returns {?} * @returns {?}
*/ */
async join(participantsUpdateHandler, errorHandler, disconnectHandler) async join(playersUpdateHandler, errorHandler, disconnectHandler)
{ {
if (!await this.client.isAuthenticated()) if (!await this.client.isAuthenticated())
return null; return null;
@ -157,7 +151,7 @@ class Tourmanent
this.connected = true; this.connected = true;
this.isParticipating = false; this.isParticipating = false;
this.participantsUpdateHandler = participantsUpdateHandler; this.playersUpdateHandler = playersUpdateHandler;
this.errorHandler = errorHandler; this.errorHandler = errorHandler;
this.disconnectHandler = disconnectHandler; this.disconnectHandler = disconnectHandler;

View File

@ -30,13 +30,12 @@ class Tourmanents
/** /**
* *
* @param {Number} nb_players * @param {Number} nb_players
* @param {Number} nb_players_by_game
* @param {String} name * @param {String} name
* @returns {Response} * @returns {Response}
*/ */
async createTournament(nb_players, nb_players_by_game, name = "") async createTournament(nb_players, name = "")
{ {
let response = await this.client._post("/api/tournaments/", {nb_players: nb_players, nb_players_by_game: nb_players_by_game, name: name}); let response = await this.client._post("/api/tournaments/", {nb_players: nb_players, name: name});
return response; return response;
} }
@ -56,17 +55,16 @@ class Tourmanents
return null; return null;
} }
let tournaments = []; let tournaments = [];``
response_data.forEach(tournament_data => { response_data.forEach(tournament_data => {
tournaments.push(new Tourmanent(this.client, tournaments.push(new Tourmanent(this.client,
tournament_data.name, tournament_data.name,
tournament_data.nb_players, tournament_data.nb_players,
tournament_data.nb_players_by_game, tournament_data.round,
tournament_data.level,
tournament_data.started, tournament_data.started,
tournament_data.finished, tournament_data.finished,
tournament_data.levels, tournament_data.rounds,
tournament_data.id, tournament_data.id,
tournament_data.state)); tournament_data.state));
}); });

View File

@ -14,9 +14,8 @@ export default class extends AbstractAuthenticatedView
{ {
let name = document.getElementById("name-input").value; let name = document.getElementById("name-input").value;
let nb_players = document.getElementById("nb-players-input").value; let nb_players = document.getElementById("nb-players-input").value;
let nb_players_by_game = document.getElementById("nb-players-by-game-input").value;
let response = await client.tournaments.createTournament(nb_players, nb_players_by_game, name); let response = await client.tournaments.createTournament(nb_players, name);
let response_data = await response.json(); let response_data = await response.json();
let id = response_data.id; let id = response_data.id;
@ -26,7 +25,7 @@ export default class extends AbstractAuthenticatedView
return; return;
} }
clearIds("innerHTML", ["name", "nb_players", "nb_players_by_game"]); clearIds("innerHTML", ["name", "nb_players"]);
fill_errors(response_data, "innerHTML"); fill_errors(response_data, "innerHTML");
} }
@ -41,16 +40,11 @@ export default class extends AbstractAuthenticatedView
<div class='container-fluid'> <div class='container-fluid'>
<div class='border border-2 rounded bg-light-subtle mx-auto p-2 col-md-7 col-lg-4'> <div class='border border-2 rounded bg-light-subtle mx-auto p-2 col-md-7 col-lg-4'>
<h4 class='text-center fw-semibold mb-4' id="title">${lang.get("TournamentCreateTitle")}</h4> <h4 class='text-center fw-semibold mb-4' id="title">${lang.get("TournamentCreateTitle")}</h4>
<div class='form-floating mb-2'> <div class='form-floating mb-2'>
<input type='text' class='form-control' id='name-input' placeholder='${lang.get("TournamentCreateTournamentName")}'> <input type='text' class='form-control' id='name-input' placeholder='${lang.get("TournamentCreateTournamentName")}'>
<label for='name-input' id='name-label'>${lang.get("TournamentCreateTournamentName")}</label> <label for='name-input' id='name-label'>${lang.get("TournamentCreateTournamentName")}</label>
<span class='text-danger' id='name'></span> <span class='text-danger' id='name'></span>
</div> </div>
<div class='form-floating mb-2'>
<input type='number' class='form-control' min='2' max='4' value='2' id='nb-players-by-game-input' placeholder='${lang.get("TournamentCreateNbPlayerByGame")}'>
<label for='nb-players-by-game-input' id='nb-players-by-game-label'>${lang.get("TournamentCreateNbPlayerByGame")}</label>
<span class='text-danger' id='nb_players_by_game'></span>
</div>
<div class='form-floating mb-2'> <div class='form-floating mb-2'>
<input type='number' class='form-control' min='2' value='4' id='nb-players-input' placeholder='${lang.get("TournamentCreateNbPlayer")}'> <input type='number' class='form-control' min='2' value='4' id='nb-players-input' placeholder='${lang.get("TournamentCreateNbPlayer")}'>
<label for='nb-players-input' id='nb-players-label'>${lang.get("TournamentCreateNbPlayer")}</label> <label for='nb-players-input' id='nb-players-label'>${lang.get("TournamentCreateNbPlayer")}</label>

View File

@ -1,8 +1,9 @@
from __future__ import annotations from __future__ import annotations
from django.db import models from django.db import models
from django.db.models import QuerySet, CASCADE
from django.db.models import QuerySet from profiles.models import ProfileModel
import time import time
@ -12,16 +13,15 @@ class GameModel(models.Model):
finished = models.BooleanField(default = False) finished = models.BooleanField(default = False)
started = models.BooleanField(default = False) started = models.BooleanField(default = False)
winner_id = models.IntegerField(default = -1) winner = models.ForeignKey(ProfileModel, on_delete=CASCADE, null=True, blank=True)
start_timestamp = models.BigIntegerField(null = True, blank = True) start_timestamp = models.BigIntegerField(null = True, blank = True)
stop_timestamp = models.BigIntegerField(null = True, blank = True) stop_timestamp = models.BigIntegerField(null = True, blank = True)
game_type = models.CharField(max_length = 60, default = "pong") game_type = models.CharField(max_length = 60, default = "pong")
def create(self, game_type: str, players_id: list[int]): def create(self, players: list[ProfileModel]):
self.game_type = game_type
self.save() self.save()
for player_id in players_id: for player in players:
GameMembersModel(game_id = self.pk, player_id = player_id).save() GameMembersModel(game = self.pk, player=player).save()
return self.pk return self.pk
def start(self): def start(self):
@ -35,8 +35,8 @@ class GameModel(models.Model):
self.stop_timestamp = round(time.time() * 1000, 1) self.stop_timestamp = round(time.time() * 1000, 1)
self.save() self.save()
def get_players_id(self): def get_players(self) -> list[ProfileModel]:
return [game_player.player_id for game_player in GameMembersModel.objects.filter(game_id = self.pk)] return [game_player.player for game_player in GameMembersModel.objects.filter(game = self)]
def get_score_by_player_id(self, player_id: int) -> list[int]: def get_score_by_player_id(self, player_id: int) -> list[int]:
query: QuerySet = GameGoalModel.objects.filter(game_id = self.pk, player_id = player_id) query: QuerySet = GameGoalModel.objects.filter(game_id = self.pk, player_id = player_id)
@ -55,11 +55,11 @@ class GameModel(models.Model):
return timestamp return timestamp
class GameMembersModel(models.Model): class GameMembersModel(models.Model):
game_id = models.IntegerField() game = models.ForeignKey(GameModel, on_delete=CASCADE)
player_id = models.IntegerField() player = models.ForeignKey(ProfileModel, on_delete=CASCADE)
class GameGoalModel(models.Model): class GameGoalModel(models.Model):
game_id = models.IntegerField() game = models.ForeignKey(GameModel, on_delete=CASCADE)
player_id = models.IntegerField() player = models.ForeignKey(ProfileModel, on_delete=CASCADE)
timestamp = models.IntegerField() timestamp = models.IntegerField()

View File

@ -6,18 +6,16 @@ from django.db.models import Q, Model, CASCADE, ForeignKey, ImageField
from django.db.models.signals import post_save, pre_delete from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver from django.dispatch import receiver
from games.consumers import game_manager
def upload_to(instance, filename: str): def upload_to(instance, filename: str):
return f"./profiles/static/avatars/{instance.pk}{splitext(filename)[1]}" return f"./profiles/static/avatars/{instance.pk}{splitext(filename)[1]}"
class ProfileModel(Model): class ProfileModel(Model):
user = ForeignKey(User, on_delete=CASCADE) user = ForeignKey(User, on_delete=CASCADE)
avatar = ImageField(upload_to=upload_to, default="./profiles/static/avatars/default.avif") avatar = ImageField(upload_to=upload_to, default="./profiles/static/avatars/default.avif")
def get_game(self) -> int: def get_game(self) -> int:
from games.consumers import game_manager
for game in game_manager._game_list: for game in game_manager._game_list:
for player in game.get_players_connected(): for player in game.get_players_connected():
if (player.user_id == self.user.pk): if (player.user_id == self.user.pk):

View File

@ -6,32 +6,25 @@ from games.models import GameModel
import json import json
from .models import tournament_manager, TournamentMember, TournamentRoom, TournamentRoomManager from .models import tournament_manager, TournamentPlayer, TournamentSpectator, TournamentRoom, TournamentRoomManager
class TournamentWebConsumer(WebsocketConsumer): class TournamentWebConsumer(WebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.channel_name = "tournament"
self.group_name = "tournament"
def connect(self): def connect(self):
self.user: User = self.scope["user"] self.user: User = self.scope["user"]
if (self.user.is_anonymous or not self.user.is_authenticated): if (self.user.is_anonymous or not self.user.is_authenticated):
return return
self.channel_layer.group_add(self.group_name, self.channel_name)
self.tournament_id = int(self.scope['url_route']['kwargs']['tournament_id']) self.tournament_id = int(self.scope['url_route']['kwargs']['tournament_id'])
self.room = tournament_manager.get(self.tournament_id) self.room = tournament_manager.get(self.tournament_id)
self.member = TournamentMember(self.user.pk, self, self.room) self.member: TournamentPlayer | TournamentSpectator = self.room(self.user.pk, self, self.room)
if (self.room is None): if (self.room is None):
self.member.send("Tournament not found") self.member.send("Tournament not found")
self.disconnect(1017) self.disconnect(1017)
self.room.append(self.member) self.room.append(self.member)
def receive(self, text_data: str = None, bytes_data: bytes = None): def receive(self, text_data: str = None, bytes_data: bytes = None):

View File

@ -1,155 +1,127 @@
from __future__ import annotations
from django.db import models from django.db import models
from channels.generic.websocket import WebsocketConsumer
from games.models import GameModel
import json
from transcendence.abstract.AbstractRoomMember import AbstractRoomMember from transcendence.abstract.AbstractRoomMember import AbstractRoomMember
from transcendence.abstract.AbstractRoom import AbstractRoom from transcendence.abstract.AbstractRoom import AbstractRoom
from transcendence.abstract.AbstractRoomManager import AbstractRoomManager from transcendence.abstract.AbstractRoomManager import AbstractRoomManager
from profiles.models import ProfileModel
from games.models import GameModel
from django.contrib.auth.models import User
from django.db.models import CASCADE
from channels.generic.websocket import WebsocketConsumer
# Create your models here.tu # Create your models here.tu
class TournamentModel(models.Model): class TournamentModel(models.Model):
name = models.CharField(max_length = 100) name = models.CharField(max_length = 100)
nb_players = models.IntegerField() nb_players = models.IntegerField()
nb_players_by_game = models.IntegerField() rounds = models.IntegerField()
level = models.IntegerField()
started = models.BooleanField(default = False) started = models.BooleanField(default = False)
finished = models.BooleanField(default = False) finished = models.BooleanField(default = False)
gamemode = models.CharField(max_length = 50, default = "pong") winner = models.ForeignKey(ProfileModel, on_delete=CASCADE)
def create_game(self, level, players_id): def _add_player(self, player: ProfileModel) -> None:
game_id = GameModel().create(self.gamemode, players_id = players_id) TournamentPlayerModel(player=player, tournament=self).save()
TournamentGamesModel(game_id = game_id, tournament_id = self.pk, tournament_level = level).save()
return game_id
def get_games_id_by_level(self, level):
tmp = TournamentGamesModel.objects.filter(tournament_id = self.pk, tournament_level = level)
return [instance.game_id for instance in tmp]
def get_games_id(self): def start(self, players: list[ProfileModel]) -> None:
return [tournament_game.game_id for tournament_game in TournamentGamesModel.objects.filter(tournament_id = self.pk)]
def get_participants_id(self):
return [model.participant_id for model in TournamentParticipantsModel.objects.filter(tournament_id=self.pk)]
def is_a_participant(self, participant_id: int):
return TournamentParticipantsModel.objects.filter(participant_id = participant_id, tournament_id = self.pk).exists()
def add_participants(self, participants_id: [int]): self.started = False
for participant_id in participants_id:
TournamentParticipantsModel(tournament_id = self.pk, participant_id = participant_id).save()
def start(self, participants_id: [int]): for player in players:
self.started = True self._add_player(player)
self.add_participants(participants_id)
games_id = [int]
for i in range(0, len(participants_id), self.nb_players_by_game):
game_id = self.create_game(0, participants_id[i : i + self.nb_players_by_game])
games_id.append(game_id)
self.save()
return games_id
class TournamentParticipantsModel(models.Model): for (player1, player2) in zip(players[0::2], players[1::2]):
tournament_id = models.IntegerField() self.create_game([player1, player2], round=1)
participant_id = models.IntegerField()
class TournamentGamesModel(models.Model):
tournament_id = models.IntegerField()
tournament_level = models.IntegerField()
game_id = models.IntegerField()
class TournamentMember(AbstractRoomMember):
def __init__(self, user_id: int, socket: WebsocketConsumer, room):
super().__init__(user_id, socket)
self.participate = False
self.room = room
def receive(self, text_data: str = None, byte_dates: bytes = None):
if (text_data is None): self.save()
return
data: dict = json.loads(text_data) def create_game(self, players: list[ProfileModel], round: int) -> GameModel:
if (data.get("participate") is not None): if (self.started == False):
self.room.update_participants(self) return None
if (len(players) != 2):
return None
from games.models import GameModel
def send_error_message(self, message: str): game: GameModel = GameModel().create(players=players)
self.send("error", {"error_message": message})
def go_to(self, url: str): TournamentGameModel(tournament=self, game=game, round=round).save()
self.send("go_to", {"url": url})
return game
def start(self, players: list[ProfileModel]) -> int:
if (len(players) != self.nb_players):
return 1
for player in players:
TournamentPlayerModel(tournament=self, player=player).save()
return 0
def get_games(self) -> list[GameModel]:
return [tournament_game.game for tournament_game in TournamentGameModel.objects.filter(tournament=self)]
def send_participating(self): def get_games_by_round(self, round: int) -> list[GameModel]:
self.send("is_participant", {"is_participant": self.participate}) return [tournament_game.game for tournament_game in TournamentGameModel.objects.filter(tournament=self, round=round)]
def get_players_by_round(self, round: int) -> list[ProfileModel]:
return [game.get_players() for game in self.get_games_by_round(round)]
def get_winners_by_round(self, round: int) -> list[ProfileModel]:
return [game.winner for game in self.get_games_by_round(round)]
def get_players(self) -> list[TournamentPlayerModel]:
return TournamentPlayerModel.objects.filter(tournament=self.pk)
def get_state(self) -> str:
return ("waiting to start", "in progress", "finish")[self.started + self.finished]
def is_player(self, profile: ProfileModel) -> bool:
return TournamentPlayerModel.objects.filter(player=profile, tournament=self).exists()
class TournamentPlayerModel(models.Model):
player = models.ForeignKey(ProfileModel, on_delete=CASCADE)
tournament = models.ForeignKey(TournamentModel, on_delete=CASCADE)
class TournamentGameModel(models.Model):
tournament = models.ForeignKey(TournamentModel, on_delete=CASCADE, null=True, blank=True)
round = models.IntegerField()
game = models.ForeignKey(GameModel, on_delete=CASCADE)
class TournamentSpectator(AbstractRoomMember):
pass
class TournamentPlayer(TournamentSpectator):
pass
class TournamentRoom(AbstractRoom): class TournamentRoom(AbstractRoom):
def __init__(self, room_manager, tournament_id: int): def __init__(self, room_manager: TournamentRoomManager, tournament_id: int):
super().__init__(room_manager) super().__init__(room_manager)
self.tournament_id = tournament_id self.room_manager: TournamentRoomManager
self.tournament = TournamentModel.objects.get(pk = tournament_id) self.id: int = id
self.model: TournamentModel = TournamentModel.objects.get(pk=tournament_id)
def start(self): def join(self, profile: ProfileModel, socket: WebsocketConsumer) -> TournamentPlayer | TournamentSpectator:
self.broadcast("tournament_start") if (self.model.started):
games_id = self.tournament.start(self.get_participants_id()) if (self.model.is_player(profile)):
for i, participant in enumerate(self.get_participants()): return TournamentPlayer(profile.pk, socket)
participant: TournamentMember else:
participant.go_to(f"games/{games_id[i // self.tournament.nb_players_by_game]}") return TournamentSpectator(profile.pk, socket)
else:
def update_participants(self, member: TournamentMember): return TournamentSpectator(profile.pk, socket)
if (self.tournament.started):
member.send_error_message("Tournament already started")
return
member.participate = not member.participate
nb_participants = self.get_nb_participants()
self.broadcast("update_participants", {"nb_participants": nb_participants})
member.send_participating()
if (nb_participants == self.tournament.nb_players):
self.start()
def get_nb_participants(self):
if (self.tournament.started):
return self.tournament.nb_players
nb_participants = 0
for member in self._member_list:
member: TournamentMember
if (member.participate):
nb_participants += 1
return nb_participants
def get_participants(self):
return [member for member in self._member_list if member.participate]
def get_participants_id(self):
return [member.user_id for member in self._member_list if member.participate]
def append(self, member: TournamentMember):
super().append(member)
if self.tournament.started:
member.participate = self.tournament.is_a_participant(member.user_id)
member.send_participating()
self.broadcast("update_participants", {"participants": [self.get_participants_id()]})
class TournamentRoomManager(AbstractRoomManager): class TournamentRoomManager(AbstractRoomManager):
pass
def get(self, tournament_id: int):
for room in self._room_list:
if (room.tournament_id == tournament_id):
return room
if (TournamentModel.objects.filter(pk = tournament_id).exists()):
room = TournamentRoom(self, tournament_id)
self.append(room)
return room
return None
tournament_manager: TournamentRoomManager = TournamentRoomManager() tournament_manager: TournamentRoomManager = TournamentRoomManager()

View File

@ -7,35 +7,35 @@ from django.contrib.auth.models import User
from .models import TournamentModel, tournament_manager from .models import TournamentModel, tournament_manager
from profiles.models import ProfileModel from profiles.models import ProfileModel
from profiles.serializers import ProfileSerializer from profiles.serializers.ProfileSerializer import ProfileSerializer
from games.serializers import GameSerializer from games.serializers import GameSerializer
class TournamentSerializer(serializers.ModelSerializer): class TournamentSerializer(serializers.ModelSerializer):
levels = serializers.SerializerMethodField(read_only=True, required=False) rounds = serializers.SerializerMethodField(read_only=True, required=False)
state = serializers.SerializerMethodField(read_only=True, required=False) state = serializers.SerializerMethodField(read_only=True, required=False)
participants = serializers.SerializerMethodField(read_only=True, required=False) players = serializers.SerializerMethodField(read_only=True, required=False)
level = serializers.ReadOnlyField() round = serializers.ReadOnlyField()
started = serializers.ReadOnlyField() started = serializers.ReadOnlyField()
finished = serializers.ReadOnlyField() finished = serializers.ReadOnlyField()
name = serializers.CharField(default="") name = serializers.CharField(default="")
class Meta: class Meta:
model = TournamentModel model = TournamentModel
fields = ["name", "nb_players", "nb_players_by_game", "level", "started", "finished", "levels", "id", "state", "participants"] fields = ["name", "nb_players", "nb_players_by_game", "round", "started", "finished", "rounds", "id", "state", "players"]
def get_participants(self, instance: TournamentModel): def get_players(self, instance: TournamentModel):
participants_id: list[ProfileModel] players_id: list[ProfileModel]
if (instance.started): if (instance.started):
participants_id = instance.get_participants_id() players_id = instance.get_players_id()
else: else:
participants_id = tournament_manager.get(instance.pk).get_participants_id() players_id = tournament_manager.get(instance.pk).get_players_id()
participants_profile: list[ProfileModel] = [] players_profile: list[ProfileModel] = []
for participant_id in participants_id: for player_id in players_id:
query: QuerySet = ProfileModel.objects.filter(user_id = participant_id) query: QuerySet = ProfileModel.objects.filter(user_id = player_id)
profile_data: dict profile_data: dict
if query.exists(): if query.exists():
profile_data = ProfileSerializer(query[0]).data profile_data = ProfileSerializer(query[0]).data
@ -43,23 +43,24 @@ class TournamentSerializer(serializers.ModelSerializer):
profile_data = { profile_data = {
"username": "deleted_user", "username": "deleted_user",
"avatar": "/static/avatars/default.avif", "avatar": "/static/avatars/default.avif",
"user_id": participants_id "user_id": players_id
} }
participants_profile.append(profile_data) players_profile.append(profile_data)
return participants_profile return players_profile
def get_state(self, instance: TournamentModel): def get_state(self, instance: TournamentModel):
return ["waiting", "started", "finished"][instance.started + instance.finished] return ["waiting", "started", "finished"][instance.started + instance.finished]
def get_levels(self, instance: TournamentModel): def get_rounds(self, instance: TournamentModel):
levels: list[list[int]] = [] rounds: list[list[int]] = []
for i in range(instance.level): for i in range(instance.round):
games_id: [int] = instance.get_games_id_by_level(i) games_id: list[int] = instance.get_games_id_by_round(i)
if (games_id == []): if (games_id == []):
break break
levels.append(games_id) rounds.append(games_id)
return levels return rounds
def validate_nb_players(self, value: int): def validate_nb_players(self, value: int):
if (value < 2): if (value < 2):

View File

@ -21,14 +21,8 @@ class TournamentViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer: TournamentSerializer): def perform_create(self, serializer: TournamentSerializer):
nb_players = serializer.validated_data["nb_players"] nb_players = serializer.validated_data["nb_players"]
nb_players_by_game = serializer.validated_data["nb_players_by_game"] name = serializer.validated_data["name"]
level = 1 tournament = serializer.save(name=name, nb_players=nb_players, round=1)
number: int = nb_players
while (number != nb_players_by_game):
number = number // 2 + (number % 2)
level += 1
tournament = serializer.save(level = level)
return Response(self.serializer_class(tournament).data, status=status.HTTP_201_CREATED) return Response(self.serializer_class(tournament).data, status=status.HTTP_201_CREATED)
@ -43,7 +37,7 @@ class TournamentViewSet(viewsets.ModelViewSet):
query = TournamentModel.objects.filter(started=False, finished=False) query = TournamentModel.objects.filter(started=False, finished=False)
case _: case _:
query = TournamentModel.objects.all() query = TournamentModel.objects.all()
serializer = self.serializer_class(query, many=True) serializer = self.serializer_class(query, many=True)
return Response(serializer.data) return Response(serializer.data)
def retrieve(self, request: HttpRequest, pk): def retrieve(self, request: HttpRequest, pk):

View File

@ -3,7 +3,7 @@ from .AbstractRoom import AbstractRoom
class AbstractRoomManager: class AbstractRoomManager:
def __init__(self): def __init__(self):
self._room_list: [AbstractRoom] = [] self._room_list: list[AbstractRoom] = []
def remove(self, room: AbstractRoom): def remove(self, room: AbstractRoom):
self._room_list.remove(room) self._room_list.remove(room)