diff options
Diffstat (limited to 'bidding_data.py')
-rw-r--r-- | bidding_data.py | 222 |
1 files changed, 165 insertions, 57 deletions
diff --git a/bidding_data.py b/bidding_data.py index ab377ab..9f6c4b3 100644 --- a/bidding_data.py +++ b/bidding_data.py @@ -1,7 +1,12 @@ -import csv, sys, json, glob, re +import csv +import sys +import glob +import re + from os import path from bs4 import BeautifulSoup as bs4 + class JFRBidding: # alignment of the bidding table @@ -16,18 +21,23 @@ class JFRBidding: file_data.append(line) return file_data - # converts CSV lineup data to {round}.{sector}_{table}.{pair numbers} structure + # converts CSV lineup data to + # {round}.{sector}_{table}.{pair numbers} structure def __parse_lineup_data(self, sitting_data): round_lineups = {} for sitting in sitting_data[1:]: round_no = int(sitting[2]) table_no = sitting[0] + '_' + sitting[1] - if not round_lineups.has_key(round_no): + if round_no not in round_lineups: round_lineups[round_no] = {} - round_lineups[round_no][table_no] = sorted([int(sitting[3]), int(sitting[4])]) + round_lineups[round_no][table_no] = sorted([ + int(sitting[3]), + int(sitting[4]) + ]) return round_lineups - # converts CSV bidding to {board}.{sector}_{table}.{round}.{bidding}[] structure, + # converts CSV bidding to + # {board}.{sector}_{table}.{round}.{bidding}[] structure, # including erased calls def __parse_bidding_data(self, bidding_data): bids = {} @@ -37,18 +47,25 @@ class JFRBidding: table_no = bid[1] + '_' + bid[2] bid_counter = int(bid[5]) bid_erased = int(bid[10]) - if not bids.has_key(board_no): + if board_no not in bids: bids[board_no] = {} - if not bids[board_no].has_key(table_no): + if table_no not in bids[board_no]: bids[board_no][table_no] = {} - if not bids[board_no][table_no].has_key(round_no): + if round_no not in bids[board_no][table_no]: bids[board_no][table_no][round_no] = {} if bid_erased == 1: - if bids[board_no][table_no][round_no].has_key(bid_counter): - if bids[board_no][table_no][round_no][bid_counter]['direction'] == bid[6]: - bids[board_no][table_no][round_no].pop(bid_counter, None) + if bid_counter in bids[board_no][table_no][round_no]: + if bids[board_no][table_no][round_no][bid_counter][ + 'direction'] == bid[6]: + bids[board_no][table_no][round_no].pop( + bid_counter, + None + ) else: - bids[board_no][table_no][round_no][bid_counter] = {'direction': bid[6], 'bid': bid[7] } + bids[board_no][table_no][round_no][bid_counter] = { + 'direction': bid[6], + 'bid': bid[7] + } return bids # converts bidding data into HTML table @@ -63,7 +80,10 @@ class JFRBidding: for bid in bid_round: bid_match = re.match(r'(\d)([SHDCN])', bid) if bid_match: - bid = bid_match.group(1) + '<img src="images/' + bid_match.group(2) + '.gif" />' + bid = bid_match.group(1) + bid = bid + '<img src="images/' + bid = bid + bid_match.group(2) + bid = bid + '.gif" />' html_output = html_output + '<td>' + bid + '</td>' html_output = html_output + '</tr>' html_output = html_output + '</table>' @@ -71,39 +91,63 @@ class JFRBidding: # returns file path for bidding HTML output # {prefix}_bidding_{jfr_board_number}_{pair_numbers}.txt - def __get_bidding_file_output_path(self, board_no, round_no=None, table_no=None, pair_numbers=None): + def __get_bidding_file_output_path(self, + board_no, + round_no=None, + table_no=None, + pair_numbers=None): return '{0}_bidding_{1:03}_{2}.txt'.format( self.__tournament_prefix, board_no, '_'.join( map(str, - self.__round_lineups[round_no][table_no] if pair_numbers is None # read pair numbers from lineup - else pair_numbers) # or use numbers provided, e.g. from JFR HTML + self.__round_lineups[round_no][table_no] + if pair_numbers is None # read pair numbers from lineup + else pair_numbers) # or use provided pair numbers ) ) def __map_board_numbers(self, custom_mapping=None): - self.__tournament_files = [f for f - in glob.glob(self.__tournament_prefix + '*.html') - if re.search(self.__tournament_files_match, f)] + self.__tournament_files = [ + f for f + in glob.glob(self.__tournament_prefix + '*.html') + if re.search(self.__tournament_files_match, f) + ] if custom_mapping is not None: custom_files = [] for jfr_number in range(custom_mapping[0], custom_mapping[1]+1): - # only include these board numbers from custom mapping which actually exist in JFP output - board_files = [f for f in self.__tournament_files if f.endswith('{0:03}.html'.format(jfr_number))] + # only include these board numbers from custom mapping + # which actually exist in JFP output + board_files = [ + f for f + in self.__tournament_files + if f.endswith('{0:03}.html'.format(jfr_number)) + ] if len(board_files): - self.__board_number_mapping[jfr_number - custom_mapping[0] + custom_mapping[2]] = jfr_number + self.__board_number_mapping[ + jfr_number - custom_mapping[0] + custom_mapping[2] + ] = jfr_number custom_files = custom_files + board_files self.__tournament_files = custom_files else: for tournament_file in self.__tournament_files: - # scan for all JFR board HTML files and read actual board numbers from HTML headers - file_number = re.match(self.__tournament_files_match, tournament_file).group(1) + # scan for all JFR board HTML files + # and read actual board numbers from HTML headers + file_number = re.match( + self.__tournament_files_match, + tournament_file + ).group(1) with file(tournament_file, 'r+') as board_html: board_content = bs4(board_html, from_encoding='utf-8') # first found <h4> element should be actual board number - board_number = re.sub('[^0-9]', '', board_content.select('h4')[0].contents[0].strip()) - self.__board_number_mapping[int(board_number, 10)] = int(file_number, 10) + board_number = re.sub( + '[^0-9]', + '', + board_content.select('h4')[0].contents[0].strip() + ) + self.__board_number_mapping[ + int(board_number, 10) + ] = int(file_number, 10) # sitting read from BWS __round_lineups = {} @@ -121,10 +165,18 @@ class JFRBidding: __board_number_mapping = {} def __init__(self, bidding_file, lineup_file, file_prefix, board_mapping): - self.__round_lineups = self.__parse_lineup_data(self.__csv_to_list(lineup_file)) - self.__bids = self.__parse_bidding_data(self.__csv_to_list(bidding_file)) - self.__tournament_prefix = path.splitext(path.realpath(file_prefix + '.html'))[0] - self.__tournament_files_match = re.compile(re.escape(self.__tournament_prefix) + '([0-9]{3})\.html') + self.__round_lineups = self.__parse_lineup_data( + self.__csv_to_list(lineup_file) + ) + self.__bids = self.__parse_bidding_data( + self.__csv_to_list(bidding_file) + ) + self.__tournament_prefix = path.splitext( + path.realpath(file_prefix + '.html') + )[0] + self.__tournament_files_match = re.compile( + re.escape(self.__tournament_prefix) + '([0-9]{3})\.html' + ) self.__map_board_numbers(board_mapping) def write_bidding_tables(self): @@ -138,19 +190,33 @@ class JFRBidding: # compile bidding player-by-player for bid_index in bidding: bid = round_data[bid_index] - bidding_table[self.__directions.index(bid['direction'])].append(bid['bid']) + bidding_table[ + self.__directions.index(bid['direction']) + ].append(bid['bid']) last_bidder = bid['direction'] - # fill skipped calls for players before dealer in the first round + # fill skipped calls for players before dealer + # in the first round of bidding for pos in range(0, self.__directions.index(dealer)): bidding_table[pos].insert(0, '') - # fill skipped calls for players after pass out (so that bidding table is a proper matrix) - for pos in range(self.__directions.index(last_bidder), len(self.__directions)): + # fill skipped calls for players after pass out + # (so that bidding table is a proper matrix) + for pos in range( + self.__directions.index(last_bidder), + len(self.__directions) + ): bidding_table[pos].append('') - # transpose the bidding table, align it row-by-row (bidding round-by-round) + # transpose the bidding table + # aligning it row-by-row (bidding round-by-round) bidding_table = map(list, zip(*bidding_table)) - bidding_file_path = self.__get_bidding_file_output_path(self.__board_number_mapping[board_no], round_no, table_no) - with file(bidding_file_path, 'w') as bidding_file: - bidding_file.write(self.__format_bidding(bidding_table)) + bidding_fpath = self.__get_bidding_file_output_path( + self.__board_number_mapping[board_no], + round_no, + table_no + ) + with file(bidding_fpath, 'w') as bidding_file: + bidding_file.write( + self.__format_bidding(bidding_table) + ) def write_bidding_scripts(self): for tournament_file in self.__tournament_files: @@ -158,48 +224,90 @@ class JFRBidding: board_content = bs4(board_html, from_encoding='utf-8') header_scripts = board_content.select('head script') # check for jQuery, append if necessary - jquery_scripts = [script for script in header_scripts if script['src'] == 'javas/jquery.js'] + jquery_scripts = [ + script for script + in header_scripts + if script['src'] == 'javas/jquery.js' + ] if not len(jquery_scripts): - jquery_scripts.append(bs4('<script src="javas/jquery.js" type="text/javascript"></script>').script) + jquery_scripts.append( + bs4(''' + <script src="javas/jquery.js" + type="text/javascript"> + </script> + ''').script + ) board_content.head.append(jquery_scripts[0]) # check for bidding.js - bidding_scripts = [script for script in header_scripts if script['src'] == 'javas/bidding.js'] + bidding_scripts = [ + script for script + in header_scripts + if script['src'] == 'javas/bidding.js' + ] # and make sure bidding.js is appended after jQuery for script in bidding_scripts: script.extract() - jquery_scripts[0].insert_after(bs4('<script src="javas/bidding.js" type="text/javascript"></script>').script) + jquery_scripts[0].insert_after( + bs4(''' + <script src="javas/bidding.js" + type="text/javascript"> + </script> + ''').script + ) board_html.seek(0) - board_html.write(board_content.prettify('utf-8', formatter='html')) + board_html.write(board_content.prettify( + 'utf-8', + formatter='html' + )) board_html.truncate() def write_bidding_links(self): for tournament_file in self.__tournament_files: - file_number = re.match(self.__tournament_files_match, tournament_file).group(1) + file_number = re.match( + self.__tournament_files_match, + tournament_file + ).group(1) board_text_path = path.splitext(tournament_file)[0] + '.txt' with file(board_text_path, 'r+') as board_text: - board_text_content = bs4(board_text, from_encoding='iso-8859-2') + board_text_content = bs4( + board_text, + from_encoding='iso-8859-2' + ) for row in board_text_content.select('tr'): cells = row.select('td') - # traveller table rows for specific score entries should have 11 cells + # traveller table rows for specific score entries + # should have 11 cells if len(cells) == 11: - pair_numbers = sorted([int(cells[1].contents[0]), int(cells[2].contents[0])]) - bidding_link = bs4('<a href="#" class="biddingLink">[lic]</a>') - bidding_link.a['data-bidding-link'] = path.basename(self.__get_bidding_file_output_path( - int(file_number, 10), - pair_numbers=pair_numbers - )) + pair_numbers = sorted([ + int(cells[1].contents[0]), + int(cells[2].contents[0]) + ]) + bidding_link = bs4( + '<a href="#" class="biddingLink">[lic]</a>' + ) + bidding_link.a['data-bidding-link'] = path.basename( + self.__get_bidding_file_output_path( + int(file_number, 10), + pair_numbers=pair_numbers + ) + ) # fourth cell is the contract for link in cells[3].select('a.biddingLink'): link.extract() cells[3].append(bidding_link) board_text.seek(0) - board_text.write(board_text_content.table.prettify('iso-8859-2', formatter='html')) + board_text.write(board_text_content.table.prettify( + 'iso-8859-2', + formatter='html' + )) board_text.truncate() -bidding_parser = JFRBidding(bidding_file=sys.argv[1], - lineup_file=sys.argv[2], - file_prefix=sys.argv[3], - board_mapping=map(int, sys.argv[4:]) if len(sys.argv) > 4 else None) +bidding_parser = JFRBidding( + bidding_file=sys.argv[1], + lineup_file=sys.argv[2], + file_prefix=sys.argv[3], + board_mapping=map(int, sys.argv[4:]) if len(sys.argv) > 4 else None +) bidding_parser.write_bidding_tables() bidding_parser.write_bidding_scripts() bidding_parser.write_bidding_links() |