Spaces:
Running
Running
from ctypes import c_long, c_uint, c_ulong | |
import dds | |
SUIT_ORDER = {"S": 0, "H": 1, "D": 2, "C": 3} | |
RANK_ORDER = { | |
"A": 14, | |
"K": 13, | |
"Q": 12, | |
"J": 11, | |
"T": 10, | |
"9": 9, | |
"8": 8, | |
"7": 7, | |
"6": 6, | |
"5": 5, | |
"4": 4, | |
"3": 3, | |
"2": 2, | |
} | |
RANK_STRENGTH = { | |
"A": 1, | |
"K": 2, | |
"Q": 3, | |
"J": 4, | |
"T": 5, | |
"9": 6, | |
"8": 7, | |
"7": 8, | |
"6": 9, | |
"5": 10, | |
"4": 11, | |
"3": 12, | |
"2": 13, | |
} | |
SUIT_STRENGTH = { | |
"S": 0, | |
"H": 1, | |
"D": 2, | |
"C": 3, | |
} | |
RANK_TO_BIT = {rank: 2**power for rank, power in RANK_ORDER.items()} | |
def is_text_valid(text): | |
text = ( | |
text.replace("1O", "T") | |
.replace("10", "T") | |
.replace("0", "T") | |
.replace("O", "T") | |
.replace("U", "J") | |
.replace("1", "7") | |
) | |
for rank in RANK_ORDER.keys(): | |
if rank in text: | |
return rank | |
return None | |
def arrange_hand(hand): | |
unique_hand = list(set(hand)) | |
sorted_hand = sorted( | |
unique_hand, | |
key=lambda card: ( | |
SUIT_ORDER.get(card[0], 99), | |
-RANK_ORDER.get(card[1:], 0), | |
), | |
) | |
return sorted_hand | |
def convert2xhd(all_result, title): | |
xhd = f"""<?xml version="1.0" encoding="shift_jis"?> | |
<HandData> | |
<Prop> | |
<Title>{title}</Title> | |
</Prop> | |
""" | |
for i, result in enumerate(all_result): | |
if "error" in result.keys(): | |
continue | |
xhd += f'<Board id="{i+1}">\r\n' | |
xhd += convert2xhd_board(result["hands"]) | |
xhd += "\r\n</Board>\r\n" | |
xhd += "</HandData>" | |
return xhd | |
def convert2xhd_board(board): | |
north_hand = convert2xhd_hand(board["north"]) | |
south_hand = convert2xhd_hand(board["south"]) | |
west_hand = convert2xhd_hand(board["west"]) | |
east_hand = convert2xhd_hand(board["east"]) | |
return f"<Deal>{north_hand} {east_hand} {south_hand} {west_hand}</Deal>" | |
def convert2xhd_hand(hand): | |
arranged_cards = arrange_hand(hand) | |
S, H, D, C = "", "", "", "" | |
for card in arranged_cards: | |
if card[0] == "S": | |
S += card[1:] | |
if card[0] == "H": | |
H += card[1:] | |
if card[0] == "D": | |
D += card[1:] | |
if card[0] == "C": | |
C += card[1:] | |
return f"{S}.{H}.{D}.{C}" | |
def convert2dup(all_result, _): | |
num = len(all_result) | |
dup = "" | |
for result in all_result: | |
if "error" in result.keys(): | |
continue | |
dup += convert2dup_board(result["hands"], num) | |
return dup | |
def convert2dup_board(board, num): | |
north_hand_num = convert2dup_hand_num(board["north"]) | |
east_hand_num = convert2dup_hand_num(board["east"]) | |
south_hand_num = convert2dup_hand_num(board["south"]) | |
north_hand = convert2dup_hand_str(board["north"]) | |
south_hand = convert2dup_hand_str(board["south"]) | |
west_hand = convert2dup_hand_str(board["west"]) | |
east_hand = convert2dup_hand_str(board["east"]) | |
return f"{north_hand_num}{east_hand_num}{south_hand_num}{north_hand}{east_hand}{south_hand}{west_hand}YN1 1 {str(num).ljust(2)} " | |
def convert2dup_hand_num(hand): | |
arranged_hand = arrange_hand(hand) | |
cards_num = [convert_card2num(card) for card in arranged_hand] | |
sorted(cards_num) | |
return "".join(str(c).zfill(2) for c in cards_num) | |
def convert2dup_hand_str(hand): | |
arranged_hand = arrange_hand(hand) | |
S, H, D, C = "", "", "", "" | |
for card in arranged_hand: | |
if card[0] == "S": | |
S += card[1] | |
if card[0] == "H": | |
H += card[1] | |
if card[0] == "D": | |
D += card[1] | |
if card[0] == "C": | |
C += card[1] | |
return f"{S}{H}{D}{C}" | |
def convert_card2num(card): | |
suit = SUIT_STRENGTH.get(card[0]) | |
rank = RANK_STRENGTH.get(card[1]) | |
if suit is None or rank is None: | |
return -1 | |
return suit * 13 + rank | |
def convert2pbn(all_result): | |
res = "% Dealer4 ver 4.82\r\n" | |
for i, result in enumerate(all_result): | |
if "error" in result.keys(): | |
continue | |
res += '[Event "#"]\r\n' if i != 0 else '[Event ""]\r\n' | |
res += '[Site "#"]\r\n' if i != 0 else '[Site ""]\r\n' | |
res += '[Date "#"]\r\n' if i != 0 else '[Date ""]\r\n' | |
res += f'[Board "{i}"]\r\n' | |
res += f'[Dealer "{get_dealer(i)}"]\r\n' | |
res += f'[Vulnerable "{get_vul(i)}"]\r\n' | |
res += f'{convert2pbn_board(result["hands"], get_dealer(i))}\r\n\r\n' | |
return res | |
def convert2pbn_board(board, dealer): | |
return f'[Deal "{convert2pbn_txt(board, dealer)}"]' | |
def convert2pbn_txt(board, dealer): | |
player_order = ["north", "south", "west", "east"] | |
dealer_dict = {"N": 0, "E": 1, "S": 2, "W": 3} | |
north_hand = convert2pbn_hand(board[player_order[dealer_dict[dealer]]]) | |
south_hand = convert2pbn_hand( | |
board[player_order[(dealer_dict[dealer] + 1) % 4]] | |
) | |
west_hand = convert2pbn_hand( | |
board[player_order[(dealer_dict[dealer] + 2) % 4]] | |
) | |
east_hand = convert2pbn_hand( | |
board[player_order[(dealer_dict[dealer] + 3) % 4]] | |
) | |
return f"{dealer}:{north_hand} {east_hand} {south_hand} {west_hand}" | |
def convert2pbn_hand(hand): | |
arranged_cards = arrange_hand(hand) | |
S, H, D, C = "", "", "", "" | |
for card in arranged_cards: | |
if card[0] == "S": | |
S += card[1:] | |
if card[0] == "H": | |
H += card[1:] | |
if card[0] == "D": | |
D += card[1:] | |
if card[0] == "C": | |
C += card[1:] | |
return f"{S}.{H}.{D}.{C}" | |
def get_vul(num): | |
r = num % 4 | |
q = (num - 1) // 4 | |
if (r + q) % 4 == 1: | |
return "None" | |
elif (r + q) % 4 == 2: | |
return "NS" | |
elif (r + q) % 4 == 3: | |
return "EW" | |
else: | |
return "All" | |
def get_dealer(num): | |
if num % 4 == 1: | |
return "N" | |
elif num % 4 == 2: | |
return "E" | |
elif num % 4 == 3: | |
return "S" | |
else: | |
return "W" | |
def convert2ddTableDeal(hands_dict): | |
table_deal = dds.ddTableDeal() | |
# C言語の配列のように振る舞うため、このように初期化 | |
cards = ((c_uint * 4) * 4)() # ddTableDealはc_uintでOK | |
hand_map = {"north": 0, "east": 1, "south": 2, "west": 3} | |
suit_map = {"S": 0, "H": 1, "D": 2, "C": 3} | |
for player_name, hand in hands_dict.items(): | |
for card in hand: | |
suit_char = card[0] | |
rank_char = card[1:] | |
player_idx = hand_map.get(player_name) | |
suit_idx = suit_map.get(suit_char) | |
if player_idx is not None and suit_idx is not None: | |
cards[player_idx][suit_idx] |= RANK_TO_BIT.get(rank_char, 0) | |
table_deal.cards = cards | |
return table_deal | |
# DDSのdealオブジェクトを作成する最終確定版の関数 | |
def convert_hands_to_binary_deal(hands_dict): | |
from ctypes import c_uint | |
deal = dds.deal() | |
deal.trump = 0 | |
deal.first = 0 | |
deal.currentTrickSuit = (0, 0, 0) | |
deal.currentTrickRank = (0, 0, 0) | |
cards = ((c_long * 4) * 4)() | |
hand_map = {"north": 0, "east": 1, "south": 2, "west": 3} | |
suit_map = {"S": 0, "H": 1, "D": 2, "C": 3} | |
for player_name, hand in hands_dict.items(): | |
for card in hand: | |
suit_char = card[0] | |
rank_char = card[1:] | |
player_idx = hand_map.get(player_name) | |
suit_idx = suit_map.get(suit_char) | |
if player_idx is not None and suit_idx is not None: | |
cards[player_idx][suit_idx] |= RANK_TO_BIT.get(rank_char, 0) | |
deal.remainCards = cards | |
return deal | |
def PrintTable(table): | |
dcardSuit = ["S", "H", "D", "C", "N"] | |
print( | |
"{:5} {:<5} {:<5} {:<5} {:<5}".format( | |
"", "North", "South", "East", "West" | |
) | |
) | |
print( | |
"{:>5} {:5} {:5} {:5} {:5}".format( | |
"NT", | |
table.resTable[0][4], | |
table.resTable[2][4], | |
table.resTable[1][4], | |
table.resTable[3][4], | |
) | |
) | |
for suit in range(0, dds.DDS_SUITS): | |
print( | |
"{:>5} {:5} {:5} {:5} {:5}".format( | |
dcardSuit[suit], | |
table.resTable[0][suit], | |
table.resTable[2][suit], | |
table.resTable[1][suit], | |
table.resTable[3][suit], | |
) | |
) | |
print("") | |
def reshape_table(table): | |
players_map = {0: "North", 1: "East", 2: "South", 3: "West"} | |
suits_map = {4: "nt", 0: "s", 1: "h", 2: "d", 3: "c"} | |
res = {p_name: {} for p_name in players_map.values()} | |
for i, suit in suits_map.items(): | |
for j, player in players_map.items(): | |
# new_suit = suits_map[(i + 5 * j) // 4] | |
# new_player = players_map[(i + 5 * j) % 4] | |
# print( | |
# suit, player, i, j, new_suit, new_player, table.resTable[j][i] | |
# ) | |
res[player][suit] = table.resTable[i][j] | |
return res | |