mirror of
https://github.com/kmitresse/Cards-Rush.git
synced 2026-05-13 17:11:49 +00:00
feat!(DevWeb):Add timer for games
/!\ Warning: Need to rebuild the DB
This commit is contained in:
@@ -22,6 +22,7 @@ CREATE TABLE IF NOT EXISTS game
|
|||||||
nb_rounds INT NOT NULL,
|
nb_rounds INT NOT NULL,
|
||||||
nb_colors INT NOT NULL,
|
nb_colors INT NOT NULL,
|
||||||
nb_values_per_color INT NOT NULL,
|
nb_values_per_color INT NOT NULL,
|
||||||
|
timer INT NOT NULL,
|
||||||
PRIMARY KEY (id)
|
PRIMARY KEY (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class Game implements Serializable {
|
|||||||
@Transient
|
@Transient
|
||||||
private Deck deck;
|
private Deck deck;
|
||||||
|
|
||||||
@Transient
|
@Column(name = "timer")
|
||||||
private int timer;
|
private int timer;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
@@ -90,6 +90,7 @@ public class Game implements Serializable {
|
|||||||
public Game() {
|
public Game() {
|
||||||
this.createdAt = new Date();
|
this.createdAt = new Date();
|
||||||
this.players = new ArrayList<>();
|
this.players = new ArrayList<>();
|
||||||
|
this.timer = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ public enum ClickChoice {
|
|||||||
COLOR_VALUE,
|
COLOR_VALUE,
|
||||||
COLOR,
|
COLOR,
|
||||||
VALUE,
|
VALUE,
|
||||||
NONE
|
NONE,
|
||||||
|
TIMER_END
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class SimpleGame {
|
|||||||
this.id = game.getId().intValue();
|
this.id = game.getId().intValue();
|
||||||
this.players = new ArrayList<>();
|
this.players = new ArrayList<>();
|
||||||
for (Player p : playerArrayList) players.add(new SimplePlayer(p, game.getCurrentRound()));
|
for (Player p : playerArrayList) players.add(new SimplePlayer(p, game.getCurrentRound()));
|
||||||
this.currentCard = game.getDeck().getCards().get(game.getCurrentRound());
|
this.currentCard = game.getDeck().getCards().get(game.getCurrentRound() % game.getDeck().getCards().size());
|
||||||
this.currentRound = game.getCurrentRound();
|
this.currentRound = game.getCurrentRound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class SimplePlayer {
|
|||||||
this.rightClickCount = player.getRightClickCount();
|
this.rightClickCount = player.getRightClickCount();
|
||||||
this.rapidClickCount = player.getRapidClickCount();
|
this.rapidClickCount = player.getRapidClickCount();
|
||||||
|
|
||||||
this.currentCard = player.getDeck().getCards().get(currentRound);
|
this.currentCard = player.getDeck().getCards().get(currentRound % player.getDeck().getCards().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public SimplePlayer(Player player) {
|
public SimplePlayer(Player player) {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import jakarta.websocket.server.ServerEndpoint;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
import uppa.project.bean.PlayerBean;
|
import uppa.project.bean.PlayerBean;
|
||||||
import uppa.project.database.dao.DAO;
|
import uppa.project.database.dao.DAO;
|
||||||
import uppa.project.database.dao.DAOException;
|
import uppa.project.database.dao.DAOException;
|
||||||
@@ -27,19 +29,20 @@ import uppa.project.json.websocket.Message;
|
|||||||
import uppa.project.json.websocket.SimpleGame;
|
import uppa.project.json.websocket.SimpleGame;
|
||||||
import uppa.project.json.websocket.SimplePlayer;
|
import uppa.project.json.websocket.SimplePlayer;
|
||||||
import uppa.project.json.websocket.SimpleUser;
|
import uppa.project.json.websocket.SimpleUser;
|
||||||
import uppa.project.utils.GameProvider;
|
|
||||||
|
|
||||||
@ServerEndpoint(value = "/ws/game/{game_id}")
|
@ServerEndpoint(value = "/ws/game/{game_id}")
|
||||||
public class GameWS {
|
public class GameWS {
|
||||||
|
|
||||||
private static final HashMap<Game, ArrayList<Player>> games = new HashMap<>();
|
private static final HashMap<Game, ArrayList<Player>> games = new HashMap<>();
|
||||||
|
private static final HashMap<Game, Timer> timers = new HashMap<>();
|
||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
private Game game;
|
private Game game;
|
||||||
private Player player;
|
private Player player;
|
||||||
|
|
||||||
@OnOpen
|
@OnOpen
|
||||||
public void onOpen(Session session, @PathParam("game_id") String gameId) throws DAOException {
|
public void onOpen(Session session, @PathParam("game_id") String gameId) throws DAOException {
|
||||||
this.game = GameProvider.getGame(Integer.parseInt(gameId));
|
DAO<Game> gameDAO = new Game_JPA_DAO_Factory().getDAOGame();
|
||||||
|
this.game = gameDAO.findById(Integer.parseInt(gameId));
|
||||||
if (!games.containsKey(game)) games.put(game, new ArrayList<>());
|
if (!games.containsKey(game)) games.put(game, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +87,18 @@ public class GameWS {
|
|||||||
if (message.getType().equals("start")) {
|
if (message.getType().equals("start")) {
|
||||||
game.setGameState(Game.GameState.STARTED);
|
game.setGameState(Game.GameState.STARTED);
|
||||||
broadcast(new Message("start", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
broadcast(new Message("start", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||||
// TODO Start Timer
|
|
||||||
|
// TODO Start the timer
|
||||||
|
Timer timer = new Timer();
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Broadcast the end of the game
|
||||||
|
broadcast(new Message("timerEnd", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
}, game.getTimer() * 1000L);
|
||||||
|
timers.put(game, timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.getType().equals("click")) {
|
if (message.getType().equals("click")) {
|
||||||
@@ -151,6 +165,7 @@ public class GameWS {
|
|||||||
player.setScore(playerScore - 1);
|
player.setScore(playerScore - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case TIMER_END -> {}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int nbSameCard = countSameCard(gameCard, games.get(game), game.getCurrentRound());
|
int nbSameCard = countSameCard(gameCard, games.get(game), game.getCurrentRound());
|
||||||
@@ -194,6 +209,7 @@ public class GameWS {
|
|||||||
player.setScore(playerScore - 1);
|
player.setScore(playerScore - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case TIMER_END -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,6 +221,8 @@ public class GameWS {
|
|||||||
|
|
||||||
// If all players have clicked
|
// If all players have clicked
|
||||||
if (gameClickCount >= games.get(game).size()) {
|
if (gameClickCount >= games.get(game).size()) {
|
||||||
|
// Stop the timer if it's running
|
||||||
|
timers.get(game).cancel();
|
||||||
|
|
||||||
// Reset the current click for all players
|
// Reset the current click for all players
|
||||||
for (Player p : games.get(game)) p.setCurrentClick(null);
|
for (Player p : games.get(game)) p.setCurrentClick(null);
|
||||||
@@ -223,7 +241,16 @@ public class GameWS {
|
|||||||
// Check if the game is over
|
// Check if the game is over
|
||||||
if (game.nextRound() || (second.getScore() == theoricWinner.getScore() && second.getRapidClickCount() == theoricWinner.getRapidClickCount())) {
|
if (game.nextRound() || (second.getScore() == theoricWinner.getScore() && second.getRapidClickCount() == theoricWinner.getRapidClickCount())) {
|
||||||
broadcast(new Message("nextRound", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
broadcast(new Message("nextRound", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||||
// TODO Start Timer
|
Timer timer = new Timer();
|
||||||
|
timer.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
// Broadcast the end of the game
|
||||||
|
broadcast(new Message("timerEnd", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||||
|
timer.cancel();
|
||||||
|
}
|
||||||
|
}, game.getTimer() * 1000L);
|
||||||
|
timers.put(game, timer);
|
||||||
} else {
|
} else {
|
||||||
theoricWinner.setWinner();
|
theoricWinner.setWinner();
|
||||||
|
|
||||||
@@ -232,10 +259,9 @@ public class GameWS {
|
|||||||
for (Player p : games.get(game)) {
|
for (Player p : games.get(game)) {
|
||||||
PlayerBean playerBean = new PlayerBean(p);
|
PlayerBean playerBean = new PlayerBean(p);
|
||||||
if (playerBean.validate()) System.out.println("Player " + p.getUser().getUsername() + " sauvegardé en base de données");
|
if (playerBean.validate()) System.out.println("Player " + p.getUser().getUsername() + " sauvegardé en base de données");
|
||||||
else System.out.println("");
|
else System.out.println();
|
||||||
};
|
}
|
||||||
em.getTransaction().commit();
|
em.getTransaction().commit();
|
||||||
em.close();
|
|
||||||
|
|
||||||
// Broadcast the end of the game
|
// Broadcast the end of the game
|
||||||
broadcast(new Message("end", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
broadcast(new Message("end", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||||
@@ -246,6 +272,7 @@ public class GameWS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retourne le nombre de joueurs avec une carte identique à celle du plateau
|
* Retourne le nombre de joueurs avec une carte identique à celle du plateau
|
||||||
|
*
|
||||||
* @param gameCard carte du plateau
|
* @param gameCard carte du plateau
|
||||||
* @param players liste des joueurs
|
* @param players liste des joueurs
|
||||||
* @param currentRound manche courante
|
* @param currentRound manche courante
|
||||||
@@ -264,6 +291,7 @@ public class GameWS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retourne le nombre de joueurs avec une carte avec seulement la couleur correspondante à celle du plateau
|
* Retourne le nombre de joueurs avec une carte avec seulement la couleur correspondante à celle du plateau
|
||||||
|
*
|
||||||
* @param gameCard
|
* @param gameCard
|
||||||
* @param players
|
* @param players
|
||||||
* @param currentRound
|
* @param currentRound
|
||||||
@@ -282,6 +310,7 @@ public class GameWS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retourne le nombre de joueurs avec une carte avec seulement la valeur correspondante à celle du plateau
|
* Retourne le nombre de joueurs avec une carte avec seulement la valeur correspondante à celle du plateau
|
||||||
|
*
|
||||||
* @param gameCard carte du plateau
|
* @param gameCard carte du plateau
|
||||||
* @param players liste des joueurs
|
* @param players liste des joueurs
|
||||||
* @param currentRound manche courante
|
* @param currentRound manche courante
|
||||||
@@ -300,6 +329,7 @@ public class GameWS {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retourne le nombre de joueurs avec une carte totalement différente de celle du plateau
|
* Retourne le nombre de joueurs avec une carte totalement différente de celle du plateau
|
||||||
|
*
|
||||||
* @param gameCard
|
* @param gameCard
|
||||||
* @param players
|
* @param players
|
||||||
* @param currentRound
|
* @param currentRound
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
style="position: absolute; right: 0; z-index: 9999">
|
style="position: absolute; right: 0; z-index: 9999">
|
||||||
<div class="buttons is-flex-direction-column">
|
<div class="buttons is-flex-direction-column">
|
||||||
<p id="round" class="title has-text-white"></p>
|
<p id="round" class="title has-text-white"></p>
|
||||||
|
<p id="timer" class="subtitle has-text-white"></p>
|
||||||
<button class="button is-fullwidth" data-value="COLOR_VALUE">Même couleur et valeur</button>
|
<button class="button is-fullwidth" data-value="COLOR_VALUE">Même couleur et valeur</button>
|
||||||
<button class="button is-fullwidth" data-value="COLOR">Même couleur</button>
|
<button class="button is-fullwidth" data-value="COLOR">Même couleur</button>
|
||||||
<button class="button is-fullwidth" data-value="VALUE">Même valeur</button>
|
<button class="button is-fullwidth" data-value="VALUE">Même valeur</button>
|
||||||
@@ -212,6 +213,22 @@
|
|||||||
import Card from "${pageContext.request.contextPath}/static/js/Card.js"
|
import Card from "${pageContext.request.contextPath}/static/js/Card.js"
|
||||||
|
|
||||||
const choice = document.querySelector('#choice');
|
const choice = document.querySelector('#choice');
|
||||||
|
let havePlayed = false;
|
||||||
|
|
||||||
|
const timer = ${game.timer};
|
||||||
|
let remainingTime = timer;
|
||||||
|
let timerInterval;
|
||||||
|
|
||||||
|
// Display timer
|
||||||
|
document.querySelector('#timer').innerText = "Temps restant: " + remainingTime + "s";
|
||||||
|
|
||||||
|
const interval = () => {
|
||||||
|
remainingTime--;
|
||||||
|
|
||||||
|
document.querySelector('#timer').innerText = "Temps restant: " + remainingTime + "s";
|
||||||
|
|
||||||
|
if (remainingTime <= 0) clearInterval(timerInterval);
|
||||||
|
}
|
||||||
|
|
||||||
choice.querySelectorAll('button').forEach(button => {
|
choice.querySelectorAll('button').forEach(button => {
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
@@ -221,6 +238,8 @@
|
|||||||
}
|
}
|
||||||
wsgame.ws.send(JSON.stringify(message));
|
wsgame.ws.send(JSON.stringify(message));
|
||||||
|
|
||||||
|
havePlayed = true;
|
||||||
|
|
||||||
// Disable buttons
|
// Disable buttons
|
||||||
choice.querySelectorAll('button').forEach(button => button.disabled = true);
|
choice.querySelectorAll('button').forEach(button => button.disabled = true);
|
||||||
});
|
});
|
||||||
@@ -255,6 +274,8 @@
|
|||||||
document.querySelector('#gameWaiting').style.display = 'none';
|
document.querySelector('#gameWaiting').style.display = 'none';
|
||||||
document.querySelector('#gameStarted').style.display = 'block';
|
document.querySelector('#gameStarted').style.display = 'block';
|
||||||
|
|
||||||
|
timerInterval = setInterval(interval, 1000);
|
||||||
|
|
||||||
const deck = document.querySelector('#deck'); // Column
|
const deck = document.querySelector('#deck'); // Column
|
||||||
const myCard = document.querySelector('#myCard'); // Column
|
const myCard = document.querySelector('#myCard'); // Column
|
||||||
const otherCards = document.querySelector('#otherCards'); // Columns
|
const otherCards = document.querySelector('#otherCards'); // Columns
|
||||||
@@ -296,9 +317,16 @@
|
|||||||
wsgame.onMessage("updatePlayer", (p) => {
|
wsgame.onMessage("updatePlayer", (p) => {
|
||||||
document.querySelector(".player-" + p.user.id + " .card-play").style.boxShadow = "inset 0px 0px 30px 10px orange";
|
document.querySelector(".player-" + p.user.id + " .card-play").style.boxShadow = "inset 0px 0px 30px 10px orange";
|
||||||
})
|
})
|
||||||
wsgame.onMessage("end", (game) => {
|
wsgame.onMessage("timerEnd", (game) => {
|
||||||
window.location.href = "${pageContext.request.contextPath}/game-statistics?id=${game.id}&endGame=true";
|
if (!havePlayed) {
|
||||||
|
const message = {
|
||||||
|
type: "click",
|
||||||
|
data: "TIMER_END"
|
||||||
|
}
|
||||||
|
wsgame.ws.send(JSON.stringify(message));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
wsgame.onMessage("nextRound", (game) => {
|
wsgame.onMessage("nextRound", (game) => {
|
||||||
currentGame = game;
|
currentGame = game;
|
||||||
|
|
||||||
@@ -311,12 +339,17 @@
|
|||||||
const otherCards = document.querySelector('#otherCards'); // Columns
|
const otherCards = document.querySelector('#otherCards'); // Columns
|
||||||
const round = document.querySelector('#round');
|
const round = document.querySelector('#round');
|
||||||
|
|
||||||
|
clearInterval(timerInterval);
|
||||||
|
remainingTime = timer;
|
||||||
|
document.querySelector('#timer').innerText = "Temps restant: " + remainingTime + "s";
|
||||||
|
timerInterval = setInterval(interval, 1000);
|
||||||
|
|
||||||
// Reset content
|
// Reset content
|
||||||
deck.innerHTML = "";
|
deck.innerHTML = "";
|
||||||
myCard.innerHTML = "";
|
myCard.innerHTML = "";
|
||||||
otherCards.innerHTML = "";
|
otherCards.innerHTML = "";
|
||||||
round.innerText = "";
|
round.innerText = "";
|
||||||
|
havePlayed = false;
|
||||||
choice.querySelectorAll('button').forEach(button => button.disabled = false);
|
choice.querySelectorAll('button').forEach(button => button.disabled = false);
|
||||||
|
|
||||||
// Show the current round
|
// Show the current round
|
||||||
@@ -347,6 +380,11 @@
|
|||||||
deck.innerHTML = deckCard.render();
|
deck.innerHTML = deckCard.render();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
wsgame.onMessage("end", (game) => {
|
||||||
|
clearInterval(timerInterval);
|
||||||
|
window.location.href = "${pageContext.request.contextPath}/game-statistics?id=${game.id}&endGame=true";
|
||||||
|
})
|
||||||
|
|
||||||
// Close handling
|
// Close handling
|
||||||
wsgame.onClose(() => console.log("Disconnected from the server (GameWS)"));
|
wsgame.onClose(() => console.log("Disconnected from the server (GameWS)"));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user