tournament: add: les crampte
This commit is contained in:
parent
1d8c2c633a
commit
aafc61d40a
@ -42,14 +42,33 @@ class Tourmanent extends AExchangeable
|
|||||||
* @type {Number}
|
* @type {Number}
|
||||||
*/
|
*/
|
||||||
this.finished;
|
this.finished;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {"finished" | "started" | "waiting"} must be "finished", or "started", or "waiting". Any other return all elements
|
* @type {"finished" | "started" | "waiting"} must be "finished", or "started", or "waiting". Any other return all elements
|
||||||
*/
|
*/
|
||||||
this.state;
|
this.state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {Boolean} the client is a participant of the tournament
|
||||||
|
*/
|
||||||
|
this.is_participating;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Boolean} newParticipation
|
||||||
|
*/
|
||||||
|
async setParticipation(newParticipation)
|
||||||
|
{
|
||||||
|
if (this.isParticipating == newParticipation)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.isParticipating = newParticipation;
|
||||||
|
|
||||||
|
this._socket.send(JSON.stringify({"detail": "update_participating",
|
||||||
|
"is_participating": newParticipation})
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns {Promise<?>}
|
* @returns {Promise<?>}
|
||||||
@ -72,18 +91,35 @@ class Tourmanent extends AExchangeable
|
|||||||
return;
|
return;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
this._socket.close();
|
this._socket.close();
|
||||||
this.disconnectHandler(event);
|
this._disconnectHandler(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
*/
|
*/
|
||||||
async _receiveParticipantUpdate(data)
|
async _receiveAddParticipant(data)
|
||||||
{
|
{
|
||||||
this.par
|
const participant = new Profile(this.client, undefined, data.participant.user_id);
|
||||||
|
participant.import(data.participant)
|
||||||
|
|
||||||
|
this.participantList.push(participant);
|
||||||
|
|
||||||
|
await this._addParticipantHandler(this.participantList.length)
|
||||||
}
|
}
|
||||||
|
|
||||||
async onError(data)
|
/**
|
||||||
|
* @param {Object} data
|
||||||
|
*/
|
||||||
|
async _receiveDelParticipant(data)
|
||||||
|
{
|
||||||
|
const index = this.participantList.indexOf((profile) => profile.id === data.profile.user_id)
|
||||||
|
|
||||||
|
this.participantList.splice(index, 1);
|
||||||
|
|
||||||
|
await this._delParticipantHandler(this.participantList.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _receiveError(data)
|
||||||
{
|
{
|
||||||
await this.errorHandler(data);
|
await this.errorHandler(data);
|
||||||
}
|
}
|
||||||
@ -92,14 +128,26 @@ class Tourmanent extends AExchangeable
|
|||||||
*
|
*
|
||||||
* @param {MessageEvent} event
|
* @param {MessageEvent} event
|
||||||
*/
|
*/
|
||||||
onReceive(event)
|
async onReceive(event)
|
||||||
{
|
{
|
||||||
const data = JSON.parse(event.data);
|
const data = JSON.parse(event.data);
|
||||||
|
|
||||||
if (data.detail === "error")
|
switch (data.detail) {
|
||||||
this.onError(data);
|
case "error":
|
||||||
else if (["del_participant", "add_participant"].includes(data.detail))
|
await this._receiveError(data)
|
||||||
this._receiveParticipantUpdate(data);
|
break;
|
||||||
|
|
||||||
|
case "add_participant":
|
||||||
|
await this._receiveAddParticipant(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "del_participant":
|
||||||
|
await this._receiveDelParticipant(data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,9 +157,11 @@ class Tourmanent extends AExchangeable
|
|||||||
* @param {CallableFunction} delParticipantHandler called when a participants leave the tournament
|
* @param {CallableFunction} delParticipantHandler called when a participants leave the tournament
|
||||||
* @param {CallableFunction} disconnectHandler
|
* @param {CallableFunction} disconnectHandler
|
||||||
* @param {CallableFunction} goToHandler called when the next game will start
|
* @param {CallableFunction} goToHandler called when the next game will start
|
||||||
* @returns {?}
|
* @param {CallableFunction} startHandler called when tournament start
|
||||||
|
* @param {CallableFunction} finishHandler called when tournament finish
|
||||||
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
async join(participantsUpdateHandler, errorHandler, goToHandler, disconnectHandler)
|
async join(addParticipantHandler, delParticipantHandler, startHandler, finishHandler, errorHandler, goToHandler, disconnectHandler)
|
||||||
{
|
{
|
||||||
if (!await this.client.isAuthenticated())
|
if (!await this.client.isAuthenticated())
|
||||||
return null;
|
return null;
|
||||||
@ -123,10 +173,13 @@ class Tourmanent extends AExchangeable
|
|||||||
this.connected = true;
|
this.connected = true;
|
||||||
this.isParticipating = false;
|
this.isParticipating = false;
|
||||||
|
|
||||||
this.participantsUpdateHandler = participantsUpdateHandler;
|
this._startHandler = startHandler;
|
||||||
this.errorHandler = errorHandler;
|
this._finishHandler = finishHandler;
|
||||||
this.disconnectHandler = disconnectHandler;
|
this._addParticipantHandler = addParticipantHandler;
|
||||||
this.goToHandler = goToHandler;
|
this._delParticipantHandler = delParticipantHandler;
|
||||||
|
this._errorHandler = errorHandler;
|
||||||
|
this._disconnectHandler = disconnectHandler;
|
||||||
|
this._goToHandler = goToHandler;
|
||||||
|
|
||||||
this._socket.onmessage = this.onReceive.bind(this);
|
this._socket.onmessage = this.onReceive.bind(this);
|
||||||
|
|
||||||
|
@ -16,10 +16,9 @@ export default class extends AbstractAuthenticatedView
|
|||||||
if (name.length == 0)
|
if (name.length == 0)
|
||||||
name = lang.get("TournamentCreateTournamentName");
|
name = lang.get("TournamentCreateTournamentName");
|
||||||
|
|
||||||
console.log(name);
|
let nb_participant = document.getElementById("nb-participant-input").value;
|
||||||
let nb_players = document.getElementById("nb-players-input").value;
|
|
||||||
|
|
||||||
let response = await client.tournaments.createTournament(nb_players, name);
|
let response = await client.tournaments.createTournament(nb_participant, name);
|
||||||
let response_data = await response.json();
|
let response_data = await response.json();
|
||||||
|
|
||||||
let id = response_data.id;
|
let id = response_data.id;
|
||||||
@ -29,7 +28,7 @@ export default class extends AbstractAuthenticatedView
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearIds("innerHTML", ["name", "nb_players"]);
|
clearIds("innerHTML", ["name", "nb_participants"]);
|
||||||
fill_errors(response_data, "innerHTML");
|
fill_errors(response_data, "innerHTML");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,9 +49,16 @@ export default class extends AbstractAuthenticatedView
|
|||||||
<span class='text-danger' id='name'></span>
|
<span class='text-danger' id='name'></span>
|
||||||
</div>
|
</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")}'>
|
<select class='form-control' id="nb-participant-input">
|
||||||
<label for='nb-players-input' id='nb-players-label'>${lang.get("TournamentCreateNbPlayer")}</label>
|
<option value="2">2</option>
|
||||||
<span class='text-danger' id='nb_players'></span>
|
<option value="4">4</option>
|
||||||
|
<option value="8">8</option>
|
||||||
|
<option value="16">16</option>
|
||||||
|
<option value="32">32</option>
|
||||||
|
<option value="64">64</option>
|
||||||
|
</select>
|
||||||
|
<label for='nb-participant-input' id='nb-participant-label'>${lang.get("TournamentCreateNbPlayer")}</label>
|
||||||
|
<span class='text-danger' id='nb_participants'></span>
|
||||||
</div>
|
</div>
|
||||||
<div class='d-flex'>
|
<div class='d-flex'>
|
||||||
<button type='button' class='btn btn-primary mt-3 mb-2 mx-2' id='create-button'>${lang.get("TournamentCreateButton")}</button>
|
<button type='button' class='btn btn-primary mt-3 mb-2 mx-2' id='create-button'>${lang.get("TournamentCreateButton")}</button>
|
||||||
|
@ -3,6 +3,10 @@ import { Tourmanent } from "../../api/tournament/Tournament.js";
|
|||||||
import {client, navigateTo} from "../../index.js";
|
import {client, navigateTo} from "../../index.js";
|
||||||
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
|
import AbstractAuthenticatedView from "../abstracts/AbstractAuthenticatedView.js";
|
||||||
|
|
||||||
|
const TEXT_CONVENTION = {
|
||||||
|
"error": "[ERROR]"
|
||||||
|
}
|
||||||
|
|
||||||
export default class extends AbstractAuthenticatedView
|
export default class extends AbstractAuthenticatedView
|
||||||
{
|
{
|
||||||
constructor(params)
|
constructor(params)
|
||||||
@ -13,95 +17,49 @@ export default class extends AbstractAuthenticatedView
|
|||||||
|
|
||||||
pressButton()
|
pressButton()
|
||||||
{
|
{
|
||||||
this.tournament.toggle_participation();
|
this.tournament.setParticipation(!this.tournament.isParticipating);
|
||||||
|
this.updateParticipating()
|
||||||
}
|
}
|
||||||
|
|
||||||
createGraph()
|
updateParticipating()
|
||||||
{
|
{
|
||||||
console.log(this.tournament);
|
document.getElementById("button").value = this.tournament.isParticipating ? `Leave ${this.tournament.name}` : `Join ${this.tournament.name}`;
|
||||||
let tournament_tree = document.createElement("div");
|
document.getElementById("display").innerText = this.tournament.isParticipating ? "You are a particpant" : "You are not a participant";
|
||||||
|
|
||||||
tournament_tree.id = "tournament-tree";
|
|
||||||
|
|
||||||
document.getElementById("app").appendChild(tournament_tree);
|
|
||||||
|
|
||||||
for (let round_id = 0; round_id < this.tournament.round.length; round_id++)
|
|
||||||
{
|
|
||||||
let current_round = document.createElement("ul");
|
|
||||||
|
|
||||||
tournament_tree.appendChild(current_round);
|
|
||||||
|
|
||||||
current_round.className = `round round-${round_id}`;
|
|
||||||
|
|
||||||
for (let participant_i = 0; participant_i < this.tournament.round[round_id].length; participant_i += 2)
|
|
||||||
{
|
|
||||||
let spacer = document.createElement("li");
|
|
||||||
|
|
||||||
spacer.className = "spacer";
|
|
||||||
spacer.innerText = " ";
|
|
||||||
|
|
||||||
current_round.appendChild(spacer);
|
|
||||||
|
|
||||||
let game_top = document.createElement("li");
|
|
||||||
|
|
||||||
game_top.className = "game game-top";
|
|
||||||
game_top.innerText = `${this.tournament.round[round_id][participant_i]}`;
|
|
||||||
|
|
||||||
current_round.appendChild(game_top);
|
|
||||||
|
|
||||||
let game_spacer = document.createElement("li");
|
|
||||||
|
|
||||||
spacer.className = "game game-spacer";
|
|
||||||
spacer.innerText = " ";
|
|
||||||
|
|
||||||
current_round.appendChild(game_spacer);
|
|
||||||
|
|
||||||
let game_bottom = document.createElement("li");
|
|
||||||
|
|
||||||
game_bottom.className = "game game-bottom";
|
|
||||||
game_bottom.innerText = `${this.tournament.round[round_id][participant_i + 1]}`;
|
|
||||||
|
|
||||||
current_round.appendChild(game_bottom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
async receive(data)
|
|
||||||
{
|
|
||||||
if (data.detail === "update_participants")
|
|
||||||
document.getElementById("nb_participants").innerText = `${data.participants} / ${this.tournament.nb_participants}`;
|
|
||||||
if (data.detail === "go_to")
|
|
||||||
navigateTo(data.url);
|
|
||||||
if (data.detail === "is_participant")
|
|
||||||
this.updateParticipating(data.is_participant);
|
|
||||||
if (data.detail === "error")
|
|
||||||
document.getElementById("display").innerText = data.error_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateParticipating(state)
|
|
||||||
{
|
|
||||||
document.getElementById("button").value = state ? `Leave ${this.tournament.name}` : `Join ${this.tournament.name}`;
|
|
||||||
document.getElementById("display").innerText = state ? "You are a particpant" : "You are not a participant";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {[Profile]} oldParticipantsList
|
|
||||||
* @param {[Profile]} currentParticipantsList
|
|
||||||
*/
|
|
||||||
async onParticipantsUpdate(oldParticipantsList, currentParticipantsList)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onDisconnect(event)
|
async onDisconnect(event)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onError(data)
|
async onError(data)
|
||||||
{
|
{
|
||||||
|
this.addChatMessage(`${TEXT_CONVENTION} data.error_message`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onFinish()
|
||||||
|
{
|
||||||
|
document.getElementById("state").innerText = "finished"
|
||||||
|
}
|
||||||
|
|
||||||
|
async onStart()
|
||||||
|
{
|
||||||
|
document.getElementById("state").innerText = "started"
|
||||||
|
}
|
||||||
|
|
||||||
|
async onGoTo(data)
|
||||||
|
{
|
||||||
|
await navigateTo(`/games/pong/${data.game_id}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAddParticipant(nb_participants)
|
||||||
|
{
|
||||||
|
document.getElementById("nb_participants").innerText = nb_participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onDelParticipant(nb_participants)
|
||||||
|
{
|
||||||
|
document.getElementById("nb_participants").innerText = nb_participants;
|
||||||
}
|
}
|
||||||
|
|
||||||
async postInit()
|
async postInit()
|
||||||
@ -114,20 +72,27 @@ export default class extends AbstractAuthenticatedView
|
|||||||
if (this.tournament === null)
|
if (this.tournament === null)
|
||||||
return 404;
|
return 404;
|
||||||
|
|
||||||
this.tournament.join(this.onParticipantsUpdate.bind(this), this.onError.bind(this), this.onDisconnect.bind(this));
|
this.tournament.join(this.onAddParticipant, this.onDelParticipant, this.onStart, this.onFinish, this.onError, this.onGoTo, this.onDisconnect);
|
||||||
|
|
||||||
let button = document.getElementById("button");
|
let button = document.getElementById("button");
|
||||||
|
|
||||||
button.onclick = this.pressButton.bind(this);
|
button.onclick = this.pressButton.bind(this);
|
||||||
|
|
||||||
document.getElementById("name").innerText = this.tournament.name;
|
document.getElementById("name").innerText = this.tournament.name;
|
||||||
document.getElementById("nb_participants").innerText = this.tournament.nb_participants;
|
document.getElementById("nb_participants").innerText = this.tournament.participantList.length;
|
||||||
|
document.getElementById("expected_nb_participants").innerText = this.tournament.nb_participants;
|
||||||
document.getElementById("round").innerText = this.tournament.round;
|
document.getElementById("round").innerText = this.tournament.round;
|
||||||
document.getElementById("state").innerText = this.tournament.state;
|
document.getElementById("state").innerText = this.tournament.state;
|
||||||
|
|
||||||
if (this.tournament.started === false)
|
if (this.tournament.started === false)
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
this.createGraph();
|
|
||||||
|
this.chat = document.getElementById("chat");
|
||||||
|
}
|
||||||
|
|
||||||
|
addChatMessage(message)
|
||||||
|
{
|
||||||
|
this.chat.innerText += message;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getHtml()
|
async getHtml()
|
||||||
@ -150,13 +115,19 @@ export default class extends AbstractAuthenticatedView
|
|||||||
<td id="nb_participants">Loading...</td>
|
<td id="nb_participants">Loading...</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>status</td>
|
<td>Expected number of participants</td>
|
||||||
|
<td id="expected_nb_participants">Loading...</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>state</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>
|
<input type="button" id="button" value="Join tournament" disabled>
|
||||||
<span id="display"></span>
|
<span id="display"></span>
|
||||||
|
<textarea id="chat" rows="4" cols="50" readonly>
|
||||||
|
</textarea>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ from django.contrib.auth.models import User
|
|||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
from games.models import GameModel
|
||||||
from profiles.models import ProfileModel
|
from profiles.models import ProfileModel
|
||||||
from profiles.serializers.ProfileSerializer import ProfileSerializer
|
from profiles.serializers.ProfileSerializer import ProfileSerializer
|
||||||
from .models import TournamentModel
|
from .models import TournamentModel
|
||||||
@ -31,6 +31,9 @@ class TournamentMember:
|
|||||||
data_to_send.update(data)
|
data_to_send.update(data)
|
||||||
|
|
||||||
self.send("error", data_to_send)
|
self.send("error", data_to_send)
|
||||||
|
|
||||||
|
def send_goto(self, game: GameModel):
|
||||||
|
self.send("go_to", {"game_id": game.pk})
|
||||||
|
|
||||||
def _receive_participating(self, data: dict) -> None:
|
def _receive_participating(self, data: dict) -> None:
|
||||||
|
|
||||||
@ -38,20 +41,18 @@ class TournamentMember:
|
|||||||
if (is_participating is None):
|
if (is_participating is None):
|
||||||
self.send_error(_("Missing is_participating statement."))
|
self.send_error(_("Missing is_participating statement."))
|
||||||
return
|
return
|
||||||
self._room.set_participation()
|
|
||||||
|
self._room.set_participation(self, is_participating)
|
||||||
|
|
||||||
def receive(self, data: dict):
|
def receive(self, data: dict):
|
||||||
|
|
||||||
if self.is_participating == False:
|
|
||||||
return
|
|
||||||
|
|
||||||
detail: str | None = data.get("detail")
|
detail: str | None = data.get("detail")
|
||||||
if (detail is None):
|
if (detail is None):
|
||||||
return
|
return
|
||||||
|
|
||||||
match(detail):
|
match(detail):
|
||||||
case "update_particapating":
|
case "update_participating":
|
||||||
self._receive_participating()
|
self._receive_participating(data)
|
||||||
case _:
|
case _:
|
||||||
print("bozo_send")
|
print("bozo_send")
|
||||||
|
|
||||||
@ -80,16 +81,35 @@ class TournamentRoom:
|
|||||||
|
|
||||||
def __init__(self, room_manager: TournamentRoomManager, tournament: TournamentModel):
|
def __init__(self, room_manager: TournamentRoomManager, tournament: TournamentModel):
|
||||||
self._room_manager: TournamentRoomManager = room_manager
|
self._room_manager: TournamentRoomManager = room_manager
|
||||||
self._member_list: list[TournamentMember] = []
|
self._member_list: set[TournamentMember] = set()
|
||||||
self._model: TournamentModel = tournament
|
self._model: TournamentModel = tournament
|
||||||
|
|
||||||
def join(self, socket: TournamentWebConsumer) -> TournamentMember:
|
def join(self, socket: TournamentWebConsumer) -> TournamentMember:
|
||||||
|
|
||||||
member: TournamentMember = TournamentMember(socket, self)
|
member: TournamentMember = TournamentMember(socket, self)
|
||||||
self._member_list.append(member)
|
self._member_list.add(member)
|
||||||
|
|
||||||
return member
|
return member
|
||||||
|
|
||||||
|
def get_participants_profiles(self) -> list[ProfileModel]:
|
||||||
|
return [participant._socket.user.profilemodel for participant in self.get_participants()]
|
||||||
|
|
||||||
|
def start(self) -> None:
|
||||||
|
|
||||||
|
games: list[GameModel] = self._model.start()
|
||||||
|
|
||||||
|
self.broadcast("start")
|
||||||
|
|
||||||
|
for game in games:
|
||||||
|
for player in game.get_players():
|
||||||
|
participant: TournamentMember = self.get_participant_by_profile(player)
|
||||||
|
participant.send_goto(game)
|
||||||
|
|
||||||
|
def get_participant_by_profile(self, profile: ProfileModel):
|
||||||
|
for participant in self.get_participants():
|
||||||
|
if (participant._socket.user.profilemodel == profile):
|
||||||
|
return participant
|
||||||
|
|
||||||
def leave(self, member: TournamentMember) -> None:
|
def leave(self, member: TournamentMember) -> None:
|
||||||
|
|
||||||
# Delete room if nobody connected, no cringe memory leak
|
# Delete room if nobody connected, no cringe memory leak
|
||||||
@ -100,10 +120,13 @@ class TournamentRoom:
|
|||||||
self._member_list.remove(member)
|
self._member_list.remove(member)
|
||||||
|
|
||||||
self.set_participation(member, False)
|
self.set_participation(member, False)
|
||||||
|
|
||||||
|
def everybody_is_here(self):
|
||||||
|
return len(self.get_participants()) == self._model.nb_participants
|
||||||
|
|
||||||
def broadcast(self, detail: str, data: dict, excludes: list[TournamentMember] = []) -> None:
|
def broadcast(self, detail: str, data: dict, excludes: set[TournamentMember] = set()) -> None:
|
||||||
|
|
||||||
member_list: list[TournamentMember] = [member for member in self._member_list if member not in excludes]
|
member_list: list[TournamentMember] = self._member_list - excludes
|
||||||
|
|
||||||
for member in member_list:
|
for member in member_list:
|
||||||
member.send(detail, data)
|
member.send(detail, data)
|
||||||
@ -120,11 +143,14 @@ class TournamentRoom:
|
|||||||
return
|
return
|
||||||
|
|
||||||
if (is_participating == True):
|
if (is_participating == True):
|
||||||
self.broadcast("add_participant", {"profile", ProfileSerializer(member._socket.user.profilemodel).data})
|
self.broadcast("add_participant", {"participant": ProfileSerializer(member._socket.user.profilemodel).data})
|
||||||
else:
|
else:
|
||||||
self.broadcast("del_participant", {"profile", ProfileSerializer(member._socket.user.profilemodel).data})
|
self.broadcast("del_participant", {"participant": ProfileSerializer(member._socket.user.profilemodel).data})
|
||||||
|
|
||||||
member.is_participating = is_participating
|
member.is_participating = is_participating
|
||||||
|
|
||||||
|
if self.everybody_is_here():
|
||||||
|
self.start()
|
||||||
|
|
||||||
tournament_manager: TournamentRoomManager = TournamentRoomManager()
|
tournament_manager: TournamentRoomManager = TournamentRoomManager()
|
||||||
|
|
||||||
|
@ -1,21 +1,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
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 games.models import GameModel
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import CASCADE
|
from django.db.models import CASCADE
|
||||||
from channels.generic.websocket import WebsocketConsumer
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
# 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)
|
||||||
@ -23,12 +14,14 @@ class TournamentModel(models.Model):
|
|||||||
round = models.IntegerField()
|
round = models.IntegerField()
|
||||||
started = models.BooleanField(default = False)
|
started = models.BooleanField(default = False)
|
||||||
finished = models.BooleanField(default = False)
|
finished = models.BooleanField(default = False)
|
||||||
winner = models.ForeignKey(ProfileModel, on_delete=CASCADE, blank=True, null=True)
|
winner = models.ForeignKey(User, on_delete=CASCADE, blank=True, null=True)
|
||||||
|
|
||||||
def _register_participant(self, participant: ProfileModel) -> None:
|
def _register_participant(self, participant: User) -> None:
|
||||||
TournamentParticipantModel(participant=participant, tournament=self).save()
|
TournamentParticipantModel(participant=participant, tournament=self).save()
|
||||||
|
|
||||||
def start(self, participants: list[ProfileModel]) -> None:
|
def start(self, participants: list[User]) -> None:
|
||||||
|
|
||||||
|
games: list[GameModel] = []
|
||||||
|
|
||||||
self.started = True
|
self.started = True
|
||||||
|
|
||||||
@ -36,11 +29,14 @@ class TournamentModel(models.Model):
|
|||||||
self._register_participant(player)
|
self._register_participant(player)
|
||||||
|
|
||||||
for (participant1, participant2) in zip(participants[0::2], participants[1::2]):
|
for (participant1, participant2) in zip(participants[0::2], participants[1::2]):
|
||||||
self.create_game([participant1, participant2], round=1)
|
game: GameModel = self.create_game([participant1, participant2], round=1)
|
||||||
|
games.append(game)
|
||||||
|
|
||||||
self.save()
|
self.save()
|
||||||
|
|
||||||
def create_game(self, participants: list[ProfileModel], round: int) -> GameModel:
|
return games
|
||||||
|
|
||||||
|
def create_game(self, participants: list[User], round: int) -> GameModel:
|
||||||
|
|
||||||
if (self.started == False):
|
if (self.started == False):
|
||||||
return None
|
return None
|
||||||
@ -62,10 +58,10 @@ class TournamentModel(models.Model):
|
|||||||
def get_games_by_round(self, round: int) -> list[GameModel]:
|
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)]
|
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]:
|
def get_players_by_round(self, round: int) -> list[User]:
|
||||||
return [game.get_players() for game in self.get_games_by_round(round)]
|
return [game.get_players() for game in self.get_games_by_round(round)]
|
||||||
|
|
||||||
def get_winners_by_round(self, round: int) -> list[ProfileModel]:
|
def get_winners_by_round(self, round: int) -> list[User]:
|
||||||
return [game.winner for game in self.get_games_by_round(round)]
|
return [game.winner for game in self.get_games_by_round(round)]
|
||||||
|
|
||||||
def get_participants(self) -> list[TournamentParticipantModel]:
|
def get_participants(self) -> list[TournamentParticipantModel]:
|
||||||
@ -74,13 +70,12 @@ class TournamentModel(models.Model):
|
|||||||
def get_state(self) -> str:
|
def get_state(self) -> str:
|
||||||
return ("waiting to start", "in progress", "finish")[self.started + self.finished]
|
return ("waiting to start", "in progress", "finish")[self.started + self.finished]
|
||||||
|
|
||||||
def is_participanting(self, profile: ProfileModel) -> bool:
|
def is_participanting(self, profile: User) -> bool:
|
||||||
return TournamentParticipantModel.objects.filter(participant=profile, tournament=self).exists()
|
return TournamentParticipantModel.objects.filter(participant=profile, tournament=self).exists()
|
||||||
|
|
||||||
class TournamentParticipantModel(models.Model):
|
class TournamentParticipantModel(models.Model):
|
||||||
participant = models.ForeignKey(ProfileModel, on_delete=CASCADE)
|
participant = models.ForeignKey(User, on_delete=CASCADE)
|
||||||
tournament = models.ForeignKey(TournamentModel, on_delete=CASCADE)
|
tournament = models.ForeignKey(TournamentModel, on_delete=CASCADE)
|
||||||
#prout à encore frappé
|
|
||||||
|
|
||||||
class TournamentGameModel(models.Model):
|
class TournamentGameModel(models.Model):
|
||||||
|
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from django.db.models.query import QuerySet
|
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
|
||||||
|
|
||||||
from .models import TournamentModel
|
from .models import TournamentModel
|
||||||
|
|
||||||
from profiles.models import ProfileModel
|
from profiles.models import ProfileModel
|
||||||
from profiles.serializers.ProfileSerializer import ProfileSerializer
|
from profiles.serializers.ProfileSerializer import ProfileSerializer
|
||||||
from games.serializers import GameSerializer
|
from games.serializers import GameSerializer
|
||||||
|
|
||||||
|
nb_participants = [2 ** i for i in range(2, 6)]
|
||||||
|
|
||||||
class TournamentSerializer(serializers.ModelSerializer):
|
class TournamentSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
state = serializers.SerializerMethodField(read_only=True, required=False)
|
state = serializers.SerializerMethodField(read_only=True, required=False)
|
||||||
@ -30,16 +28,6 @@ class TournamentSerializer(serializers.ModelSerializer):
|
|||||||
return ["waiting", "started", "finished"][instance.started + instance.finished]
|
return ["waiting", "started", "finished"][instance.started + instance.finished]
|
||||||
|
|
||||||
def validate_nb_participants(self, value: int):
|
def validate_nb_participants(self, value: int):
|
||||||
if (value < 2):
|
if (value not in nb_participants):
|
||||||
raise serializers.ValidationError("The numbers of participants must be greather than 2.")
|
raise serializers.ValidationError(f"The numbers of participants must be {str(nb_participants)}.")
|
||||||
return value
|
|
||||||
|
|
||||||
def validate_nb_participants_by_game(self, value: int):
|
|
||||||
if (value < 2):
|
|
||||||
raise serializers.ValidationError("The numbers of participants by game must be greather than 2.")
|
|
||||||
nb_participants: str = self.initial_data.get("nb_participants")
|
|
||||||
if (nb_participants is not None and nb_participants.isnumeric()):
|
|
||||||
nb_participants: int = int(nb_participants)
|
|
||||||
if (value > nb_participants):
|
|
||||||
raise serializers.ValidationError("The numbers of participants by game must be smaller than the numbers of participants.")
|
|
||||||
return value
|
return value
|
Loading…
Reference in New Issue
Block a user