dominicprice / endplay

A suite of tools for generation and analysis of bridge deals. Read the documentation at https://endplay.readthedocs.io
MIT License
21 stars 5 forks source link

Conversion from PBN to LIN is losing information #26

Open ThorvaldAagaard opened 11 months ago

ThorvaldAagaard commented 11 months ago

I have a match recorded in a PBN-file and would like to convert it to a LIN-file, so I created a small script like this

image

The file was converted fine, but all information about the match was lost

The file usafrance.pbn is part of the old BBO-client, and using that application the PBN-file is converted correctly.

I have attached the 3 files as a zip-file because github is not supporting the extensions

usafrance.zip

It would be nice with some extra linefeeds in the lin-file for improved readabiliy

dominicprice commented 11 months ago

Hi, I didn't know about the vg tag in lin - I'll do some investigating. Also looking into your other bug about the comments in PBN. Thanks for bringing to my attention, it is sometimes hard to find enough data to test this stuff against! Dom

ThorvaldAagaard commented 11 months ago

I have implemented a small script, that can create a better .lin-file from the PBN. That .lin-file can now be read from the BBO-application and show the match.

Interestingly, there are some bugs in the implementation in the BBO-application, so the two .lin-files are not identical.

For now I have two differences: 1: endplay is printing deals in the wrong order 2: BBO-application is messing up names in the lin-file, but displaying it correctly

image

Here is the script if you can make any use of it:

import sys
import endplay.parsers.pbn as pbn
import endplay.parsers.lin as lin
import endplay.config as config

# Create a dictionary to map suit symbols to character representations
suit_symbols = {
    'C': '♣',  # Clubs
    'D': '♦',  # Diamonds
    'H': '♥',  # Hearts
    'S': '♠',  # Spades
}

try:
   with open("usafrance.pbn") as f:
      boards = pbn.load(f)
except pbn.PBNDecodeError as e:
    print("OK: There was an issue decoding the PBN file.")
    print("Error message:", e)
    print("Current line:", e.line)
    print("Line number:", e.lineno)
    sys.exit(1)

# Define a function to convert room values to numeric values for sorting
def room_to_numeric(room):
    if room == "Open":
        return 0
    elif room == "Closed":
        return 1
    else:
        return 2  # Handle other cases as needed

# Sort the array of Board objects based on board.number and board.info.room
sorted_boards = sorted(
    boards,
    key=lambda board: (board.board_num, room_to_numeric(board.info.room))
)

config.use_unicode = False 
# Use a list comprehension to extract the contract information from each board
contract_info = [board.contract for board in sorted_boards]

# Join the contract information into a single line
contract_line = ','.join(str(contract) for contract in contract_info).replace('NT','N')

print(f"vg|{boards[0].info.event},{boards[0].info.stage},I,1,16,{boards[0].info.hometeam},0,{boards[0].info.visitteam},0|")
# Print the single line with all contract information
print(f"rs|{contract_line}|")
print("pn|")
print(sorted_boards[0].info.south, end=",")
print(sorted_boards[0].info.west, end=",")
print(sorted_boards[0].info.north, end=",")
print(sorted_boards[0].info.east, end=",")
print(sorted_boards[1].info.south, end=",")
print(sorted_boards[1].info.west, end=",")
print(sorted_boards[1].info.north, end=",")
print(sorted_boards[1].info.east, end="")
print("|pg||")
print(f"mn|{boards[0].info.event} - {boards[0].info.stage}|", end='')
for board in boards:
    # Remove st| (small text) from the lin-file
    linfile = lin.dumps([board])
    linfile = linfile.replace('\n', '')
    if board.info.room == "Closed":
        # replace the board number. Board number will be added for room
        linfile = linfile.replace(f',|rh||ah|Board {board.board_num}','')
        linfile = linfile.replace('|mb|','\n|sa|0|mb|',1)
        linfile = linfile.replace('st|',f'qx|c{board.board_num},BOARD {board.board_num}|rh||ah|Board {board.board_num}')
    if board.info.room == "Open":
        linfile = linfile.replace(f',|rh||ah|Board {board.board_num}','')
        linfile = linfile.replace('|mb|','\n|sa|0|mb|',1)
        linfile = linfile.replace('st|',f'qx|o{board.board_num},BOARD {board.board_num}|rh||ah|Board {board.board_num}')
    linfile += 'pg||'
    linfile = linfile.replace('||','||\n') 
    # remove just to compare
    linfile = linfile.replace('||\n','||',1) 
    print(linfile)

And this is how it now looks in the application: image

ThorvaldAagaard commented 11 months ago

I have found another bug in the BBO vugraph as the above sheet for some strange reason will print the open room as the last names read in the lin-file, so I have just added an extra line with the same information as the first line with player names

dominicprice commented 11 months ago

Thanks for sharing --- I will have to do some more studying of the LIN format, and am thinking about some extra flags to make it a bit more customizable, but this is handy to see what sort of things people might want to do