@Test
  public void testPlayersGetNewStatus() throws com.yazino.game.api.GameException {
    whenGameStart();
    command = commandFrom(PLAYER1_ID);
    com.yazino.game.api.GamePlayer p1 =
        new com.yazino.game.api.GamePlayer(PLAYER1_ID, SESSION_ID, "");
    com.yazino.game.api.GamePlayer p2 =
        new com.yazino.game.api.GamePlayer(PLAYER2_ID, SESSION_ID, "");
    table.setCurrentGame(gameStatus1);
    whenPlayers(p1, p2);
    when(gameRules.getObservableStatus(gameStatus1, getContextFor(p1, false, table.getIncrement())))
        .thenReturn(new PrintlnStatus());
    when(gameRules.getObservableStatus(gameStatus1, getContextFor(p2, true, table.getIncrement())))
        .thenReturn(new PrintlnStatus());
    final com.yazino.game.api.ExecutionResult result =
        new com.yazino.game.api.ExecutionResult.Builder(gameRules, gameStatus1)
            .scheduledEvents(emptyEvents)
            .build();
    when(gameRules.execute(
            isA(com.yazino.game.api.ExecutionContext.class), eq(command.toCommand(PLAYER_NAME))))
        .thenReturn(result);
    final List<HostDocument> hostDocuments = executeCommand();

    // table.lastGameChanges?
    assertThat(hostDocuments.size(), is(equalTo(2)));
    assertThat(
        (GameStatusHostDocument) hostDocuments.get(0), Matchers.isA(GameStatusHostDocument.class));
    assertThat(
        (GameStatusHostDocument) hostDocuments.get(1), Matchers.isA(GameStatusHostDocument.class));
  }
 @Test
 public void testProcessTransactionResultCorrectlyCallsAuditOnSuccessWithNonNullExecutionResult()
     throws com.yazino.game.api.GameException {
   final String auditLabel = "test424243542354";
   gameStatus = mock(com.yazino.game.api.GameStatus.class);
   when(gameRules.canBeClosed(gameStatus)).thenReturn(false);
   when(gameRules.isComplete(gameStatus)).thenReturn(false);
   whenPlayers();
   when(gameRules.getPlayerInformation(gameStatus))
       .thenReturn(Collections.<com.yazino.game.api.PlayerAtTableInformation>emptyList());
   when(gameRules.getNumberOfSeatsTaken(gameStatus)).thenReturn(0);
   table.setCurrentGame(gameStatus);
   table.setGameId(GAME_ID);
   final com.yazino.game.api.TransactionResult txResult =
       new com.yazino.game.api.TransactionResult("foo", true, null, null, null, null);
   final com.yazino.game.api.ExecutionResult executionResult =
       new com.yazino.game.api.ExecutionResult.Builder(gameRules, gameStatus).build();
   when(gameRules.processTransactionResult(
           isA(com.yazino.game.api.ExecutionContext.class), eq(txResult)))
       .thenReturn(executionResult);
   auditor = mock(Auditor.class);
   when(auditor.newLabel()).thenReturn(auditLabel);
   host = gameHost(new InMemoryGameRepository(gameRules));
   host.processTransactionResult(table, GAME_ID, txResult);
 }
 @Test
 public void statsDontGetPublishedToActivePlayersIfGameNotOver()
     throws com.yazino.game.api.GameException {
   whenGameStart();
   com.yazino.game.api.GamePlayer p1 =
       new com.yazino.game.api.GamePlayer(PLAYER1_ID, SESSION_ID, "");
   com.yazino.game.api.GamePlayer p2 =
       new com.yazino.game.api.GamePlayer(PLAYER2_ID, SESSION_ID, "");
   whenPlayers(p1, p2);
   when(gameRules.getObservableStatus(gameStatus1, getContextFor(p1)))
       .thenReturn(new PrintlnStatus());
   when(gameRules.getObservableStatus(gameStatus1, getContextFor(p2)))
       .thenReturn(new PrintlnStatus());
   when(gameRules.isComplete(gameStatus1)).thenReturn(false);
   final com.yazino.game.api.ExecutionResult result =
       new com.yazino.game.api.ExecutionResult.Builder(gameRules, gameStatus1)
           .scheduledEvents(emptyEvents)
           .build();
   when(gameRules.execute(
           isA(com.yazino.game.api.ExecutionContext.class), eq(command.toCommand(PLAYER_NAME))))
       .thenReturn(result);
   executeCommand();
   verify(locationService, times(2))
       .notify(
           any(BigDecimal.class),
           any(BigDecimal.class),
           any(LocationChangeType.class),
           any(Location.class));
   verifyNoMoreInteractions(locationService);
 }
  private void addPlayersToGame(
      com.yazino.game.api.GameStatus gameStatus, com.yazino.game.api.GamePlayer... players) {
    Collection<com.yazino.game.api.PlayerAtTableInformation> playerAtTableInformationCollection =
        new ArrayList<>();
    for (com.yazino.game.api.GamePlayer player : players) {
      playerAtTableInformationCollection.add(
          new com.yazino.game.api.PlayerAtTableInformation(
              player, Collections.<String, String>emptyMap()));
      if (table.playerAtTable(player.getId()) == null) {
        if (player.getId().equals(PLAYER_ID)) {
          table.addPlayerToTable(
              new PlayerInformation(
                  PLAYER_ID, PLAYER_NAME, PLAYER_ACCOUNT_ID, BigDecimal.TEN, BigDecimal.ZERO));
        } else if (player.getId().equals(PLAYER1_ID)) {
          table.addPlayerToTable(
              new PlayerInformation(
                  PLAYER1_ID, "player1", PLAYER1_ACCOUNT_ID, BigDecimal.TEN, BigDecimal.ZERO));
        } else if (player.getId().equals(PLAYER2_ID)) {
          table.addPlayerToTable(
              new PlayerInformation(
                  PLAYER2_ID, "player2", PLAYER2_ACCOUNT_ID, BigDecimal.TEN, BigDecimal.ZERO));
        } else {
          table.addPlayerToTable(
              new PlayerInformation(
                  player.getId(),
                  player.getName(),
                  player.getId(),
                  BigDecimal.TEN,
                  BigDecimal.ZERO));
        }
      }
    }

    when(gameRules.getPlayerInformation(gameStatus)).thenReturn(playerAtTableInformationCollection);
  }
 private void whenGameStart() {
   com.yazino.game.api.GameStatus newStatus =
       new com.yazino.game.api.GameStatus(new HashMap<String, Object>());
   final com.yazino.game.api.ExecutionResult r =
       new com.yazino.game.api.ExecutionResult.Builder(gameRules, newStatus).build();
   when(gameRules.startNewGame(isA(com.yazino.game.api.GameCreationContext.class))).thenReturn(r);
 }
 @Test
 public void forceNewGameWillRestartTableAndStartNewGame() {
   Map<BigDecimal, BigDecimal> playerIdToAccountIdOverrides = new HashMap<>();
   playerIdToAccountIdOverrides.put(PLAYER_ID, BigDecimal.valueOf(202020));
   com.yazino.game.api.GameStatus status = new GameStatus(new PrintlnStatus());
   com.yazino.game.api.ExecutionResult result =
       new com.yazino.game.api.ExecutionResult.Builder(gameRules, status).build();
   when(gameRules.startNewGame(isA(com.yazino.game.api.GameCreationContext.class)))
       .thenReturn(result);
   when(auditor.newLabel()).thenReturn("X");
   host = gameHost(new InMemoryGameRepository(gameRules));
   table.setTableStatus(TableStatus.closed);
   table.setCurrentGame(null);
   Collection<com.yazino.game.api.PlayerAtTableInformation> playersAtTable =
       Arrays.asList(
           new com.yazino.game.api.PlayerAtTableInformation(
               new com.yazino.game.api.GamePlayer(PLAYER1_ID, null, "One"),
               Collections.<String, String>emptyMap()),
           new com.yazino.game.api.PlayerAtTableInformation(
               new com.yazino.game.api.GamePlayer(PLAYER2_ID, null, "Two"),
               Collections.<String, String>emptyMap()));
   host.forceNewGame(table, playersAtTable, playerIdToAccountIdOverrides);
   ArgumentCaptor<com.yazino.game.api.GameCreationContext> contextCaptor =
       ArgumentCaptor.forClass(com.yazino.game.api.GameCreationContext.class);
   verify(gameRules).startNewGame(contextCaptor.capture());
   assertEquals(TableStatus.open, table.getTableStatus());
   assertEquals(status, table.getCurrentGame());
   assertEquals(playersAtTable, contextCaptor.getValue().getPlayersAtTableInformation());
 }
 @Test
 public void testObserversGetNotified() throws com.yazino.game.api.GameException {
   whenGameStart();
   final com.yazino.game.api.ExecutionResult executionResult =
       new com.yazino.game.api.ExecutionResult.Builder(
               new PrintlnRules(), new GameStatus(new PrintlnStatus()))
           .scheduledEvents(emptyEvents)
           .build();
   when(gameRules.getObservableStatus(gameStatus1, getContextFor(null)))
       .thenReturn(new PrintlnStatus());
   when(gameRules.execute(
           isA(com.yazino.game.api.ExecutionContext.class), eq(command.toCommand(PLAYER_NAME))))
       .thenReturn(executionResult);
   final List<HostDocument> hostDocuments = executeCommand();
   assertThat(
       (GameStatusHostDocument) hostDocuments.get(0), Matchers.isA(GameStatusHostDocument.class));
   assertThat(
       (GameStatusHostDocument) hostDocuments.get(1), Matchers.isA(GameStatusHostDocument.class));
 }
 @SuppressWarnings({"ThrowableInstanceNeverThrown"})
 @Test
 public void senderGetsErrorMessageWhenExceptionThrownInGameHost()
     throws com.yazino.game.api.GameException {
   whenGameStart();
   com.yazino.game.api.ParameterisedMessage pm =
       new com.yazino.game.api.ParameterisedMessage("UPS!");
   when(gameRules.execute(
           isA(com.yazino.game.api.ExecutionContext.class), eq(command.toCommand(PLAYER_NAME))))
       .thenThrow(new com.yazino.game.api.GameException(pm));
   final List<HostDocument> hostDocuments = executeCommand();
   assertThat((ErrorHostDocument) hostDocuments.get(1), Matchers.isA(ErrorHostDocument.class));
 }
 @SuppressWarnings({"ThrowableResultOfMethodCallIgnored", "ThrowableInstanceNeverThrown"})
 @Test
 public void testProcessTransactionResultCorrectlyCallsAuditOnFailure()
     throws com.yazino.game.api.GameException {
   final String auditLabel = "test42454254345345";
   gameStatus = mock(com.yazino.game.api.GameStatus.class);
   when(gameRules.isComplete(gameStatus)).thenReturn(false);
   table.setCurrentGame(gameStatus);
   table.setGameId(GAME_ID);
   final com.yazino.game.api.TransactionResult txResult =
       new com.yazino.game.api.TransactionResult("foo", true, null, null, null, null);
   final com.yazino.game.api.GameException thrownException =
       new com.yazino.game.api.GameException(
           new com.yazino.game.api.ParameterisedMessage("test.mock.error"));
   when(gameRules.processTransactionResult(
           isA(com.yazino.game.api.ExecutionContext.class), eq(txResult)))
       .thenThrow(thrownException);
   auditor = mock(Auditor.class);
   when(auditor.newLabel()).thenReturn(auditLabel);
   host = gameHost(new InMemoryGameRepository(gameRules));
   host.processTransactionResult(table, GAME_ID, txResult);
   verify(auditor, times(1)).newLabel();
 }
 @Test
 public void testProcessTransactionResultCorrectlyCallsAuditOnSuccessWithNullExecutionResult() {
   final String auditLabel = "test424542542354";
   gameStatus = mock(com.yazino.game.api.GameStatus.class);
   when(gameRules.isComplete(gameStatus)).thenReturn(false);
   table.setCurrentGame(gameStatus);
   table.setGameId(GAME_ID);
   final com.yazino.game.api.TransactionResult txResult =
       new com.yazino.game.api.TransactionResult("foo", true, null, null, null, null);
   auditor = mock(Auditor.class);
   when(auditor.newLabel()).thenReturn(auditLabel);
   host = gameHost(new InMemoryGameRepository(gameRules));
   host.processTransactionResult(table, GAME_ID, txResult);
 }
 @Test
 public void testProcessTransactionResultIsNotProcessedForCompleteGame() {
   final GameRepository mockGameRepository = mock(GameRepository.class);
   when(mockGameRepository.getGameRules(GAME_TYPE)).thenReturn(gameRules);
   gameStatus = mock(com.yazino.game.api.GameStatus.class);
   when(gameRules.isComplete(gameStatus)).thenReturn(true);
   table.setCurrentGame(gameStatus);
   table.setGameId(GAME_ID);
   final com.yazino.game.api.TransactionResult txResult =
       new com.yazino.game.api.TransactionResult("foo", true, null, null, null, null);
   host = gameHost(mockGameRepository);
   host.processTransactionResult(table, GAME_ID, txResult);
   verifyNoMoreInteractions(documentDispatcher);
 }
 @Test
 public void testProcessTransactionResultIsOnlyExecutedForTheCurrentGame() {
   final GameRepository mockGameRepository = mock(GameRepository.class);
   when(mockGameRepository.getGameRules(GAME_TYPE)).thenReturn(gameRules);
   final long differentGameId = GAME_ID + 6;
   gameStatus = mock(com.yazino.game.api.GameStatus.class);
   when(gameRules.isComplete(gameStatus)).thenReturn(false);
   table.setCurrentGame(gameStatus);
   table.setGameId(GAME_ID);
   final com.yazino.game.api.TransactionResult txResult =
       new com.yazino.game.api.TransactionResult("foo", true, null, null, null, null);
   host = gameHost(mockGameRepository);
   host.processTransactionResult(table, differentGameId, txResult);
   verifyNoMoreInteractions(locationService);
 }
  @Test
  public void shouldntRunPostProcessorsWhenDisabledAndNextGameCreated() {
    Table table = tableWithPhase(GameFinished, 6L);
    when(wallet.getTable()).thenReturn(table);
    GameInitialiser.GameInitialisationContext context = defaultEventContext();
    context.setAllowedToMoveToNextGame(true);
    context.setRunPostProcessors(false);
    when(gameRules.isComplete(table.getCurrentGame())).thenReturn(true);
    underTest.setPostInitialisationProcessors(toList(postprocessor));

    underTest.initialiseGame(context);

    assertEquals(Long.valueOf(7), table.getGameId());
    verifyZeroInteractions(postprocessor);
  }
 @Test
 public void commandsAndStatusChangesGetAudited() throws com.yazino.game.api.GameException {
   whenGameStart();
   whenPlayers();
   final com.yazino.game.api.ExecutionResult result =
       new com.yazino.game.api.ExecutionResult.Builder(gameRules, gameStatus1)
           .scheduledEvents(emptyEvents)
           .build();
   when(gameRules.execute(
           isA(com.yazino.game.api.ExecutionContext.class),
           isA(com.yazino.game.api.Command.class)))
       .thenReturn(result);
   executeCommand();
   verify(auditor).audit(eq(AUDIT_LABEL), eq(command.toCommand(PLAYER_NAME)));
 }
 @Test
 public void shutdownReturnsInvestedAmountsOnlyOnceForPlayer() throws WalletServiceException {
   com.yazino.game.api.GamePlayer player1 =
       new com.yazino.game.api.GamePlayer(BigDecimal.valueOf(1), null, "p1");
   com.yazino.game.api.PlayerAtTableInformation p1 =
       new com.yazino.game.api.PlayerAtTableInformation(
           player1, BigDecimal.valueOf(10), Collections.<String, String>emptyMap());
   PlayerInformation pi1 =
       new PlayerInformation(
           player1.getId(),
           player1.getName(),
           BigDecimal.valueOf(501),
           BigDecimal.TEN,
           BigDecimal.valueOf(0));
   com.yazino.game.api.PlayerAtTableInformation p2 =
       new com.yazino.game.api.PlayerAtTableInformation(
           player1, BigDecimal.valueOf(15), Collections.<String, String>emptyMap());
   PlayerInformation pi2 =
       new PlayerInformation(
           player1.getId(),
           player1.getName(),
           BigDecimal.valueOf(501),
           BigDecimal.TEN,
           BigDecimal.valueOf(0));
   table.addPlayerToTable(pi1);
   table.addPlayerToTable(pi2);
   Collection<com.yazino.game.api.PlayerAtTableInformation> players = Arrays.asList(p1, p2);
   when(gameRules.getPlayerInformation(gameStatus)).thenReturn(players);
   table.setCurrentGame(gameStatus);
   List<HostDocument> documents = gameHost(gameRules).shutdown(table);
   assertEquals(1, documents.size());
   verify(bufferedGameHostWallet)
       .post(
           table.getTableId(),
           table.getGameId(),
           pi1,
           BigDecimal.valueOf(25),
           com.yazino.game.api.TransactionType.Return,
           AUDIT_LABEL,
           "Shutdown refund",
           NEW_UUID);
   verify(bufferedGameHostWallet).flush();
   verifyNoMoreInteractions(bufferedGameHostWallet);
 }
 @Test
 public void executeAcknowledgement() {
   table.playerAcknowledgesIncrement(A_PLAYER.getId(), 1L);
   table.setIncrement(10L);
   table.setCurrentGame(gameStatus);
   when(gameRules.isAPlayer(gameStatus, A_PLAYER)).thenReturn(true);
   addPlayersToGame(gameStatus, A_PLAYER);
   command =
       new CommandWrapper(
           table.getTableId(),
           table.getGameId(),
           A_PLAYER.getId(),
           SESSION_ID,
           com.yazino.game.api.Command.CommandType.Ack.getCode(),
           "9");
   command.setRequestId(UUID);
   executeCommand();
   assertEquals(9L, table.playerAtTable(A_PLAYER.getId()).getAcknowledgedIncrement());
 }
  @Test
  public void shouldIncrementGameIdWhenCreatedNextGameAndNotifyPostProcessors() {
    Table table = tableWithPhase(GameFinished, 6L);
    when(wallet.getTable()).thenReturn(table);
    GameInitialiser.GameInitialisationContext context = defaultEventContext();
    context.setAllowedToMoveToNextGame(true);
    when(gameRules.isComplete(table.getCurrentGame())).thenReturn(true);
    underTest.setPostInitialisationProcessors(toList(postprocessor));

    underTest.initialiseGame(context);

    assertEquals(Long.valueOf(7), table.getGameId());
    verify(postprocessor)
        .postProcess(
            any(com.yazino.game.api.ExecutionResult.class),
            any(com.yazino.game.api.Command.class),
            eq(table),
            anyString(),
            anyList(),
            eq(context.getPlayerId()));
  }
 @Test
 public void testTableGetsNewEvents() throws com.yazino.game.api.GameException {
   whenGameStart();
   whenPlayers();
   List<com.yazino.game.api.ScheduledEvent> events =
       Arrays.asList(
           new com.yazino.game.api.ScheduledEvent(
               100l, 100l, "X", "Y", new HashMap<String, String>(), false),
           new com.yazino.game.api.ScheduledEvent(
               300l, 100l, "Z", "Y", new HashMap<String, String>(), false),
           new com.yazino.game.api.ScheduledEvent(
               200l, 100l, "X", "Z", new HashMap<String, String>(), false));
   final com.yazino.game.api.ExecutionResult result =
       new com.yazino.game.api.ExecutionResult.Builder(gameRules, gameStatus1)
           .scheduledEvents(events)
           .build();
   when(gameRules.execute(
           (com.yazino.game.api.ExecutionContext) anyObject(), eq(command.toCommand(PLAYER_NAME))))
       .thenReturn(result);
   executeCommand();
   assertEquals(3, table.scheduledEventCount());
 }
 @Test
 public void shutdownIgnoresNullInvestedAmounts() {
   com.yazino.game.api.PlayerAtTableInformation p1 =
       new com.yazino.game.api.PlayerAtTableInformation(
           new com.yazino.game.api.GamePlayer(BigDecimal.valueOf(1), SESSION_ID, "p1"),
           null,
           Collections.<String, String>emptyMap());
   PlayerInformation pi1 =
       new PlayerInformation(
           BigDecimal.valueOf(1),
           "p1",
           BigDecimal.valueOf(501),
           BigDecimal.TEN,
           BigDecimal.valueOf(0));
   table.addPlayerToTable(pi1);
   Collection<com.yazino.game.api.PlayerAtTableInformation> players = Arrays.asList(p1);
   when(gameRules.getPlayerInformation(gameStatus)).thenReturn(players);
   table.setCurrentGame(gameStatus);
   List<HostDocument> documents = gameHost(gameRules).shutdown(table);
   assertEquals(1, documents.size());
   verify(bufferedGameHostWallet).flush();
   verifyNoMoreInteractions(bufferedGameHostWallet);
 }
  @Before
  public void setUp() throws com.yazino.game.api.GameException, WalletServiceException {
    MockitoAnnotations.initMocks(this);

    timeSource = new SettableTimeSource(System.currentTimeMillis());

    command = new CommandWrapper(TABLE_ID, GAME_ID, A_PLAYER.getId(), SESSION_ID, "T");
    command.setRequestId(UUID);
    playerStatisticEventsPublisher = new InMemoryPlayerStatisticEventsPublisher();

    table =
        new Table(
            new com.yazino.game.api.GameType(GAME_TYPE, "Test", Collections.<String>emptySet()),
            BigDecimal.ONE,
            "test",
            true);
    table.setTableId(TABLE_ID);
    table.setTableStatus(TableStatus.open);
    table.setVariationProperties(new HashMap<String, String>());

    when(bufferedGameHostWalletFactory.create(table.getTableId(), command.getRequestId()))
        .thenReturn(bufferedGameHostWallet);
    when(bufferedGameHostWalletFactory.create(table.getTableId()))
        .thenReturn(bufferedGameHostWallet);

    when(auditor.newLabel()).thenReturn(AUDIT_LABEL);
    when(bufferedGameHostWallet.getBalance(Mockito.isA(BigDecimal.class)))
        .thenReturn(BigDecimal.ZERO);

    when(uuidSource.getNewUUID()).thenReturn(NEW_UUID);
    when(auditor.newLabel()).thenReturn(AUDIT_LABEL);
    when(bufferedGameHostWallet.getBalance(Mockito.isA(BigDecimal.class)))
        .thenReturn(ACCOUNT_BALANCE);

    when(gameRules.getGameType()).thenReturn("TEST");

    when(playerRepository.findSummaryByPlayerAndSession(PLAYER_ID, SESSION_ID))
        .thenReturn(
            aPlayerSessionSummary(PLAYER_ID, "Player", PLAYER_ACCOUNT_ID, BigDecimal.valueOf(100)));
    when(playerRepository.findSummaryByPlayerAndSession(PLAYER_ID, null))
        .thenReturn(
            aPlayerSessionSummary(PLAYER_ID, "Player", PLAYER_ACCOUNT_ID, BigDecimal.valueOf(100)));
    when(playerRepository.findSummaryByPlayerAndSession(PLAYER1_ID, null))
        .thenReturn(
            aPlayerSessionSummary(
                PLAYER1_ID, "Player1", PLAYER1_ACCOUNT_ID, BigDecimal.valueOf(200)));
    when(playerRepository.findSummaryByPlayerAndSession(PLAYER2_ID, null))
        .thenReturn(
            aPlayerSessionSummary(
                PLAYER2_ID, "Player2", PLAYER2_ACCOUNT_ID, BigDecimal.valueOf(300)));

    when(chatRepository.getOrCreateForLocation(TABLE_ID.toPlainString()))
        .thenReturn(new ChatChannel(TABLE_ID.toPlainString()));
  }