feat(DevWeb): Le push du siecle

This commit is contained in:
Lucàs
2024-04-30 15:44:53 +02:00
parent e4f3edcc04
commit 275ad640dc
10 changed files with 177 additions and 102 deletions
+1 -1
View File
@@ -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();
});
}
/**
@@ -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());
}
}