merge de con?
This commit is contained in:
commit
8087f305fc
@ -2,7 +2,7 @@ from rest_framework import serializers
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from profiles.models.ProfileModel import ProfileModel
|
||||
from profiles.models import ProfileModel
|
||||
from .models import ChatChannelModel, ChatMessageModel
|
||||
|
||||
|
||||
|
@ -9,13 +9,13 @@ class Tourmanent
|
||||
* @param {Number} name
|
||||
* @param {Number} nb_players
|
||||
* @param {Number} nb_players_by_game
|
||||
* @param {Number} level
|
||||
* @param {Number} round
|
||||
* @param {Boolean} started
|
||||
* @param {Boolean} finished
|
||||
* @param {[]} levels
|
||||
* @param {[]} rounds
|
||||
* @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}
|
||||
@ -31,16 +31,11 @@ class Tourmanent
|
||||
* @type {Number}
|
||||
*/
|
||||
this.nb_players = nb_players;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
this.nb_players_by_game = nb_players_by_game;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
this.level = level;
|
||||
this.round = round;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
@ -55,7 +50,7 @@ class Tourmanent
|
||||
/**
|
||||
* @type {[]}
|
||||
*/
|
||||
this.levels = levels;
|
||||
this.rounds = rounds;
|
||||
|
||||
/**
|
||||
* @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();
|
||||
|
||||
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_by_game = response_data.nb_players_by_game;
|
||||
this.level = response_data.level;
|
||||
this.round = response_data.round;
|
||||
this.started = response_data.started;
|
||||
this.finished = response_data.finished;
|
||||
this.levels = response_data.levels;
|
||||
this.rounds = response_data.rounds;
|
||||
this.state = response_data.state;
|
||||
}
|
||||
|
||||
@ -112,11 +106,11 @@ class Tourmanent
|
||||
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)
|
||||
@ -134,18 +128,18 @@ class Tourmanent
|
||||
|
||||
if (data?.detail === "error")
|
||||
this.onError(data);
|
||||
else if (data?.detail === "participants_update")
|
||||
this.onParticipantsUpdate(data);
|
||||
else if (data?.detail === "players_update")
|
||||
this.onPlayersUpdate(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the tournament Websocket
|
||||
* @param {CallableFunction} errorHandler
|
||||
* @param {CallableFunction} participantsUpdateHandler
|
||||
* @param {CallableFunction} playersUpdateHandler
|
||||
* @param {CallableFunction} disconnectHandler
|
||||
* @returns {?}
|
||||
*/
|
||||
async join(participantsUpdateHandler, errorHandler, disconnectHandler)
|
||||
async join(playersUpdateHandler, errorHandler, disconnectHandler)
|
||||
{
|
||||
if (!await this.client.isAuthenticated())
|
||||
return null;
|
||||
@ -157,7 +151,7 @@ class Tourmanent
|
||||
this.connected = true;
|
||||
this.isParticipating = false;
|
||||
|
||||
this.participantsUpdateHandler = participantsUpdateHandler;
|
||||
this.playersUpdateHandler = playersUpdateHandler;
|
||||
this.errorHandler = errorHandler;
|
||||
this.disconnectHandler = disconnectHandler;
|
||||
|
||||
|
@ -30,13 +30,12 @@ class Tourmanents
|
||||
/**
|
||||
*
|
||||
* @param {Number} nb_players
|
||||
* @param {Number} nb_players_by_game
|
||||
* @param {String} name
|
||||
* @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;
|
||||
}
|
||||
@ -56,17 +55,16 @@ class Tourmanents
|
||||
return null;
|
||||
}
|
||||
|
||||
let tournaments = [];
|
||||
let tournaments = [];``
|
||||
|
||||
response_data.forEach(tournament_data => {
|
||||
tournaments.push(new Tourmanent(this.client,
|
||||
tournament_data.name,
|
||||
tournament_data.nb_players,
|
||||
tournament_data.nb_players_by_game,
|
||||
tournament_data.level,
|
||||
tournament_data.round,
|
||||
tournament_data.started,
|
||||
tournament_data.finished,
|
||||
tournament_data.levels,
|
||||
tournament_data.rounds,
|
||||
tournament_data.id,
|
||||
tournament_data.state));
|
||||
});
|
||||
|
@ -14,9 +14,8 @@ export default class extends AbstractAuthenticatedView
|
||||
{
|
||||
let name = document.getElementById("name-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 id = response_data.id;
|
||||
@ -26,7 +25,7 @@ export default class extends AbstractAuthenticatedView
|
||||
return;
|
||||
}
|
||||
|
||||
clearIds("innerHTML", ["name", "nb_players", "nb_players_by_game"]);
|
||||
clearIds("innerHTML", ["name", "nb_players"]);
|
||||
fill_errors(response_data, "innerHTML");
|
||||
}
|
||||
|
||||
@ -41,16 +40,11 @@ export default class extends AbstractAuthenticatedView
|
||||
<div class='container-fluid'>
|
||||
<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>
|
||||
<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")}'>
|
||||
<label for='name-input' id='name-label'>${lang.get("TournamentCreateTournamentName")}</label>
|
||||
<span class='text-danger' id='name'></span>
|
||||
</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'>
|
||||
<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>
|
||||
|
@ -1,8 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
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
|
||||
|
||||
@ -12,16 +13,15 @@ class GameModel(models.Model):
|
||||
|
||||
finished = 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)
|
||||
stop_timestamp = models.BigIntegerField(null = True, blank = True)
|
||||
game_type = models.CharField(max_length = 60, default = "pong")
|
||||
|
||||
def create(self, game_type: str, players_id: list[int]):
|
||||
self.game_type = game_type
|
||||
def create(self, players: list[ProfileModel]):
|
||||
self.save()
|
||||
for player_id in players_id:
|
||||
GameMembersModel(game_id = self.pk, player_id = player_id).save()
|
||||
for player in players:
|
||||
GameMembersModel(game = self.pk, player=player).save()
|
||||
return self.pk
|
||||
|
||||
def start(self):
|
||||
@ -35,8 +35,8 @@ class GameModel(models.Model):
|
||||
self.stop_timestamp = round(time.time() * 1000, 1)
|
||||
self.save()
|
||||
|
||||
def get_players_id(self):
|
||||
return [game_player.player_id for game_player in GameMembersModel.objects.filter(game_id = self.pk)]
|
||||
def get_players(self) -> list[ProfileModel]:
|
||||
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]:
|
||||
query: QuerySet = GameGoalModel.objects.filter(game_id = self.pk, player_id = player_id)
|
||||
@ -55,11 +55,11 @@ class GameModel(models.Model):
|
||||
return timestamp
|
||||
|
||||
class GameMembersModel(models.Model):
|
||||
game_id = models.IntegerField()
|
||||
player_id = models.IntegerField()
|
||||
game = models.ForeignKey(GameModel, on_delete=CASCADE)
|
||||
player = models.ForeignKey(ProfileModel, on_delete=CASCADE)
|
||||
|
||||
class GameGoalModel(models.Model):
|
||||
|
||||
game_id = models.IntegerField()
|
||||
player_id = models.IntegerField()
|
||||
game = models.ForeignKey(GameModel, on_delete=CASCADE)
|
||||
player = models.ForeignKey(ProfileModel, on_delete=CASCADE)
|
||||
timestamp = models.IntegerField()
|
@ -1,12 +1,9 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from .models.BlockModel import BlockModel
|
||||
from .models.FriendModel import FriendModel
|
||||
# from .models.FriendRequestModel import FriendRequestModel
|
||||
from .models.ProfileModel import ProfileModel
|
||||
from .models import ProfileModel, FriendModel, FriendRequestModel, BlockModel
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(ProfileModel)
|
||||
admin.site.register(BlockModel)
|
||||
admin.site.register(FriendModel)
|
||||
# admin.site.register(AskFriendModel)
|
||||
admin.site.register(FriendRequestModel)
|
||||
|
@ -6,19 +6,16 @@ from django.db.models import Q, Model, CASCADE, ForeignKey, ImageField
|
||||
from django.db.models.signals import post_save, pre_delete
|
||||
from django.dispatch import receiver
|
||||
|
||||
from games.consumers import game_manager
|
||||
from . import FriendModel
|
||||
|
||||
|
||||
def upload_to(instance, filename: str):
|
||||
return f"./profiles/static/avatars/{instance.pk}{splitext(filename)[1]}"
|
||||
|
||||
|
||||
class ProfileModel(Model):
|
||||
user = ForeignKey(User, on_delete=CASCADE)
|
||||
avatar = ImageField(upload_to=upload_to, default="./profiles/static/avatars/default.avif")
|
||||
|
||||
def get_game(self) -> int:
|
||||
from games.consumers import game_manager
|
||||
for game in game_manager._game_list:
|
||||
for player in game.get_players_connected():
|
||||
if (player.user_id == self.user.pk):
|
||||
@ -28,21 +25,38 @@ class ProfileModel(Model):
|
||||
def get_friends(self) -> list[ProfileModel]:
|
||||
friends: list[ProfileModel] = []
|
||||
|
||||
for friendship in FriendModel.FriendModel.objects.filter(Q(friend1=self) | Q(friend2=self)):
|
||||
for friendship in FriendModel.objects.filter(Q(friend1=self) | Q(friend2=self)):
|
||||
friends.append(friendship.friend1 if friendship.friend1 != self else friendship.friend2)
|
||||
|
||||
return friends
|
||||
|
||||
def is_friend(self, friend):
|
||||
return friend in self.get_friends()
|
||||
return FriendModel.objects.filter(
|
||||
(Q(friend1=self) & Q(friend2=friend)) |
|
||||
(Q(friend2=self) & Q(friend1=friend))
|
||||
).exists()
|
||||
|
||||
def delete_friend(self, friend):
|
||||
print(friend)
|
||||
FriendModel.FriendModel.objects.get(
|
||||
FriendModel.objects.get(
|
||||
(Q(friend1=self) & Q(friend2=friend)) |
|
||||
(Q(friend2=self) & Q(friend1=friend))
|
||||
).delete()
|
||||
|
||||
def is_friend_requested_by(self, profile):
|
||||
return self.get_received_friend_request_from(profile) is None
|
||||
|
||||
def get_received_friend_request_from(self, profile):
|
||||
return FriendRequestModel.objects.filter(author=profile, target=self).first()
|
||||
|
||||
def is_friend_requesting(self, profile):
|
||||
return FriendRequestModel.objects.filter(author=self, target=profile).exists()
|
||||
|
||||
def get_sent_friend_requests(self) -> list[ProfileModel]:
|
||||
return FriendRequestModel.objects.filter(author=self)
|
||||
|
||||
def get_received_friend_requests(self) -> list[ProfileModel]:
|
||||
return FriendRequestModel.objects.filter(target=self)
|
||||
|
||||
|
||||
@receiver(pre_delete, sender=ProfileModel)
|
||||
def delete_profile_picture(sender, instance, **kwargs):
|
||||
@ -55,3 +69,22 @@ def on_user_created(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
profile: ProfileModel = ProfileModel.objects.create(pk=instance.pk, user=instance)
|
||||
profile.save()
|
||||
|
||||
|
||||
class FriendModel(Model):
|
||||
friend1 = ForeignKey(ProfileModel, on_delete=CASCADE, related_name='friend1')
|
||||
friend2 = ForeignKey(ProfileModel, on_delete=CASCADE, related_name='friend2')
|
||||
|
||||
|
||||
class FriendRequestModel(Model):
|
||||
author = ForeignKey(ProfileModel, on_delete=CASCADE, related_name='author')
|
||||
target = ForeignKey(ProfileModel, on_delete=CASCADE, related_name='target')
|
||||
|
||||
def accept(self):
|
||||
FriendModel(friend1=self.author, friend2=self.target).save()
|
||||
self.delete()
|
||||
|
||||
|
||||
class BlockModel(Model):
|
||||
blocker = ForeignKey(ProfileModel, on_delete=CASCADE, related_name='blocker')
|
||||
blocked = ForeignKey(ProfileModel, on_delete=CASCADE, related_name='blocked')
|
@ -1,7 +0,0 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
|
||||
class BlockModel(models.Model):
|
||||
blocker = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blocker')
|
||||
blocked = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blocked')
|
@ -1,8 +0,0 @@
|
||||
from django.db import models
|
||||
|
||||
from . import ProfileModel
|
||||
|
||||
|
||||
class FriendModel(models.Model):
|
||||
friend1 = models.ForeignKey(ProfileModel.ProfileModel, on_delete=models.CASCADE, related_name='friend1')
|
||||
friend2 = models.ForeignKey(ProfileModel.ProfileModel, on_delete=models.CASCADE, related_name='friend2')
|
@ -3,7 +3,7 @@ from django.utils.translation import gettext as _
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models.ProfileModel import ProfileModel
|
||||
from ..models import ProfileModel
|
||||
|
||||
|
||||
class ProfileSerializer(serializers.ModelSerializer):
|
||||
|
@ -7,8 +7,7 @@ from rest_framework.request import Request
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from ..models.BlockModel import BlockModel
|
||||
from ..models.ProfileModel import ProfileModel
|
||||
from ..models import BlockModel, ProfileModel
|
||||
from ..serializers.ProfileSerializer import ProfileSerializer
|
||||
|
||||
|
||||
@ -17,14 +16,10 @@ class GetBlocksView(APIView):
|
||||
authentication_classes = (SessionAuthentication,)
|
||||
|
||||
def get(self, request: Request):
|
||||
profiles = []
|
||||
blocks = BlockModel.objects.filter(blocker=request.user)
|
||||
for block in blocks:
|
||||
profile = ProfileModel.objects.filter(user=block.blocked)
|
||||
if (profile.exists()):
|
||||
profiles.append(profile[0])
|
||||
blocks = BlockModel.objects.filter(blocker=ProfileModel.objects.filter(user=request.user).first())
|
||||
bloked_profiles = [block.blocked for block in blocks]
|
||||
|
||||
return Response(ProfileSerializer(profiles, many=True).data)
|
||||
return Response(ProfileSerializer(bloked_profiles, many=True).data)
|
||||
|
||||
|
||||
class EditBlocksView(APIView):
|
||||
|
@ -7,8 +7,7 @@ from django.utils.translation import gettext as _
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from ..models.FriendModel import FriendModel
|
||||
from ..models.ProfileModel import ProfileModel
|
||||
from ..models import ProfileModel, FriendModel
|
||||
from ..serializers.ProfileSerializer import ProfileSerializer
|
||||
|
||||
|
||||
|
@ -4,7 +4,7 @@ from rest_framework.response import Response
|
||||
from rest_framework.authentication import SessionAuthentication
|
||||
|
||||
from ..serializers.ProfileSerializer import ProfileSerializer
|
||||
from ..models.ProfileModel import ProfileModel
|
||||
from ..models import ProfileModel
|
||||
|
||||
|
||||
class MyProfileViewSet(viewsets.ModelViewSet):
|
||||
|
@ -6,7 +6,7 @@ from rest_framework import viewsets
|
||||
from rest_framework.response import Response
|
||||
|
||||
from ..serializers.ProfileSerializer import ProfileSerializer
|
||||
from ..models.ProfileModel import ProfileModel
|
||||
from ..models import ProfileModel
|
||||
|
||||
|
||||
class ProfileViewSet(viewsets.ModelViewSet):
|
||||
|
@ -6,32 +6,25 @@ from games.models import GameModel
|
||||
|
||||
import json
|
||||
|
||||
from .models import tournament_manager, TournamentMember, TournamentRoom, TournamentRoomManager
|
||||
from .models import tournament_manager, TournamentPlayer, TournamentSpectator, TournamentRoom, TournamentRoomManager
|
||||
|
||||
class TournamentWebConsumer(WebsocketConsumer):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.channel_name = "tournament"
|
||||
self.group_name = "tournament"
|
||||
|
||||
def connect(self):
|
||||
|
||||
self.user: User = self.scope["user"]
|
||||
if (self.user.is_anonymous or not self.user.is_authenticated):
|
||||
return
|
||||
|
||||
self.channel_layer.group_add(self.group_name, self.channel_name)
|
||||
|
||||
self.tournament_id = int(self.scope['url_route']['kwargs']['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):
|
||||
self.member.send("Tournament not found")
|
||||
self.disconnect(1017)
|
||||
|
||||
|
||||
self.room.append(self.member)
|
||||
|
||||
def receive(self, text_data: str = None, bytes_data: bytes = None):
|
||||
|
@ -1,155 +1,127 @@
|
||||
from __future__ import annotations
|
||||
|
||||
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.AbstractRoom import AbstractRoom
|
||||
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
|
||||
class TournamentModel(models.Model):
|
||||
|
||||
name = models.CharField(max_length = 100)
|
||||
nb_players = models.IntegerField()
|
||||
nb_players_by_game = models.IntegerField()
|
||||
level = models.IntegerField()
|
||||
rounds = models.IntegerField()
|
||||
started = 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):
|
||||
game_id = GameModel().create(self.gamemode, players_id = players_id)
|
||||
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 _add_player(self, player: ProfileModel) -> None:
|
||||
TournamentPlayerModel(player=player, tournament=self).save()
|
||||
|
||||
def get_games_id(self):
|
||||
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 start(self, players: list[ProfileModel]) -> None:
|
||||
|
||||
def add_participants(self, participants_id: [int]):
|
||||
for participant_id in participants_id:
|
||||
TournamentParticipantsModel(tournament_id = self.pk, participant_id = participant_id).save()
|
||||
self.started = False
|
||||
|
||||
def start(self, participants_id: [int]):
|
||||
self.started = True
|
||||
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
|
||||
for player in players:
|
||||
self._add_player(player)
|
||||
|
||||
class TournamentParticipantsModel(models.Model):
|
||||
tournament_id = models.IntegerField()
|
||||
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):
|
||||
for (player1, player2) in zip(players[0::2], players[1::2]):
|
||||
self.create_game([player1, player2], round=1)
|
||||
|
||||
if (text_data is None):
|
||||
return
|
||||
self.save()
|
||||
|
||||
data: dict = json.loads(text_data)
|
||||
def create_game(self, players: list[ProfileModel], round: int) -> GameModel:
|
||||
|
||||
if (data.get("participate") is not None):
|
||||
self.room.update_participants(self)
|
||||
if (self.started == False):
|
||||
return None
|
||||
|
||||
if (len(players) != 2):
|
||||
return None
|
||||
|
||||
from games.models import GameModel
|
||||
|
||||
def send_error_message(self, message: str):
|
||||
self.send("error", {"error_message": message})
|
||||
game: GameModel = GameModel().create(players=players)
|
||||
|
||||
def go_to(self, url: str):
|
||||
self.send("go_to", {"url": url})
|
||||
TournamentGameModel(tournament=self, game=game, round=round).save()
|
||||
|
||||
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):
|
||||
self.send("is_participant", {"is_participant": self.participate})
|
||||
def get_games_by_round(self, round: int) -> list[GameModel]:
|
||||
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):
|
||||
|
||||
def __init__(self, room_manager, tournament_id: int):
|
||||
|
||||
def __init__(self, room_manager: TournamentRoomManager, tournament_id: int):
|
||||
super().__init__(room_manager)
|
||||
self.tournament_id = tournament_id
|
||||
self.tournament = TournamentModel.objects.get(pk = tournament_id)
|
||||
self.room_manager: TournamentRoomManager
|
||||
self.id: int = id
|
||||
self.model: TournamentModel = TournamentModel.objects.get(pk=tournament_id)
|
||||
|
||||
|
||||
def start(self):
|
||||
self.broadcast("tournament_start")
|
||||
games_id = self.tournament.start(self.get_participants_id())
|
||||
for i, participant in enumerate(self.get_participants()):
|
||||
participant: TournamentMember
|
||||
participant.go_to(f"games/{games_id[i // self.tournament.nb_players_by_game]}")
|
||||
|
||||
def update_participants(self, member: TournamentMember):
|
||||
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()]})
|
||||
def join(self, profile: ProfileModel, socket: WebsocketConsumer) -> TournamentPlayer | TournamentSpectator:
|
||||
if (self.model.started):
|
||||
if (self.model.is_player(profile)):
|
||||
return TournamentPlayer(profile.pk, socket)
|
||||
else:
|
||||
return TournamentSpectator(profile.pk, socket)
|
||||
else:
|
||||
return TournamentSpectator(profile.pk, socket)
|
||||
|
||||
class TournamentRoomManager(AbstractRoomManager):
|
||||
|
||||
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
|
||||
pass
|
||||
|
||||
tournament_manager: TournamentRoomManager = TournamentRoomManager()
|
@ -7,35 +7,35 @@ from django.contrib.auth.models import User
|
||||
from .models import TournamentModel, tournament_manager
|
||||
|
||||
from profiles.models import ProfileModel
|
||||
from profiles.serializers import ProfileSerializer
|
||||
from profiles.serializers.ProfileSerializer import ProfileSerializer
|
||||
from games.serializers import GameSerializer
|
||||
|
||||
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)
|
||||
participants = serializers.SerializerMethodField(read_only=True, required=False)
|
||||
level = serializers.ReadOnlyField()
|
||||
players = serializers.SerializerMethodField(read_only=True, required=False)
|
||||
round = serializers.ReadOnlyField()
|
||||
started = serializers.ReadOnlyField()
|
||||
finished = serializers.ReadOnlyField()
|
||||
name = serializers.CharField(default="")
|
||||
|
||||
class Meta:
|
||||
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):
|
||||
participants_id = instance.get_participants_id()
|
||||
players_id = instance.get_players_id()
|
||||
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] = []
|
||||
for participant_id in participants_id:
|
||||
query: QuerySet = ProfileModel.objects.filter(user_id = participant_id)
|
||||
players_profile: list[ProfileModel] = []
|
||||
for player_id in players_id:
|
||||
query: QuerySet = ProfileModel.objects.filter(user_id = player_id)
|
||||
profile_data: dict
|
||||
if query.exists():
|
||||
profile_data = ProfileSerializer(query[0]).data
|
||||
@ -43,23 +43,24 @@ class TournamentSerializer(serializers.ModelSerializer):
|
||||
profile_data = {
|
||||
"username": "deleted_user",
|
||||
"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):
|
||||
return ["waiting", "started", "finished"][instance.started + instance.finished]
|
||||
|
||||
def get_levels(self, instance: TournamentModel):
|
||||
levels: list[list[int]] = []
|
||||
for i in range(instance.level):
|
||||
games_id: [int] = instance.get_games_id_by_level(i)
|
||||
def get_rounds(self, instance: TournamentModel):
|
||||
rounds: list[list[int]] = []
|
||||
for i in range(instance.round):
|
||||
games_id: list[int] = instance.get_games_id_by_round(i)
|
||||
if (games_id == []):
|
||||
break
|
||||
levels.append(games_id)
|
||||
return levels
|
||||
rounds.append(games_id)
|
||||
return rounds
|
||||
|
||||
def validate_nb_players(self, value: int):
|
||||
if (value < 2):
|
||||
|
@ -21,14 +21,8 @@ class TournamentViewSet(viewsets.ModelViewSet):
|
||||
def perform_create(self, serializer: TournamentSerializer):
|
||||
|
||||
nb_players = serializer.validated_data["nb_players"]
|
||||
nb_players_by_game = serializer.validated_data["nb_players_by_game"]
|
||||
level = 1
|
||||
number: int = nb_players
|
||||
while (number != nb_players_by_game):
|
||||
number = number // 2 + (number % 2)
|
||||
level += 1
|
||||
|
||||
tournament = serializer.save(level = level)
|
||||
name = serializer.validated_data["name"]
|
||||
tournament = serializer.save(name=name, nb_players=nb_players, round=1)
|
||||
|
||||
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)
|
||||
case _:
|
||||
query = TournamentModel.objects.all()
|
||||
serializer = self.serializer_class(query, many=True)
|
||||
serializer = self.serializer_class(query, many=True)
|
||||
return Response(serializer.data)
|
||||
|
||||
def retrieve(self, request: HttpRequest, pk):
|
||||
|
@ -3,7 +3,7 @@ from .AbstractRoom import AbstractRoom
|
||||
class AbstractRoomManager:
|
||||
|
||||
def __init__(self):
|
||||
self._room_list: [AbstractRoom] = []
|
||||
self._room_list: list[AbstractRoom] = []
|
||||
|
||||
def remove(self, room: AbstractRoom):
|
||||
self._room_list.remove(room)
|
||||
|
Loading…
Reference in New Issue
Block a user