public double CalculateOuts(IEnumerable<Card> playerCards, IEnumerable<Card> cards)
        {
            var deck = new List<Card>();

            for (int i = 0; i <= 3; i++)
            {
                for (int j = 2; j <= 14; j++)
                {
                    deck.Add(new Card((CardSuit)i, (CardType)j));
                }
            }

            List<Card[]> pairsCombos = new List<Card[]>();

            for (int i = 0; i < deck.Count; i++)
            {
                for (int j = 0; j < deck.Count; j++)
                {
                    if (i != j)
                    {
                        pairsCombos.Add(new Card[2] { deck[i], deck[j] });
                    }
                }
            }

            HashSet<Card> board = new HashSet<Card>(cards);

            var handEvaluator = new HandEvaluator();

            var myPlayerCards = new HashSet<Card>();

            foreach (var card in playerCards)
            {
                myPlayerCards.Add(card);
            }

            foreach (var card in board)
            {
                myPlayerCards.Add(card);
            }

            var handEvaluatorExtended = new HandEvaluatorExtension();
            var bestHandFromBoard = handEvaluatorExtended.GetBestHandForFlop(board);
            var playerBestHand = handEvaluator.GetBestHand(myPlayerCards);

            if (playerBestHand.RankType <= bestHandFromBoard.RankType &&
                (cards.ToList().Count() == 3))
            {
                return 21;
            }

            if (cards.Count() == 4 && cards.Any())
            {
                var bestHandFromBoardOnTurn = handEvaluatorExtended.GetBestHandForTurn(board);
                if (playerBestHand.RankType <= bestHandFromBoardOnTurn.RankType)
                {
                    return 21;
                }
            }

            long wins = 0, ties = 0, loses = 0, count = 0;

            // Iterate through all possible opponent hole cards
            // This is one because it is very slow otherwise.
            // I have tested it and there is not much of a difference
            for (var i = 0; i < 1; i++)
            {
                var otherHand = new HashSet<Card>();
                foreach (var pairsCombo in pairsCombos)
                {
                    foreach (var card in pairsCombo)
                    {
                        otherHand.Add(card);
                    }

                    foreach (var card in board)
                    {
                        otherHand.Add(card);
                    }

                    if (otherHand.Count < 5)
                    {
                        continue;
                    }

                    var otherBestHand = handEvaluator.GetBestHand(otherHand);
                    if (playerBestHand.RankType > otherBestHand.RankType)
                    {
                        wins++;
                    }
                    else if (playerBestHand.RankType == otherBestHand.RankType)
                    {
                        ties++;
                    }
                    else
                    {
                        loses++;
                    }

                    count++;
                    otherHand.Clear();
                }
            }

            var percent = (((double)wins) + ((double)ties) / 2.0) / ((double)count) * 100.0;
            return percent;
        }
        private PlayerAction GetActionForFlop(GetTurnContext context)
        {
            var playHand = HandStrengthValuation.Flop(this.FirstCard, this.SecondCard, this.CommunityCards);

            if (playHand == CardValuationType.Unplayable)
            {
                if (context.CanCheck)
                {
                    return PlayerAction.CheckOrCall();
                }

                return PlayerAction.Fold();
            }

            if (playHand == CardValuationType.Risky)
            {
                if (context.CanCheck)
                {
                    return PlayerAction.CheckOrCall();
                }

                return PlayerAction.Fold();
            }

            HandEvaluatorExtension handEvaluator = new HandEvaluatorExtension();
            var cards = new List<Card>();
            cards.AddRange(this.CommunityCards);
            cards.Add(this.FirstCard);
            cards.Add(this.SecondCard);
            var handsInCommunity = handEvaluator.GetBestHandForFlop(cards);

            if (handsInCommunity.RankType == HandRankType.Pair)
            {
                if (this.FirstCard.Type < CardType.Ten && this.SecondCard.Type < CardType.Ten)
                {
                    return PlayerAction.Fold();
                }
            }

            if (playHand == CardValuationType.Recommended)
            {
                var smallBlindsTimes = RandomProvider.Next(1, 14);
                if (context.CanCheck)
                {
                    if (context.MoneyToCall <= context.MoneyLeft / 10)
                    {
                        return PlayerAction.CheckOrCall();
                    }

                    return PlayerAction.Fold();
                }

                if (this.raisesOnFlop < 2)
                {
                    this.raisesOnPreFlop += 1;
                    return PlayerAction.Raise(context.SmallBlind * smallBlindsTimes);
                }

                return PlayerAction.CheckOrCall();
            }

            if (playHand == CardValuationType.StronglyRecommended)
            {
                if (this.raisesOnFlop < 1)
                {
                    this.raisesOnPreFlop += 1;
                    return PlayerAction.Raise(context.SmallBlind * 4);
                }
                else
                {
                    return PlayerAction.Fold();
                }
            }

            return PlayerAction.CheckOrCall();
        }