diff --git a/backend/src/main/java/fr/zelytra/game/manager/message/MessageType.java b/backend/src/main/java/fr/zelytra/game/manager/message/MessageType.java index 3a621b9..941664c 100644 --- a/backend/src/main/java/fr/zelytra/game/manager/message/MessageType.java +++ b/backend/src/main/java/fr/zelytra/game/manager/message/MessageType.java @@ -10,6 +10,7 @@ public enum MessageType { UPDATE_TEAMS, UPDATE_GAME_ACTION, PLAY_GAME_ACTION, + SILENT_JOIN_POOL, //Notification message types INIT_NOTIFICATION, diff --git a/backend/src/main/java/fr/zelytra/game/manager/socket/SessionSocket.java b/backend/src/main/java/fr/zelytra/game/manager/socket/SessionSocket.java index da8e204..422ed00 100644 --- a/backend/src/main/java/fr/zelytra/game/manager/socket/SessionSocket.java +++ b/backend/src/main/java/fr/zelytra/game/manager/socket/SessionSocket.java @@ -3,10 +3,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import fr.zelytra.game.manager.message.SocketMessage; import fr.zelytra.game.manager.message.SocketTimeOutManager; -import fr.zelytra.game.pool.data.GameAction; -import fr.zelytra.game.pool.data.GameRules; -import fr.zelytra.game.pool.data.GameStatus; -import fr.zelytra.game.pool.data.PoolTeam; +import fr.zelytra.game.pool.data.*; import io.quarkus.logging.Log; import jakarta.inject.Inject; import jakarta.websocket.*; @@ -52,6 +49,10 @@ public void onMessage(String message, Session session, @PathParam("sessionId") S socketService.joinPool(username, sessionId, session); socketTimeOutManager.complete(session.getId()); } + case SILENT_JOIN_POOL -> { + PoolSilentJoin silentJoin = objectMapper.convertValue(socketMessage.data(), PoolSilentJoin.class); + socketService.joinPool(silentJoin.username(), silentJoin.sessionId(), null); + } case SET_RULES -> { socketService.setRule(objectMapper.convertValue(socketMessage.data(), GameRules.class), session.getId()); } diff --git a/backend/src/main/java/fr/zelytra/game/pool/PoolParty.java b/backend/src/main/java/fr/zelytra/game/pool/PoolParty.java index 98e033f..ab7eb3d 100644 --- a/backend/src/main/java/fr/zelytra/game/pool/PoolParty.java +++ b/backend/src/main/java/fr/zelytra/game/pool/PoolParty.java @@ -4,9 +4,10 @@ import fr.zelytra.game.manager.message.SocketTimeOutManager; import fr.zelytra.game.manager.socket.PoolSocketService; import fr.zelytra.game.pool.data.*; -import fr.zelytra.game.pool.game.AmericanEightPoolGame; import fr.zelytra.game.pool.game.PoolGameInterface; import fr.zelytra.game.pool.game.PoolVictoryState; +import fr.zelytra.game.pool.game.customs.AmericanEightPoolGame; +import fr.zelytra.game.pool.game.customs.ManualPoolGame; import fr.zelytra.notification.NotificationMessageKey; import fr.zelytra.poolpoint.PoolPointCalculator; import fr.zelytra.user.UserEntity; @@ -55,6 +56,9 @@ public void setGame() { case AMERICAN_8: game = new AmericanEightPoolGame(); break; + case MANUAL: + game = new ManualPoolGame(); + break; default: throw new IllegalArgumentException("Unsupported game type: " + rules); } diff --git a/backend/src/main/java/fr/zelytra/game/pool/data/GameRules.java b/backend/src/main/java/fr/zelytra/game/pool/data/GameRules.java index 91e5540..95cbfc9 100644 --- a/backend/src/main/java/fr/zelytra/game/pool/data/GameRules.java +++ b/backend/src/main/java/fr/zelytra/game/pool/data/GameRules.java @@ -1,7 +1,8 @@ package fr.zelytra.game.pool.data; public enum GameRules { - AMERICAN_8(6); + AMERICAN_8(6), + MANUAL(6); //AMERICAN_9, //AMERICAN_9_CONTINUE, //AMERICAN_10, diff --git a/backend/src/main/java/fr/zelytra/game/pool/data/PoolSilentJoin.java b/backend/src/main/java/fr/zelytra/game/pool/data/PoolSilentJoin.java new file mode 100644 index 0000000..5cb65bc --- /dev/null +++ b/backend/src/main/java/fr/zelytra/game/pool/data/PoolSilentJoin.java @@ -0,0 +1,4 @@ +package fr.zelytra.game.pool.data; + +public record PoolSilentJoin(String username,String sessionId) { +} diff --git a/backend/src/main/java/fr/zelytra/game/pool/game/AmericanEightPoolGame.java b/backend/src/main/java/fr/zelytra/game/pool/game/customs/AmericanEightPoolGame.java similarity index 95% rename from backend/src/main/java/fr/zelytra/game/pool/game/AmericanEightPoolGame.java rename to backend/src/main/java/fr/zelytra/game/pool/game/customs/AmericanEightPoolGame.java index 3c222f7..8f3808c 100644 --- a/backend/src/main/java/fr/zelytra/game/pool/game/AmericanEightPoolGame.java +++ b/backend/src/main/java/fr/zelytra/game/pool/game/customs/AmericanEightPoolGame.java @@ -1,8 +1,11 @@ -package fr.zelytra.game.pool.game; +package fr.zelytra.game.pool.game.customs; import fr.zelytra.game.pool.data.GameAction; import fr.zelytra.game.pool.data.PoolBalls; import fr.zelytra.game.pool.data.PoolFault; +import fr.zelytra.game.pool.game.PoolGameInterface; +import fr.zelytra.game.pool.game.PoolGameManager; +import fr.zelytra.game.pool.game.PoolVictoryState; import java.util.ArrayList; import java.util.List; diff --git a/backend/src/main/java/fr/zelytra/game/pool/game/customs/ManualPoolGame.java b/backend/src/main/java/fr/zelytra/game/pool/game/customs/ManualPoolGame.java new file mode 100644 index 0000000..8e4763c --- /dev/null +++ b/backend/src/main/java/fr/zelytra/game/pool/game/customs/ManualPoolGame.java @@ -0,0 +1,40 @@ +package fr.zelytra.game.pool.game.customs; + +import fr.zelytra.game.pool.data.GameAction; +import fr.zelytra.game.pool.data.PoolBalls; +import fr.zelytra.game.pool.game.PoolGameInterface; +import fr.zelytra.game.pool.game.PoolGameManager; +import fr.zelytra.game.pool.game.PoolVictoryState; + +public class ManualPoolGame extends PoolGameManager implements PoolGameInterface { + + @Override + public void play(GameAction action) { + this.getHistory().add(action); + } + + @Override + public PoolVictoryState winDetection() { + PoolVictoryState victoryState = PoolVictoryState.NONE; + boolean isEightIn = isEightIn(); + PoolVictoryState lastActionTeamId = getLastTeamPlay(); + + if (isEightIn) { + return lastActionTeamId.getInvertTeam(); + } + + return victoryState; + + } + + public boolean isEightIn() { + for (GameAction action : getHistory()) { + for (PoolBalls ball : action.balls()) { + if (ball.number == 8) { + return true; + } + } + } + return false; + } +} diff --git a/backend/src/test/java/fr/zelytra/game/pool/PoolPartyTest.java b/backend/src/test/java/fr/zelytra/game/pool/PoolPartyTest.java index 64cb5f2..9eaf1fc 100644 --- a/backend/src/test/java/fr/zelytra/game/pool/PoolPartyTest.java +++ b/backend/src/test/java/fr/zelytra/game/pool/PoolPartyTest.java @@ -4,7 +4,7 @@ import fr.zelytra.game.pool.data.GameRules; import fr.zelytra.game.pool.data.GameStatus; import fr.zelytra.game.pool.data.PoolTeam; -import fr.zelytra.game.pool.game.AmericanEightPoolGame; +import fr.zelytra.game.pool.game.customs.AmericanEightPoolGame; import fr.zelytra.user.UserEntity; import io.quarkus.test.junit.QuarkusTest; import jakarta.transaction.Transactional; diff --git a/backend/src/test/java/fr/zelytra/game/pool/game/AmericanEightPoolGameTest.java b/backend/src/test/java/fr/zelytra/game/pool/game/AmericanEightPoolGameTest.java index b05e6ce..c2811ab 100644 --- a/backend/src/test/java/fr/zelytra/game/pool/game/AmericanEightPoolGameTest.java +++ b/backend/src/test/java/fr/zelytra/game/pool/game/AmericanEightPoolGameTest.java @@ -3,6 +3,7 @@ import fr.zelytra.game.pool.data.GameAction; import fr.zelytra.game.pool.data.PoolBalls; import fr.zelytra.game.pool.data.PoolFault; +import fr.zelytra.game.pool.game.customs.AmericanEightPoolGame; import io.quarkus.test.junit.QuarkusTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/webapp/src/assets/locales/fr.json b/webapp/src/assets/locales/fr.json index 205e55e..868903e 100644 --- a/webapp/src/assets/locales/fr.json +++ b/webapp/src/assets/locales/fr.json @@ -76,6 +76,8 @@ }, "loose": "Looser bhouuuu", "round": "Tour", + "team1": "Equipe 1", + "team2": "Equipe 2", "win": "Vainqueur(s)" }, "rules": { @@ -84,6 +86,11 @@ "amount": "2 à 6 joueurs", "description": "Les regles classique du billard. Rentrer les boules de votre familles puis rentrer la noire !", "title": "La 8 Américaine" + }, + "manual": { + "amount": "2 à 6 joueurs", + "description": "Aucune regles, seulement pour rentrer le resultat d'un match", + "title": "Manuel" } }, "selection": "Choisissez le mode de jeux !" diff --git a/webapp/src/components/PoolGame.vue b/webapp/src/components/PoolGame.vue index 451886f..8844775 100644 --- a/webapp/src/components/PoolGame.vue +++ b/webapp/src/components/PoolGame.vue @@ -11,10 +11,13 @@ mode="out-in" > - + + @@ -29,6 +32,7 @@ import {GameRule, GameState} from "@/objects/pool/Pool.ts"; import TeamingPlayers from "@/components/pool/TeamingPlayers.vue"; import EightPoolGame from "@/components/pool/pools/EightPoolGame.vue"; import PoolGameResult from "@/components/pool/PoolGameResult.vue"; +import ManualPoolGame from "@/components/pool/pools/ManualPoolGame.vue"; const poolStore = usePoolParty(); diff --git a/webapp/src/components/pool/FriendInvitation.vue b/webapp/src/components/pool/FriendInvitation.vue index 7b31568..ec91ffa 100644 --- a/webapp/src/components/pool/FriendInvitation.vue +++ b/webapp/src/components/pool/FriendInvitation.vue @@ -44,6 +44,14 @@ const currentUser = useUserStore(); const poolStore = usePoolParty(); const notification = useNotification(); +const props = defineProps({ + silentInvit: { + type: Boolean, + required: false, + default: () => false + } +}) + onMounted(() => { loadFriendList() }) @@ -72,14 +80,20 @@ function getFriendUser(friend: Friend): User { } function inviteToGame(user: User) { - notification.send({ - users: [user.authUsername], - data: { - data: poolStore.pool.uuid, - type: NotificationType.INVITE_TO_GAME - } - }); - user.gameInviteStatus = InviteStatus.PENDING; + if (!props.silentInvit) { + notification.send({ + users: [user.authUsername], + data: { + data: poolStore.pool.uuid, + type: NotificationType.INVITE_TO_GAME + } + }); + user.gameInviteStatus = InviteStatus.PENDING; + } else { + poolStore.poolSocket.silentJoinPool(user.authUsername) + user.gameInviteStatus = InviteStatus.ACCEPT + } + } function filterPlayer(users: User[]): User[] { diff --git a/webapp/src/components/pool/GameRuleSelector.vue b/webapp/src/components/pool/GameRuleSelector.vue index 11eb992..ca3549a 100644 --- a/webapp/src/components/pool/GameRuleSelector.vue +++ b/webapp/src/components/pool/GameRuleSelector.vue @@ -9,6 +9,14 @@ :selected="selectedRules == GameRule.AMERICAN_8" @click="selectedRules = GameRule.AMERICAN_8" /> + {{ t('pool.action.continue') }} diff --git a/webapp/src/components/pool/SilentFriendInvitation.vue b/webapp/src/components/pool/SilentFriendInvitation.vue new file mode 100644 index 0000000..7b31568 --- /dev/null +++ b/webapp/src/components/pool/SilentFriendInvitation.vue @@ -0,0 +1,173 @@ + + + {{ t('pool.friend.selection') }} + + Vos amis + + + + Plus d'amis à inviter + + + + + Joueurs de la partie + + + + + + {{ t('pool.action.continue') }} + + + + + + + \ No newline at end of file diff --git a/webapp/src/components/pool/pools/ManualPoolGame.vue b/webapp/src/components/pool/pools/ManualPoolGame.vue new file mode 100644 index 0000000..b715fe6 --- /dev/null +++ b/webapp/src/components/pool/pools/ManualPoolGame.vue @@ -0,0 +1,158 @@ + + + + + + {{ user }} + + + + {{ user }} + + + + + + + {{ t('pool.game.team1') }} + {{ t('pool.game.win') }} + {{ t('pool.game.loose') }} + + + + + {{ t('pool.game.team2') }} + {{ t('pool.game.win') }} + {{ t('pool.game.loose') }} + + + + + + + {{ t('pool.action.continue') }} + + + + + + + + + \ No newline at end of file diff --git a/webapp/src/objects/pool/Pool.ts b/webapp/src/objects/pool/Pool.ts index f74e5c6..726e301 100644 --- a/webapp/src/objects/pool/Pool.ts +++ b/webapp/src/objects/pool/Pool.ts @@ -54,8 +54,14 @@ export interface GameReportPlayer { username: string } +export interface PoolSilentJoin{ + username:string + sessionId:string +} + export enum GameRule { - AMERICAN_8 = "AMERICAN_8" + AMERICAN_8 = "AMERICAN_8", + MANUAL = "MANUAL" } export enum PoolVictoryState { diff --git a/webapp/src/objects/pool/PoolSocket.ts b/webapp/src/objects/pool/PoolSocket.ts index 5d057ed..808bb99 100644 --- a/webapp/src/objects/pool/PoolSocket.ts +++ b/webapp/src/objects/pool/PoolSocket.ts @@ -4,7 +4,7 @@ import {tsi18n} from "@/objects/i18n"; import {WebSocketMessage, WebSocketMessageType} from "@/objects/pool/WebSocet.ts"; import {useUserStore} from "@/objects/stores/UserStore.ts"; import {usePoolParty} from "@/objects/stores/PoolStore.ts"; -import {GameAction, GameRule, GameState, PoolTeams} from "@/objects/pool/Pool.ts"; +import {GameAction, GameRule, GameState, PoolSilentJoin, PoolTeams} from "@/objects/pool/Pool.ts"; import router from "@/router"; const {t} = tsi18n.global; @@ -127,4 +127,13 @@ export class PoolSocket { }; this.socket.send(JSON.stringify(message)); } + + public silentJoinPool(username: string) { + if (!this.socket) return; + const message: WebSocketMessage = { + data: {sessionId: this.poolStore.pool.uuid, username: username} as PoolSilentJoin, + messageType: WebSocketMessageType.SILENT_JOIN_POOL, + }; + this.socket.send(JSON.stringify(message)); + } } \ No newline at end of file diff --git a/webapp/src/objects/pool/WebSocet.ts b/webapp/src/objects/pool/WebSocet.ts index 2fae83b..5f80e28 100644 --- a/webapp/src/objects/pool/WebSocet.ts +++ b/webapp/src/objects/pool/WebSocet.ts @@ -12,5 +12,6 @@ export enum WebSocketMessageType { SEND_NOTIFICATION = "SEND_NOTIFICATION", UPDATE_TEAMS = "UPDATE_TEAMS", UPDATE_GAME_ACTION = "UPDATE_GAME_ACTION", - PLAY_GAME_ACTION = "PLAY_GAME_ACTION" + PLAY_GAME_ACTION = "PLAY_GAME_ACTION", + SILENT_JOIN_POOL = "SILENT_JOIN_POOL" } diff --git a/webapp/src/vue/templates/RulesCard.vue b/webapp/src/vue/templates/RulesCard.vue index 8e891ab..a677aa4 100644 --- a/webapp/src/vue/templates/RulesCard.vue +++ b/webapp/src/vue/templates/RulesCard.vue @@ -45,7 +45,7 @@ const props = defineProps({ position: relative; overflow: hidden; width: 100%; - min-height: 56px; + min-height: 99px; gap: 8px; padding: 16px; border-radius: 15px;
{{ t('pool.action.continue') }}
Plus d'amis à inviter
{{ user }}
{{ t('pool.game.win') }}
{{ t('pool.game.loose') }}