def _hand_description_two_pair(hand: List[Card]): """ Private method that produces the proper hand description for a two pair hand. :param hand: List of Card objects representing a players hand :return: String of the hand description """ higher_pair_value = hand_highest_value_tuple(hand, 2) higher_pair_rank = list( filter(lambda card: card.value == higher_pair_value, hand))[0].rank remaining_cards = list( filter(lambda card: card.value != higher_pair_value, hand)) lower_pair_value = hand_highest_value_tuple(remaining_cards, 2) lower_pair_rank = list( filter(lambda card: card.value == lower_pair_value, remaining_cards))[0].rank kicker = list( filter(lambda card: card.value != lower_pair_value, remaining_cards)) if kicker: return f"Two Pair ({higher_pair_rank}s and {lower_pair_rank}s with kicker {kicker[0].rank})" else: return f"Two Pair ({higher_pair_rank}s and {lower_pair_rank}s)"
def _rank_full_house(hands: List[List[Card]]): """ Private tiebreaker method to determine the best full house hand in the list of hands :param hands: List of list of cards. each internal list of cards represents a full house hand :return: Dictionary in the following format of KEY = Rank number (1,2,3,4...) VALUE = List of hands for that rank If there are tied hands, then multiple hands will appear as the value for that rank. """ ordered_hands = [] for hand in hands: trips_value = hand_highest_value_tuple(hand, 3) remaining_cards = filter(lambda card: card.value != trips_value, hand) pair_value = hand_highest_value_tuple(remaining_cards, 2) ordered_hands.append((hand, trips_value, pair_value)) ordered_hands.sort(key=lambda tup: (tup[1], tup[2]), reverse=True) current_rank = 1 ranked_hands = {current_rank: [ordered_hands[0][0]]} current_trip = ordered_hands[0][1] current_pair = ordered_hands[0][2] for hand, trip, pair in ordered_hands[1:]: if current_trip == trip and current_pair == pair: ranked_hands[current_rank].append(hand) else: current_rank += 1 current_trip = trip current_pair = pair ranked_hands[current_rank] = [hand] return ranked_hands
def _hand_test_two_pair(hand: List[Card]) -> bool: """ Private method to test if a hand is a two pair hand :param hand: List of Card objects representing a players hand :return: Boolean indicating if the hand is a straight flush """ high_pair_value = hand_highest_value_tuple(hand, 2) remaining_cards = list(filter(lambda card: card.value != high_pair_value, hand)) low_pair_value = hand_highest_value_tuple(remaining_cards, 2) return bool(high_pair_value and low_pair_value)
def _hand_test_full_house(hand: List[Card]) -> bool: """ Private method to test if a hand is a quads hand :param hand: List of Card objects representing a players hand :return: Boolean indicating if the hand is a straight flush """ trips_value = hand_highest_value_tuple(hand, 3) remaining_cards = filter(lambda card: card.value != trips_value, hand) pair_value = hand_highest_value_tuple(remaining_cards, 2) return bool(trips_value and pair_value)
def _hand_description_full_house(hand: List[Card]): """ Private method that produces the proper hand description for a full house hand. :param hand: List of Card objects representing a players hand :return: String of the hand description """ trips_value = hand_highest_value_tuple(hand, 3) trips_rank = list(filter(lambda card: card.value == trips_value, hand))[0].rank remaining_cards = filter(lambda card: card.value != trips_value, hand) pair_value = hand_highest_value_tuple(remaining_cards, 2) pair_rank = list(filter(lambda card: card.value == pair_value, hand))[0].rank return f"Full House ({trips_rank}s full of {pair_rank}s)"
def _rank_pair(hands: List[List[Card]]): """ Private tiebreaker method to determine the best pair hand in the list of hands :param hands: List of list of cards. each internal list of cards represents a pair hand :return: Dictionary in the following format of KEY = Rank number (1,2,3,4...) VALUE = List of hands for that rank If there are tied hands, then multiple hands will appear as the value for that rank. """ hands_pair = [(hand, hand_highest_value_tuple(hand, 2)) for hand in hands] pair_values = list(set([tup[1] for tup in hands_pair])) pair_values.sort(reverse=True) ranked_hands = dict() for pair_value in pair_values: pair_value_hands = filter( lambda hand_tuple: hand_tuple[1] == pair_value, hands_pair) pair_value_hands = order_hands_highest_card( [tup[0] for tup in pair_value_hands]) current_rank = 1 if not ranked_hands else max(ranked_hands.keys()) + 1 ranked_hands[current_rank] = [pair_value_hands[0]] for hand in pair_value_hands[1:]: if hands_have_same_card_values(hand, ranked_hands[current_rank][0]): ranked_hands[current_rank].append(hand) else: current_rank += 1 ranked_hands[current_rank] = [hand] return ranked_hands
def _rank_two_pair(hands: List[List[Card]]): """ Private tiebreaker method to determine the best two pair hand in the list of hands :param hands: List of list of cards. each internal list of cards represents a two pair hand :return: Dictionary in the following format of KEY = Rank number (1,2,3,4...) VALUE = List of hands for that rank If there are tied hands, then multiple hands will appear as the value for that rank. """ hands_two_pair_kicker = [] for hand in hands: high_pair_value = hand_highest_value_tuple(hand, 2) remaining_cards = filter(lambda card: card.value != high_pair_value, hand) low_pair_value = hand_highest_value_tuple(remaining_cards, 2) kicker_value = list( filter( lambda card: card.value != high_pair_value and card.value != low_pair_value, hand, ))[0].value hands_two_pair_kicker.append( (hand, high_pair_value, low_pair_value, kicker_value)) hands_two_pair_kicker.sort(key=lambda tup: (tup[1], tup[2], tup[3]), reverse=True) current_rank = 1 current_high_pair = hands_two_pair_kicker[0][1] current_low_pair = hands_two_pair_kicker[0][2] current_kicker = hands_two_pair_kicker[0][3] ranked_hands = {current_rank: [hands_two_pair_kicker[0][0]]} for hand, high_pair, low_pair, kicker in hands_two_pair_kicker[1:]: if (high_pair == current_high_pair and low_pair == current_low_pair and kicker == current_kicker): ranked_hands[current_rank].append(hand) else: current_rank += 1 current_high_pair = high_pair current_low_pair = low_pair current_kicker = kicker ranked_hands[current_rank] = [hand] return ranked_hands
def _hand_test_pair(hand: List[Card]) -> bool: """ Private method to test if a hand is a two pair hand :param hand: List of Card objects representing a players hand :return: Boolean indicating if the hand is a straight flush """ return bool(hand_highest_value_tuple(hand, 2))
def _hand_description_quads(hand: List[Card]): """ Private method that produces the proper hand description for a quads hand. :param hand: List of Card objects representing a players hand :return: String of the hand description """ quads_value = hand_highest_value_tuple(hand, 4) quads_rank = list(filter(lambda card: card.value == quads_value, hand))[0].rank kicker = list(filter(lambda card: card.value != quads_value, hand)) if kicker: return f"Quads ({quads_rank}s with {kicker[0].rank} kicker)" else: return f"Quads ({quads_rank}s)"
def _hand_description_trips(hand: List[Card]): """ Private method that produces the proper hand description for a quads hand. :param hand: List of Card objects representing a players hand :return: String of the hand description """ trips_value = hand_highest_value_tuple(hand, 3) trips_rank = list(filter(lambda card: card.value == trips_value, hand))[0].rank kickers = list(filter(lambda card: card.value != trips_value, hand)) if not kickers: return f"Trips ({trips_rank}s)" kickers.sort(key=lambda card: card.value, reverse=True) kickers_rank = [card.rank for card in kickers] return f"Trips ({trips_rank}s with kickers {', '.join(kickers_rank)})"
def _hand_description_pair(hand: List[Card]): """ Private method that produces the proper hand description for a pair hand. :param hand: List of Card objects representing a players hand :return: String of the hand description """ pair_value = hand_highest_value_tuple(hand, 2) pair_rank = list(filter(lambda card: card.value == pair_value, hand))[0].rank kickers = list(filter(lambda card: card.value != pair_value, hand)) if kickers: kickers.sort(key=lambda card: card.value, reverse=True) kickers = [kicker.rank for kicker in kickers] return f"Pair ({pair_rank}s with kickers {', '.join(kickers)})" else: return f"Pair ({pair_rank}s)"
def test_when_hand_has_value_tuple_then_correct_response_returned( hand_name, tuple_length, expected_tuple_value): hand = get_hand(hand_name) tuple_value = hand_highest_value_tuple(hand, tuple_length) assert tuple_value == expected_tuple_value