Spaces:
Sleeping
Sleeping
from bridgebots import Suit, Direction, Card, Rank | |
from bridgebots.pbn import from_pbn_deal | |
from pbn_util import pbn_deal_string | |
from collections import Counter | |
DEALER_LIST = ['N', 'E', 'S', 'W'] | |
VULNERABILITY_LIST = ["None","NS","EW","All","NS","EW","All","None","EW","All","None","NS","All","None","NS","EW"] | |
SUITS = [Suit.SPADES, Suit.HEARTS, Suit.DIAMONDS, Suit.CLUBS] | |
RANKS = [r.abbreviation() for r in Rank] | |
def get_vulnerabilty_from_board_number(board_no: int) -> str: | |
# Get vulnerability from board number | |
return VULNERABILITY_LIST[(board_no-1) % 16] | |
def get_dealer_from_board_number(board_no: int) -> str: | |
return DEALER_LIST[(board_no-1) % 4] | |
def validate_dataframe(df) -> None: | |
""" validate submitted dataframe before saving pbn """ | |
# Check column names to be NESW | |
missing_direction = [direction.abbreviation() for direction in Direction if not direction.abbreviation() in df.columns] | |
assert len(missing_direction) == 0, f"Expect directions in table to be {','.join([d.abbreviation() for d in Direction])}" + \ | |
f" missing {','.join(missing_direction)}" | |
err_msg = '' | |
# Check each direction to have 13 cards | |
invalid_num_cards_direction = [direction.name for direction in Direction if len((''.join(df[direction.abbreviation()].tolist()))) != 13] | |
if invalid_num_cards_direction: | |
err_msg += f'Expect 13 cards in each hand, received invalid number of cards in {",".join(invalid_num_cards_direction)}. ' | |
# Check card values in RANKS | |
cards = [] | |
invalid_values = set() | |
for direction in Direction: | |
for ranks, suit in zip(df[direction.abbreviation()], SUITS): | |
for r in ranks: | |
try: | |
Rank.from_str(r) | |
except: | |
invalid_values.add(r) | |
assert not invalid_values, f'Expect card values in {",".join(RANKS)}, received {invalid_values}' | |
for direction in Direction: | |
for ranks, suit in zip(df[direction.abbreviation()], SUITS): | |
cards.extend([Card(rank=Rank.from_str(v), suit=suit) for v in ranks]) | |
# Check duplicated and missing cards | |
duplicated, missing = get_invalid_cards(cards) | |
if len(duplicated) > 0: | |
err_msg += f'Duplicated cards: {duplicated}. ' | |
if len(missing) > 0: | |
err_msg += f'Missing cards: {missing}. ' | |
assert not err_msg, err_msg | |
def df_info(df): | |
# missing_direction = [direction.abbreviation() for direction in Direction if not direction.abbreviation() in df.columns] | |
num_cards_direction = {direction.name: len((''.join(df[direction.abbreviation()].tolist()))) for direction in Direction} | |
invalid_values = set() | |
for direction in Direction: | |
for ranks, suit in zip(df[direction.abbreviation()], SUITS): | |
for r in ranks: | |
try: | |
Rank.from_str(r) | |
except: | |
invalid_values.add(r) | |
if invalid_values: | |
return f'Expect card values in {",".join(RANKS)}, received {invalid_values}' | |
cards = [] | |
for direction in Direction: | |
for ranks, suit in zip(df[direction.abbreviation()], SUITS): | |
cards.extend([Card(rank=Rank.from_str(v), suit=suit) for v in ranks]) | |
# Check duplicated and missing cards | |
duplicated, missing = get_invalid_cards(cards) | |
if (not duplicated) and (not missing) and not [True for n in num_cards_direction.values() if n!=13]: | |
return f'It looks good!' | |
print_info = f'Number of cards: {num_cards_direction} \n' | |
print_info += f'Duplicated cards: {",".join(sorted(map(Card.__repr__,duplicated)))} \n' | |
print_info += f'Missing cards: {",".join(sorted(map(Card.__repr__,missing)))}' | |
return print_info | |
def get_invalid_cards(cards: list[Card]) -> tuple[set, set]: | |
"""Get duplicated and missing cards""" | |
counter_cards = Counter(cards) | |
duplicated = {c for c, cnt in counter_cards.items() if cnt > 1} | |
missing = {Card(s,r) for r in Rank for s in Suit if not Card(s,r) in counter_cards.keys()} | |
return duplicated, missing | |
def roll_direction(df, idx): | |
new_df = df.copy(deep=True) | |
for i, direction in enumerate(DEALER_LIST): | |
new_direction = DEALER_LIST[(idx+i)%4] | |
new_df[direction] = df[new_direction] | |
return new_df |