summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2017-12-13 23:35:03 +0100
committeremkael <emkael@tlen.pl>2017-12-13 23:37:35 +0100
commit5fafec026532c9b00675f62658e08314e2096967 (patch)
treeaac99e4ad998d8c27542b466c6525b667bf0252b
parent1bda1e000faf1e10cf0cb2860b8d07a1edd88c0b (diff)
Compressing bidding data files into JSON files
Fixes #3
-rw-r--r--res/javas/bidding.js71
-rw-r--r--src/bidding_data.py129
2 files changed, 146 insertions, 54 deletions
diff --git a/res/javas/bidding.js b/res/javas/bidding.js
index 72a4ec4..bacbeca 100644
--- a/res/javas/bidding.js
+++ b/res/javas/bidding.js
@@ -1,39 +1,48 @@
-var display_bidding = function(element, bidding) {
- var popup = $('<tr class="bidding_popup"><td class="n">&nbsp;</td><td class="bidding_cell noc" colspan="1000"></td></tr>');
- popup.find('.bidding_cell').html(bidding);
- element.closest('tr').after(popup);
- element.data('bidding-row', popup);
-}
+var BIDDING_DATA = {
+ toggle_bidding: function() {
+ var element = $(this);
+ if (element.data('bidding-row')) {
+ element.data('bidding-row').remove();
+ element.removeData('bidding-row');
+ } else {
+ var popup = $('<tr class="bidding_popup"><td class="n">&nbsp;</td><td class="bidding_cell noc" colspan="1000"></td></tr>');
+ var bidding = BIDDING_DATA.data[element.attr('data-bidding-link')] || BIDDING_DATA.errorString;
+ popup.find('.bidding_cell').html(bidding);
+ element.closest('tr').after(popup);
+ element.data('bidding-row', popup);
+ }
+ return false;
+ },
-var load_bidding = function() {
- var elem = $(this);
- if (elem.data('bidding-row')) {
- elem.data('bidding-row').remove();
- elem.removeData('bidding-row');
- } else {
- $.ajax(
- {
- url: elem.attr('data-bidding-link'),
- complete: function(xhr, status) {
- if (status == 'success') {
- display_bidding(elem, xhr.responseText);
- }
- else {
- display_bidding(elem, 'Brak danych');
+ load_bidding: function() {
+ $('a.biddingLink').hide();
+ var dataLink = $('link[rel="bidding-file"]');
+ if (dataLink.size() > 0) {
+ $.ajax(
+ {
+ url: dataLink.eq(0).attr('src'),
+ complete: function(xhr, status) {
+ if (status == 'success') {
+ BIDDING_DATA.data = JSON.parse(xhr.responseText);
+ }
+ $('a.biddingLink').show();
}
}
- }
- );
- }
- return false;
-};
+ );
+ }
+ },
+
+ bind_bidding_links: function() {
+ $('a.biddingLink').each(function() {
+ $(this).unbind('click').attr('title', 'Pokaż/ukryj licytację').click(BIDDING_DATA.toggle_bidding);
+ });
+ },
-var bind_bidding_links = function() {
- $('a.biddingLink').each(function() {
- $(this).unbind('click').attr('title', 'Pokaż/ukryj licytację').click(load_bidding);
- });
+ data: {},
+ errorString: 'Brak danych'
};
$(document).ready(function() {
- setInterval(bind_bidding_links, 1000);
+ BIDDING_DATA.load_bidding();
+ setInterval(BIDDING_DATA.bind_bidding_links, 1000);
});
diff --git a/src/bidding_data.py b/src/bidding_data.py
index 6a41994..5c5b50a 100644
--- a/src/bidding_data.py
+++ b/src/bidding_data.py
@@ -8,10 +8,11 @@ by JFR Pary.
import glob
import logging as log
import hashlib
+import json
import re
import socket
import sys
-from os import path, remove
+from os import mkdir, path, remove, sep
import pypyodbc
@@ -163,6 +164,12 @@ def get_last_bidder(bidding):
return bidding[max(bidding.keys())]['direction']
+def filter_scripts(header_scripts, name):
+ """Return specific scripts from among script tag list."""
+ return [script for script in header_scripts
+ if script['src'] == name]
+
+
class JFRBidding(object):
"""Bidding data converter (from BWS data to JFR HTML pages)."""
@@ -210,24 +217,33 @@ class JFRBidding(object):
bid_cell.append(bid)
bidding_row.append(bid_cell)
log.getLogger('b_format').debug('%5s' * 4, *bid_round)
- return html_output.table.prettify()
+ return unicode(html_output.table)
def __get_bidding_file_output_path(self,
board_no,
- round_no=None,
- table_no=None,
- pair_numbers=None):
+ pair_numbers=None,
+ position_info=(None, None),
+ compressed=False):
"""
Compile file path for bidding data (HTML file with bidding).
Path format: {prefix}_bidding_{jfr_board_number}_{pair_numbers}.txt
+ Compressed path format: {prefix}_bidding_{jfr_board_number}.json
"""
- if pair_numbers is None:
- # read numbers from lineup
- pair_numbers = self.__round_lineups[round_no][table_no]
- return u'{0}_bidding_{1:03}_{2}.txt'.format(
- self.__tournament_prefix, board_no,
- '_'.join([str(num) for num in pair_numbers]))
+ if compressed:
+ return path.join(
+ path.dirname(self.__tournament_prefix),
+ 'bidding-data',
+ u'{0}_bidding_{1:03}.json'.format(
+ path.basename(self.__tournament_prefix), board_no))
+ else:
+ if pair_numbers is None:
+ # read numbers from lineup
+ (round_no, table_no) = position_info
+ pair_numbers = self.__round_lineups[round_no][table_no]
+ return u'{0}_bidding_{1:03}_{2}.txt'.format(
+ self.__tournament_prefix, board_no,
+ '_'.join([str(num) for num in pair_numbers]))
def __map_board_numbers(self):
"""
@@ -346,12 +362,10 @@ class JFRBidding(object):
bidding_path = self.__get_bidding_file_output_path(
int(file_number, 10),
pair_numbers=pair_numbers)
- bidding_link['data-bidding-link'] = path.basename(
- bidding_path)
+ bidding_link['data-bidding-link'] = '_'.join(
+ [str(pair) for pair in pair_numbers])
# only append link if we've got bidding data
- if isfile(path.join(
- path.dirname(self.__tournament_prefix),
- bidding_link['data-bidding-link'])):
+ if isfile(bidding_path):
if bidding_path in self.__bidding_files:
used_files.append(bidding_path)
log.getLogger('links').info(
@@ -375,6 +389,33 @@ class JFRBidding(object):
board_text.truncate()
return used_files
+ def __link_compressed_bidding_file(self, traveller_file, bidding_file):
+ """Put <link> markup for compressed bidding file in a traveller."""
+ if traveller_file in self.__tournament_files:
+ with file(traveller_file, 'r+') as traveller_html:
+ traveller = bs4(traveller_html, 'lxml')
+ for link in traveller.findAll('link', rel='bidding-file'):
+ link.extract()
+ bidding_scripts = filter_scripts(
+ traveller.select('head script'), 'javas/bidding.js')
+ if len(bidding_scripts) < 0:
+ log.getLogger('compress').warning(
+ 'traveller file %s lacks bidding JavaScript, skipping',
+ traveller_file)
+ else:
+ bidding_data_tag = traveller.new_tag('link')
+ bidding_data_tag['rel'] = 'bidding-file'
+ bidding_data_tag['src'] = path.relpath(
+ bidding_file, path.dirname(traveller_file)
+ ).replace(sep, '/')
+ bidding_scripts[0].insert_after(bidding_data_tag)
+ traveller_html.seek(0)
+ traveller_html.write(traveller.prettify(
+ 'utf-8', formatter='html'))
+ else:
+ log.getLogger('compress').warning(
+ 'traveller file %s not registered, skipping', traveller_file)
+
# sitting read from BWS
__round_lineups = {}
# bidding read from BWS
@@ -469,7 +510,7 @@ class JFRBidding(object):
bidding_fpath = \
self.__get_bidding_file_output_path(
self.__board_number_mapping[board_no],
- round_no, table_no)
+ position_info=(round_no, table_no))
self.__bidding_files.append(bidding_fpath)
self.__store_file_hash(bidding_fpath)
with file(bidding_fpath, 'w') as bidding_file:
@@ -501,8 +542,8 @@ class JFRBidding(object):
board_content = bs4(board_html, 'lxml', 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 = filter_scripts(
+ header_scripts, 'javas/jquery.js')
if not len(jquery_scripts):
jquery = board_content.new_tag(
'script', src='javas/jquery.js',
@@ -511,9 +552,8 @@ class JFRBidding(object):
board_content.head.append(jquery)
log.getLogger('scripts').debug('jQuery not found, adding')
# check for bidding.js
- bidding_scripts = [
- script for script in header_scripts
- if script['src'] == 'javas/bidding.js']
+ bidding_scripts = filter_scripts(
+ header_scripts, 'javas/bidding.js')
log.getLogger('scripts').debug('found %d bidding.js scripts',
len(bidding_scripts))
# and make sure bidding.js is appended after jQuery
@@ -577,6 +617,48 @@ class JFRBidding(object):
'bidding file %s does not exist', unused_file)
return used_board_files
+ def compress_bidding_files(self):
+ """Compile all *.txt for a traveller into a single *.json file."""
+ output_directory = path.join(
+ path.dirname(self.__tournament_prefix),
+ 'bidding-data'
+ )
+ if not path.exists(output_directory):
+ try:
+ mkdir(output_directory)
+ except OSError:
+ log.getLogger('compress').error(
+ 'unable to create directory for bidding-data: %s',
+ output_directory)
+ return []
+ compressed_files = []
+ for traveller in self.__tournament_files:
+ traveller_match = re.match(
+ self.__tournament_files_match, traveller)
+ if traveller_match:
+ board_number = int(traveller_match.group(1), 10)
+ compressed_file_path = self.__get_bidding_file_output_path(
+ board_number, compressed=True)
+ board_file_prefix = path.basename(
+ compressed_file_path).split('.')[0]
+ board_files = [filename for
+ filename in self.__bidding_files
+ if path.exists(filename) and
+ path.basename(filename).startswith(
+ board_file_prefix)]
+ compressed_board = {}
+ for board_file in board_files:
+ compressed_board[
+ '_'.join(board_file.split('.')[-2].split('_')[-2:])
+ ] = file(board_file).read()
+ json.dump(compressed_board, file(compressed_file_path, 'w'))
+ for board_file in board_files:
+ remove(board_file)
+ compressed_files.append(compressed_file_path)
+ self.__link_compressed_bidding_file(
+ traveller, compressed_file_path)
+ return compressed_files
+
def send_changed_files(self, files_to_send):
"""Send specified files from working directory via Goniec."""
if self.__goniec['host'] is not None:
@@ -701,10 +783,11 @@ def main():
goniec_setup=arguments.send_files,
goniec_force=arguments.force_resend
)
+ bidding_parser.write_bidding_tables()
all_files = []
- all_files += bidding_parser.write_bidding_tables()
all_files += bidding_parser.write_bidding_scripts()
all_files += bidding_parser.write_bidding_links()
+ all_files += bidding_parser.compress_bidding_files()
bidding_parser.send_changed_files(all_files)
except Exception as ex:
log.getLogger('root').error(ex)