2022-11-18 20:45:19 +00:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2022-11-18 21:00:37 +00:00
|
|
|
from collections import Counter
|
|
|
|
|
2022-11-18 19:30:19 +00:00
|
|
|
from pydantic import BaseModel, validator
|
2022-11-18 13:10:08 +00:00
|
|
|
|
2022-11-18 20:45:19 +00:00
|
|
|
from poker.constants import Rank, Suit, Value
|
2022-11-18 13:10:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Card(BaseModel):
|
|
|
|
"""Card domain model class."""
|
|
|
|
|
|
|
|
suit: Suit
|
|
|
|
value: Value
|
|
|
|
|
2022-11-18 19:30:19 +00:00
|
|
|
def __hash__(self) -> int:
|
|
|
|
"""Hash function."""
|
|
|
|
return hash(f"{self.value} {self.suit}")
|
|
|
|
|
2022-11-18 20:45:19 +00:00
|
|
|
def __le__(self, other: Card) -> bool:
|
|
|
|
"""Less than or equal to."""
|
|
|
|
return self.value <= other.value
|
2022-11-18 19:30:19 +00:00
|
|
|
|
2022-11-18 20:45:19 +00:00
|
|
|
def __lt__(self, other: Card) -> bool:
|
|
|
|
"""Strictly less than."""
|
|
|
|
return self.value < other.value
|
2022-11-18 19:30:19 +00:00
|
|
|
|
2022-11-18 13:10:08 +00:00
|
|
|
|
|
|
|
class Hand(BaseModel):
|
|
|
|
"""Hand domain model class."""
|
|
|
|
|
2022-11-18 20:45:19 +00:00
|
|
|
cards: list[Card]
|
2022-11-18 19:30:19 +00:00
|
|
|
|
|
|
|
@validator("cards")
|
2022-11-18 20:45:19 +00:00
|
|
|
def validate_unique(cls, cards: list[Card]) -> list[Card]:
|
2022-11-18 19:30:19 +00:00
|
|
|
"""Validate hand comprises unique cards."""
|
|
|
|
if len(cards) != len(set(cards)):
|
|
|
|
raise ValueError("Hand contains duplicate cards.")
|
|
|
|
return cards
|
2022-11-18 20:45:19 +00:00
|
|
|
|
|
|
|
@validator("cards")
|
|
|
|
def validate_length(cls, cards: list[Card]) -> list[Card]:
|
|
|
|
"""Validate hand has five cards."""
|
|
|
|
if len(cards) != 5:
|
|
|
|
raise ValueError("Hand must have five cards.")
|
|
|
|
return cards
|
|
|
|
|
2022-11-18 21:00:37 +00:00
|
|
|
@property
|
|
|
|
def value_counts(self) -> list[tuple[Value, int]]:
|
|
|
|
"""Return count of each card value in hand."""
|
|
|
|
return Counter([card.value for card in self.cards]).most_common()
|
|
|
|
|
2022-11-18 20:45:19 +00:00
|
|
|
|
|
|
|
class RankedHand(Hand):
|
|
|
|
"""Ranked hand domain model class."""
|
|
|
|
|
|
|
|
rank: Rank
|
|
|
|
description: str
|