game: add: goal statistic

This commit is contained in:
2024-02-26 17:11:31 +01:00
committed by AdrienLSH
parent d961130de3
commit b9de0f3619
15 changed files with 335 additions and 82 deletions

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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}
*/

View File

@ -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;

File diff suppressed because one or more lines are too long

View 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;
}

View File

@ -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>
`;
}
}

View File

@ -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");