from fpdf import FPDF import tempfile import os import bridgebots from pbn_util import merge_pbn, parse_pbn 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 = [bridgebots.Suit.SPADES, bridgebots.Suit.HEARTS, bridgebots.Suit.DIAMONDS, bridgebots.Suit.CLUBS] SUIT_SYMBOLS = ['♠','♥','♦','♣'] class PDF(FPDF): value_column_span = 7 def __init__(self, event, site, *args, **kwargs): super().__init__(*args, **kwargs) self.event = event self.site = site def header(self) -> None: # Setting font: helvetica bold 15 self.set_font("helvetica", "B", 12) # Moving cursor to the right: self.cell(80, 5, self.event) # Printing title: self.cell(80, 5, self.site, align="C", new_x="LMARGIN", new_y="NEXT",) # Performing a line break: self.ln(5) def footer(self) -> None: return super().footer() def print_boards(self, results): self.add_page() self.add_font('times2', style='', fname='times.ttf') self.set_font("times2", "", 10) self.c_margin = 0.1 table_config = { 'borders_layout':'NONE', 'col_widths':3, 'line_height':self.font_size + 0.4, 'align': 'L', 'text_align': 'L', 'first_row_as_headings': False, } start_x,start_y = 9, self.y table_size = 45, 46 table_margin = 2 for i, result in enumerate(results): deal = result[0] board_no = int(result[1][0]['Board']) dds_tricks_table = result[1][0]['dds_tricks_table'] page_i = i % 20 if (i % 20 == 0) and (i != 0): self.add_page() row_idx = page_i // 4 col_idx = page_i % 4 x = start_x + (table_size[0] + 2 * table_margin + 1) * col_idx y = start_y + (table_size[1] + 2 * table_margin + 1) * row_idx top_left = x - table_margin, y - table_margin top_right = x + table_size[0] + table_margin, y - table_margin bottom_left = x - table_margin, y + table_size[1] + table_margin bottom_right = x + table_size[0] + table_margin, y + table_size[1] + table_margin self.set_xy(x,y) self.line(*top_left, *bottom_left) self.line(*top_left, * top_right) self.line(*top_right, *bottom_right) self.line(*bottom_left, *bottom_right) dds_top_left = x - table_margin, y + 35 - 1 dds_top_right = x - table_margin + 18, y + 35 - 1 dds_bottom_right = x - table_margin + 18, y + table_size[1] + table_margin self.line(*dds_top_left, *dds_top_right) self.line(*dds_top_right, *dds_bottom_right) dealer = DEALER_LIST[(board_no-1) % 4] vul = VULNERABILITY_LIST[(board_no-1) % 16] self.set_font_size(10) with self.table(**table_config) as table: row = table.row() self.set_font_size(16) row.cell(str(board_no), colspan=6, rowspan=2, align='C', v_align='C', padding=(2,0,0,0)) self.set_font_size(10) for i, (suit, values) in enumerate(zip(SUIT_SYMBOLS, get_values(deal, 'N'))): if i!=0: row = table.row() if i == 2: row.cell(f'{dealer} / {vul}', colspan=6, rowspan=2, align='C', v_align='C') print_suit_values(self,row,suit,values) # row = table.row() # row = table.row() for i, (suit, values1, values2) in enumerate(zip(SUIT_SYMBOLS, get_values(deal, 'W'), get_values(deal, 'E'))): row = table.row() row.cell('', colspan=1, rowspan=1) print_suit_values(self, row, suit, values1) # row.cell('',colspan=1) print_suit_values(self, row, suit, values2) # row = table.row() row = table.row() row.cell('', colspan=6, rowspan=4) for i, (suit, values) in enumerate(zip(SUIT_SYMBOLS, get_values(deal, 'S'))): if i!=0: row = table.row() print_suit_values(self, row, suit, values) self.set_xy(x-1,y+34) self.set_font_size(7) dds_table_config = { 'borders_layout':'NONE', 'col_widths':2.8, 'line_height':self.font_size + 0.1, 'align': 'L', 'text_align': 'L', 'first_row_as_headings': False, 'padding': 0.1 } with self.table(**dds_table_config) as table: row = table.row() row.cell('') self.set_font_size(5) row.cell('NT', align='C') self.set_font_size(7) row.cell(SUIT_SYMBOLS[0], align='C') row.cell(SUIT_SYMBOLS[1], align='C') row.cell(SUIT_SYMBOLS[2], align='C') row.cell(SUIT_SYMBOLS[3], align='C') row = table.row() for i in range(4): if i!=0: row = table.row() row.cell(dds_tricks_table[i*5][0], align='C') row.cell(dds_tricks_table[i*5][2], align='C') row.cell(dds_tricks_table[i*5+1][2], align='C') row.cell(dds_tricks_table[i*5+2][2], align='C') row.cell(dds_tricks_table[i*5+3][2], align='C') row.cell(dds_tricks_table[i*5+4][2], align='C') def create_hand_record_pdf(pbn_paths, event, site): filepath_merged_pbn = merge_pbn(pbn_paths) results = parse_pbn(filepath_merged_pbn) fd,fn = tempfile.mkstemp(".pdf") pdf = PDF(event, site) pdf.print_boards(results) pdf.output(fn) os.close(fd) return fn def get_values(result, direction): d = bridgebots.Direction.from_str(direction) hand = result.hands[d] return [''.join([value.abbreviation() for value in hand.suits[suit]]) for suit in SUITS] def print_suit_values(pdf, row, suit, values): if (suit=='♥') or (suit=='♦'): # Hearts or Diamonds pdf.set_text_color(255,0,0) row.cell(suit, colspan=1) pdf.set_text_color(0,0,0) row.cell(values, colspan=PDF.value_column_span)