@RequestMapping("/stats")
 public WebServiceResponse gameStatus() {
   WebServiceResponse response = new WebServiceResponse();
   response.getResponseObject().setGameStats(gameService.getOverallGameStats());
   response.getResponseMetaData().success();
   return response;
 }
  @RequestMapping("/place_chip/{boardColumn}")
  public WebServiceResponse placeChip(
      @PathVariable String boardColumn,
      @RequestParam(required = true) String playerRef,
      @RequestParam(required = true) String boardSessionId) {
    WebServiceResponse response = new WebServiceResponse();
    if (playerRef.isEmpty() || boardSessionId.isEmpty()) {
      response.getResponseMetaData().failure(HttpStatus.BAD_REQUEST.value(), invalidPlayerRefMsg);
    } else {
      try {
        String[] boardMoves = gameService.placeBoardPiece(boardSessionId, playerRef, boardColumn);

        if (boardMoves != null && boardMoves.length >= 3) {
          response.getResponseObject().setYourTurn(boardMoves[0]);
          response.getResponseObject().setOpponentTurn(boardMoves[1]);
          response.getResponseObject().setChipColor(boardMoves[2]);
          response.getResponseObject().setBoardData(boardMoves[3]);
          response.getResponseObject().setGameStatus(GameStatus.GAME_IN_PROGRESS);
          response.getResponseMetaData().success();
        } else {
          response
              .getResponseMetaData()
              .failure(
                  HttpStatus.FORBIDDEN.value(),
                  "Sorry, I'm still waiting for other players to join.");
        }
      } catch (GameFinished ge) {
        response.getResponseObject().setGameStatus(ge.getGameStatus());
        if (!ge.getGameStatus().equals(GameStatus.GAME_TIED)) {
          try {
            if (ge.getWinningMove().equals(playerRef)) {
              response.getResponseObject().setMessage(aiWinMsg);
              response.getResponseObject().setBoardData(ge.getBoardData());

            } else {
              response.getResponseObject().setMessage(playerWinMsg);
            }
          } catch (PlayerNotRegisteredException ex) {
            // this won't occur as the player is aleady been verfied.
          }
        } else {
          response.getResponseObject().setMessage(gameTieMsg);
        }
        response.getResponseMetaData().success();

      } catch (IllegalMoveException
          | InvalidGameSessionException
          | PlayerNotRegisteredException e) {
        response.getResponseMetaData().failure(HttpStatus.BAD_REQUEST.value(), e.getMessage());
      } catch (ColumnFilledException e) {
        response
            .getResponseMetaData()
            .failure(
                HttpStatus.BAD_REQUEST.value(),
                MessageFormat.format(invalidMoveColumnMsg, boardColumn));
      }
    }
    return response;
  }
 @RequestMapping("/setup")
 public WebServiceResponse setupGame(
     @Valid @RequestBody BoardConfiguration setup, BindingResult result) {
   WebServiceResponse resp = new WebServiceResponse();
   if (!result.hasErrors()) {
     gameService.setupBoard(setup);
     resp.getResponseMetaData().success();
   } else {
     resp.getResponseMetaData()
         .failure(HttpStatus.BAD_REQUEST.value(), result.getFieldError().getDefaultMessage());
   }
   return resp;
 }
  @RequestMapping("/start")
  public WebServiceResponse startGame(
      @RequestParam(required = false, defaultValue = "false", name = "multi_player")
          boolean multiPlayer) {
    WebServiceResponse welcomeResponse = new WebServiceResponse();

    try {
      String[] gameRefs = gameService.createNewGameSession(multiPlayer);
      thisLogger.log(Level.INFO, "Start game request with refs: {0}", Arrays.toString(gameRefs));
      welcomeResponse.getResponseObject().setBoardSession(gameRefs[0]);
      welcomeResponse.getResponseObject().setPlayerRef(gameRefs[1]);
      welcomeResponse.getResponseObject().setChipColor(gameRefs[2]);
      welcomeResponse.getResponseObject().setMessage(newGameMsg);
      welcomeResponse.getResponseMetaData().success();

    } catch (GameNotSetupException ex) {
      welcomeResponse.getResponseMetaData().failure(HttpStatus.FORBIDDEN.value(), ex.getMessage());
    }
    return welcomeResponse;
  }
  @RequestMapping("/join")
  public WebServiceResponse joinGame(
      @RequestParam(required = true, name = "session") String boardSessionId) {
    WebServiceResponse response = new WebServiceResponse();

    thisLogger.log(
        Level.INFO,
        "New join request, ref: {0} with board session id: {1} .",
        new Object[] {boardSessionId});

    try {
      String[] gameRefs = gameService.registerAndJoinGame(boardSessionId);
      response.getResponseObject().setMessage(newJoinMsg);
      response.getResponseObject().setBoardSession(gameRefs[0]);
      response.getResponseObject().setPlayerRef(gameRefs[1]);
      response.getResponseObject().setChipColor(gameRefs[2]);
      response.getResponseMetaData().success();
    } catch (InvalidGameSessionException | MaxPlayerRegisteredException ex) {
      response.getResponseMetaData().failure(HttpStatus.BAD_REQUEST.value(), ex.getMessage());
    }

    return response;
  }