from enum import Enum from functools import total_ordering from typing import List, Tuple, Union, TypeVar, Any from .card import Card, Rank, ShortDeckRank HandTypeVar = TypeVar('HandTypeVar', bound=Enum) @total_ordering class HandType(Enum): HIGH_CARD = (1, "High Card") ONE_PAIR = (2, "Pair") TWO_PAIR = (3, "Two Pair") THREE_OF_A_KIND = (4, "Three of a Kind") STRAIGHT = (5, "Straight") FLUSH = (6, "Flush") FULL_HOUSE = (7, "Full House") FOUR_OF_A_KIND = (8, "Four of a Kind") STRAIGHT_FLUSH = (9, "Straight Flush") ROYAL_FLUSH = (10, "Royal Flush") def __new__(cls, strength, name): obj = object.__new__(cls) obj._value_ = strength obj.strength = strength obj.type_name = name return obj def __str__(self): return self.type_name def __lt__(self, other): if isinstance(other, HandType): return self.strength < other.strength return NotImplemented def __eq__(self, other): if isinstance(other, HandType): return self.strength == other.strength return NotImplemented def __hash__(self): return hash(self.strength) class HandRanking: """通用手牌排名类,支持标准扑克和短牌扑克的手牌类型""" def __init__(self, hand_type: Any, key_ranks: List[Union[Rank, ShortDeckRank]], cards: List[Card]): self.hand_type = hand_type self.key_ranks = key_ranks # 用于比较的关键点数 self.cards = cards # 组成这个ranking的5张牌 def __str__(self): hand_type_name = self.hand_type.name if hasattr(self.hand_type, 'name') else str(self.hand_type) if hand_type_name == "FOUR_OF_A_KIND": return f"Quad({self.key_ranks[0].symbol})" elif hand_type_name == "FULL_HOUSE": return f"Full House({self.key_ranks[0].symbol} over {self.key_ranks[1].symbol})" elif hand_type_name == "FLUSH": return f"Flush({self.key_ranks[0].symbol} high)" elif hand_type_name == "STRAIGHT": return f"Straight({self.key_ranks[0].symbol} high)" elif hand_type_name == "STRAIGHT_FLUSH": if hasattr(self.key_ranks[0], 'symbol') and self.key_ranks[0].symbol == 'A': return "Royal Flush" else: return f"Straight Flush({self.key_ranks[0].symbol} high)" elif hand_type_name == "ROYAL_FLUSH": return "Royal Flush" elif hand_type_name == "THREE_OF_A_KIND": return f"Three of a Kind({self.key_ranks[0].symbol})" elif hand_type_name == "TWO_PAIR": return f"Two Pair({self.key_ranks[0].symbol} and {self.key_ranks[1].symbol})" elif hand_type_name == "ONE_PAIR": return f"Pair({self.key_ranks[0].symbol})" else: # HIGH_CARD return f"High Card({self.key_ranks[0].symbol})" def __eq__(self, other): if not isinstance(other, HandRanking): return False self_strength = getattr(self.hand_type, 'strength', self.hand_type.value[0] if hasattr(self.hand_type.value, '__getitem__') else self.hand_type.value) other_strength = getattr(other.hand_type, 'strength', other.hand_type.value[0] if hasattr(other.hand_type.value, '__getitem__') else other.hand_type.value) return (self_strength == other_strength and self.key_ranks == other.key_ranks) def __lt__(self, other): if not isinstance(other, HandRanking): return NotImplemented self_strength = getattr(self.hand_type, 'strength', self.hand_type.value[0] if hasattr(self.hand_type.value, '__getitem__') else self.hand_type.value) other_strength = getattr(other.hand_type, 'strength', other.hand_type.value[0] if hasattr(other.hand_type.value, '__getitem__') else other.hand_type.value) if self_strength != other_strength: return self_strength < other_strength for self_rank, other_rank in zip(self.key_ranks, other.key_ranks): if self_rank != other_rank: return self_rank < other_rank return False