package com.flexpoker.table.command.service;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import org.springframework.stereotype.Service;
import com.flexpoker.model.HandRanking;
import com.flexpoker.model.card.Card;
import com.flexpoker.model.card.CardRank;
import com.flexpoker.model.card.CardSuit;
import com.flexpoker.model.card.FlopCards;
import com.flexpoker.model.card.PocketCards;
import com.flexpoker.model.card.RiverCard;
import com.flexpoker.model.card.TurnCard;
import com.flexpoker.table.command.aggregate.CommonCards;
import com.flexpoker.table.command.aggregate.HandEvaluation;
@Service
public class DefaultHandEvaluatorService implements HandEvaluatorService {
@Override
public List<HandRanking> determinePossibleHands(FlopCards flopCards,
TurnCard turnCard, RiverCard riverCard) {
CommonCards commonCards = new CommonCards(flopCards, turnCard, riverCard);
List<HandRanking> possibleHandRankings = new ArrayList<>(
Arrays.asList(HandRanking.values()));
filterByStraightFlushStatus(commonCards, possibleHandRankings);
filterByFourOfAKindStatus(commonCards, possibleHandRankings);
filterByFullHouseStatus(commonCards, possibleHandRankings);
filterByFlushStatus(commonCards, possibleHandRankings);
filterByStraightStatus(commonCards, possibleHandRankings);
filterByThreeOfAKindStatus(commonCards, possibleHandRankings);
filterByTwoPairStatus(commonCards, possibleHandRankings);
filterByOnePairStatus(commonCards, possibleHandRankings);
return possibleHandRankings;
}
@Override
public Map<PocketCards, HandEvaluation> determineHandEvaluation(FlopCards flopCards,
TurnCard turnCard, RiverCard riverCard, List<PocketCards> pocketCardsList,
List<HandRanking> possibleHandRankings) {
CommonCards commonCards = new CommonCards(flopCards, turnCard, riverCard);
Map<PocketCards, HandEvaluation> handEvaluations = new HashMap<>();
Consumer<PocketCards> evaluatePocketCardsConsumer = (PocketCards pocketCards) -> {
HandEvaluation handEvaluation = new HandEvaluation();
List<Card> cardList = new ArrayList<>(commonCards.getCards());
cardList.add(pocketCards.getCard1());
cardList.add(pocketCards.getCard2());
fillInHandEvaluation(handEvaluation, cardList, possibleHandRankings);
handEvaluations.put(pocketCards, handEvaluation);
};
pocketCardsList.forEach(evaluatePocketCardsConsumer);
return handEvaluations;
}
/**
* Enum meant to be used as a return value for the hand ranking methods. The
* returned value is then used to decide what hand rankings are available.
*/
private enum CommonCardStatus {
NOT_POSSIBLE, POSSIBLE, BOARD;
}
private void fillInHandEvaluation(HandEvaluation handEvaluation, List<Card> cardList,
List<HandRanking> possibleHandRankings) {
Collections.sort(possibleHandRankings);
Collections.reverse(possibleHandRankings);
for (HandRanking handRanking : possibleHandRankings) {
switch (handRanking) {
case STRAIGHT_FLUSH:
if (evaluateStraightFlush(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.STRAIGHT_FLUSH);
return;
}
break;
case FOUR_OF_A_KIND:
if (evaluateFourOfAKind(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.FOUR_OF_A_KIND);
return;
}
break;
case FULL_HOUSE:
if (evaluateFullHouse(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.FULL_HOUSE);
return;
}
break;
case FLUSH:
if (evaluateFlush(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.FLUSH);
return;
}
break;
case STRAIGHT:
if (evaluateStraight(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.STRAIGHT);
return;
}
break;
case THREE_OF_A_KIND:
if (evaluateThreeOfAKind(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.THREE_OF_A_KIND);
return;
}
break;
case TWO_PAIR:
if (evaluateTwoPair(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.TWO_PAIR);
return;
}
break;
case ONE_PAIR:
if (evaluateOnePair(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.ONE_PAIR);
return;
}
break;
case HIGH_CARD:
if (evaluateHighCard(handEvaluation, cardList)) {
handEvaluation.setHandRanking(HandRanking.HIGH_CARD);
return;
}
break;
default:
throw new IllegalArgumentException("Invalid hand rank: " + handRanking);
}
}
}
private boolean evaluateStraightFlush(HandEvaluation handEvaluation,
List<Card> cardList) {
List<Card> cardsInLargestSuit = findCardsInLargestSuit(cardList);
if (cardsInLargestSuit.size() < 5) {
return false;
}
CardRank cardRank = findCardRankOfHighestStraight(cardsInLargestSuit);
if (cardRank == null) {
return false;
}
handEvaluation.setPrimaryCardRank(cardRank);
return true;
}
private boolean evaluateFourOfAKind(HandEvaluation handEvaluation, List<Card> cardList) {
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
CardRank cardRank6 = cardList.get(5).getCardRank();
CardRank cardRank7 = cardList.get(6).getCardRank();
if (cardRank1 == cardRank4) {
handEvaluation.setPrimaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
if (cardRank2 == cardRank5) {
handEvaluation.setPrimaryCardRank(cardRank2);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
if (cardRank3 == cardRank6) {
handEvaluation.setPrimaryCardRank(cardRank3);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
if (cardRank4 == cardRank7) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setFirstKicker(cardRank3);
return true;
}
return false;
}
private boolean evaluateFullHouse(HandEvaluation handEvaluation, List<Card> cardList) {
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
CardRank cardRank6 = cardList.get(5).getCardRank();
CardRank cardRank7 = cardList.get(6).getCardRank();
if (cardRank5 == cardRank7) {
if (cardRank3 == cardRank4) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setSecondaryCardRank(cardRank3);
return true;
}
if (cardRank2 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setSecondaryCardRank(cardRank2);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setSecondaryCardRank(cardRank1);
return true;
}
}
if (cardRank4 == cardRank6) {
if (cardRank2 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setSecondaryCardRank(cardRank2);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setSecondaryCardRank(cardRank1);
return true;
}
}
if (cardRank3 == cardRank5) {
if (cardRank6 == cardRank7) {
handEvaluation.setPrimaryCardRank(cardRank3);
handEvaluation.setSecondaryCardRank(cardRank6);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank3);
handEvaluation.setSecondaryCardRank(cardRank1);
return true;
}
}
if (cardRank2 == cardRank4) {
if (cardRank6 == cardRank7) {
handEvaluation.setPrimaryCardRank(cardRank2);
handEvaluation.setSecondaryCardRank(cardRank6);
return true;
}
if (cardRank5 == cardRank6) {
handEvaluation.setPrimaryCardRank(cardRank2);
handEvaluation.setSecondaryCardRank(cardRank5);
return true;
}
}
if (cardRank1 == cardRank3) {
if (cardRank6 == cardRank7) {
handEvaluation.setPrimaryCardRank(cardRank1);
handEvaluation.setSecondaryCardRank(cardRank6);
return true;
}
if (cardRank5 == cardRank6) {
handEvaluation.setPrimaryCardRank(cardRank1);
handEvaluation.setSecondaryCardRank(cardRank5);
return true;
}
if (cardRank4 == cardRank5) {
handEvaluation.setPrimaryCardRank(cardRank1);
handEvaluation.setSecondaryCardRank(cardRank4);
return true;
}
}
return false;
}
private boolean evaluateFlush(HandEvaluation handEvaluation, List<Card> cardList) {
List<Card> cards = findCardsInLargestSuit(cardList);
if (cards.size() < 5) {
return false;
}
Collections.sort(cards);
handEvaluation.setPrimaryCardRank(cards.get(cards.size() - 1).getCardRank());
handEvaluation.setFirstKicker(cards.get(cards.size() - 2).getCardRank());
handEvaluation.setSecondKicker(cards.get(cards.size() - 3).getCardRank());
handEvaluation.setThirdKicker(cards.get(cards.size() - 4).getCardRank());
handEvaluation.setFourthKicker(cards.get(cards.size() - 5).getCardRank());
return true;
}
private boolean evaluateStraight(HandEvaluation handEvaluation, List<Card> cardList) {
CardRank cardRank = findCardRankOfHighestStraight(cardList);
if (cardRank == null) {
return false;
}
handEvaluation.setPrimaryCardRank(cardRank);
return true;
}
private boolean evaluateThreeOfAKind(HandEvaluation handEvaluation,
List<Card> cardList) {
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
CardRank cardRank6 = cardList.get(5).getCardRank();
CardRank cardRank7 = cardList.get(6).getCardRank();
if (cardRank5 == cardRank7) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setFirstKicker(cardRank4);
handEvaluation.setSecondKicker(cardRank3);
return true;
}
if (cardRank4 == cardRank6) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank3);
return true;
}
if (cardRank3 == cardRank5) {
handEvaluation.setPrimaryCardRank(cardRank3);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
return true;
}
if (cardRank2 == cardRank4) {
handEvaluation.setPrimaryCardRank(cardRank2);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
return true;
}
if (cardRank1 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
return true;
}
return false;
}
private boolean evaluateTwoPair(HandEvaluation handEvaluation, List<Card> cardList) {
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
CardRank cardRank6 = cardList.get(5).getCardRank();
CardRank cardRank7 = cardList.get(6).getCardRank();
if (cardRank6 == cardRank7) {
if (cardRank4 == cardRank5) {
handEvaluation.setPrimaryCardRank(cardRank6);
handEvaluation.setSecondaryCardRank(cardRank4);
handEvaluation.setFirstKicker(cardRank3);
return true;
}
if (cardRank3 == cardRank4) {
handEvaluation.setPrimaryCardRank(cardRank6);
handEvaluation.setSecondaryCardRank(cardRank3);
handEvaluation.setFirstKicker(cardRank5);
return true;
}
if (cardRank2 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank6);
handEvaluation.setSecondaryCardRank(cardRank2);
handEvaluation.setFirstKicker(cardRank5);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank6);
handEvaluation.setSecondaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank5);
return true;
}
}
if (cardRank5 == cardRank6) {
if (cardRank3 == cardRank4) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setSecondaryCardRank(cardRank3);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
if (cardRank2 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setSecondaryCardRank(cardRank2);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setSecondaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
}
if (cardRank4 == cardRank5) {
if (cardRank2 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setSecondaryCardRank(cardRank2);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setSecondaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
}
if (cardRank3 == cardRank4) {
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setSecondaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank7);
return true;
}
}
return false;
}
private boolean evaluateOnePair(HandEvaluation handEvaluation, List<Card> cardList) {
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
CardRank cardRank6 = cardList.get(5).getCardRank();
CardRank cardRank7 = cardList.get(6).getCardRank();
if (cardRank6 == cardRank7) {
handEvaluation.setPrimaryCardRank(cardRank6);
handEvaluation.setFirstKicker(cardRank5);
handEvaluation.setSecondKicker(cardRank4);
handEvaluation.setThirdKicker(cardRank3);
return true;
}
if (cardRank5 == cardRank6) {
handEvaluation.setPrimaryCardRank(cardRank5);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank4);
handEvaluation.setThirdKicker(cardRank3);
return true;
}
if (cardRank4 == cardRank5) {
handEvaluation.setPrimaryCardRank(cardRank4);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
handEvaluation.setThirdKicker(cardRank3);
return true;
}
if (cardRank3 == cardRank4) {
handEvaluation.setPrimaryCardRank(cardRank3);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
handEvaluation.setThirdKicker(cardRank5);
return true;
}
if (cardRank2 == cardRank3) {
handEvaluation.setPrimaryCardRank(cardRank2);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
handEvaluation.setThirdKicker(cardRank5);
return true;
}
if (cardRank1 == cardRank2) {
handEvaluation.setPrimaryCardRank(cardRank1);
handEvaluation.setFirstKicker(cardRank7);
handEvaluation.setSecondKicker(cardRank6);
handEvaluation.setThirdKicker(cardRank5);
return true;
}
return false;
}
private boolean evaluateHighCard(HandEvaluation handEvaluation, List<Card> cardList) {
Collections.sort(cardList);
handEvaluation.setPrimaryCardRank(cardList.get(6).getCardRank());
handEvaluation.setFirstKicker(cardList.get(5).getCardRank());
handEvaluation.setSecondKicker(cardList.get(4).getCardRank());
handEvaluation.setThirdKicker(cardList.get(3).getCardRank());
handEvaluation.setFourthKicker(cardList.get(2).getCardRank());
return true;
}
private void filterByStraightFlushStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
CommonCardStatus straightFlushStatus = determineStraightFlushStatus(commonCards);
if (straightFlushStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.FOUR_OF_A_KIND);
possibleHandRankings.remove(HandRanking.FULL_HOUSE);
possibleHandRankings.remove(HandRanking.FLUSH);
possibleHandRankings.remove(HandRanking.STRAIGHT);
possibleHandRankings.remove(HandRanking.THREE_OF_A_KIND);
possibleHandRankings.remove(HandRanking.TWO_PAIR);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
} else if (straightFlushStatus == CommonCardStatus.NOT_POSSIBLE) {
possibleHandRankings.remove(HandRanking.STRAIGHT_FLUSH);
}
}
private void filterByFourOfAKindStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.FOUR_OF_A_KIND)) {
CommonCardStatus fourOfAKindStatus = determineFourOfAKindStatus(commonCards);
if (fourOfAKindStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.STRAIGHT_FLUSH);
possibleHandRankings.remove(HandRanking.FULL_HOUSE);
possibleHandRankings.remove(HandRanking.FLUSH);
possibleHandRankings.remove(HandRanking.STRAIGHT);
possibleHandRankings.remove(HandRanking.THREE_OF_A_KIND);
possibleHandRankings.remove(HandRanking.TWO_PAIR);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
} else if (fourOfAKindStatus == CommonCardStatus.NOT_POSSIBLE) {
possibleHandRankings.remove(HandRanking.FOUR_OF_A_KIND);
possibleHandRankings.remove(HandRanking.FULL_HOUSE);
}
}
}
private void filterByFullHouseStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.FULL_HOUSE)) {
CommonCardStatus fullHouseStatus = determineFullHouseStatus(commonCards);
if (fullHouseStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.FLUSH);
possibleHandRankings.remove(HandRanking.STRAIGHT);
possibleHandRankings.remove(HandRanking.THREE_OF_A_KIND);
possibleHandRankings.remove(HandRanking.TWO_PAIR);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
}
}
}
private void filterByFlushStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.FLUSH)) {
CommonCardStatus flushStatus = determineFlushStatus(commonCards);
if (flushStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.STRAIGHT);
possibleHandRankings.remove(HandRanking.THREE_OF_A_KIND);
possibleHandRankings.remove(HandRanking.TWO_PAIR);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
} else if (flushStatus == CommonCardStatus.NOT_POSSIBLE) {
possibleHandRankings.remove(HandRanking.FLUSH);
}
}
}
private void filterByStraightStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.STRAIGHT)) {
CommonCardStatus straightStatus = determineStraightStatus(commonCards);
if (straightStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.THREE_OF_A_KIND);
possibleHandRankings.remove(HandRanking.TWO_PAIR);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
} else if (straightStatus == CommonCardStatus.NOT_POSSIBLE) {
possibleHandRankings.remove(HandRanking.STRAIGHT);
}
}
}
private void filterByThreeOfAKindStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.THREE_OF_A_KIND)) {
CommonCardStatus threeOfAKindStatus = determineThreeOfAKindStatus(commonCards);
if (threeOfAKindStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.TWO_PAIR);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
}
}
}
private void filterByTwoPairStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.TWO_PAIR)) {
CommonCardStatus twoPairStatus = determineTwoPairStatus(commonCards);
if (twoPairStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.THREE_OF_A_KIND);
possibleHandRankings.remove(HandRanking.ONE_PAIR);
possibleHandRankings.remove(HandRanking.HIGH_CARD);
}
}
}
private void filterByOnePairStatus(CommonCards commonCards,
List<HandRanking> possibleHandRankings) {
if (possibleHandRankings.contains(HandRanking.ONE_PAIR)) {
CommonCardStatus onePairStatus = determineOnePairStatus(commonCards);
if (onePairStatus == CommonCardStatus.BOARD) {
possibleHandRankings.remove(HandRanking.HIGH_CARD);
}
}
}
private CommonCardStatus determineStraightFlushStatus(CommonCards commonCards) {
List<Card> cards = findCardsInLargestSuit(commonCards.getCards());
// we have a flush, check to see if it's a straight also
if (cards.size() == 5 && isStraight(commonCards)) {
return CommonCardStatus.BOARD;
}
if (cards.size() < 3) {
return CommonCardStatus.NOT_POSSIBLE;
}
if (isStraightPossible(cards)) {
return CommonCardStatus.POSSIBLE;
}
return CommonCardStatus.NOT_POSSIBLE;
}
private CommonCardStatus determineFourOfAKindStatus(CommonCards commonCards) {
List<Card> cardList = commonCards.getCards();
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
if ((cardRank1 == cardRank2 && cardRank2 == cardRank3 && cardRank3 == cardRank4)
|| (cardRank2 == cardRank3 && cardRank3 == cardRank4 && cardRank4 == cardRank5)) {
return CommonCardStatus.BOARD;
}
if (cardRank1 == cardRank2 || cardRank2 == cardRank3 || cardRank3 == cardRank4
|| cardRank4 == cardRank5) {
return CommonCardStatus.POSSIBLE;
}
return CommonCardStatus.NOT_POSSIBLE;
}
private CommonCardStatus determineFullHouseStatus(CommonCards commonCards) {
List<Card> cardList = commonCards.getCards();
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
if ((cardRank1 == cardRank2 && cardRank2 == cardRank3 && cardRank4 == cardRank5)
|| (cardRank1 == cardRank2 && cardRank3 == cardRank4 && cardRank4 == cardRank5)) {
return CommonCardStatus.BOARD;
}
if (cardRank1 == cardRank2 || cardRank2 == cardRank3 || cardRank3 == cardRank4
|| cardRank4 == cardRank5) {
return CommonCardStatus.POSSIBLE;
}
return CommonCardStatus.NOT_POSSIBLE;
}
private CommonCardStatus determineFlushStatus(CommonCards commonCards) {
List<Card> cards = findCardsInLargestSuit(commonCards.getCards());
switch (cards.size()) {
case 5:
return CommonCardStatus.BOARD;
case 4:
return CommonCardStatus.POSSIBLE;
case 3:
return CommonCardStatus.POSSIBLE;
default:
return CommonCardStatus.NOT_POSSIBLE;
}
}
private CommonCardStatus determineStraightStatus(CommonCards commonCards) {
if (isStraight(commonCards)) {
return CommonCardStatus.BOARD;
}
if (isStraightPossible(commonCards.getCards())) {
return CommonCardStatus.POSSIBLE;
}
return CommonCardStatus.NOT_POSSIBLE;
}
private CommonCardStatus determineThreeOfAKindStatus(CommonCards commonCards) {
List<Card> cardList = commonCards.getCards();
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
if ((cardRank1 == cardRank2 && cardRank2 == cardRank3)
|| (cardRank2 == cardRank3 && cardRank3 == cardRank4)
|| (cardRank3 == cardRank4 && cardRank4 == cardRank5)) {
return CommonCardStatus.BOARD;
}
return CommonCardStatus.POSSIBLE;
}
private CommonCardStatus determineTwoPairStatus(CommonCards commonCards) {
List<Card> cardList = commonCards.getCards();
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
if ((cardRank1 == cardRank2 && cardRank3 == cardRank4)
|| (cardRank1 == cardRank2 && cardRank4 == cardRank5)
|| (cardRank2 == cardRank3 && cardRank4 == cardRank5)) {
return CommonCardStatus.BOARD;
}
return CommonCardStatus.POSSIBLE;
}
private CommonCardStatus determineOnePairStatus(CommonCards commonCards) {
List<Card> cardList = commonCards.getCards();
Collections.sort(cardList);
CardRank cardRank1 = cardList.get(0).getCardRank();
CardRank cardRank2 = cardList.get(1).getCardRank();
CardRank cardRank3 = cardList.get(2).getCardRank();
CardRank cardRank4 = cardList.get(3).getCardRank();
CardRank cardRank5 = cardList.get(4).getCardRank();
if (cardRank1 == cardRank2 || cardRank2 == cardRank3 || cardRank3 == cardRank4
|| cardRank4 == cardRank5) {
return CommonCardStatus.BOARD;
}
return CommonCardStatus.POSSIBLE;
}
private boolean isStraight(CommonCards commonCards) {
List<Card> cardList = commonCards.getCards();
Collections.sort(cardList);
int cardRankOrdinal1 = cardList.get(0).getCardRank().ordinal();
int cardRankOrdinal2 = cardList.get(1).getCardRank().ordinal();
int cardRankOrdinal3 = cardList.get(2).getCardRank().ordinal();
int cardRankOrdinal4 = cardList.get(3).getCardRank().ordinal();
int cardRankOrdinal5 = cardList.get(4).getCardRank().ordinal();
if (cardRankOrdinal1 + 1 != cardRankOrdinal2
|| cardRankOrdinal2 + 1 != cardRankOrdinal3
|| cardRankOrdinal3 + 1 != cardRankOrdinal4) {
return false;
}
// check to see if it's a 2, then see if the 5th card is an ace
if (cardRankOrdinal1 == 0 && cardRankOrdinal5 == 12) {
return true;
}
return cardRankOrdinal4 + 1 == cardRankOrdinal5;
}
private boolean isStraightPossible(List<Card> cardList) {
List<CardRank> cardRanks = new ArrayList<>();
for (Card card : cardList) {
cardRanks.add(card.getCardRank());
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.ACE, CardRank.TWO,
CardRank.THREE, CardRank.FOUR, CardRank.FIVE }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.TWO, CardRank.THREE,
CardRank.FOUR, CardRank.FIVE, CardRank.SIX }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.THREE, CardRank.FOUR,
CardRank.FIVE, CardRank.SIX, CardRank.SEVEN }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.FOUR, CardRank.FIVE,
CardRank.SIX, CardRank.SEVEN, CardRank.EIGHT }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.FIVE, CardRank.SIX,
CardRank.SEVEN, CardRank.EIGHT, CardRank.NINE }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.SIX, CardRank.SEVEN,
CardRank.EIGHT, CardRank.NINE, CardRank.TEN }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.SEVEN, CardRank.EIGHT,
CardRank.NINE, CardRank.TEN, CardRank.JACK }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.EIGHT, CardRank.NINE,
CardRank.TEN, CardRank.JACK, CardRank.QUEEN }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.NINE, CardRank.TEN,
CardRank.JACK, CardRank.QUEEN, CardRank.KING }), 3)) {
return true;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.TEN, CardRank.JACK,
CardRank.QUEEN, CardRank.KING, CardRank.ACE }), 3)) {
return true;
}
return false;
}
private boolean doCardRanksMatch(List<CardRank> cardRanks,
List<CardRank> straightCardRanks, int numberToMatch) {
Set<CardRank> cardRankSet = new HashSet<>(cardRanks);
int numberOfMatched = 0;
for (CardRank cardRank : cardRankSet) {
if (straightCardRanks.contains(cardRank)) {
numberOfMatched++;
}
}
return numberOfMatched >= numberToMatch;
}
/**
* Return the list of cards in the largest suit. If that number is three,
* then the correct suit will be represented. If that number is only two,
* then the first suit scanned will be returned in the following order:
* HEARTS, CLUBS, DIAMONDS, SPADES
*/
private List<Card> findCardsInLargestSuit(List<Card> cards) {
Map<CardSuit, List<Card>> suitMap = new HashMap<>();
for (Card card : cards) {
CardSuit cardSuit = card.getCardSuit();
if (suitMap.get(cardSuit) == null) {
suitMap.put(cardSuit, new ArrayList<Card>());
}
suitMap.get(cardSuit).add(card);
}
int numberOfHearts = suitMap.get(CardSuit.HEARTS) == null ? 0 : suitMap.get(
CardSuit.HEARTS).size();
int numberOfClubs = suitMap.get(CardSuit.CLUBS) == null ? 0 : suitMap.get(
CardSuit.CLUBS).size();
int numberOfDiamonds = suitMap.get(CardSuit.DIAMONDS) == null ? 0 : suitMap.get(
CardSuit.DIAMONDS).size();
int numberOfSpades = suitMap.get(CardSuit.SPADES) == null ? 0 : suitMap.get(
CardSuit.SPADES).size();
if (numberOfHearts >= 3) {
return suitMap.get(CardSuit.HEARTS);
}
if (numberOfClubs >= 3) {
return suitMap.get(CardSuit.CLUBS);
}
if (numberOfDiamonds >= 3) {
return suitMap.get(CardSuit.DIAMONDS);
}
if (numberOfSpades >= 3) {
return suitMap.get(CardSuit.SPADES);
}
if (numberOfHearts == 2) {
return suitMap.get(CardSuit.HEARTS);
}
if (numberOfClubs == 2) {
return suitMap.get(CardSuit.CLUBS);
}
if (numberOfDiamonds == 2) {
return suitMap.get(CardSuit.DIAMONDS);
}
if (numberOfSpades == 2) {
return suitMap.get(CardSuit.SPADES);
}
throw new IllegalArgumentException("CommonCards must contain at least "
+ "two instances of a suit.");
}
private CardRank findCardRankOfHighestStraight(List<Card> cardList) {
if (cardList.size() < 5) {
return null;
}
List<CardRank> cardRanks = new ArrayList<>();
for (Card card : cardList) {
cardRanks.add(card.getCardRank());
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.TEN, CardRank.JACK,
CardRank.QUEEN, CardRank.KING, CardRank.ACE }), 5)) {
return CardRank.ACE;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.NINE, CardRank.TEN,
CardRank.JACK, CardRank.QUEEN, CardRank.KING }), 5)) {
return CardRank.KING;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.EIGHT, CardRank.NINE,
CardRank.TEN, CardRank.JACK, CardRank.QUEEN }), 5)) {
return CardRank.QUEEN;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.SEVEN, CardRank.EIGHT,
CardRank.NINE, CardRank.TEN, CardRank.JACK }), 5)) {
return CardRank.JACK;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.SIX, CardRank.SEVEN,
CardRank.EIGHT, CardRank.NINE, CardRank.TEN }), 5)) {
return CardRank.TEN;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.FIVE, CardRank.SIX,
CardRank.SEVEN, CardRank.EIGHT, CardRank.NINE }), 5)) {
return CardRank.NINE;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.FOUR, CardRank.FIVE,
CardRank.SIX, CardRank.SEVEN, CardRank.EIGHT }), 5)) {
return CardRank.EIGHT;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.THREE, CardRank.FOUR,
CardRank.FIVE, CardRank.SIX, CardRank.SEVEN }), 5)) {
return CardRank.SEVEN;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.TWO, CardRank.THREE,
CardRank.FOUR, CardRank.FIVE, CardRank.SIX }), 5)) {
return CardRank.SIX;
}
if (doCardRanksMatch(
cardRanks,
Arrays.asList(new CardRank[] { CardRank.ACE, CardRank.TWO,
CardRank.THREE, CardRank.FOUR, CardRank.FIVE }), 5)) {
return CardRank.FIVE;
}
return null;
}
}