mirror of
https://github.com/kmitresse/Cards-Rush.git
synced 2026-05-13 17:11:49 +00:00
feat(DevWeb): Le push du siecle
This commit is contained in:
@@ -43,7 +43,7 @@ mvn install
|
||||
````
|
||||
|
||||
## Lancement du projet
|
||||
Depuis IntelliJ, ouvrir l'onglet file > project structure et ajouter les artefacts suivants :
|
||||
Depuis IntelliJ, ouvrir l'onglet `file > project structure` et ajouter les artefacts suivants :
|
||||
- project: war
|
||||
- project: war exploded
|
||||
|
||||
|
||||
@@ -291,16 +291,13 @@ public class Game implements Serializable {
|
||||
/**
|
||||
* Tri des joueurs de la partie par score
|
||||
*/
|
||||
public void sortPlayersByScore() {
|
||||
for (int i = 0; i < players.size(); i++) {
|
||||
for (int j = i + 1; j < players.size(); j++) {
|
||||
if (players.get(i).getScore() < players.get(j).getScore()) {
|
||||
Player temp = players.get(i);
|
||||
players.set(i, players.get(j));
|
||||
players.set(j, temp);
|
||||
}
|
||||
}
|
||||
public void sortPlayersByScoreAndRapidity() {
|
||||
players.sort((p1, p2) -> {
|
||||
if (p1.getScore() == p2.getScore()) {
|
||||
return p2.getRapidClickCount() - p1.getRapidClickCount();
|
||||
}
|
||||
return p2.getScore() - p1.getScore();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-2
@@ -9,9 +9,10 @@ import java.io.IOException;
|
||||
import uppa.project.database.dao.DAO;
|
||||
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
|
||||
import uppa.project.database.pojo.Game;
|
||||
import uppa.project.database.pojo.Player;
|
||||
|
||||
@WebServlet(name = "game-statistics", value = "/game-statistics")
|
||||
public class GameStatistics extends HttpServlet {
|
||||
public class GameStatisticsServlet extends HttpServlet {
|
||||
|
||||
public void init() {
|
||||
}
|
||||
@@ -22,7 +23,7 @@ public class GameStatistics extends HttpServlet {
|
||||
DAO<Game> gameDAO = new Game_JPA_DAO_Factory().getDAOGame();
|
||||
game = gameDAO.findById(Integer.parseInt(request.getParameter("id")));
|
||||
request.removeAttribute("id");
|
||||
game.sortPlayersByScore();
|
||||
game.sortPlayersByScoreAndRapidity();
|
||||
request.setAttribute("game", game);
|
||||
request.getRequestDispatcher("/WEB-INF/pages/game-statistics.jsp").forward(request, response);
|
||||
} catch (Exception e) {
|
||||
@@ -29,10 +29,8 @@ import uppa.project.utils.GameProvider;
|
||||
@ServerEndpoint(value = "/ws/game/{game_id}")
|
||||
public class GameWS {
|
||||
|
||||
Gson gson = new Gson();
|
||||
|
||||
private static final HashMap<Game, ArrayList<Player>> games = new HashMap<>();
|
||||
|
||||
Gson gson = new Gson();
|
||||
private Game game;
|
||||
private Player player;
|
||||
|
||||
@@ -79,11 +77,13 @@ public class GameWS {
|
||||
// Broadcast the new player
|
||||
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());
|
||||
// TODO Start Timer
|
||||
}
|
||||
|
||||
if (message.getType().equals("click")) {
|
||||
ClickChoice choice = gson.fromJson(message.getData(), ClickChoice.class);
|
||||
|
||||
@@ -150,34 +150,45 @@ public class GameWS {
|
||||
}
|
||||
|
||||
// Broadcast the player choice with score
|
||||
|
||||
broadcast(new Message("updatePlayer", gson.toJson(new SimplePlayer(player))).toJson());
|
||||
|
||||
System.out.println(gameClickCount + " / " + games.get(game).size());
|
||||
|
||||
|
||||
// If all players have clicked
|
||||
if (gameClickCount >= games.get(game).size()) {
|
||||
|
||||
// Reset the current click for all players
|
||||
for (Player p : games.get(game)) 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);
|
||||
|
||||
// Check if the game is over
|
||||
if (game.nextRound()) { // TODO: if score is the same add a round
|
||||
if (game.nextRound() || (second.getScore() == theoricWinner.getScore() && second.getRapidClickCount() == theoricWinner.getRapidClickCount())) {
|
||||
broadcast(new Message("nextRound", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||
// TODO Start Timer
|
||||
} else {
|
||||
// TODO: determine the winner
|
||||
theoricWinner.setWinner();
|
||||
|
||||
// Broadcast the end of the game
|
||||
broadcast(new Message("end", gson.toJson(new SimpleGame(game, games.get(game)))).toJson());
|
||||
|
||||
// TODO: persist the game in the database
|
||||
// EntityManager em = EntityManagerProvider.getInstance();
|
||||
// game.setPlayers(games.get(game));
|
||||
//
|
||||
// em.getTransaction().begin();
|
||||
// em.persist(game);
|
||||
// em.getTransaction().commit();
|
||||
|
||||
EntityManager em = EntityManagerProvider.getInstance();
|
||||
|
||||
em.getTransaction().begin();
|
||||
em.persist(game);
|
||||
for (Player p : games.get(game)) em.persist(p);
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
<jsp:body>
|
||||
<table id="playerList" class="table is-fullwidth">
|
||||
<thead>
|
||||
<tr><td>Joueur</td></tr>
|
||||
<tr>
|
||||
<td>Joueur</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
@@ -182,7 +184,7 @@
|
||||
url.searchParams.delete("id")
|
||||
|
||||
const ws = new WebsocketToolkit(url);
|
||||
ws.onOpen(() => console.log("Connected to the server"));
|
||||
ws.onOpen(_ => console.log("Connected to the server"));
|
||||
ws.onMessage("init", (data) => {
|
||||
users = data;
|
||||
updateUsers();
|
||||
@@ -205,12 +207,23 @@
|
||||
|
||||
<script type="module" defer>
|
||||
import WebsocketToolkit from "${pageContext.request.contextPath}/static/js/WebsocketToolkit.js";
|
||||
import PlayerHand from "${pageContext.request.contextPath}/static/js/PlayerHand.js"
|
||||
import Card from "${pageContext.request.contextPath}/static/js/Card.js"
|
||||
|
||||
const getCardColorValue = (color) => {
|
||||
return (color === "DIAMONDS" || color === "HEART")
|
||||
? "red" : "black"
|
||||
;
|
||||
const choice = document.querySelector('#choice');
|
||||
|
||||
choice.querySelectorAll('button').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const message = {
|
||||
type: "click",
|
||||
data: button.dataset.value
|
||||
}
|
||||
wsgame.ws.send(JSON.stringify(message));
|
||||
|
||||
// Disable buttons
|
||||
choice.querySelectorAll('button').forEach(button => button.disabled = true);
|
||||
});
|
||||
});
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
url.pathname = "${pageContext.request.contextPath}/ws/game/${game.id}";
|
||||
@@ -241,99 +254,89 @@
|
||||
document.querySelector('#gameWaiting').style.display = 'none';
|
||||
document.querySelector('#gameStarted').style.display = 'block';
|
||||
|
||||
const deck = document.querySelector('#deck');
|
||||
const choice = document.querySelector('#choice');
|
||||
const myCard = document.querySelector('#myCard');
|
||||
const otherCards = document.querySelector('#otherCards');
|
||||
const deck = document.querySelector('#deck'); // Column
|
||||
const myCard = document.querySelector('#myCard'); // Column
|
||||
const otherCards = document.querySelector('#otherCards'); // Columns
|
||||
|
||||
// Choices
|
||||
choice.querySelectorAll('button').forEach(button => {
|
||||
button.addEventListener('click', () => {
|
||||
const message = {
|
||||
type: "click",
|
||||
data: button.dataset.value
|
||||
}
|
||||
wsgame.ws.send(JSON.stringify(message));
|
||||
|
||||
// Disable buttons
|
||||
choice.querySelectorAll('button').forEach(button => button.disabled = true);
|
||||
});
|
||||
});
|
||||
// Reset content
|
||||
deck.innerHTML = "";
|
||||
myCard.innerHTML = "";
|
||||
otherCards.innerHTML = "";
|
||||
|
||||
// Show other player cards
|
||||
game.players
|
||||
.filter(p => p.user.id !== ${user.id})
|
||||
.forEach(p => {
|
||||
// Create column in OtherCards
|
||||
const column = document.createElement('div');
|
||||
column.classList.add('column');
|
||||
column.id = 'otherCards-' + p.id;
|
||||
|
||||
const cardValue = document.createElement('p');
|
||||
cardValue.textContent = p.currentCard.color + " " + p.currentCard.value;
|
||||
|
||||
column.appendChild(cardValue);
|
||||
otherCards.appendChild(column);
|
||||
const playerHand = new PlayerHand(p);
|
||||
otherCards.innerHTML += playerHand.render({
|
||||
textPosition: PlayerHand.TextPosition.TOP,
|
||||
className: "column"
|
||||
});
|
||||
});
|
||||
|
||||
// Show my card
|
||||
const myCardValue = document.createElement('p');
|
||||
const me = game.players.find(p => p.user.id === ${user.id});
|
||||
myCardValue.textContent = me.currentCard.color + " " + me.currentCard.value;
|
||||
|
||||
myCard.appendChild(myCardValue);
|
||||
const playerHand = new PlayerHand(me);
|
||||
myCard.innerHTML += playerHand.render({
|
||||
textPosition: PlayerHand.TextPosition.BOTTOM,
|
||||
className: "column"
|
||||
});
|
||||
|
||||
// Show deck
|
||||
const deckValue = document.createElement('div');
|
||||
deckValue.classList.add("card-play", game.currentCard.color.toLowerCase(), getCardColorValue(game.currentCard.color) + "_" +game.currentCard.value.toLowerCase());
|
||||
deck.appendChild(deckValue);
|
||||
const deckCard = new Card(game.currentCard.color, game.currentCard.value);
|
||||
deck.innerHTML = deckCard.render();
|
||||
})
|
||||
wsgame.onMessage("updatePlayer", (player) => {
|
||||
|
||||
wsgame.onMessage("updatePlayer", (p) => {
|
||||
document.querySelector(".player-" + p.user.id + " .card-play").style.boxShadow = "inset 0px 0px 30px 10px orange";
|
||||
})
|
||||
wsgame.onMessage("end", (game) => {
|
||||
currentGame = game;
|
||||
|
||||
document.querySelector('#gameWaiting').style.display = 'block';
|
||||
document.querySelector('#gameStarted').style.display = 'none';
|
||||
window.location.href = "${pageContext.request.contextPath}/game-statistics?id=${game.id}&endGame=true";
|
||||
})
|
||||
wsgame.onMessage("nextRound", (game) => {
|
||||
currentGame = game;
|
||||
|
||||
const deck = document.querySelector('#deck');
|
||||
const choice = document.querySelector('#choice');
|
||||
const myCard = document.querySelector('#myCard');
|
||||
const otherCards = document.querySelector('#otherCards');
|
||||
document.querySelector('#gameWaiting').style.display = 'none';
|
||||
document.querySelector('#gameStarted').style.display = 'block';
|
||||
|
||||
const deck = document.querySelector('#deck'); // Column
|
||||
const choice = document.querySelector('#choice');
|
||||
const myCard = document.querySelector('#myCard'); // Column
|
||||
const otherCards = document.querySelector('#otherCards'); // Columns
|
||||
|
||||
// Reset content
|
||||
deck.innerHTML = "";
|
||||
myCard.innerHTML = "";
|
||||
otherCards.innerHTML = "";
|
||||
choice.querySelectorAll('button').forEach(button => button.disabled = false);
|
||||
|
||||
// Show other player cards
|
||||
game.players
|
||||
.filter(p => p.user.id !== ${user.id})
|
||||
.forEach(p => {
|
||||
const column = document.querySelector('#otherCards-' + p.id);
|
||||
column.innerHTML = '';
|
||||
|
||||
// TODO Update card
|
||||
// const cardValue = document.createElement('p');
|
||||
// cardValue.textContent = p.currentCard.color + " " + p.currentCard.value;
|
||||
|
||||
column.appendChild(cardValue);
|
||||
const playerHand = new PlayerHand(p);
|
||||
otherCards.innerHTML += playerHand.render({
|
||||
textPosition: PlayerHand.TextPosition.TOP,
|
||||
className: "column"
|
||||
});
|
||||
});
|
||||
|
||||
// Show my card
|
||||
const myCardValue = document.querySelector('#myCard p');
|
||||
const me = game.players.find(p => p.user.id === ${user.id});
|
||||
myCardValue.textContent = me.currentCard.color + " " + me.currentCard.value;
|
||||
|
||||
const playerHand = new PlayerHand(me);
|
||||
myCard.innerHTML += playerHand.render({
|
||||
textPosition: PlayerHand.TextPosition.BOTTOM,
|
||||
className: "column"
|
||||
});
|
||||
|
||||
// Show deck
|
||||
const deckValue = document.querySelector('#deck p');
|
||||
deckValue.textContent = game.currentCard.color + " " + game.currentCard.value;
|
||||
const deckCard = new Card(game.currentCard.color, game.currentCard.value);
|
||||
deck.innerHTML = deckCard.render();
|
||||
})
|
||||
wsgame.onError((error) => console.error(error));
|
||||
wsgame.onClose(() => {
|
||||
console.log("Disconnected from the server (GameWS)")
|
||||
});
|
||||
|
||||
// Close handling
|
||||
wsgame.onClose(() => console.log("Disconnected from the server (GameWS)"));
|
||||
|
||||
// Game
|
||||
let currentGame;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<filter-name>AuthenticationFilter</filter-name>
|
||||
<!-- <url-pattern>/main-menu</url-pattern>-->
|
||||
<url-pattern>/lobby</url-pattern>
|
||||
<url-pattern>/rules</url-pattern>
|
||||
<url-pattern>/profile</url-pattern>
|
||||
<url-pattern>/game-statistics</url-pattern>
|
||||
<url-pattern>/new</url-pattern>
|
||||
|
||||
@@ -5,31 +5,31 @@ body {
|
||||
.card-play {
|
||||
position: relative;
|
||||
aspect-ratio: 2/3;
|
||||
width: 246px;
|
||||
/*height: 340px;*/
|
||||
width: 150px;
|
||||
background: #F8FAFC;
|
||||
border-radius: 20px;
|
||||
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
background-size: 60%;
|
||||
}
|
||||
|
||||
.card-play::before, .card-play::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
aspect-ratio: 1/1;
|
||||
width: 25%;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.card-play::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
aspect-ratio: 1/1;
|
||||
width: 65px;
|
||||
}
|
||||
|
||||
.card-play::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
aspect-ratio: 1/1;
|
||||
width: 65px;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
export default class Card {
|
||||
static Color = {
|
||||
DIAMONDS: "DIAMONDS",
|
||||
HEART: "HEART",
|
||||
SPADES: "SPADES",
|
||||
CLUBS: "CLUBS",
|
||||
}
|
||||
|
||||
constructor(color, value) {
|
||||
this.color = color;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
getValueColor() {
|
||||
return (this.color === Card.Color.DIAMONDS || this.color === Card.Color.HEART)
|
||||
? 'red' : 'black'
|
||||
}
|
||||
|
||||
render() {
|
||||
const className = [
|
||||
"card-play",
|
||||
this.color.toLowerCase(),
|
||||
`${this.getValueColor()}_${this.value.toLowerCase()}`
|
||||
]
|
||||
|
||||
return `<div class="${className.join(" ")}"></div>`
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import Card from "./Card.js";
|
||||
|
||||
export default class PlayerHand {
|
||||
static TextPosition = {
|
||||
TOP: "TOP",
|
||||
BOTTOM: "BOTTOM"
|
||||
}
|
||||
|
||||
constructor(player) {
|
||||
this.player = player;
|
||||
this.card = new Card(player.currentCard.color, player.currentCard.value)
|
||||
}
|
||||
|
||||
render({className, textPosition}) {
|
||||
if (!textPosition) textPosition = PlayerHand.TextPosition.TOP;
|
||||
|
||||
const text = `
|
||||
<div class="pb-1 pt-1">
|
||||
<p class="has-text-centered has-text-white title is-4 mb-1">${this.player.user.username}</p>
|
||||
<p class="has-text-centered has-text-white title is-5">${this.player.score}</p>
|
||||
|
||||
</div>
|
||||
`;
|
||||
|
||||
return `
|
||||
<div class="${className} player-${this.player.user.id} is-flex is-flex-direction-column is-align-items-center">
|
||||
${textPosition === PlayerHand.TextPosition.TOP ? text : ""}
|
||||
${this.card.render()}
|
||||
${textPosition === PlayerHand.TextPosition.BOTTOM ? text : ""}
|
||||
</div>
|
||||
`;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -309,7 +309,7 @@ class GameTest {
|
||||
|
||||
for (Game game : TESTS.keySet()) {
|
||||
ArrayList<Player> expected = TESTS.get(game);
|
||||
game.sortPlayersByScore();
|
||||
game.sortPlayersByScoreAndRapidity();
|
||||
assertEquals(expected, game.getPlayers());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user