@Test
  public void testHandDouble() {
    PlayingStrategy playingStrategy = new PlayingStrategyFixed(Round.Offer.DOUBLE, MONEY_1, false);
    Game game = new Game(playingStrategy, 1, MONEY_10);
    Deck deck = new MockDeck(Rank.THREE, Rank.TEN, Rank.TEN, Rank.TWO, Rank.EIGHT);
    game.setDeck(deck);
    playGameWrapException(game);
    Round round = game.getLastRound();
    Hand hand = round.getHand(1);
    Hand dealerHand = round.getDealerHand();

    // dealing of cards
    assertEquals(hand, HandTest.toHand(Rank.THREE, Rank.TEN, Rank.TWO));
    assertEquals(dealerHand, HandTest.toHand(Rank.TEN, Rank.EIGHT));

    // calculation of points
    assertEquals(hand.getFinalPoints().intValue(), 15);
    assertEquals(dealerHand.getFinalPoints().intValue(), 18);

    // status changes
    assertEquals(hand.getHandOutcome(), Hand.HandOutcome.LOSS);
    assertEquals(hand.getInsuranceOutcome(), Hand.InsuranceOutcome.NOT_OFFERED);

    // money adjustment
    assertEquals(round.getMoneyStart(), MONEY_10);
    assertEquals(round.getMoneyEnd(), MONEY_8);
    assertEquals(game.getMoneyStart(), MONEY_10);
    assertEquals(game.getMoneyCurrent(), MONEY_8);
  }
  @Test
  public void testInsuranceWinGameLose() {
    PlayingStrategy playingStrategy = new PlayingStrategyFixed(Round.Offer.STAND, MONEY_1, true);
    Game game = new Game(playingStrategy, 1, MONEY_10);
    Deck deck = new MockDeck(Rank.THREE, Rank.TEN, Rank.ACE, Rank.JACK);
    game.setDeck(deck);
    playGameWrapException(game);
    Round round = game.getLastRound();
    Hand hand = round.getHand(1);
    Hand dealerHand = round.getDealerHand();

    // dealing of cards
    assertEquals(hand, HandTest.toHand(Rank.THREE, Rank.TEN));
    assertEquals(dealerHand, HandTest.toHand(Rank.ACE, Rank.JACK));

    // calculation of points
    assertEquals(hand.getFinalPoints().intValue(), 13);
    assertEquals(dealerHand.getFinalPoints().intValue(), 21);

    // status changes
    assertEquals(hand.getHandOutcome(), Hand.HandOutcome.LOSS);
    assertEquals(hand.getInsuranceOutcome(), Hand.InsuranceOutcome.WIN);

    // money adjustment
    assertEquals(round.getMoneyStart(), MONEY_10);
    assertEquals(round.getMoneyEnd(), MONEY_10);
    assertEquals(game.getMoneyStart(), MONEY_10);
    assertEquals(game.getMoneyCurrent(), MONEY_10);
  }
  /**
   * Tests that the game starts and stops properly given the number of rounds requested and money
   * available
   */
  @Test
  public void testNumRounds() {
    // test number of rounds played (1 round)
    PlayingStrategy playingStrategy = new PlayingStrategyFixed(Round.Offer.STAND, MONEY_1, false);
    Game game = new Game(playingStrategy, 1, MONEY_10);
    playGameWrapException(game);
    assertEquals(game.getNumRoundsPlayed(), 1);
    assertEquals(game.getNumRoundsToPlay(), 1);
    assertEquals(game.getPastRounds().size(), 1);
    assertEquals(game.isUserInputNeeded(), false);
    assertEquals(game.isFinished(), true);
    assertNull(game.getCurrentRound());
    Round round = game.getLastRound();
    assertEquals(round.getRoundStatus(), Round.RoundStatus.ROUND_FINISHED);
    assertNull(round.getCurrentHand());
    assertEquals(round.getHands().size(), 1);

    // test number of rounds played (5 rounds)
    playingStrategy = new PlayingStrategyFixed(Round.Offer.STAND, MONEY_1, false);
    game = new Game(playingStrategy, 5, MONEY_10);
    playGameWrapException(game);
    assertEquals(game.getNumRoundsPlayed(), 5);
    assertEquals(game.getNumRoundsToPlay(), 5);
    assertEquals(game.getPastRounds().size(), 5);
    assertEquals(game.isUserInputNeeded(), false);
    assertEquals(game.isFinished(), true);
    assertNull(game.getCurrentRound());
    round = game.getLastRound();
    assertEquals(round.getRoundStatus(), Round.RoundStatus.ROUND_FINISHED);
    assertNull(round.getCurrentHand());
    assertEquals(round.getHands().size(), 1);

    // test number of rounds played (money runs out)
    playingStrategy = new PlayingStrategyFixed(Round.Offer.HIT, MONEY_1, false);
    game = new Game(playingStrategy, 20, MONEY_10);
    game.setDeck(
        new MockDeckFixed(
            Rank.TEN)); // by getting only 10s and hitting each time will definitely lose
    playGameWrapException(game);
    assertEquals(game.getNumRoundsPlayed(), 10);
    assertEquals(game.getNumRoundsToPlay(), 20);
    assertEquals(game.getPastRounds().size(), 10);
    assertEquals(game.isUserInputNeeded(), false);
    assertEquals(game.isFinished(), true);
    assertNull(game.getCurrentRound());
    round = game.getLastRound();
    assertEquals(round.getRoundStatus(), Round.RoundStatus.ROUND_FINISHED);
    assertNull(round.getCurrentHand());
    assertEquals(round.getHands().size(), 1);
  }
  /** Tests that the interactive strategy properly stops and waits for input and then continues */
  @Test
  public void testGameInteractive() {
    // test number of rounds played (1 round)
    PlayingStrategy playingStrategy = new PlayingStrategyInteractive();
    Game game = new Game(playingStrategy, 1, MONEY_10);
    playGameWrapException(game);
    game.setDeck(
        new MockDeckFixed(
            Rank.TEN)); // deterministic deck needed here; with random may sometimes deal an ACE to
    // dealer, which will cause insurance offer to be made
    assertEquals(game.isFinished(), false);
    assertEquals(game.isUserInputNeeded(), true);
    Round round = game.getCurrentRound();
    assertEquals(Round.RoundStatus.HAND_BEING_DEALT, round.getRoundStatus());

    playingStrategy.setAmountBet(MONEY_1);
    playGameWrapException(game);

    assertEquals(game.isFinished(), false);
    assertEquals(game.isUserInputNeeded(), true);
    round = game.getCurrentRound();
    assertEquals(Round.RoundStatus.HANDS_BEING_PLAYED_OUT, round.getRoundStatus());

    playingStrategy.setResponseToOffer(Offer.STAND);
    playGameWrapException(game);

    assertEquals(game.isFinished(), true);
    assertEquals(game.isUserInputNeeded(), false);
    assertNull(game.getCurrentRound());
    round = game.getLastRound();
    assertEquals(round.getRoundStatus(), Round.RoundStatus.ROUND_FINISHED);
    assertNull(round.getCurrentHand());
    assertEquals(round.getHands().size(), 1);
    assertEquals(game.getNumRoundsPlayed(), 1);
    assertEquals(game.getNumRoundsToPlay(), 1);
    assertEquals(game.getPastRounds().size(), 1);
  }
  @Test
  public void testHandSplit() {
    PlayingStrategy playingStrategy = new PlayingStrategyInteractive();
    Game game = new Game(playingStrategy, 1, MONEY_10);
    Deck deck = new MockDeck(Rank.THREE, Rank.THREE, Rank.TEN, Rank.TWO, Rank.EIGHT, Rank.SEVEN);
    game.setDeck(deck);

    playGameWrapException(game);
    playingStrategy.setAmountBet(MONEY_1);
    playGameWrapException(game);
    playingStrategy.setResponseToOffer(Offer.SPLIT);
    playGameWrapException(game);
    playingStrategy.setResponseToOffer(Offer.STAND);
    playGameWrapException(game);
    playingStrategy.setResponseToOffer(Offer.STAND);

    Round round = game.getLastRound();
    Hand hand1 = round.getHand(1);
    Hand hand2 = round.getHand(2);
    Hand dealerHand = round.getDealerHand();

    // dealing of cards
    assertEquals(hand1, HandTest.toHand(Rank.THREE, Rank.TWO));
    assertEquals(hand2, HandTest.toHand(Rank.THREE, Rank.EIGHT));
    assertEquals(dealerHand, HandTest.toHand(Rank.TEN, Rank.SEVEN));

    // status changes
    assertEquals(hand1.getHandOutcome(), Hand.HandOutcome.LOSS);
    assertEquals(hand2.getHandOutcome(), Hand.HandOutcome.LOSS);

    // money adjustment
    assertEquals(round.getMoneyStart(), MONEY_10);
    assertEquals(round.getMoneyEnd(), MONEY_8);
    assertEquals(game.getMoneyStart(), MONEY_10);
    assertEquals(game.getMoneyCurrent(), MONEY_8);
  }