Coverage Summary for Class: GameController (it.polimi.ingsw.Server.Controller)

Class Class, % Method, % Line, %
GameController 100% (1/1) 100% (24/24) 88,4% (114/129)


 package it.polimi.ingsw.Server.Controller;
 
 import it.polimi.ingsw.Common.*;
 import it.polimi.ingsw.Server.Model.*;
 
 import java.rmi.RemoteException;
 import java.util.*;
 
 /**
  * This class represents the controller, which manages the logic of the game, such as login, turn management, chat.
  */
 public class GameController {
     /**
      * Lobby where players wait until the start of the game
      */
     private final List<String> lobby;
     /**
      * Controller's identifier
      */
     private final String identifier;
     /**
      * Game instance associated to the Controller
      */
     private Game game = null;
     /**
      * Player who is playing his/her turn at this very moment
      */
     private Player activePlayer = null;
     /**
      * Maximum number of Players accepted in a game
      */
     private int maxPlayers;
 
     /**
      * This attribute indicates if a game has been re-entered after a disconnection of the server or not
      */
     private boolean refreshed = false;
 
     /**
      * This attribute indicates a map where are stored pairs of CommonGoalCard and its relative ScoreCard
      */
     private Map<ScoreCard, CommonGoalCard> lastTurnScores;
 
     /**
      * GameController creator
      *
      * @param identifier ID of this Controller
      */
 
     public GameController(String identifier) {
         lobby = new ArrayList<>();
         this.identifier = identifier;
         this.lastTurnScores = new HashMap<>();
     }
 
     /**
      * Related to Game's refresh strategy
      */
     private GameController(List<String> lobby, String identifier, Game game, Player activePlayer, int maxPlayers, boolean refreshed, Map<ScoreCard, CommonGoalCard> lastTurnScores) {
         this.lobby = lobby;
         this.identifier = identifier;
         this.game = game;
         this.activePlayer = activePlayer;
         this.maxPlayers = maxPlayers;
         this.refreshed = refreshed;
         this.lastTurnScores = lastTurnScores;
     }
 
     /**
      * getter method for the Game Identifier
      *
      * @return Game's identifier
      */
     public String getIdentifier() {
         return identifier;
     }
 
     /**
      * This method accepts a new Player in the lobby, if his/her nickname is a regular expression of alphanumeric strings and if the number of
      * players waiting in the lobby is less than the maxPlayers number, chosed by the first player
      *
      * @param nickname   nickname chosen by the player
      * @param maxPlayers maximum number of players chosen by the first player
      * @return true if the player has been accepted, false otherwise
      * @throws Exception if prepareGame() or newPlayer() return an Exception
      */
     public boolean acceptPlayer(String nickname, int maxPlayers) throws Exception {
         if (refreshed)
             return false;
         if (game != null && lobby.size() >= game.getMaxPlayers())
             return false;
         // Regular expression of alphanumeric strings
         if (!nickname.matches("^[a-zA-Z0-9_]+$") || nickname.length() < 3 || lobby.contains(nickname.toLowerCase()) || lobby.contains(nickname.toUpperCase()))
             return false;
         else {
             if (lobby.isEmpty()) {
                 if (maxPlayers >= 2 && maxPlayers <= 4) {
                     game = new Game(identifier, maxPlayers);
                     this.maxPlayers = maxPlayers;
                     lobby.add(nickname);
                 } else return false;
             } else {
                 lobby.add(nickname);
             }
             Player p = game.newPlayer(nickname);
             if (lobby.size() == game.getMaxPlayers()) {
                 game.prepareGame();
                 activePlayer = game.getPlayers().get(0);
             }
             return true;
         }
     }
 
     /**
      * getter method for lobby
      *
      * @return List of nicknames (players who are waiting in the lobby)
      */
     public List<String> getLobby() {
         return lobby;
     }
 
     /**
      * getter method for MaxPlayers
      *
      * @return maxPlayers
      */
     public int getMaxPlayers() {
         return maxPlayers;
     }
 
     /**
      * This method indicates if the game is prepared
      *
      * @return false if the game doesn't exist or the game isn't prepared, true otherwise
      */
     public boolean isGamePrepared() {
         if (game == null)
             return false;
         else return game.isPrepared();
     }
 
     /**
      * getter method for GameBoard
      *
      * @return Board interface if game isn't null, null otherwise
      * @throws RemoteException related to RMI
      */
     public BoardInterface getGameBoard() throws RemoteException {
         if (!(game == null))
             return game.getBoard();
         else return null;
     }
 
     /**
      * getter method for Shelf
      *
      * @param nickname player's nickname
      * @return Shelf interface of the player with this nickname (if game isn't null), null otherwise
      */
     public ShelfInterface getShelf(String nickname) {
         if (!(game == null))
             return game.getShelfInterfaceFromNickname(nickname);
         else return null;
     }
 
     /**
      * getter method for PersonalGoalCard
      *
      * @param nickname player's nickname
      * @return PersonalGoalCard interface of the player with this nickname (if game isn't null), null otherwise
      */
     public PersonalGoalCardInterface getPersonalGoalCard(String nickname) {
         if (!(game == null))
             return game.getPersonalGoalCardInterfaceFromNickname(nickname);
         else return null;
     }
 
     /**
      * getter method for CommonGoalCards
      *
      * @return List of CommonGoalCard interface if game isn't null, null otherwise
      */
     public List<CommonGoalCardInterface> getCommonGoalCards() {
         if (!(game == null))
             return game.getCommonGoalCards();
         else return null;
     }
 
     /**
      * @param nickname Player's nickname
      * @return Player's obtained ScoreCards
      */
     public Stack<ScoreCard> getScoreCardsFromNickname(String nickname) {
         if (!(game == null))
             return game.getScoreCardsFromNickname(nickname);
         else return null;
     }
 
     /**
      * This method returns a list of nicknames of the players, who are playing a game (if game isn't null), null otherwise
      *
      * @return a list of player's nicknames
      */
     public List<String> nicknames() {
         if (game == null)
             return null;
         else return game.nicknames();
     }
 
     /**
      * getter method for ScoreBoard
      *
      * @return null if game is null, Scoreboard otherwise
      */
     public Scoreboard getScoreboard() {
         if (game == null)
             return null;
         else return game.getScoreboard();
     }
 
     /**
      * getter method for MoveIntermediate
      *
      * @param nickname player's nickname
      * @return MoveIntermediateInterface
      * @throws RemoteException related to RMI
      */
     public MoveIntermediateInterface getMoveIntermediate(String nickname) throws RemoteException {
         return new MoveIntermediate(game.getBoard(), game.getShelfFromNickname(nickname), this, game.getPlayerFromNickname(nickname));
     }
 
     /**
      * Getter method for activePlayer
      *
      * @return activePlayer
      */
     public Player getActivePlayer() {
         return activePlayer;
     }
 
     /**
      * This method manages turn evolution during the game. Turn order is decided in class Game.
      */
     private void nextPlayer() {
         if (activePlayer == null) {
             activePlayer = game.getPlayers().get(0);
         } else {
             if (lastTurnScores != null) {
                 lastTurnScores.clear();
             }
             lastTurnScores = activePlayer.getLastAchieved();
             Map<Integer, Player> players = game.getPlayers();
             activePlayer = players.get((players.entrySet()
                     .stream()
                     .filter(entry -> activePlayer.equals(entry.getValue()))
                     .map(Map.Entry::getKey)
                     .findFirst()
                     .orElseThrow() + 1) % players.size());
         }
     }
 
     /**
      * getter method for LastTurnScores (if a player has achieved a CommonGoal)
      *
      * @return a map of ScoreCard and CommonGoalCard
      */
     public Map<ScoreCard, CommonGoalCard> getLastTurnScores() {
         Map<ScoreCard, CommonGoalCard> temp = new HashMap<>();
         if (lastTurnScores != null) {
             for (ScoreCard sc : lastTurnScores.keySet()) {
                 temp.put(sc, lastTurnScores.get(sc));
             }
             return temp;
         }
         return null;
     }
 
     /**
      * This method manages the move m, decided by the Player
      *
      * @param m Move
      * @return true if move has been correctly accomplished, false otherwise
      * @throws Exception if updateScore() in gameComplete() throws an Exception
      */
     public boolean make(Move m) throws Exception {
         if (activePlayer.isInGame()) {
             if (m.take()) {
                 if (m.place()) {
                     activePlayer.updateScore();
                     if (game.checkEndGame(activePlayer)) {
                         for (Player p : game.getPlayers().values()) {
                             if (p.equals(activePlayer)) {
                                 p.setOutOfTurn();
                                 break;
                             } else
                                 p.setOutOfTurn();
                         }
                         if (game.gameComplete()) {
                             return true;
                         }
                     }
                     nextPlayer();
                     return true;
                 } else {
                     m.restoreTaken();
                     return false;
                 }
             } else {
                 return false;
             }
         } else return false;
     }
 
     /**
      * Getter method for isGameEnded
      *
      * @return true if the game has ended, false otherwise
      */
     public boolean isGameEnded() {
         if (game == null)
             return false;
         else return game.isGameEnded();
     }
 
     /**
      * this method indicates if the game is completed
      *
      * @return false if game is null or isn't completed, true otherwise
      */
     public boolean isGameComplete() {
         if (game == null)
             return false;
         else try {
             return game.gameComplete();
         } catch (Exception ignored) {
             return false;
         }
     }
 
     /**
      * getter method for PlayerByNickname
      *
      * @param nickname player's nickname
      * @return player recognized by his nickname
      */
     public Player getPlayerByNickname(String nickname) {
         return game.getPlayerFromNickname(nickname);
     }
 
 
     /**
      * Objects refresh following a game reloaded from a persistency file
      *
      * @return the refreshed controller
      * @throws RemoteException Related to RMI
      */
     public GameController refreshEntities() throws RemoteException {
         lobby.clear();
         refreshed = true;
         this.game = game.refreshEntities();
         this.activePlayer = game.getPlayers()
                 .values()
                 .stream()
                 .filter(p -> p.getNickname().equals(activePlayer.getNickname()))
                 .findFirst()
                 .orElseThrow();
         if (lastTurnScores != null && !lastTurnScores.isEmpty())
             this.lastTurnScores = new HashMap<>(this.lastTurnScores);
         else this.lastTurnScores = new HashMap<>();
         return new GameController(this.lobby, this.identifier, this.game, this.activePlayer, this.maxPlayers, this.refreshed, this.lastTurnScores);
     }
 
     /**
      * Game's re-entering strategy (related to a game reloaded from a persistency file)
      *
      * @param nickname of the player
      * @return completion of the admission phase
      */
     public boolean reEnterGame(String nickname) {
         if (game != null) {
             if (refreshed && !lobby.contains(nickname) && nicknames().contains(nickname)) {
                 lobby.add(nickname);
                 if (lobby.size() == this.getMaxPlayers())
                     refreshed = false;
                 return true;
             }
         }
         return false;
     }
 }