mirror of
https://github.com/kmitresse/Cards-Rush.git
synced 2026-05-13 17:11:49 +00:00
398 lines
14 KiB
Java
398 lines
14 KiB
Java
package uppa.project.web.websocket;
|
|
|
|
import com.google.gson.Gson;
|
|
import jakarta.persistence.EntityManager;
|
|
import jakarta.websocket.OnClose;
|
|
import jakarta.websocket.OnError;
|
|
import jakarta.websocket.OnMessage;
|
|
import jakarta.websocket.OnOpen;
|
|
import jakarta.websocket.Session;
|
|
import jakarta.websocket.server.PathParam;
|
|
import jakarta.websocket.server.ServerEndpoint;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
import uppa.project.bean.PlayerBean;
|
|
import uppa.project.database.dao.DAO;
|
|
import uppa.project.database.dao.DAOException;
|
|
import uppa.project.database.dao.EntityManagerProvider;
|
|
import uppa.project.database.dao.jpa.DAO_JPA_User;
|
|
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
|
|
import uppa.project.database.pojo.Card;
|
|
import uppa.project.database.pojo.Game;
|
|
import uppa.project.database.pojo.Player;
|
|
import uppa.project.database.pojo.User;
|
|
import uppa.project.json.websocket.ClickChoice;
|
|
import uppa.project.json.websocket.Message;
|
|
import uppa.project.json.websocket.SimpleGame;
|
|
import uppa.project.json.websocket.SimplePlayer;
|
|
import uppa.project.json.websocket.SimpleUser;
|
|
|
|
@ServerEndpoint(value = "/ws/game/{game_id}")
|
|
public class GameWS {
|
|
|
|
private static final HashMap<Game, ArrayList<Player>> games = new HashMap<>();
|
|
private static final HashMap<Game, Timer> timers = new HashMap<>();
|
|
Gson gson = new Gson();
|
|
private Game game;
|
|
private Player player;
|
|
|
|
@OnOpen
|
|
public void onOpen(Session session, @PathParam("game_id") String gameId) throws DAOException {
|
|
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<>());
|
|
}
|
|
|
|
@OnClose
|
|
public void onClose(Session session, @PathParam("game_id") String gameId) throws DAOException {
|
|
games.get(game).remove(this.player);
|
|
|
|
// Broadcast the new player
|
|
ArrayList<SimplePlayer> simplePlayerList = new ArrayList<>();
|
|
for (Player player : games.get(game)) simplePlayerList.add(new SimplePlayer(player));
|
|
|
|
broadcast(new Message("updatePlayerList", gson.toJson(simplePlayerList)).toJson());
|
|
}
|
|
|
|
@OnError
|
|
public void onError(Throwable throwable) {
|
|
throwable.printStackTrace();
|
|
}
|
|
|
|
@OnMessage
|
|
public void onMessage(String rawMessage, Session session, @PathParam("game_id") String gameId) throws DAOException {
|
|
DAO<User> userDAO = new DAO_JPA_User();
|
|
|
|
Message message = gson.fromJson(rawMessage, Message.class);
|
|
|
|
if (message.getType().equals("connection")) {
|
|
SimpleUser simpleUser = gson.fromJson(message.getData(), SimpleUser.class);
|
|
|
|
// find the user
|
|
User user = userDAO.findById(simpleUser.getId());
|
|
|
|
this.player = new Player(game, user, session);
|
|
games.get(game).add(this.player);
|
|
|
|
ArrayList<SimplePlayer> simplePlayerList = new ArrayList<>();
|
|
for (Player p : games.get(game)) simplePlayerList.add(new SimplePlayer(p));
|
|
|
|
// Diffusion de la nouvelle liste de joueurs
|
|
broadcast(new Message("updatePlayerList", gson.toJson(simplePlayerList)).toJson());
|
|
}
|
|
|
|
if (message.getType().equals("start")) {
|
|
game.setGameState(Game.GameState.STARTED);
|
|
broadcast(new Message("start", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
|
|
|
Timer timer = new Timer();
|
|
timer.schedule(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
// Fin du timer
|
|
broadcast(new Message("timerEnd", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
|
timer.cancel();
|
|
}
|
|
}, game.getTimer() * 1000L);
|
|
timers.put(game, timer);
|
|
}
|
|
|
|
ArrayList<Card> playersCurrentCards = new ArrayList<>(games.get(game).size());
|
|
for (Player player : games.get(game)) {
|
|
playersCurrentCards.add(player.getDeck().getCards().get((player.getPartialRightClickCount()+player.getRightClickCount()) % player.getDeck().getCards().size()));
|
|
}
|
|
|
|
|
|
if (message.getType().equals("click")) {
|
|
ClickChoice choice = gson.fromJson(message.getData(), ClickChoice.class);
|
|
|
|
int playerScore = player.getScore();
|
|
Card gameCard = game.getDeck().getCards().get(game.getCurrentRound());
|
|
Card playerCard = player.getDeck().getCards().get((player.getPartialRightClickCount()+player.getRightClickCount()) % player.getDeck().getCards().size());
|
|
|
|
player.setCurrentClick(choice);
|
|
|
|
// Récupérer le nombre de joueurs ayant cliqué
|
|
int gameClickCount = 0;
|
|
for (Player player : games.get(game)) {
|
|
if (player.getCurrentClick() != null) gameClickCount++;
|
|
}
|
|
|
|
// Compteur de clics
|
|
player.incrementClickCount();
|
|
|
|
boolean isRapid = false;
|
|
// Compteur de clics rapides
|
|
if (gameClickCount == 1 && choice != ClickChoice.TIMER_END) {
|
|
isRapid = true;
|
|
};
|
|
|
|
// Vérifier le choix du joueur et attribuer les points
|
|
if (game.getDifficulty().equals(Game.Difficulty.EASY)) {
|
|
switch (choice) {
|
|
case COLOR_VALUE -> {
|
|
if (gameCard.equals(playerCard)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case COLOR -> {
|
|
if (gameCard.getColor().equals(playerCard.getColor())) {
|
|
if (!gameCard.equals(playerCard)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.incrementPartialRightClickCount();
|
|
player.setScore(playerScore + 1);
|
|
}
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case VALUE -> {
|
|
if (gameCard.getValue() == playerCard.getValue()) {
|
|
if (!gameCard.equals(playerCard)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.incrementPartialRightClickCount();
|
|
player.setScore(playerScore + 1);
|
|
}
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case NONE -> {
|
|
if (!gameCard.getColor().equals(playerCard.getColor()) && gameCard.getValue() != playerCard.getValue()) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case TIMER_END -> {}
|
|
}
|
|
} else {
|
|
int nbSameCard = countSameCard(gameCard, playersCurrentCards);
|
|
int nbSameColor = countSameColor(gameCard, playersCurrentCards);
|
|
int nbSameValue = countSameValue(gameCard, playersCurrentCards);
|
|
int nbNone = countNone(gameCard, playersCurrentCards);
|
|
|
|
switch (choice) {
|
|
case COLOR_VALUE -> {
|
|
if ((nbSameCard >= nbSameColor) && (nbSameCard >= nbSameValue) && (nbSameCard >= nbNone)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementTmpRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case COLOR -> {
|
|
if ((nbSameCard >= nbSameColor) && (nbSameCard >= nbSameValue) && (nbSameCard >= nbNone)) {
|
|
player.incrementTmpPartialRightClickCount();
|
|
player.setScore(playerScore + 1);
|
|
} else if ((nbSameColor > nbSameCard) && (nbSameColor >= nbSameValue) && (nbSameColor >= nbNone)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementTmpRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case VALUE -> {
|
|
if ((nbSameCard >= nbSameColor) && (nbSameCard >= nbSameValue) && (nbSameCard >= nbNone)) {
|
|
player.incrementTmpPartialRightClickCount();
|
|
player.setScore(playerScore + 1);
|
|
} else if ((nbSameValue > nbSameCard) && (nbSameValue > nbSameColor) && (nbSameValue >= nbNone)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementTmpRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case NONE -> {
|
|
if ((nbNone > nbSameCard) && (nbNone >= nbSameColor) && (nbNone > nbSameValue)) {
|
|
if (isRapid) {
|
|
player.incrementRapidClickCount();
|
|
playerScore++;
|
|
}
|
|
player.incrementTmpRightClickCount();
|
|
player.setScore(playerScore + 2);
|
|
} else {
|
|
player.setScore(playerScore - 1);
|
|
}
|
|
}
|
|
case TIMER_END -> {}
|
|
}
|
|
|
|
}
|
|
|
|
// Diffuser le score du joueur
|
|
broadcast(new Message("updatePlayer", gson.toJson(new SimplePlayer(player))).toJson());
|
|
|
|
// Si tous les joueurs ont cliqué
|
|
if (gameClickCount >= games.get(game).size()) {
|
|
// Stopper le timer
|
|
timers.get(game).cancel();
|
|
|
|
// Réinitialiser les clics courrants
|
|
for (Player p : games.get(game)) {
|
|
p.setRightClickCount(p.getTmpRightClickCount());
|
|
p.setPartialRightClickCount(p.getTmpPartialRightClickCount());
|
|
p.setCurrentClick(null);
|
|
}
|
|
|
|
List<Player> players = games.get(game);
|
|
players.sort((p1, p2) -> {
|
|
if (p1.getScore() == p2.getScore()) {
|
|
return p2.getRapidClickCount() - p1.getRapidClickCount();
|
|
}
|
|
return p2.getScore() - p1.getScore();
|
|
});
|
|
|
|
Player theoricWinner = players.get(0);
|
|
Player second = players.get(1);
|
|
|
|
// Vérifier si la partie est terminée
|
|
if (game.nextRound() || (second.getScore() == theoricWinner.getScore() && second.getRapidClickCount() == theoricWinner.getRapidClickCount())) {
|
|
broadcast(new Message("nextRound", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
|
Timer timer = new Timer();
|
|
timer.schedule(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
// Diffuser la fin du timer
|
|
broadcast(new Message("timerEnd", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
|
timer.cancel();
|
|
}
|
|
}, game.getTimer() * 1000L);
|
|
timers.put(game, timer);
|
|
} else {
|
|
theoricWinner.setWinner();
|
|
|
|
EntityManager em = EntityManagerProvider.getFactory().createEntityManager();
|
|
em.getTransaction().begin();
|
|
for (Player p : games.get(game)) {
|
|
PlayerBean playerBean = new PlayerBean(p);
|
|
if (playerBean.validate()) System.out.println("Player " + p.getUser().getUsername() + " sauvegardé en base de données");
|
|
}
|
|
em.getTransaction().commit();
|
|
|
|
// Diffusion de la fin de la partie
|
|
broadcast(new Message("end", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Retourne le nombre de joueurs avec une carte identique à celle du plateau
|
|
*
|
|
* @param gameCard carte du plateau
|
|
* @param currentCards liste des cartes des joueurs
|
|
* @return nombre de cartes identiques à celle du plateau
|
|
*/
|
|
private int countSameCard(Card gameCard, List<Card> currentCards) {
|
|
int counter = 0;
|
|
for (Card card : currentCards) {
|
|
if (gameCard.equals(card)) {
|
|
|
|
counter++;
|
|
}
|
|
}
|
|
return counter;
|
|
}
|
|
|
|
/**
|
|
* Retourne le nombre de joueurs avec une carte avec seulement la couleur correspondante à celle du plateau
|
|
*
|
|
* @param gameCard carte du plateau
|
|
* @param currentCards liste des cartes des joueurs
|
|
* @return nombre de couleurs identiques à celle du plateau
|
|
*/
|
|
private int countSameColor(Card gameCard, List<Card> currentCards) {
|
|
int counter = 0;
|
|
for (Card card : currentCards) {
|
|
if (gameCard.getColor().equals(card.getColor()) && !gameCard.getValue().equals(card.getValue())) {
|
|
counter++;
|
|
}
|
|
}
|
|
return counter;
|
|
}
|
|
|
|
/**
|
|
* Retourne le nombre de joueurs avec une carte avec seulement la valeur correspondante à celle du plateau
|
|
*
|
|
* @param gameCard carte du plateau
|
|
* @param currentCards liste des cartes des joueurs
|
|
* @return nombre de valeurs identiques à celle du plateau
|
|
*/
|
|
private int countSameValue(Card gameCard, List<Card> currentCards) {
|
|
int counter = 0;
|
|
for (Card card : currentCards) {
|
|
if (gameCard.getValue().equals(card.getValue()) && !gameCard.getColor().equals(card.getColor())) {
|
|
counter++;
|
|
}
|
|
}
|
|
return counter;
|
|
}
|
|
|
|
/**
|
|
* Retourne le nombre de joueurs avec une carte totalement différente de celle du plateau
|
|
*
|
|
* @param gameCard carte du plateau
|
|
* @param currentCards liste des cartes des joueurs
|
|
* @return nombre de cartes totalement différentes de celle du plateau
|
|
*/
|
|
private int countNone(Card gameCard, List<Card> currentCards) {
|
|
int counter = 0;
|
|
for (Card card : currentCards) {
|
|
if (!gameCard.getColor().equals(card.getColor()) && !gameCard.getValue().equals(card.getValue())) {
|
|
counter++;
|
|
}
|
|
}
|
|
return counter;
|
|
}
|
|
|
|
private void broadcast(String message) {
|
|
for (Player player : games.get(game)) {
|
|
try {
|
|
player.getSession().getBasicRemote().sendText(message);
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
}
|
|
}
|