add: game history

This commit is contained in:
starnakin 2024-03-05 10:53:32 +01:00 committed by AdrienLSH
parent 90ce697a3a
commit d8e767405a
8 changed files with 201 additions and 24 deletions

View File

@ -0,0 +1,15 @@
#game-list {
justify-content: flex-start;
display: flex;
flex-wrap: wrap;
}
#game-list .game-item {
display: flex;
flex-direction: column;
height: 160px;
width: 160px;
margin: 10px;
border-radius: 5%;
}

View File

@ -1,4 +1,5 @@
import { Client } from "./Client.js"; import { Client } from "./Client.js";
import { Game } from "./game/Game.js";
class Profile class Profile
{ {
@ -59,6 +60,36 @@ class Profile
} }
/**
* @returns {[Game]}
*/
async getGameHistory()
{
let response = await this.client._get(`/api/games/history/${this.id}`);
let response_data = await response.json();
let games = [];
response_data.forEach(game_data => {
games.push(new Game(this.client,
game_data.id,
null,
null,
null,
game_data.winner_id,
game_data.state,
game_data.started,
game_data.finished,
game_data.players,
game_data.start_timestamp,
game_data.stop_timestamp
)
);
});
return games;
}
async getBlock() { async getBlock() {
let block_response = await this.client._get("/api/profiles/block"); let block_response = await this.client._get("/api/profiles/block");

View File

@ -42,6 +42,11 @@ class Profiles
return profile; return profile;
} }
/**
*
* @param {Number} id
* @returns {Profile}
*/
async getProfileId(id) async getProfileId(id)
{ {
let profile = new Profile(this.client, undefined, id); let profile = new Profile(this.client, undefined, id);

View File

@ -13,8 +13,16 @@ class Game
* @param {CallableFunction} goal_handler * @param {CallableFunction} goal_handler
* @param {CallableFunction} finish_handler * @param {CallableFunction} finish_handler
* @param {CallableFunction} disconnect_handler * @param {CallableFunction} disconnect_handler
* @param {Boolean} finished
* @param {Number} id
* @param {[Object]} players_data
* @param {Number} start_timestamp
* @param {Number} stop_timestamp
* @param {Boolean} started
* @param {Number} winner_id
* @param {String} state
*/ */
constructor(client, id, disconnect_handler, goal_handler, finish_handler) constructor(client, id, disconnect_handler, goal_handler, finish_handler, winner_id, state, started, finished, players_data, start_timestamp, stop_timestamp)
{ {
/** /**
* @type {Client} * @type {Client}
@ -40,6 +48,50 @@ class Game
* @type {CallableFunction} * @type {CallableFunction}
*/ */
this.disconnect_handler = disconnect_handler; this.disconnect_handler = disconnect_handler;
/**
* @type {String}
*/
this.state = state;
/**
* @type {Boolean}
*/
this.started = started;
/**
* @type {Boolean}
*/
this.finished = finished;
/**
* @type {Number}
*/
this.winner_id = this.finished ? winner_id : undefined;
/**
* @type {Number}
*/
this.start_timestamp = start_timestamp;
/**
* @type {Number}
*/
this.stop_timestamp = stop_timestamp;
/**
* @type {[Player]}
*/
this.players = [];
players_data.forEach(player_data => {
this.players.push(new Player(this,
player_data.player_id,
player_data.username,
player_data.score
)
);
});
} }
/** /**
@ -55,9 +107,6 @@ class Game
let response_data = await response.json(); let response_data = await response.json();
/**
* @type {[Player]}
*/
this.players = []; this.players = [];
response_data.players.forEach(player_data => { response_data.players.forEach(player_data => {
@ -69,34 +118,14 @@ class Game
); );
}); });
/**
* @type {String}
*/
this.state = response_data.state; this.state = response_data.state;
/**
* @type {Boolean}
*/
this.started = response_data.started; this.started = response_data.started;
/**
* @type {Boolean}
*/
this.finished = response_data.finished; this.finished = response_data.finished;
/**
* @type {Number}
*/
this.winner_id = this.finished ? response_data.winner_id : undefined; this.winner_id = this.finished ? response_data.winner_id : undefined;
/**
* @type {Number}
*/
this.start_timestamp = response_data.start_timestamp; this.start_timestamp = response_data.start_timestamp;
/**
* @type {Number}
*/
this.stop_timestamp = response_data.stop_timestamp; this.stop_timestamp = response_data.stop_timestamp;
if (this.finished === true) if (this.finished === true)

View File

@ -19,6 +19,7 @@ import TournamentsView from "./views/tournament/TournamentsListView.js";
import TournamentCreateView from "./views/tournament/TournamentCreateView.js"; import TournamentCreateView from "./views/tournament/TournamentCreateView.js";
import AuthenticationView from "./views/accounts/AuthenticationView.js"; import AuthenticationView from "./views/accounts/AuthenticationView.js";
import TicTacToeView from "./views/TicTacToeView.js"; import TicTacToeView from "./views/TicTacToeView.js";
import GameHistoryView from "./views/GameHistoryView.js";
let client = new Client(location.origin); let client = new Client(location.origin);
let lang = client.lang; let lang = client.lang;
@ -77,6 +78,7 @@ const router = async(uri) => {
const routes = [ const routes = [
{ path: "/", view: Dashboard }, { path: "/", view: Dashboard },
{ path: "/profiles/:id/history", view: GameHistoryView },
{ path: "/profiles/:username", view: ProfilePageView }, { path: "/profiles/:username", view: ProfilePageView },
{ path: "/tournaments/create", view: TournamentCreateView }, { path: "/tournaments/create", view: TournamentCreateView },
{ path: "/tournaments/:id", view: TournamentPageView }, { path: "/tournaments/:id", view: TournamentPageView },

View File

@ -0,0 +1,66 @@
import { client, lang } from "../index.js";
import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js";
export default class extends AbstractAuthenticatedView
{
constructor(params)
{
super(params, 'homeWindowTitle');
this.id = params.id;
}
async postInit()
{
this.profile = await client.profiles.getProfileId(this.id);
if (this.profile === null)
return 404;
await this.fillHistory();
}
async fillHistory()
{
let games = await this.profile.getGameHistory();
let game_list = document.getElementById("game-list");
games.forEach(game => {
let a = document.createElement("a");
a.href = `/games/${game.id}/0`;
a.setAttribute("data-link", true);
let game_item = document.createElement("div");
game_item.className = "game-item";
game_item.style.backgroundColor = "grey";
if (game.started)
game_item.style.backgroundColor = "yellow";
if (game.finished)
game_item.style.backgroundColor = this.profile.id === game.winner_id ? "green" : "red";
game.players.forEach(player => {
let player_score = document.createElement("a");
player_score.href = `/profiles/${player.username}`;
player_score.innerText = `${player.username}: ${player.score.length}`;
player_score.setAttribute("data-link", true);
game_item.appendChild(player_score);
});
a.appendChild(game_item);
game_list.appendChild(a);
});
}
async getHtml()
{
return /* HTML */ `
<link rel="stylesheet" href="/static/css/gameHistory.css">
<h1>Game History</h1>
<div id="game-list">
</div>
`;
}
}

27
games/GameHistoryView.py Normal file
View File

@ -0,0 +1,27 @@
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions, status
from django.http import HttpRequest
from .models import GameMembersModel, GameModel
from .serializers import GameSerializer
from . import config
class GameHistoryView(APIView):
permission_classes = (permissions.AllowAny,)
def get(self, request: HttpRequest, pk: int = None):
member_game_model_list: list[GameMembersModel] = GameMembersModel.objects.filter(player_id = pk)
game_model_list: list[GameModel] = []
for member_game_model in member_game_model_list:
game_model_list.append(GameModel.objects.get(pk = member_game_model.game_id))
games_data: list[dict] = [GameSerializer(game_model).data for game_model in game_model_list]
return Response(games_data)

View File

@ -3,9 +3,11 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from .GameViewSet import GameViewSet from .GameViewSet import GameViewSet
from .GameHistoryView import GameHistoryView
from .GameConfigView import GameConfigView from .GameConfigView import GameConfigView
urlpatterns = [ urlpatterns = [
path("<int:pk>", GameViewSet.as_view({"get": "retrieve"}), name="game_page"), path("<int:pk>", GameViewSet.as_view({"get": "retrieve"}), name="game_page"),
path("history/<int:pk>", GameHistoryView.as_view(), name="history_page"),
path("", GameConfigView.as_view(), name = "game_config") path("", GameConfigView.as_view(), name = "game_config")
] ]