game: add: goal statistic
This commit is contained in:
parent
d961130de3
commit
b9de0f3619
@ -50,9 +50,18 @@ class Game
|
||||
let response_data = await response.json();
|
||||
|
||||
/**
|
||||
* @type {[Number]}
|
||||
* @type {[Player]}
|
||||
*/
|
||||
this.players_id = response_data.players_id;
|
||||
this.players = []
|
||||
|
||||
response_data.players.forEach(player_data => {
|
||||
this.players.push(new Player(this,
|
||||
player_data.player_id,
|
||||
player_data.username,
|
||||
player_data.score
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* @type {String}
|
||||
@ -74,6 +83,16 @@ class Game
|
||||
*/
|
||||
this.winner_id = this.finished ? response_data.winner_id : undefined;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
this.start_timestamp = response_data.start_timestamp;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
this.stop_timestamp = response_data.stop_timestamp;
|
||||
|
||||
if (this.finished === true)
|
||||
return 0;
|
||||
|
||||
@ -121,9 +140,8 @@ class Game
|
||||
render(ctx)
|
||||
{
|
||||
if(ctx instanceof CanvasRenderingContext2D)
|
||||
{
|
||||
ctx.clearRect(0, 0, this.config.size_x, this.config.size_y);
|
||||
}
|
||||
|
||||
this.draw_sides(ctx);
|
||||
this.ball.render(ctx);
|
||||
|
||||
@ -167,17 +185,32 @@ class Game
|
||||
this.ball.from_json(data);
|
||||
}
|
||||
|
||||
_receive_finish(data)
|
||||
async _receive_finish(data)
|
||||
{
|
||||
this.finish_handler(data)
|
||||
await this.finish_handler(data)
|
||||
}
|
||||
|
||||
_receive_goal(data)
|
||||
async _receive_goal(data)
|
||||
{
|
||||
this.goal_handler(data)
|
||||
/**
|
||||
* @type { Player }
|
||||
*/
|
||||
let player_found;
|
||||
|
||||
this.players.forEach(player => {
|
||||
if (data.player_id === player.id)
|
||||
{
|
||||
player_found = player
|
||||
return;
|
||||
}
|
||||
})
|
||||
|
||||
player_found.score.push(data.timestamp);
|
||||
|
||||
await this.goal_handler(player_found);
|
||||
}
|
||||
|
||||
_receive(data)
|
||||
async _receive(data)
|
||||
{
|
||||
if (data.detail === "update_paddle")
|
||||
this._receive_update_paddle(data);
|
||||
@ -186,9 +219,9 @@ class Game
|
||||
else if (data.detail === "init_game")
|
||||
this._init_game(data);
|
||||
else if (data.detail === "goal")
|
||||
this._receive_goal(data);
|
||||
await this._receive_goal(data);
|
||||
else if (data.detail === "finish")
|
||||
this._receive_finish(data)
|
||||
await this._receive_finish(data)
|
||||
}
|
||||
|
||||
_init_game(data)
|
||||
@ -210,11 +243,10 @@ class Game
|
||||
/**
|
||||
* @type {[Player]}
|
||||
*/
|
||||
this.players = [];
|
||||
const players_data = data.players;
|
||||
players_data.forEach((player_data) => {
|
||||
this.players.push(new Player(this).from_json(player_data));
|
||||
});
|
||||
for (let index = 0; index < players_data.length; index++) {
|
||||
this.players[index].from_json(players_data[index]);
|
||||
}
|
||||
|
||||
this._inited = true;
|
||||
}
|
||||
@ -237,9 +269,9 @@ class Game
|
||||
|
||||
this._socket = new WebSocket(url);
|
||||
|
||||
this._socket.onmessage = (event) => {
|
||||
this._socket.onmessage = async (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
this._receive(data);
|
||||
await this._receive(data);
|
||||
};
|
||||
|
||||
return this.wait_init();
|
||||
|
@ -82,6 +82,11 @@ class GameConfig
|
||||
*/
|
||||
this.stroke_thickness = response_data.STROKE_THICKNESS;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
*/
|
||||
this.game_max_score = response_data.GAME_MAX_SCORE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -9,12 +9,12 @@ class MyPlayer extends Player
|
||||
* @param {Client} client
|
||||
* @param {Game} game
|
||||
* @param {Segment} rail
|
||||
* @param {Number} nb_goal
|
||||
* @param {[Number]} score
|
||||
* @param {Number} position
|
||||
*/
|
||||
constructor(client, game, rail, nb_goal, position)
|
||||
constructor(client, game, score, rail, position)
|
||||
{
|
||||
super(game, client.me.id, client.me.username, rail, nb_goal, position, true);
|
||||
super(game, client.me.id, client.me.username, score, rail, position, true);
|
||||
/**
|
||||
* @type {Client}
|
||||
*/
|
||||
|
@ -8,12 +8,12 @@ class Player
|
||||
* @param {Number} id
|
||||
* @param {Game} game
|
||||
* @param {Segment} rail
|
||||
* @param {Number} nb_goal
|
||||
* @param {[Number]} score
|
||||
* @param {Number} position
|
||||
* @param {Boolean} is_connected
|
||||
* @param {String} username
|
||||
*/
|
||||
constructor(game, id, username, rail, nb_goal, position, is_connected)
|
||||
constructor(game, id, username, score, rail, position, is_connected)
|
||||
{
|
||||
/**
|
||||
* @type {Game}
|
||||
@ -36,9 +36,9 @@ class Player
|
||||
this.position = position;
|
||||
|
||||
/**
|
||||
* @type {Number}
|
||||
* @type {[Number]}
|
||||
*/
|
||||
this.nb_goal = nb_goal;
|
||||
this.score = score;
|
||||
|
||||
/**
|
||||
* @type {Segment}
|
||||
@ -102,7 +102,7 @@ class Player
|
||||
this.is_connected = data.is_connected;
|
||||
this.id = data.user_id;
|
||||
this.position = data.position.position ;
|
||||
this.nb_goal = data.nb_goal;
|
||||
this.score = data.score;
|
||||
this.rail = this.rail.from_json(data.rail);
|
||||
this.username = data.username;
|
||||
|
||||
|
20
frontend/static/js/chart/chart.umd.min.js
vendored
Normal file
20
frontend/static/js/chart/chart.umd.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
61
frontend/static/js/utils/graph.js
Normal file
61
frontend/static/js/utils/graph.js
Normal file
@ -0,0 +1,61 @@
|
||||
|
||||
export function generateRandomColor()
|
||||
{
|
||||
return `#${Math.floor(Math.random()*16777215).toString(16)}`
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {[Number]} data
|
||||
*/
|
||||
export function transformData(data)
|
||||
{
|
||||
let newData = [];
|
||||
|
||||
for (let index = 0; index < data.length; index++) {
|
||||
newData.push({x: Math.round(data[index] / 1000),
|
||||
y: index});
|
||||
}
|
||||
|
||||
return newData;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export function range(start, stop, step = 1)
|
||||
{
|
||||
if (stop === undefined)
|
||||
{
|
||||
stop = start
|
||||
start = 0
|
||||
}
|
||||
let newArr = [];
|
||||
for (let i = start; i <= stop; i += step)
|
||||
newArr.push(i);
|
||||
|
||||
return newArr;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {[Object]} dataset
|
||||
*/
|
||||
export function get_labels(dataset)
|
||||
{
|
||||
let labelsSet = new Set();
|
||||
|
||||
dataset.forEach(player_data => {
|
||||
player_data.data.forEach(data => {
|
||||
labelsSet.add(data.x);
|
||||
});
|
||||
});
|
||||
|
||||
let labels = Array.from(labelsSet);
|
||||
|
||||
labels.sort(function(a, b){return b - a});
|
||||
|
||||
labels.reverse()
|
||||
|
||||
return labels;
|
||||
}
|
@ -2,7 +2,10 @@ import { client, reloadView } from "../index.js";
|
||||
import { Game } from "../api/game/Game.js";
|
||||
import AbstractView from "./abstracts/AbstractView.js";
|
||||
import { MyPlayer } from "../api/game/MyPlayer.js";
|
||||
import { Player } from "../api/game/Player.js";
|
||||
import { lang } from "../index.js";
|
||||
import "https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"
|
||||
import { get_labels, transformData } from "../utils/graph.js";
|
||||
|
||||
export default class extends AbstractView
|
||||
{
|
||||
@ -14,12 +17,6 @@ export default class extends AbstractView
|
||||
this.my_player = undefined;
|
||||
}
|
||||
|
||||
on_finish(data)
|
||||
{
|
||||
console.log(data)
|
||||
reloadView()
|
||||
}
|
||||
|
||||
keyReleaseHandler(event)
|
||||
{
|
||||
const idx = this.keys_pressed.indexOf(event.key);
|
||||
@ -55,11 +52,21 @@ export default class extends AbstractView
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} data
|
||||
* @param {Player} player
|
||||
* @returns { Promise }
|
||||
*/
|
||||
on_goal(data)
|
||||
async on_goal(player)
|
||||
{
|
||||
document.getElementById(`goal-${data.player}`).innerText = data.nb_goal;
|
||||
document.getElementById(`goal-${player.id}`).innerText = player.score.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {*} data
|
||||
* @returns { Promise }
|
||||
*/
|
||||
async on_finish(data)
|
||||
{
|
||||
await reloadView();
|
||||
}
|
||||
|
||||
render()
|
||||
@ -67,8 +74,7 @@ export default class extends AbstractView
|
||||
let loop_id = setInterval(() => {
|
||||
if (this.game === undefined)
|
||||
clearInterval(loop_id);
|
||||
if (this.my_player)
|
||||
this.my_player.update_paddle(this.keys_pressed);
|
||||
this.my_player?.update_paddle(this.keys_pressed);
|
||||
this.render_game();
|
||||
this.game?.time.new_frame();
|
||||
//clearInterval(loop_id);
|
||||
@ -90,10 +96,8 @@ export default class extends AbstractView
|
||||
document.removeEventListener('keyup', this.keyReleaseHandler);
|
||||
}
|
||||
|
||||
async join_game()
|
||||
createGameBoard()
|
||||
{
|
||||
await this.game.join();
|
||||
|
||||
let canva = document.createElement("canvas");
|
||||
|
||||
canva.height = this.game.config.size_x;
|
||||
@ -101,19 +105,34 @@ export default class extends AbstractView
|
||||
canva.id = "canva";
|
||||
|
||||
document.getElementById("app").appendChild(canva);
|
||||
}
|
||||
|
||||
createMyPlayer()
|
||||
{
|
||||
let index = this.game.players.findIndex((player) => player.id === client.me.id);
|
||||
|
||||
if (index !== -1)
|
||||
{
|
||||
let my_player = this.game.players[index];
|
||||
this.my_player = new MyPlayer(client,
|
||||
this.game,
|
||||
my_player.score,
|
||||
my_player.rail,
|
||||
my_player.nb_goal,
|
||||
my_player.position,
|
||||
);
|
||||
);
|
||||
this.game.players[index] = this.my_player;
|
||||
}
|
||||
}
|
||||
|
||||
async join_game()
|
||||
{
|
||||
await this.game.join();
|
||||
|
||||
this.createGameBoard();
|
||||
|
||||
this.createMyPlayer();
|
||||
|
||||
this.displayPlayersList()
|
||||
|
||||
this.register_key();
|
||||
|
||||
@ -126,11 +145,73 @@ export default class extends AbstractView
|
||||
|
||||
if (this.game.finished === false)
|
||||
await this.join_game();
|
||||
else
|
||||
this.createGraph();
|
||||
}
|
||||
|
||||
display_players_list()
|
||||
createGraph()
|
||||
{
|
||||
let players_list = document.getElementById("players_list");
|
||||
let graph = document.createElement("canvas");
|
||||
|
||||
graph.height = 450;
|
||||
graph.width = 800;
|
||||
graph.id = "graph";
|
||||
|
||||
document.getElementById("app").appendChild(graph);
|
||||
|
||||
if (graph === null)
|
||||
return
|
||||
|
||||
let datasets = [];
|
||||
|
||||
this.game.players.forEach(player => {
|
||||
|
||||
let data = transformData(player.score);
|
||||
|
||||
data = [{x: 0, y: 0}, ...data]
|
||||
|
||||
console.log(data)
|
||||
|
||||
data.push({x: Math.round((this.game.stop_timestamp - this.game.start_timestamp) / 1000),
|
||||
y: data[data.length - 1].y});
|
||||
|
||||
datasets.push({
|
||||
data: data,
|
||||
label: player.username,
|
||||
borderColor: `#${Math.floor(Math.random()*16777215).toString(16)}`,
|
||||
fill: false,
|
||||
});
|
||||
});
|
||||
|
||||
this.chart = new Chart(graph, {
|
||||
type: "line",
|
||||
data: {
|
||||
labels: get_labels(datasets),
|
||||
datasets: datasets,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
displayPlayersList()
|
||||
{
|
||||
let table = document.createElement("table"),
|
||||
thead = document.createElement("thead"),
|
||||
tr = document.createElement("tr"),
|
||||
usernameTitle = document.createElement("th"),
|
||||
goalTitle = document.createElement("th"),
|
||||
playersList = document.createElement("tbody")
|
||||
;
|
||||
|
||||
usernameTitle.innerText = lang.get("gamePlayersListName");
|
||||
goalTitle.innerText = lang.get("gameGoalTaken");
|
||||
|
||||
tr.appendChild(usernameTitle);
|
||||
tr.appendChild(goalTitle);
|
||||
|
||||
table.appendChild(thead);
|
||||
table.appendChild(playersList);
|
||||
|
||||
document.getElementById("app").appendChild(table);
|
||||
|
||||
this.game.players.forEach(player => {
|
||||
|
||||
@ -139,23 +220,18 @@ export default class extends AbstractView
|
||||
let goal = document.createElement("td");
|
||||
|
||||
name.id = `username-${player.id}`;
|
||||
goal.id = `goal-${player.id}`;
|
||||
|
||||
name.innerText = player.username;
|
||||
goal.innerText = player.nb_goal;
|
||||
|
||||
goal.id = `goal-${player.id}`;
|
||||
goal.innerText = player.score.length;
|
||||
|
||||
tr.appendChild(name);
|
||||
tr.appendChild(goal);
|
||||
|
||||
players_list.appendChild(tr);
|
||||
playersList.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
toggle3D()
|
||||
{
|
||||
window.location.replace(location.href.substring(0, location.href.lastIndexOf('/')) + "/1");
|
||||
}
|
||||
|
||||
async postInit()
|
||||
{
|
||||
let error_code = await this.game.init();
|
||||
@ -164,8 +240,6 @@ export default class extends AbstractView
|
||||
return error_code;
|
||||
|
||||
await this.update_game_state();
|
||||
this.display_players_list();
|
||||
document.getElementById("game-mode").onclick = this.toggle3D;
|
||||
}
|
||||
|
||||
async leavePage()
|
||||
@ -181,20 +255,9 @@ export default class extends AbstractView
|
||||
async getHtml()
|
||||
{
|
||||
return /* HTML */ `
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/game.css">
|
||||
<h2 id="game-state"></h2>
|
||||
<input type="button" value="3D" id="game-mode">
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">${lang.get("gamePlayersListName")}</th>
|
||||
<th scope="col">${lang.get("gameGoalTaken")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="players_list">
|
||||
</tbody>
|
||||
</table>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ export default class extends AbstractView
|
||||
|
||||
async join_game()
|
||||
{
|
||||
await this.game.join()
|
||||
await this.game.join();
|
||||
|
||||
let canvas = document.createElement("canvas");
|
||||
|
||||
|
@ -19,4 +19,6 @@ BALL_SPAWN_POS_Y = MAP_SIZE_Y / 2
|
||||
|
||||
SERVER_TPS = 20
|
||||
|
||||
STROKE_THICKNESS = 10
|
||||
STROKE_THICKNESS = 10
|
||||
|
||||
GAME_MAX_SCORE = 7
|
@ -1,11 +1,20 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from django.db import models
|
||||
|
||||
from django.db.models import QuerySet
|
||||
|
||||
import time
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class GameModel(models.Model):
|
||||
|
||||
finished = models.BooleanField(default = False)
|
||||
started = models.BooleanField(default = False)
|
||||
winner_id = models.IntegerField(default = -1)
|
||||
start_timestamp = models.BigIntegerField(null = True, blank = True)
|
||||
stop_timestamp = models.BigIntegerField(null = True, blank = True)
|
||||
|
||||
def create(self, players_id: [int]):
|
||||
self.save()
|
||||
@ -14,16 +23,40 @@ class GameModel(models.Model):
|
||||
return self.pk
|
||||
|
||||
def start(self):
|
||||
self.start_timestamp = round(time.time() * 1000, 1)
|
||||
self.started = True
|
||||
|
||||
def finish(self, winner_id):
|
||||
self.winner_id = winner_id
|
||||
self.finished = True
|
||||
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_score_by_player_id(self, player_id: int) -> list[int]:
|
||||
query: QuerySet = GameGoalModel.objects.filter(game_id = self.pk, player_id = player_id)
|
||||
score_data: list[int] = [game_goal.timestamp for game_goal in query]
|
||||
|
||||
return score_data
|
||||
|
||||
def add_goal(self, goal_taker_id: int):
|
||||
|
||||
timestamp: int = round(time.time() * 1000, 1) - self.start_timestamp
|
||||
|
||||
goal_model: GameGoalModel = GameGoalModel.objects.create(player_id = goal_taker_id, game_id = self.pk, timestamp = timestamp)
|
||||
|
||||
goal_model.save()
|
||||
|
||||
return timestamp
|
||||
|
||||
class GameMembersModel(models.Model):
|
||||
game_id = models.IntegerField()
|
||||
player_id = models.IntegerField()
|
||||
player_id = models.IntegerField()
|
||||
|
||||
class GameGoalModel(models.Model):
|
||||
|
||||
game_id = models.IntegerField()
|
||||
player_id = models.IntegerField()
|
||||
timestamp = models.IntegerField()
|
@ -97,6 +97,13 @@ class Game(AbstractRoom):
|
||||
for member in members:
|
||||
member.send(detail, data)
|
||||
|
||||
def goal(self, goal_taker: Player):
|
||||
|
||||
timestamp = goal_taker.add_goal()
|
||||
|
||||
self.broadcast("goal", {"player_id": goal_taker.user_id,
|
||||
"timestamp": timestamp})
|
||||
|
||||
def get_player_by_user_id(self, user_id: int) -> Player:
|
||||
for player in self.players:
|
||||
if (player.user_id == user_id):
|
||||
@ -144,11 +151,10 @@ class Game(AbstractRoom):
|
||||
connected_players: list[Player] = self.get_players_connected()
|
||||
|
||||
if (self.model.started):
|
||||
print(len(connected_players))
|
||||
if (len(connected_players) == 1):
|
||||
last_player: Player = connected_players[0]
|
||||
print("finish")
|
||||
self.finish(last_player)
|
||||
#self.finish(last_player)
|
||||
return
|
||||
|
||||
self._update_player(player)
|
||||
|
@ -25,7 +25,7 @@ class Player(Spectator):
|
||||
|
||||
self.position: Position = Position(0.5, 0)
|
||||
|
||||
self.nb_goal: int = 0
|
||||
self.score: list[int] = []
|
||||
|
||||
self.rail: Segment = rail
|
||||
|
||||
@ -112,13 +112,23 @@ class Player(Spectator):
|
||||
print("bozoman")
|
||||
self.game.leave(self)
|
||||
|
||||
def add_goal(self):
|
||||
|
||||
timestamp = self.game.model.add_goal(self.user_id)
|
||||
|
||||
self.score.append(timestamp)
|
||||
|
||||
print(self.score)
|
||||
|
||||
return timestamp
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
|
||||
data = {
|
||||
"username": self.username,
|
||||
"user_id": self.user_id,
|
||||
"position": self.position.to_dict(),
|
||||
"nb_goal": self.nb_goal,
|
||||
"score": [*self.score],
|
||||
|
||||
"rail": self.rail.to_dict(),
|
||||
|
||||
|
@ -173,7 +173,7 @@ def wall_collision(ball_angle: float, wall: Segment) -> float:
|
||||
|
||||
return reflection_angle
|
||||
|
||||
async def paddle_collision(ball: Ball, impact: Point, player: Player, inc_x: float, inc_y: float):
|
||||
async def paddle_collision(game: Game, impact: Point, player: Player, inc_x: float, inc_y: float):
|
||||
|
||||
diff_x: float = player.rail.stop.x - player.rail.start.x
|
||||
diff_y: float = player.rail.stop.y - player.rail.start.y
|
||||
@ -199,8 +199,7 @@ async def paddle_collision(ball: Ball, impact: Point, player: Player, inc_x: flo
|
||||
hit_point: Point = Point(impact.x - inc_x, impact.y - inc_y)
|
||||
|
||||
if (not paddle.is_on(hit_point)):
|
||||
player.nb_goal += 1
|
||||
await SyncToAsync(player.game.broadcast)("goal", {"player": player.user_id, "nb_goal": player.nb_goal})
|
||||
await SyncToAsync(game.goal)(player)
|
||||
return None
|
||||
|
||||
paddle_angle: float = paddle.angle()
|
||||
@ -235,7 +234,7 @@ async def collision(game: Game, impact_data: dict) -> bool:
|
||||
if (player_hitted is None):
|
||||
angle = wall_collision(game.ball.angle, segment)
|
||||
else:
|
||||
angle = await paddle_collision(game.ball, impact_data.get("impact"), player_hitted, impact_data.get("inc_x"), impact_data.get("inc_y"))
|
||||
angle = await paddle_collision(game, impact_data.get("impact"), player_hitted, impact_data.get("inc_x"), impact_data.get("inc_y"))
|
||||
|
||||
if (angle is None):
|
||||
return False
|
||||
|
@ -1,17 +1,23 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import QuerySet
|
||||
|
||||
from .models import GameModel, GameMembersModel
|
||||
|
||||
class GameSerializer(serializers.ModelSerializer):
|
||||
|
||||
players_id = serializers.SerializerMethodField()
|
||||
players = serializers.SerializerMethodField()
|
||||
winner_id = serializers.ReadOnlyField()
|
||||
state = serializers.SerializerMethodField()
|
||||
started = serializers.ReadOnlyField()
|
||||
finished = serializers.ReadOnlyField()
|
||||
start_timestamp = serializers.ReadOnlyField()
|
||||
stop_timestamp = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = GameModel
|
||||
fields = ["id", "winner_id", "state", "started", "finished", "players_id"]
|
||||
fields = ["id", "winner_id", "state", "started", "finished", "players", "start_timestamp", "stop_timestamp"]
|
||||
|
||||
def get_state(self, instance: GameModel):
|
||||
if (instance.finished):
|
||||
@ -20,6 +26,20 @@ class GameSerializer(serializers.ModelSerializer):
|
||||
return "started"
|
||||
return "waiting"
|
||||
|
||||
def get_players_id(self, instance: GameModel):
|
||||
players_id = [player_game.player_id for player_game in GameMembersModel.objects.filter(game_id = instance.pk)]
|
||||
return players_id
|
||||
def get_players(self, instance: GameModel):
|
||||
players_data: list = []
|
||||
for player_id in instance.get_players_id():
|
||||
query: QuerySet = User.objects.filter(pk = player_id)
|
||||
username: str = "Deleted User"
|
||||
if (query.exists()):
|
||||
username = query[0].username
|
||||
|
||||
data: dict = {
|
||||
"id": player_id,
|
||||
"username": username,
|
||||
"score": instance.get_score_by_player_id(player_id)
|
||||
}
|
||||
|
||||
players_data.append(data)
|
||||
|
||||
return players_data
|
@ -25,5 +25,7 @@ class GameConfigView(APIView):
|
||||
"BALL_SPEED_START": config.BALL_SPEED_START,
|
||||
|
||||
"STROKE_THICKNESS": config.STROKE_THICKNESS,
|
||||
|
||||
"GAME_MAX_SCORE": config.GAME_MAX_SCORE,
|
||||
}
|
||||
return Response(config_data, status = status.HTTP_200_OK)
|
Loading…
Reference in New Issue
Block a user