public CardCombination EvaluateCards(IReadOnlyCollection <Card> cards) { var combinationType = CombinationType.HighCard; var colors = cards.GroupBy(card => card.Color); var colorGroup = colors.FirstOrDefault(group => group.Count() >= 5); bool hasColor = colorGroup != null; bool hasStraight = false; var orderedCards = cards.GroupBy(card => card.Value).Select(group => group.First()).OrderByDescending(card => card.Value); int successiveCards = 1; double combinationHeight = 0; IList <Card> combination = new List <Card>(); if (hasColor && cards.Count >= 5) { var orderedColorCards = colorGroup.OrderByDescending(card => card.Value); Card previousCard = orderedColorCards.First(); combination = new List <Card>() { previousCard }; foreach (var orderedCard in orderedColorCards.Skip(1)) { if (previousCard.Value == orderedCard.Value + 1) { successiveCards++; combination.Add(orderedCard); } else if (successiveCards < 5) { successiveCards = 1; combination.Clear(); combination.Add(orderedCard); } previousCard = orderedCard; } } else if (cards.Count >= 5) { Card previousCard = orderedCards.First(); combination = new List <Card>() { previousCard }; foreach (var orderedCard in orderedCards.Skip(1)) { if (previousCard.Value == orderedCard.Value + 1) { successiveCards++; combination.Add(orderedCard); } else if (successiveCards < 5) { successiveCards = 1; combination.Clear(); combination.Add(orderedCard); } previousCard = orderedCard; } } if (successiveCards == 4 && orderedCards.Any(card => card.Value == 14) && combination.Any(card => card.Value == 2) && cards.Count >= 5) { hasStraight = true; combinationHeight = combination.Max(card => card.Value); combination.Add(orderedCards.FirstOrDefault(card => card.Value == 14)); } else if (successiveCards >= 5 && cards.Count >= 5) { hasStraight = true; combinationHeight = combination.Max(card => card.Value); combination = combination.OrderByDescending(card => card.Value).Take(5).ToList(); } if (hasColor && hasStraight && combination.All(card => colorGroup.Contains(card)) && cards.Count >= 5) { if (combinationHeight == 14) { combinationType = CombinationType.RoyalFlush; } else { combinationType = CombinationType.StraightFlush; } } else { var valueGroups = cards.GroupBy(card => card.Value).ToList(); var quads = valueGroups.FirstOrDefault(group => group.Count() == 4); if (quads != null && cards.Count >= 4) { combinationType = CombinationType.FourOfAKind; combination = quads.ToList(); if (cards.Any(card => !combination.Contains(card))) { var remain = cards.Where(card => !combination.Contains(card)).OrderByDescending(card => card.Value).First(); combination.Add(remain); } } else { var trips = valueGroups.Where(group => group.Count() == 3); IGrouping <int, Card> bestTrips = null; if (trips.Count() == 2) { bestTrips = trips.OrderByDescending(trip => trip.First().Value).First(); valueGroups.Remove(bestTrips); } else if (trips.Count() == 1) { bestTrips = trips.First(); valueGroups.Remove(bestTrips); } var pairs = valueGroups.Where(group => group.Count() == 2 || group.Count() == 3); if (bestTrips != null && pairs.Any() && cards.Count >= 5) { var bestPair = pairs.OrderByDescending(pair => pair.First().Value).First(); combination = bestTrips.Concat(bestPair.Take(2)).ToList(); combinationType = CombinationType.FullHouse; } else if (hasColor) { if (colorGroup.Count() >= 5) { combination = colorGroup.ToList().OrderByDescending(card => card.Value).Take(5).ToList(); combinationType = CombinationType.Flush; } } else if (hasStraight && cards.Count >= 5) { combinationType = CombinationType.Straight; combination = combination.OrderByDescending(card => card.Value).Take(5).ToList(); } else if (bestTrips != null && cards.Count >= 3) { combinationType = CombinationType.ThreeOfAKind; combination = bestTrips.ToList(); var remains = cards.Where(card => !combination.Contains(card)).OrderByDescending(card => card.Value).Take(2).ToList(); for (int i = 0; i < remains.Count; i++) { combination.Add(remains[i]); } } else if (pairs.Count() >= 2 && cards.Count >= 4) { combination.Clear(); var bestPairs = pairs.OrderByDescending(pair => pair.First().Value).Take(2).ToList(); combination = combination.Concat(bestPairs[0].ToList()).ToList(); combination = combination.Concat(bestPairs[1].ToList()).ToList(); if (cards.Any(card => !combination.Contains(card))) { var remain = cards.Where(card => !combination.Contains(card)).OrderByDescending(card => card.Value).First(); combination.Add(remain); } combinationType = CombinationType.TwoPair; } else if (pairs.Count() == 1 && cards.Count >= 2) { var bestPair = pairs.OrderByDescending(pair => pair.First().Value).First(); combination = bestPair.ToList(); var remains = cards.Where(card => !combination.Contains(card)).OrderByDescending(card => card.Value).Take(3).ToList(); for (int i = 0; i < remains.Count; i++) { combination.Add(remains[i]); } combinationType = CombinationType.OnePair; } else { var bestHighCards = cards.OrderByDescending(card => card.Value).Take(5); combination = bestHighCards.ToList(); combinationType = CombinationType.HighCard; } } } combinationHeight = 0; for (int i = 0; i < Math.Min(5, combination.Count); i++) { var cardValue = combination[i].Value; if (cardValue == 14 && (combinationType == CombinationType.StraightFlush || combinationType == CombinationType.Straight) && combination.All(card => card.Value != 13)) { cardValue = 1; } combinationHeight += cardValue * Math.Pow(0.07, i); } var score = combinationHeight * Math.Pow(14, (int)combinationType); return(new CardCombination(combinationType, combination.ToList(), score)); }
private IEnumerable<dynamic> GetItemsToReduce(dynamic reduceKey, Slice key, IGrouping<dynamic, object> grouping) { RavenJToken currentStatus; if (_cache.TryGet(reduceKey, out currentStatus) == false) { using (var stream = _aggregationEngine.Storage.Reader.Read(key)) { if (stream != null) { currentStatus = RavenJToken.ReadFrom(new JsonTextReader(new StreamReader(stream))); } } } IEnumerable<dynamic> groupedResults = grouping; if (currentStatus != null) { switch (currentStatus.Type) { case JTokenType.Array: groupedResults = groupedResults.Concat(((RavenJArray) currentStatus).Select(x => new DynamicJsonObject((RavenJObject) x))); break; case JTokenType.Object: groupedResults = grouping.Concat(new dynamic[] {new DynamicJsonObject((RavenJObject) currentStatus)}); break; } } return groupedResults; }