Merge branch 'main' of codeberg.org:adrien-lsh/ft_transcendence

This commit is contained in:
Xamora 2024-05-13 16:44:33 +02:00
commit ae76b82169
9 changed files with 112 additions and 108 deletions

View File

@ -75,14 +75,14 @@ export class Profile extends AExchangeable
}
/**
* @returns {[Object]}
* @returns {Promise<[Object]>}
*/
async getGameHistory()
{
let response = await this.client._get(`/api/games/history/${this.id}`);
let response_data = await response.json();
const response = await this.client._get(`/api/games/history/${this.id}`);
const response_data = await response.json();
let games = [];
const games = [];
response_data.forEach(game_data => {
games.push(game_data);

View File

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

View File

@ -1,66 +0,0 @@
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>
`;
}
}

View File

@ -16,6 +16,13 @@ export default class extends AbstractView {
if (!this.profile)
return 404;
const games = await this.profile.getGameHistory();
console.log(games)
await this.fillHistory(games);
await this.fillStatistics(games);
if (this.profile.id === client.me.id)
return;
@ -68,13 +75,69 @@ export default class extends AbstractView {
statusIndicator.classList.add('bg-danger');
}
/**
* @param {[Object]} games
*/
async fillStatistics(games)
{
const winrateDiv = document.getElementById("winrate");
const win = 0;
const lose = 0;
games.forEach(game => {
if (game.finished === false)
return
if (client.me.id === game.winner.id)
win++;
else
lose++;
});
winrateDiv.innerText = `winrate: ${win + lose === 0 ? "🤓" : win / (win + lose)}`
}
async fillHistory(games)
{
const game_list = document.getElementById("game-list");
games.forEach(game => {
let a = document.createElement("a");
a.href = `/games/${game.game_type}/${game.id}`;
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.setAttribute("data-link", true);
game_item.appendChild(player_score);
});
a.appendChild(game_item);
game_list.appendChild(a);
});
}
async getHtml() {
this.profile = await client.profiles.getProfile(this.username);
if (!this.profile)
return '';
return `
return /* HTML */ `
<div>
<div class='mb-3' id='profileInfo'>
<h1>${this.username}<span id='statusIndicator' style='height:0.75em; width:0.75em' class='ms-2 rounded-circle border d-inline-block'></span></h1>
@ -88,6 +151,14 @@ export default class extends AbstractView {
<button class='btn btn-sm btn-danger d-none' id='blockButton'>Block</button>
<button class='btn btn-sm btn-secondary d-none' id='unblockButton'>Unblock</button>
</div>
<h1>Games</h1>
<div>
<h1 id='winrate'></h1>
</div>
<div>
<link rel="stylesheet" href="/static/css/gameHistory.css">
<div id="game-list"></div>
</div>
</div>
`;
}

View File

@ -1,27 +0,0 @@
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

@ -0,0 +1,28 @@
from rest_framework.viewsets import ViewSet
from rest_framework.response import Response
from rest_framework import permissions
from django.http import HttpRequest
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from .models import GameMembersModel, GameModel
from .serializers import GameSerializer
class GameHistoryView(ViewSet):
queryset = User.objects.all()
serializer_class = GameSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def retrive(self, request: HttpRequest, pk: int = None):
user: User = get_object_or_404(User, pk=pk)
member_game_model_list: list[GameMembersModel] = GameMembersModel.objects.filter(player=user)
game_model_list: list[GameModel] = [member_game_model.game for member_game_model in member_game_model_list]
games_data: list[dict] = self.serializer_class(game_model_list, many=True).data
return Response(games_data)

View File

@ -38,11 +38,11 @@ class GameModel(models.Model):
self.stop_timestamp = round(time.time() * 1000, 1)
self.save()
def get_players(self) -> set[User]:
return {game_player.player for game_player in GameMembersModel.objects.filter(game = self)}
def get_players(self) -> list[User]:
return [game_player.player for game_player in GameMembersModel.objects.filter(game = self)]
def get_players_profiles(self) -> set[User]:
return {game_player.player.profilemodel for game_player in GameMembersModel.objects.filter(game = self)}
def get_players_profiles(self) -> list[User]:
return [game_player.player.profilemodel for game_player in GameMembersModel.objects.filter(game = self)]
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)

View File

@ -9,7 +9,7 @@ from profiles.serializers import ProfileSerializer
class GameSerializer(serializers.ModelSerializer):
players = serializers.SerializerMethodField()
winner_id = serializers.ReadOnlyField()
winner = serializers.ReadOnlyField()
state = serializers.SerializerMethodField()
started = serializers.ReadOnlyField()
finished = serializers.ReadOnlyField()
@ -19,7 +19,7 @@ class GameSerializer(serializers.ModelSerializer):
class Meta:
model = GameModel
fields = ["id", "winner_id", "state", "started", "finished", "players", "start_timestamp", "stop_timestamp", "game_type"]
fields = ["id", "winner", "state", "started", "finished", "players", "start_timestamp", "stop_timestamp", "game_type"]
def get_state(self, instance: GameModel):
if (instance.finished):

View File

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