import random
from kansim import Simulation, Boolean

RANKS = "23456789TJQKA"
SUITS = "cdhs"
DECK = [r + s for r in RANKS for s in SUITS]

RANK_ORDER = {r: i for i, r in enumerate(RANKS)}

def deal(deck, n):
    hand = random.sample(deck, n)
    for c in hand:
        deck.remove(c)
    return hand

def best_hand_rank(cards):
    """Returns a comparable tuple representing the best 5-card hand rank."""
    from itertools import combinations
    return max(_hand_rank(h) for h in combinations(cards, 5))

def _hand_rank(hand):
    ranks = sorted([RANK_ORDER[c[0]] for c in hand], reverse=True)
    suits = [c[1] for c in hand]
    flush = len(set(suits)) == 1
    straight = (ranks[0] - ranks[4] == 4 and len(set(ranks)) == 5) or ranks == [12, 3, 2, 1, 0]
    counts = sorted([ranks.count(r) for r in set(ranks)], reverse=True)
    if straight and flush:  return (8, ranks)
    if counts[0] == 4:      return (7, ranks)
    if counts[:2] == [3,2]: return (6, ranks)
    if flush:               return (5, ranks)
    if straight:            return (4, ranks)
    if counts[0] == 3:      return (3, ranks)
    if counts[:2] == [2,2]: return (2, ranks)
    if counts[0] == 2:      return (1, ranks)
    return (0, ranks)

class PokerHandEquity(Simulation):

    def __init__(self):
        deck = DECK.copy()

        self.hole1, self.hole2 = deal(deck, 2), deal(deck, 2)
        community = deal(deck, 5)

        best1 = best_hand_rank(self.hole1 + community)
        best2 = best_hand_rank(self.hole2 + community)

        self.player1_wins = best1 > best2
        self.player2_wins = best2 > best1
        self.split =        best1 == best2

        self.hole1 = " ".join(self.hole1)
        self.hole2 = " ".join(self.hole2)

result = PokerHandEquity.run(n=10_000, seed=42)
print(result.df[["player1_wins", "player2_wins", "split"]].mean().round(3))
result.plot_histogram("player1_wins")