From bf099f2ee34a3640b91e99a6d76ff086b77c2cc1 Mon Sep 17 00:00:00 2001 From: Joffrey BION Date: Thu, 2 Feb 2017 01:02:02 +0100 Subject: Decouple Lobby and Players from the Game itself --- .../sevenwonders/controllers/GameController.java | 27 ++-- .../sevenwonders/controllers/LobbyController.java | 15 +-- .../java/org/luxons/sevenwonders/game/Game.java | 62 +++------ .../java/org/luxons/sevenwonders/game/Lobby.java | 142 -------------------- .../java/org/luxons/sevenwonders/game/Player.java | 59 --------- .../java/org/luxons/sevenwonders/game/State.java | 6 - .../sevenwonders/game/api/PlayerTurnInfo.java | 12 +- .../luxons/sevenwonders/game/api/PreparedCard.java | 24 ---- .../org/luxons/sevenwonders/game/boards/Board.java | 17 +-- .../sevenwonders/game/data/GameDefinition.java | 18 ++- .../sevenwonders/game/scoring/PlayerScore.java | 7 +- .../java/org/luxons/sevenwonders/lobby/Lobby.java | 143 +++++++++++++++++++++ .../java/org/luxons/sevenwonders/lobby/Player.java | 60 +++++++++ .../java/org/luxons/sevenwonders/lobby/State.java | 6 + .../luxons/sevenwonders/output/PreparedCard.java | 24 ++++ .../sevenwonders/repositories/GameRepository.java | 49 ------- .../sevenwonders/repositories/LobbyRepository.java | 4 +- .../repositories/PlayerRepository.java | 2 +- .../validation/DestinationAccessValidator.java | 16 +-- 19 files changed, 299 insertions(+), 394 deletions(-) delete mode 100644 backend/src/main/java/org/luxons/sevenwonders/game/Lobby.java delete mode 100644 backend/src/main/java/org/luxons/sevenwonders/game/Player.java delete mode 100644 backend/src/main/java/org/luxons/sevenwonders/game/State.java delete mode 100644 backend/src/main/java/org/luxons/sevenwonders/game/api/PreparedCard.java create mode 100644 backend/src/main/java/org/luxons/sevenwonders/lobby/Lobby.java create mode 100644 backend/src/main/java/org/luxons/sevenwonders/lobby/Player.java create mode 100644 backend/src/main/java/org/luxons/sevenwonders/lobby/State.java create mode 100644 backend/src/main/java/org/luxons/sevenwonders/output/PreparedCard.java delete mode 100644 backend/src/main/java/org/luxons/sevenwonders/repositories/GameRepository.java (limited to 'backend/src/main/java/org/luxons') diff --git a/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java b/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java index 3f3a02db..390d3e83 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java +++ b/backend/src/main/java/org/luxons/sevenwonders/controllers/GameController.java @@ -4,9 +4,12 @@ import java.security.Principal; import org.luxons.sevenwonders.actions.PrepareCardAction; import org.luxons.sevenwonders.game.Game; +import org.luxons.sevenwonders.lobby.Lobby; +import org.luxons.sevenwonders.lobby.Player; import org.luxons.sevenwonders.game.api.PlayerTurnInfo; -import org.luxons.sevenwonders.game.api.PreparedCard; -import org.luxons.sevenwonders.repositories.GameRepository; +import org.luxons.sevenwonders.output.PreparedCard; +import org.luxons.sevenwonders.game.cards.CardBack; +import org.luxons.sevenwonders.repositories.PlayerRepository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -22,23 +25,25 @@ public class GameController { private final SimpMessagingTemplate template; - private final GameRepository gameRepository; + private final PlayerRepository playerRepository; @Autowired - public GameController(SimpMessagingTemplate template, GameRepository gameRepository) { + public GameController(SimpMessagingTemplate template, PlayerRepository playerRepository) { this.template = template; - this.gameRepository = gameRepository; + this.playerRepository = playerRepository; } @MessageMapping("/game/{gameId}/prepare") public void prepareCard(@DestinationVariable long gameId, PrepareCardAction action, Principal principal) { - Game game = gameRepository.find(gameId); - PreparedCard preparedCard = game.prepareCard(principal.getName(), action.getMove()); + Player player = playerRepository.find(principal.getName()); + Game game = player.getGame(); + CardBack preparedCardBack = game.prepareCard(player.getIndex(), action.getMove()); + PreparedCard preparedCard = new PreparedCard(player, preparedCardBack); logger.info("Game '{}': player {} prepared move {}", gameId, principal.getName(), action.getMove()); if (game.areAllPlayersReady()) { game.playTurn(); - sendTurnInfo(game); + sendTurnInfo(player.getLobby(), game); } else { sendPreparedCard(preparedCard, game); } @@ -48,10 +53,10 @@ public class GameController { template.convertAndSend("/topic/game/" + game.getId() + "/prepared", preparedCard); } - private void sendTurnInfo(Game game) { + private void sendTurnInfo(Lobby lobby, Game game) { for (PlayerTurnInfo turnInfo : game.getCurrentTurnInfo()) { - String username = turnInfo.getPlayer().getUsername(); - template.convertAndSendToUser(username, "/queue/game/" + game.getId() + "/turn", turnInfo); + Player player = lobby.getPlayers().get(turnInfo.getPlayerIndex()); + template.convertAndSendToUser(player.getUsername(), "/queue/game/turn", turnInfo); } } } diff --git a/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java b/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java index cbc69602..b9381cf8 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java +++ b/backend/src/main/java/org/luxons/sevenwonders/controllers/LobbyController.java @@ -11,9 +11,8 @@ import org.luxons.sevenwonders.actions.ReorderPlayersAction; import org.luxons.sevenwonders.actions.UpdateSettingsAction; import org.luxons.sevenwonders.errors.ApiMisuseException; import org.luxons.sevenwonders.game.Game; -import org.luxons.sevenwonders.game.Lobby; -import org.luxons.sevenwonders.game.Player; -import org.luxons.sevenwonders.repositories.GameRepository; +import org.luxons.sevenwonders.lobby.Lobby; +import org.luxons.sevenwonders.lobby.Player; import org.luxons.sevenwonders.repositories.LobbyRepository; import org.luxons.sevenwonders.repositories.PlayerRepository; import org.slf4j.Logger; @@ -33,17 +32,14 @@ public class LobbyController { private final LobbyRepository lobbyRepository; - private final GameRepository gameRepository; - private final PlayerRepository playerRepository; private final SimpMessagingTemplate template; @Autowired - public LobbyController(LobbyRepository lobbyRepository, GameRepository gameRepository, - PlayerRepository playerRepository, SimpMessagingTemplate template) { + public LobbyController(LobbyRepository lobbyRepository, PlayerRepository playerRepository, + SimpMessagingTemplate template) { this.lobbyRepository = lobbyRepository; - this.gameRepository = gameRepository; this.playerRepository = playerRepository; this.template = template; } @@ -131,10 +127,9 @@ public class LobbyController { public void startGame(Principal principal) { Lobby lobby = getOwnedLobby(principal); Game game = lobby.startGame(); - gameRepository.add(game); logger.info("Game {} successfully started", game.getId()); - template.convertAndSend("/topic/lobby/" + lobby.getId() + "/started", (Object)null); + template.convertAndSend("/topic/lobby/" + lobby.getId() + "/started", (Object) null); } private Lobby getOwnedLobby(Principal principal) { diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/Game.java b/backend/src/main/java/org/luxons/sevenwonders/game/Game.java index 206b4697..d90a2381 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/game/Game.java +++ b/backend/src/main/java/org/luxons/sevenwonders/game/Game.java @@ -5,17 +5,15 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; import org.luxons.sevenwonders.game.api.Action; import org.luxons.sevenwonders.game.api.HandCard; import org.luxons.sevenwonders.game.api.PlayerMove; import org.luxons.sevenwonders.game.api.PlayerTurnInfo; -import org.luxons.sevenwonders.game.api.PreparedCard; import org.luxons.sevenwonders.game.api.Table; import org.luxons.sevenwonders.game.boards.Board; import org.luxons.sevenwonders.game.cards.Card; +import org.luxons.sevenwonders.game.cards.CardBack; import org.luxons.sevenwonders.game.cards.Decks; import org.luxons.sevenwonders.game.cards.Hands; import org.luxons.sevenwonders.game.effects.SpecialAbility; @@ -30,7 +28,7 @@ public class Game { private final Settings settings; - private final List players; + private final int nbPlayers; private final Table table; @@ -44,10 +42,10 @@ public class Game { private Hands hands; - public Game(long id, Settings settings, List players, List boards, Decks decks) { + public Game(long id, Settings settings, int nbPlayers, List boards, Decks decks) { this.id = id; this.settings = settings; - this.players = players; + this.nbPlayers = nbPlayers; this.table = new Table(boards); this.decks = decks; this.discardedCards = new ArrayList<>(); @@ -60,14 +58,6 @@ public class Game { return id; } - public boolean containsUser(String username) { - return players.stream().anyMatch(p -> p.getUsername().equals(username)); - } - - public List getPlayers() { - return players; - } - private void startNewAge() { table.increaseCurrentAge(); hands = decks.deal(table.getCurrentAge(), table.getNbPlayers()); @@ -75,17 +65,17 @@ public class Game { } private void startNewTurn() { - Function extractPlayerIndex = pti -> pti.getPlayer().getIndex(); - currentTurnInfo = players.stream() - .map(this::createPlayerTurnInfo) - .collect(Collectors.toMap(extractPlayerIndex, pti -> pti)); + currentTurnInfo.clear(); + for (int i = 0; i < nbPlayers; i++) { + currentTurnInfo.put(i, createPlayerTurnInfo(i)); + } } - private PlayerTurnInfo createPlayerTurnInfo(Player player) { - PlayerTurnInfo pti = new PlayerTurnInfo(player, table); - List hand = hands.createHand(table, player.getIndex()); + private PlayerTurnInfo createPlayerTurnInfo(int playerIndex) { + PlayerTurnInfo pti = new PlayerTurnInfo(playerIndex, table); + List hand = hands.createHand(table, playerIndex); pti.setHand(hand); - Action action = determineAction(hand, table.getBoard(player.getIndex())); + Action action = determineAction(hand, table.getBoard(playerIndex)); pti.setAction(action); pti.setMessage(action.getMessage()); return pti; @@ -109,20 +99,12 @@ public class Game { } } - public PreparedCard prepareCard(String username, PlayerMove playerMove) throws InvalidMoveException { - Player player = getPlayer(username); + public CardBack prepareCard(int playerIndex, PlayerMove playerMove) throws InvalidMoveException { Card card = decks.getCard(playerMove.getCardName()); - Move move = playerMove.getType().resolve(player.getIndex(), card, playerMove); + Move move = playerMove.getType().resolve(playerIndex, card, playerMove); validate(move); - preparedMoves.put(player.getIndex(), move); - return new PreparedCard(player, card.getBack()); - } - - private Player getPlayer(String username) { - return players.stream() - .filter(p -> p.getUsername().equals(username)) - .findAny() - .orElseThrow(() -> new UnknownPlayerException(username)); + preparedMoves.put(playerIndex, move); + return card.getBack(); } private void validate(Move move) throws InvalidMoveException { @@ -196,10 +178,10 @@ public class Game { } private void discardLastCardsOfHands() { - for (Player p : players) { - Board board = table.getBoard(p.getIndex()); + for (int i = 0; i < nbPlayers; i++) { + Board board = table.getBoard(i); if (!board.hasSpecial(SpecialAbility.PLAY_LAST_CARD)) { - discardHand(p.getIndex()); + discardHand(i); } } } @@ -242,12 +224,6 @@ public class Game { } } - private static class UnknownPlayerException extends IllegalArgumentException { - UnknownPlayerException(String username) { - super(username); - } - } - private static class InvalidMoveException extends IllegalArgumentException { InvalidMoveException(String message) { super(message); diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/Lobby.java b/backend/src/main/java/org/luxons/sevenwonders/game/Lobby.java deleted file mode 100644 index b90283a8..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/game/Lobby.java +++ /dev/null @@ -1,142 +0,0 @@ -package org.luxons.sevenwonders.game; - -import java.util.ArrayList; -import java.util.List; - -import org.luxons.sevenwonders.game.api.CustomizableSettings; -import org.luxons.sevenwonders.game.data.GameDefinition; - -public class Lobby { - - private final long id; - - private final String name; - - private final Player owner; - - private final GameDefinition gameDefinition; - - private final List players; - - private CustomizableSettings settings; - - private State state = State.LOBBY; - - public Lobby(long id, String name, Player owner, GameDefinition gameDefinition) { - this.id = id; - this.name = name; - this.owner = owner; - this.gameDefinition = gameDefinition; - this.players = new ArrayList<>(gameDefinition.getMinPlayers()); - this.settings = new CustomizableSettings(); - players.add(owner); - } - - public long getId() { - return id; - } - - public String getName() { - return name; - } - - public List getPlayers() { - return players; - } - - public CustomizableSettings getSettings() { - return settings; - } - - public void setSettings(CustomizableSettings settings) { - this.settings = settings; - } - - public State getState() { - return state; - } - - public synchronized void addPlayer(Player player) throws GameAlreadyStartedException, PlayerOverflowException { - if (hasStarted()) { - throw new GameAlreadyStartedException(); - } - if (maxPlayersReached()) { - throw new PlayerOverflowException(); - } - if (playerNameAlreadyUsed(player.getDisplayName())) { - throw new PlayerNameAlreadyUsedException(player.getDisplayName()); - } - player.setIndex(players.size()); - players.add(player); - } - - private boolean hasStarted() { - return state != State.LOBBY; - } - - private boolean maxPlayersReached() { - return players.size() >= gameDefinition.getMaxPlayers(); - } - - private boolean playerNameAlreadyUsed(String name) { - return players.stream().anyMatch(p -> p.getDisplayName().equals(name)); - } - - public synchronized Game startGame() throws PlayerUnderflowException { - if (!hasEnoughPlayers()) { - throw new PlayerUnderflowException(); - } - state = State.PLAYING; - return gameDefinition.initGame(id, settings, players); - } - - private boolean hasEnoughPlayers() { - return players.size() >= gameDefinition.getMinPlayers(); - } - - public void reorderPlayers(List orderedUsernames) { - List formerList = new ArrayList<>(players); - players.clear(); - for (int i = 0; i < orderedUsernames.size(); i++) { - Player player = getPlayer(formerList, orderedUsernames.get(i)); - players.add(player); - player.setIndex(i); - } - } - - private static Player getPlayer(List players, String username) { - return players.stream() - .filter(p -> p.getUsername().equals(username)) - .findAny() - .orElseThrow(() -> new UnknownPlayerException(username)); - } - - public boolean isOwner(String username) { - return owner.getUsername().equals(username); - } - - public boolean containsUser(String username) { - return players.stream().anyMatch(p -> p.getUsername().equals(username)); - } - - static class GameAlreadyStartedException extends IllegalStateException { - } - - static class PlayerOverflowException extends IllegalStateException { - } - - static class PlayerUnderflowException extends IllegalStateException { - } - - static class PlayerNameAlreadyUsedException extends RuntimeException { - PlayerNameAlreadyUsedException(String name) { - super(name); - } - } - - static class UnknownPlayerException extends IllegalArgumentException { - UnknownPlayerException(String username) { - super(username); - } - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/Player.java b/backend/src/main/java/org/luxons/sevenwonders/game/Player.java deleted file mode 100644 index f1095049..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/game/Player.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.luxons.sevenwonders.game; - -import com.fasterxml.jackson.annotation.JsonIgnore; - -public class Player { - - private final String username; - - private String displayName; - - private int index; - - private transient Lobby lobby; - - private transient Game game; - - public Player(String username, String displayName) { - this.username = username; - this.displayName = displayName; - } - - public String getUsername() { - return username; - } - - public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - - public int getIndex() { - return index; - } - - public void setIndex(int index) { - this.index = index; - } - - @JsonIgnore - public Lobby getLobby() { - return lobby; - } - - public void setLobby(Lobby lobby) { - this.lobby = lobby; - } - - @JsonIgnore - public Game getGame() { - return game; - } - - public void setGame(Game game) { - this.game = game; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/State.java b/backend/src/main/java/org/luxons/sevenwonders/game/State.java deleted file mode 100644 index 0bd71d3a..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/game/State.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.luxons.sevenwonders.game; - -public enum State { - LOBBY, - PLAYING -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java b/backend/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java index 14d4a9e8..c4cea17f 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java +++ b/backend/src/main/java/org/luxons/sevenwonders/game/api/PlayerTurnInfo.java @@ -2,11 +2,9 @@ package org.luxons.sevenwonders.game.api; import java.util.List; -import org.luxons.sevenwonders.game.Player; - public class PlayerTurnInfo { - private final Player player; + private final int playerIndex; private final Table table; @@ -18,13 +16,13 @@ public class PlayerTurnInfo { private String message; - public PlayerTurnInfo(Player player, Table table) { - this.player = player; + public PlayerTurnInfo(int playerIndex, Table table) { + this.playerIndex = playerIndex; this.table = table; } - public Player getPlayer() { - return player; + public int getPlayerIndex() { + return playerIndex; } public Table getTable() { diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/api/PreparedCard.java b/backend/src/main/java/org/luxons/sevenwonders/game/api/PreparedCard.java deleted file mode 100644 index 85cac1de..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/game/api/PreparedCard.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.luxons.sevenwonders.game.api; - -import org.luxons.sevenwonders.game.Player; -import org.luxons.sevenwonders.game.cards.CardBack; - -public class PreparedCard { - - private final Player player; - - private final CardBack cardBack; - - public PreparedCard(Player player, CardBack cardBack) { - this.player = player; - this.cardBack = cardBack; - } - - public Player getPlayer() { - return player; - } - - public CardBack getCardBack() { - return cardBack; - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/boards/Board.java b/backend/src/main/java/org/luxons/sevenwonders/game/boards/Board.java index 0d85ac51..16f5cf5a 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/game/boards/Board.java +++ b/backend/src/main/java/org/luxons/sevenwonders/game/boards/Board.java @@ -7,7 +7,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.luxons.sevenwonders.game.Player; import org.luxons.sevenwonders.game.Settings; import org.luxons.sevenwonders.game.api.Table; import org.luxons.sevenwonders.game.cards.Card; @@ -23,7 +22,7 @@ public class Board { private final Wonder wonder; - private final Player player; + private final int playerIndex; private final List playedCards = new ArrayList<>(); @@ -47,9 +46,9 @@ public class Board { private int pointsPer3Gold; - public Board(Wonder wonder, Player player, Settings settings) { + public Board(Wonder wonder, int playerIndex, Settings settings) { this.wonder = wonder; - this.player = player; + this.playerIndex = playerIndex; this.gold = settings.getInitialGold(); this.tradingRules = new TradingRules(settings.getDefaultTradingCost()); this.military = new Military(settings.getLostPointsPerDefeat(), settings.getWonPointsPerVictoryPerAge()); @@ -62,10 +61,6 @@ public class Board { return wonder; } - public Player getPlayer() { - return player; - } - public List getPlayedCards() { return playedCards; } @@ -149,13 +144,13 @@ public class Board { } public PlayerScore computePoints(Table table) { - PlayerScore score = new PlayerScore(player, gold); + PlayerScore score = new PlayerScore(gold); score.put(ScoreCategory.CIVIL, computePointsForCards(table, Color.BLUE)); score.put(ScoreCategory.MILITARY, military.getTotalPoints()); score.put(ScoreCategory.SCIENCE, science.computePoints()); score.put(ScoreCategory.TRADE, computePointsForCards(table, Color.YELLOW)); score.put(ScoreCategory.GUILD, computePointsForCards(table, Color.PURPLE)); - score.put(ScoreCategory.WONDER, wonder.computePoints(table, player.getIndex())); + score.put(ScoreCategory.WONDER, wonder.computePoints(table, playerIndex)); score.put(ScoreCategory.GOLD, computeGoldPoints()); return score; } @@ -164,7 +159,7 @@ public class Board { return playedCards.stream() .filter(c -> c.getColor() == color) .flatMap(c -> c.getEffects().stream()) - .mapToInt(e -> e.computePoints(table, player.getIndex())) + .mapToInt(e -> e.computePoints(table, playerIndex)) .sum(); } diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java b/backend/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java index 4c63718b..7604ca6a 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java +++ b/backend/src/main/java/org/luxons/sevenwonders/game/data/GameDefinition.java @@ -6,7 +6,6 @@ import java.util.Collections; import java.util.List; import org.luxons.sevenwonders.game.Game; -import org.luxons.sevenwonders.game.Player; import org.luxons.sevenwonders.game.Settings; import org.luxons.sevenwonders.game.api.CustomizableSettings; import org.luxons.sevenwonders.game.boards.Board; @@ -44,23 +43,22 @@ public class GameDefinition { return MAX_PLAYERS; } - public Game initGame(long id, CustomizableSettings customSettings, List orderedPlayers) { - Settings settings = new Settings(orderedPlayers.size(), customSettings); - List boards = assignBoards(settings, orderedPlayers); + public Game initGame(long id, CustomizableSettings customSettings, int nbPlayers) { + Settings settings = new Settings(nbPlayers, customSettings); + List boards = assignBoards(settings, nbPlayers); Decks decks = decksDefinition.create(settings); - return new Game(id, settings, orderedPlayers, boards, decks); + return new Game(id, settings, nbPlayers, boards, decks); } - private List assignBoards(Settings settings, List orderedPlayers) { + private List assignBoards(Settings settings, int nbPlayers) { List randomizedWonders = Arrays.asList(wonders); Collections.shuffle(randomizedWonders, settings.getRandom()); - List boards = new ArrayList<>(orderedPlayers.size()); - for (int i = 0; i < orderedPlayers.size(); i++) { - Player player = orderedPlayers.get(i); + List boards = new ArrayList<>(nbPlayers); + for (int i = 0; i < nbPlayers; i++) { WonderDefinition def = randomizedWonders.get(i); Wonder w = def.create(settings); - Board b = new Board(w, player, settings); + Board b = new Board(w, i, settings); boards.add(b); } return boards; diff --git a/backend/src/main/java/org/luxons/sevenwonders/game/scoring/PlayerScore.java b/backend/src/main/java/org/luxons/sevenwonders/game/scoring/PlayerScore.java index 42acec54..f67924e1 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/game/scoring/PlayerScore.java +++ b/backend/src/main/java/org/luxons/sevenwonders/game/scoring/PlayerScore.java @@ -2,18 +2,13 @@ package org.luxons.sevenwonders.game.scoring; import java.util.HashMap; -import org.luxons.sevenwonders.game.Player; - public class PlayerScore extends HashMap { - private final Player player; - private final int boardGold; private int totalPoints = 0; - public PlayerScore(Player player, int boardGold) { - this.player = player; + public PlayerScore(int boardGold) { this.boardGold = boardGold; } diff --git a/backend/src/main/java/org/luxons/sevenwonders/lobby/Lobby.java b/backend/src/main/java/org/luxons/sevenwonders/lobby/Lobby.java new file mode 100644 index 00000000..60637099 --- /dev/null +++ b/backend/src/main/java/org/luxons/sevenwonders/lobby/Lobby.java @@ -0,0 +1,143 @@ +package org.luxons.sevenwonders.lobby; + +import java.util.ArrayList; +import java.util.List; + +import org.luxons.sevenwonders.game.Game; +import org.luxons.sevenwonders.game.api.CustomizableSettings; +import org.luxons.sevenwonders.game.data.GameDefinition; + +public class Lobby { + + private final long id; + + private final String name; + + private final Player owner; + + private final GameDefinition gameDefinition; + + private final List players; + + private CustomizableSettings settings; + + private State state = State.LOBBY; + + public Lobby(long id, String name, Player owner, GameDefinition gameDefinition) { + this.id = id; + this.name = name; + this.owner = owner; + this.gameDefinition = gameDefinition; + this.players = new ArrayList<>(gameDefinition.getMinPlayers()); + this.settings = new CustomizableSettings(); + players.add(owner); + } + + public long getId() { + return id; + } + + public String getName() { + return name; + } + + public List getPlayers() { + return players; + } + + public CustomizableSettings getSettings() { + return settings; + } + + public void setSettings(CustomizableSettings settings) { + this.settings = settings; + } + + public State getState() { + return state; + } + + public synchronized void addPlayer(Player player) throws GameAlreadyStartedException, PlayerOverflowException { + if (hasStarted()) { + throw new GameAlreadyStartedException(); + } + if (maxPlayersReached()) { + throw new PlayerOverflowException(); + } + if (playerNameAlreadyUsed(player.getDisplayName())) { + throw new PlayerNameAlreadyUsedException(player.getDisplayName()); + } + player.setIndex(players.size()); + players.add(player); + } + + private boolean hasStarted() { + return state != State.LOBBY; + } + + private boolean maxPlayersReached() { + return players.size() >= gameDefinition.getMaxPlayers(); + } + + private boolean playerNameAlreadyUsed(String name) { + return players.stream().anyMatch(p -> p.getDisplayName().equals(name)); + } + + public synchronized Game startGame() throws PlayerUnderflowException { + if (!hasEnoughPlayers()) { + throw new PlayerUnderflowException(); + } + state = State.PLAYING; + return gameDefinition.initGame(id, settings, players.size()); + } + + private boolean hasEnoughPlayers() { + return players.size() >= gameDefinition.getMinPlayers(); + } + + public void reorderPlayers(List orderedUsernames) { + List formerList = new ArrayList<>(players); + players.clear(); + for (int i = 0; i < orderedUsernames.size(); i++) { + Player player = getPlayer(formerList, orderedUsernames.get(i)); + players.add(player); + player.setIndex(i); + } + } + + private static Player getPlayer(List players, String username) { + return players.stream() + .filter(p -> p.getUsername().equals(username)) + .findAny() + .orElseThrow(() -> new UnknownPlayerException(username)); + } + + public boolean isOwner(String username) { + return owner.getUsername().equals(username); + } + + public boolean containsUser(String username) { + return players.stream().anyMatch(p -> p.getUsername().equals(username)); + } + + static class GameAlreadyStartedException extends IllegalStateException { + } + + static class PlayerOverflowException extends IllegalStateException { + } + + static class PlayerUnderflowException extends IllegalStateException { + } + + static class PlayerNameAlreadyUsedException extends RuntimeException { + PlayerNameAlreadyUsedException(String name) { + super(name); + } + } + + static class UnknownPlayerException extends IllegalArgumentException { + UnknownPlayerException(String username) { + super(username); + } + } +} diff --git a/backend/src/main/java/org/luxons/sevenwonders/lobby/Player.java b/backend/src/main/java/org/luxons/sevenwonders/lobby/Player.java new file mode 100644 index 00000000..6698c476 --- /dev/null +++ b/backend/src/main/java/org/luxons/sevenwonders/lobby/Player.java @@ -0,0 +1,60 @@ +package org.luxons.sevenwonders.lobby; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import org.luxons.sevenwonders.game.Game; + +public class Player { + + private final String username; + + private String displayName; + + private int index; + + private transient Lobby lobby; + + private transient Game game; + + public Player(String username, String displayName) { + this.username = username; + this.displayName = displayName; + } + + public String getUsername() { + return username; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public int getIndex() { + return index; + } + + public void setIndex(int index) { + this.index = index; + } + + @JsonIgnore + public Lobby getLobby() { + return lobby; + } + + public void setLobby(Lobby lobby) { + this.lobby = lobby; + } + + @JsonIgnore + public Game getGame() { + return game; + } + + public void setGame(Game game) { + this.game = game; + } +} diff --git a/backend/src/main/java/org/luxons/sevenwonders/lobby/State.java b/backend/src/main/java/org/luxons/sevenwonders/lobby/State.java new file mode 100644 index 00000000..17f3b101 --- /dev/null +++ b/backend/src/main/java/org/luxons/sevenwonders/lobby/State.java @@ -0,0 +1,6 @@ +package org.luxons.sevenwonders.lobby; + +public enum State { + LOBBY, + PLAYING +} diff --git a/backend/src/main/java/org/luxons/sevenwonders/output/PreparedCard.java b/backend/src/main/java/org/luxons/sevenwonders/output/PreparedCard.java new file mode 100644 index 00000000..ac696890 --- /dev/null +++ b/backend/src/main/java/org/luxons/sevenwonders/output/PreparedCard.java @@ -0,0 +1,24 @@ +package org.luxons.sevenwonders.output; + +import org.luxons.sevenwonders.lobby.Player; +import org.luxons.sevenwonders.game.cards.CardBack; + +public class PreparedCard { + + private final Player player; + + private final CardBack cardBack; + + public PreparedCard(Player player, CardBack cardBack) { + this.player = player; + this.cardBack = cardBack; + } + + public Player getPlayer() { + return player; + } + + public CardBack getCardBack() { + return cardBack; + } +} diff --git a/backend/src/main/java/org/luxons/sevenwonders/repositories/GameRepository.java b/backend/src/main/java/org/luxons/sevenwonders/repositories/GameRepository.java deleted file mode 100644 index efe39b85..00000000 --- a/backend/src/main/java/org/luxons/sevenwonders/repositories/GameRepository.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.luxons.sevenwonders.repositories; - -import java.util.HashMap; -import java.util.Map; - -import org.luxons.sevenwonders.errors.ApiMisuseException; -import org.luxons.sevenwonders.game.Game; -import org.springframework.stereotype.Repository; - -@Repository -public class GameRepository { - - private Map games = new HashMap<>(); - - public void add(Game game) throws GameAlreadyExistsException { - if (games.containsKey(game.getId())) { - throw new GameAlreadyExistsException(game.getId()); - } - games.put(game.getId(), game); - } - - public Game find(long gameId) throws GameNotFoundException { - Game game = games.get(gameId); - if (game == null) { - throw new GameNotFoundException(gameId); - } - return game; - } - - public Game remove(long gameId) throws GameNotFoundException { - Game game = games.remove(gameId); - if (game == null) { - throw new GameNotFoundException(gameId); - } - return game; - } - - public static class GameNotFoundException extends ApiMisuseException { - GameNotFoundException(long id) { - super("Game " + id + " doesn't exist"); - } - } - - static class GameAlreadyExistsException extends ApiMisuseException { - GameAlreadyExistsException(long id) { - super("Game " + id + " already exists"); - } - } -} diff --git a/backend/src/main/java/org/luxons/sevenwonders/repositories/LobbyRepository.java b/backend/src/main/java/org/luxons/sevenwonders/repositories/LobbyRepository.java index 8f305791..0a7b9238 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/repositories/LobbyRepository.java +++ b/backend/src/main/java/org/luxons/sevenwonders/repositories/LobbyRepository.java @@ -4,8 +4,8 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.luxons.sevenwonders.game.Lobby; -import org.luxons.sevenwonders.game.Player; +import org.luxons.sevenwonders.lobby.Lobby; +import org.luxons.sevenwonders.lobby.Player; import org.luxons.sevenwonders.game.data.GameDefinitionLoader; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; diff --git a/backend/src/main/java/org/luxons/sevenwonders/repositories/PlayerRepository.java b/backend/src/main/java/org/luxons/sevenwonders/repositories/PlayerRepository.java index 049c5ef9..541393e1 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/repositories/PlayerRepository.java +++ b/backend/src/main/java/org/luxons/sevenwonders/repositories/PlayerRepository.java @@ -4,7 +4,7 @@ import java.util.HashMap; import java.util.Map; import org.luxons.sevenwonders.errors.ApiMisuseException; -import org.luxons.sevenwonders.game.Player; +import org.luxons.sevenwonders.lobby.Player; import org.springframework.stereotype.Repository; @Repository diff --git a/backend/src/main/java/org/luxons/sevenwonders/validation/DestinationAccessValidator.java b/backend/src/main/java/org/luxons/sevenwonders/validation/DestinationAccessValidator.java index 65b3623c..cd17b0a5 100644 --- a/backend/src/main/java/org/luxons/sevenwonders/validation/DestinationAccessValidator.java +++ b/backend/src/main/java/org/luxons/sevenwonders/validation/DestinationAccessValidator.java @@ -3,9 +3,7 @@ package org.luxons.sevenwonders.validation; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.luxons.sevenwonders.game.Game; -import org.luxons.sevenwonders.game.Lobby; -import org.luxons.sevenwonders.repositories.GameRepository; +import org.luxons.sevenwonders.lobby.Lobby; import org.luxons.sevenwonders.repositories.LobbyRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -19,12 +17,9 @@ public class DestinationAccessValidator { private final LobbyRepository lobbyRepository; - private final GameRepository gameRepository; - @Autowired - public DestinationAccessValidator(LobbyRepository lobbyRepository, GameRepository gameRepository) { + public DestinationAccessValidator(LobbyRepository lobbyRepository) { this.lobbyRepository = lobbyRepository; - this.gameRepository = gameRepository; } public boolean hasAccess(String username, String destination) { @@ -47,7 +42,7 @@ public class DestinationAccessValidator { return false; // no game reference is always OK } int gameId = extractId(gameMatcher); - return !isUserInGame(username, gameId); + return !isUserInLobby(username, gameId); } private boolean hasForbiddenLobbyReference(String username, String destination) { @@ -59,11 +54,6 @@ public class DestinationAccessValidator { return !isUserInLobby(username, lobbyId); } - private boolean isUserInGame(String username, int gameId) { - Game game = gameRepository.find(gameId); - return game.containsUser(username); - } - private boolean isUserInLobby(String username, int lobbyId) { Lobby lobby = lobbyRepository.find(lobbyId); return lobby.containsUser(username); -- cgit