tournament: add: player can join tournament now

This commit is contained in:
starnakin 2023-12-24 16:58:36 +01:00
parent 2932c2af1f
commit 8ba55d5be2
6 changed files with 191 additions and 24 deletions

View File

@ -20,6 +20,8 @@ class Tourmanent
this.levels = levels; this.levels = levels;
this.state = this.get_state(); this.state = this.get_state();
this.id = id this.id = id
this.connected = false;
} }
get_state() get_state()
@ -51,6 +53,48 @@ class Tourmanent
this.id = response_data.id this.id = response_data.id
} }
leave(event)
{
if (this.connected == false)
return
this.connected = false;
this._socket.close()
this.disconnect_func(event);
}
toggle_participation()
{
if (!this.connected)
return
console.log(this.isParticipating);
this.isParticipating = !this.isParticipating;
console.log(this.isParticipating);
this._socket.send(JSON.stringify({participate: this.isParticipating}));
}
async join(receive_func, disconnect_func)
{
if (!await this.client.isAuthentificate())
return null;
let url = `wss://${window.location.host}/ws/tournaments/${this.id}`;
this._socket = new WebSocket(url);
this.connected = true;
this.isParticipating = false;
this.receive_func = receive_func;
this.disconnect_func = disconnect_func;
this._socket.onmessage = function (event) {
const data = JSON.parse(event.data);
receive_func(data);
};
this._socket.onclose = this.leave.bind(this);
}
} }
export { Tourmanent } export { Tourmanent }

View File

@ -9,19 +9,43 @@ export default class extends AbstractAuthentifiedView
this.id = params.id; this.id = params.id;
} }
pressButton()
{
this.tournament.toggle_participation();
document.getElementById("button").value = this.tournament.isParticipating ? "Leave tournament" : "Join tournament";
}
async receive(data)
{
if (data.detail === "nb_participants" || data.detail === "update_participants")
document.getElementById("nb_participants").innerText = `${data.nb_participants} / ${this.tournament.nb_players}`
}
async ondisconnect(event)
{
}
async postInit() async postInit()
{ {
let tournament = await client.tournaments.getTournament(this.id); this.tournament = await client.tournaments.getTournament(this.id);
if (tournament === null) if (this.tournament === null)
return 1; return 1;
document.getElementById("name").innerText = tournament.name; this.tournament.join(this.receive.bind(this), this.ondisconnect.bind(this));
document.getElementById("nb_players").innerText = tournament.nb_players;
document.getElementById("nb_players_by_game").innerText = tournament.nb_players_by_game;
document.getElementById("level").innerText = tournament.level;
document.getElementById("state").innerText = tournament.state;
let button = document.getElementById("button")
button.onclick = this.pressButton.bind(this);
document.getElementById("name").innerText = this.tournament.name;
document.getElementById("nb_players").innerText = this.tournament.nb_players;
document.getElementById("nb_players_by_game").innerText = this.tournament.nb_players_by_game;
document.getElementById("level").innerText = this.tournament.level;
document.getElementById("state").innerText = this.tournament.state;
if (this.tournament.state === "waiting")
button.disabled = false;
} }
async getHtml() async getHtml()
@ -46,12 +70,17 @@ export default class extends AbstractAuthentifiedView
<td>Number of round</td> <td>Number of round</td>
<td id="level">Loading...</td> <td id="level">Loading...</td>
</tr> </tr>
<tr>
<td>Number of player</td>
<td id="nb_participants">Loading...</td>
</tr>
<tr> <tr>
<td>status</td> <td>status</td>
<td id="state">Loading...</td> <td id="state">Loading...</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<input type="button" id="button" value="Join tournament" disabled>
` `
} }
} }

View File

@ -6,9 +6,9 @@ from games.models import GameModel
import json import json
from .models import Waiter, WaitingRoom, WaitingRoomManager, normal from .models import tournament_manager, TournamentMember, TournamentRoom, TournamentRoomManager
class TournamentWaitingRoom(WebsocketConsumer): class TournamentWebConsumer(WebsocketConsumer):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -17,25 +17,27 @@ class TournamentWaitingRoom(WebsocketConsumer):
def connect(self): def connect(self):
user: User = self.scope["user"] self.user: User = self.scope["user"]
if (user.is_anonymous or not 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.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'])
waiting_room: WaitingRoom = normal.get(self.mode) self.room = tournament_manager.get(self.tournament_id)
waiting_room.append(Waiter(user.pk, self)) self.participant = TournamentMember(self.user.pk, self, self.room)
print(len(waiting_room), "/", self.mode, [len(waiting_room),self.mode]) if (self.room is None):
if (len(waiting_room) == self.mode): self.participant.send("Tournament not found")
game_id: int = GameModel().create(waiting_room.get_users_id()) self.disconnect(1017)
waiting_room.broadcast({"detail": "Game found !", "game_id": game_id})
waiting_room.clear() self.room.append(self.participant)
def receive(self, text_data: str = None, bytes_data: bytes = None):
self.participant.receive(text_data, bytes_data)
def disconnect(self, close_code): def disconnect(self, close_code):
waiting_room: WaitingRoom = normal.get(self.mode) member = self.room.get_member_by_socket(self)
waiter: Waiter = waiting_room.get_waiter_by_socket(self) if (member is not None):
if (waiter is not None): self.room.remove(self.participant, close_code)
waiting_room.remove(self.scope["user"].pk)

View File

@ -1,7 +1,15 @@
from django.db import models from django.db import models
from channels.generic.websocket import WebsocketConsumer
from games.models import GameModel 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
# Create your models here.tu # Create your models here.tu
class TournamentModel(models.Model): class TournamentModel(models.Model):
@ -34,3 +42,79 @@ class TournamentGamesModel(models.Model):
tournament_id = models.IntegerField() tournament_id = models.IntegerField()
tournament_level = models.IntegerField() tournament_level = models.IntegerField()
game_id = models.IntegerField() game_id = models.IntegerField()
class TournamentMember(AbstractRoomMember):
def __init__(self, user_id: int, socket: WebsocketConsumer, tournament):
super().__init__(user_id, socket)
self.participate = False
self.tournament = tournament
def receive(self, text_data: str = None, byte_dates: bytes = None):
if (text_data is None):
return
data: dict = json.loads(text_data)
self.update_participate(data.get("participate", self.participate))
def update_participate(self, new_participate: bool):
if (self.participate == new_participate):
return
self.participate = new_participate
self.tournament.update_participants()
class TournamentRoom(AbstractRoom):
def __init__(self, room_manager, tournament_id: int):
super().__init__(room_manager)
self.tournament_id = tournament_id
self.definitive_participant_list = []
self.started = False
self.model = TournamentModel.objects.get(pk=tournament_id)
def start(self):
self.broadcast("tournament_start")
def update_participants(self):
nb_participants = self.get_nb_participants()
self.broadcast("update_participants", {"nb_participants": nb_participants})
if (nb_participants == self.model.nb_players):
self.start()
def get_nb_participants(self):
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.user_id for member in self._member_list if member.participate]
def start(self):
self.started = True
def append(self, member: TournamentMember):
super().append(member)
member.send("nb_participants", {"nb_participants": self.get_nb_participants()})
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
tournament_manager: TournamentRoomManager = TournamentRoomManager()

6
tournament/routing.py Normal file
View File

@ -0,0 +1,6 @@
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/tournaments/(?P<tournament_id>\d+)$', consumers.TournamentWebConsumer.as_asgi())
]

View File

@ -13,6 +13,7 @@ from channels.auth import AuthMiddlewareStack
import chat.routing import chat.routing
import matchmaking.routing import matchmaking.routing
import tournament.routing
from django.core.asgi import get_asgi_application from django.core.asgi import get_asgi_application
@ -23,7 +24,8 @@ application = ProtocolTypeRouter({
'websocket':AuthMiddlewareStack( 'websocket':AuthMiddlewareStack(
URLRouter( URLRouter(
chat.routing.websocket_urlpatterns + chat.routing.websocket_urlpatterns +
matchmaking.routing.websocket_urlpatterns matchmaking.routing.websocket_urlpatterns +
tournament.routing.websocket_urlpatterns
) )
) )
}) })