From 995a808974724075627e9c507932c8bee6e91f54 Mon Sep 17 00:00:00 2001 From: Namonay Date: Tue, 14 May 2024 16:46:16 +0200 Subject: [PATCH] add: tictactoe: timers on catchup --- .../js/api/game/tictactoe/TicTacToeGame.js | 27 ++++++++++++------- .../static/js/views/ProfilePageView.js | 16 ++++++----- .../static/js/views/TicTacToeOnlineView.js | 8 +++--- django/games/consumers.py | 14 +++++++--- .../games/objects/tictactoe/TicTacToeGame.py | 10 ++++++- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/django/frontend/static/js/api/game/tictactoe/TicTacToeGame.js b/django/frontend/static/js/api/game/tictactoe/TicTacToeGame.js index 26b2751..70f4cee 100644 --- a/django/frontend/static/js/api/game/tictactoe/TicTacToeGame.js +++ b/django/frontend/static/js/api/game/tictactoe/TicTacToeGame.js @@ -1,4 +1,4 @@ -import { client, lang } from "../../../index.js"; +import { client, lang, navigateTo } from "../../../index.js"; import { AGame } from "../AGame.js"; @@ -50,7 +50,7 @@ class TicTacToe this.game.finished = false; if (this.turn) this.setOutline(4, false); - this.printTimer(); + this.printTimer(20); break; case 'game_move': @@ -59,7 +59,7 @@ class TicTacToe this.map[messageData.targetMorpion][messageData.targetCase] = (this.sign == "x") ? 1 : 0; this.printSign(messageData.targetMorpion, messageData.targetCase, (this.sign == "x") ? "o" : "x"); this.setOutline(this.currentMorpion, false); - this.printTimer(); + this.printTimer(20); break; case 'game_end': @@ -68,6 +68,7 @@ class TicTacToe this.printWin(messageData.winning_sign); break; case 'catchup': + this.game.finished = messageData.finished this.map = messageData.morpion; for (let i = 0; i < 9; i++) { @@ -81,6 +82,7 @@ class TicTacToe this.currentMorpion = messageData.currentMorpion; if (this.turn) this.setOutline(this.currentMorpion, false); + this.printTimer(Math.floor(messageData.timer)); } } @@ -96,10 +98,15 @@ class TicTacToe this.context.fillText((winning_sign == "o") ? lang.get("morpionWin") + "O" : lang.get("morpionWin") + "X", this.width / 2 - 85, this.height - this.gap / 2 + 10, 180); } - printTimer() + printTimer(sec) { - let sec = 20; - let turn = this.turn + let turn = this.turn; + + if (sec <= 0) + { + this.game.send(JSON.stringify({"timerIsDue" : this.sign})) + return; + } if (this.turn) { this.context.beginPath(); @@ -115,10 +122,10 @@ class TicTacToe this.context.fillStyle = "#1a1a1d"; this.context.fillRect(this.width / 2 - 40, 0, this.width / 2 + 40, this.gap - 10) this.context.closePath(); - if (sec == 0 || turn != this.turn || this.game.finished) + if (sec <= 0 || turn != this.turn || this.game.finished) { clearInterval(id); - if (sec == 0 && !this.turn && this.game.finished == false) + if (sec <= 0 && this.game.finished == false) this.game.send(JSON.stringify({"timerIsDue" : this.sign})) return; } @@ -175,7 +182,7 @@ class TicTacToe { morpion.setOutline(this.currentMorpion, true); morpion.sendCase(targetMorpion, targetCase); - morpion.printTimer() + morpion.printTimer(20) } else morpion.incorrectCase(); @@ -221,7 +228,7 @@ class TicTacToe this.context.strokeStyle = "red"; targetX += this.rectsize / 2; targetY += this.rectsize / 2; - this.context.arc(targetX, targetY, 15, 0, 2 * Math.PI); + this.context.arc(targetX, targetY, this.rectsize / 2 - 7, 0, 2 * Math.PI); this.context.stroke(); this.context.closePath(); } diff --git a/django/frontend/static/js/views/ProfilePageView.js b/django/frontend/static/js/views/ProfilePageView.js index 15a2f58..8127e73 100644 --- a/django/frontend/static/js/views/ProfilePageView.js +++ b/django/frontend/static/js/views/ProfilePageView.js @@ -86,8 +86,7 @@ export default class extends AbstractView { games.forEach(game => { if (game.finished === false) return - - if (this.profile.id === game.winner.id) + if (this.profile.id === game.winner?.id) win++; else lose++; @@ -114,10 +113,16 @@ export default class extends AbstractView { 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) + if (game.finished && game.winner == null) + game_item.style.backgroundColor = "red"; + else if (game.finished) game_item.style.backgroundColor = this.profile.id === game.winner.id ? "green" : "red"; + else if (game.started) + game_item.style.backgroundColor = "yellow"; + + let gametype = document.createElement("b"); + gametype.innerText = `${(game.game_type == "tictactoe") ? lang.get("ticTacToeTitle") : "Pong"}`; + game_item.appendChild(gametype); game.players.forEach(player => { let player_score = document.createElement("a"); @@ -128,7 +133,6 @@ export default class extends AbstractView { game_item.appendChild(player_score); }); - a.appendChild(game_item); game_list.appendChild(a); }); diff --git a/django/frontend/static/js/views/TicTacToeOnlineView.js b/django/frontend/static/js/views/TicTacToeOnlineView.js index 4d49ebf..eb20d96 100644 --- a/django/frontend/static/js/views/TicTacToeOnlineView.js +++ b/django/frontend/static/js/views/TicTacToeOnlineView.js @@ -1,12 +1,12 @@ -import AbstractView from "./abstracts/AbstractView.js"; import { lang } from "../index.js"; import { TicTacToe } from "../api/game/tictactoe/TicTacToeGame.js" - -export class TicTacToeOnlineView extends AbstractView +import AbstractAuthenticatedView from "./abstracts/AbstractAuthenticatedView.js"; +import { navigateTo } from "../index.js" +export class TicTacToeOnlineView extends AbstractAuthenticatedView { constructor(params, titleKey) { - super(params, lang.get('ticTacToeTitle')); + super(params, 'ticTacToeTitle'); this.params = params; this.titleKey = titleKey; this.game_id = params.id; diff --git a/django/games/consumers.py b/django/games/consumers.py index fa1c759..ee70fb1 100644 --- a/django/games/consumers.py +++ b/django/games/consumers.py @@ -5,7 +5,9 @@ from channels.generic.websocket import WebsocketConsumer from django.contrib.auth.models import User import json - + +import sys + from .objects.GameManager import GameManager from .objects.tictactoe.TicTacToePlayer import TicTacToePlayer @@ -47,7 +49,7 @@ class TicTacToeWebSocket(WebsocketConsumer): self.member.send(self.member.sign) if (self.game._everbody_is_here() and self.game.model.started == True and self.game.model.finished == False): # if an user disconnected and joined back - self.member.send("catchup", {"morpion" : self.game._map, "turn" : self.game.turn, "currentMorpion": self.member.currentMorpion}) + self.member.send("catchup", {"morpion" : self.game._map, "turn" : self.game.turn, "currentMorpion": self.member.currentMorpion, "timer" : 20 - (time.time() - self.game.time), "finished" : self.game.model.finished}) return if (self.game._everbody_is_here() and self.game.model.started == False): # Launch the game if the two players are connected @@ -64,8 +66,10 @@ class TicTacToeWebSocket(WebsocketConsumer): self.game.broadcast("game_move", data, [self.member]) if (data.get("timerIsDue") is not None and self.game.time + 20 < time.time()): # Frontend asking if the timer is due - self.winner = 'x' if self.game.turn == 'o' else 'o' - self.game.model.finish(self.user) + self.winner = "x" if self.game.turn == "o" else "o" + self.game.get_members() + + self.game.model.finish(self.game.get_players_by_sign(self.winner).user) self.game.broadcast("game_end", {"winning_sign": self.winner}) if (self.game.checkWin() != False): # Check if after a move, the game is finished @@ -77,6 +81,8 @@ class TicTacToeWebSocket(WebsocketConsumer): def disconnect(self, event): try: self.member.socket = None + if (len(self.game.get_players_connected()) == 0): + self.game.model.finish(None) except: pass diff --git a/django/games/objects/tictactoe/TicTacToeGame.py b/django/games/objects/tictactoe/TicTacToeGame.py index d8ea06b..1880017 100644 --- a/django/games/objects/tictactoe/TicTacToeGame.py +++ b/django/games/objects/tictactoe/TicTacToeGame.py @@ -8,13 +8,15 @@ from .TicTacToeSpectator import TicTacToeSpectator import time +import sys + class TicTacToeGame(AGame): def __init__(self, game_id: int, game_manager): super().__init__("tictactoe", game_id, game_manager) - players: list[int] = self.model.get_players() + players = self.model.get_players() self.players: list[TicTacToePlayer] = [TicTacToePlayer(player, None, self, ["x", "o"][i]) for i, player in enumerate(players)] @@ -29,6 +31,12 @@ class TicTacToeGame(AGame): def _everbody_is_here(self): return len(self.players) == len(self.get_players_connected()) + def get_players_by_sign(self, sign): + for player in self.players: + if (player.sign == sign): + return player + return None + def _player_join(self, user_id: int, socket: WebsocketConsumer): player = self.get_player_by_user_id(user_id)