From f118c0f3704fa07a33543ee2aa018f16ac993b5a Mon Sep 17 00:00:00 2001 From: emkael Date: Wed, 22 Feb 2017 14:25:36 +0100 Subject: Initial commit --- .gitignore | 2 + playoff.js | 137 +++++++++++++++++++++++++++++++++++ playoff.py | 205 ++++++++++++++++++++++++++++++++++++++++++++++++++++ playoff/__init__.py | 0 playoff/sql.py | 23 ++++++ playoff/template.py | 116 +++++++++++++++++++++++++++++ 6 files changed, 483 insertions(+) create mode 100644 .gitignore create mode 100644 playoff.js create mode 100644 playoff.py create mode 100644 playoff/__init__.py create mode 100644 playoff/sql.py create mode 100644 playoff/template.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8b70d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*.json diff --git a/playoff.js b/playoff.js new file mode 100644 index 0000000..9060c6d --- /dev/null +++ b/playoff.js @@ -0,0 +1,137 @@ +var playoff = { + + settings: { + 'winner_h_offset': 10, + 'loser_h_offset': 20, + 'winner_v_offset': -4, + 'loser_v_offset': 4, + 'loser_colour': '#ff0000', + 'winner_colour': '#00ff00' + }, + + drawLine: function(ctx, line) { + ctx.beginPath(); + ctx.moveTo(line[0], line[1]); + ctx.lineTo(line[2], line[3]); + ctx.stroke(); + }, + + run: function() { + var boxes = document.getElementsByClassName('playoff_matchbox'); + var lines = { + 'winner': {}, + 'loser': {} + }; + var boxes_idx = {}; + for (var b = 0; b < boxes.length; b++) { + var id = boxes[b].getAttribute('data-id'); + boxes_idx[id] = boxes[b]; + for (var attr in lines) { + var value = boxes[b].getAttribute('data-' + attr); + if (value) { + if (!lines[attr][value]) { + lines[attr][value] = []; + } + lines[attr][value].push(id); + } + } + } + var canvas = document.getElementById('playoff_canvas'); + var ctx = canvas.getContext('2d'); + for (var type in lines) { + ctx.strokeStyle = this.settings[type + '_colour']; + for (var from in lines[type]) { + var to = lines[type][from]; + from = from.split(' '); + var horizontal_from = []; + var vertical_from = [0, canvas.height, 0, 0]; + for (var f = 0; f < from.length; f++) { + var box = boxes_idx[from[f]]; + var line = [ + parseInt(box.style.left) + parseInt(box.clientWidth), + parseInt(box.style.top) + 0.5 * parseInt(box.clientHeight) + this.settings[type + '_v_offset'], + parseInt(box.style.left) + parseInt(box.clientWidth) + this.settings[type + '_h_offset'], + parseInt(box.style.top) + 0.5 * parseInt(box.clientHeight) + this.settings[type + '_v_offset'] + ]; + horizontal_from.push(line); + for (var l in horizontal_from) { + if (horizontal_from[l][2] < line[2]) { + horizontal_from[l][2] = line[2]; + } + if (vertical_from[0] < horizontal_from[l][2]) { + vertical_from[0] = horizontal_from[l][2]; + vertical_from[2] = horizontal_from[l][2]; + } + if (vertical_from[1] > horizontal_from[l][3]) { + vertical_from[1] = horizontal_from[l][3]; + } + if (vertical_from[3] < horizontal_from[l][3]) { + vertical_from[3] = horizontal_from[l][3]; + } + } + } + var horizontal_to = []; + var vertical_to = [canvas.width, canvas.height, canvas.width, 0]; + for (var t = 0; t < to.length; t++) { + var box = boxes_idx[to[t]]; + var line = [ + parseInt(box.style.left), + parseInt(box.style.top) + 0.5 * parseInt(box.clientHeight) + this.settings[type + '_v_offset'], + parseInt(box.style.left) - this.settings[type + '_h_offset'], + parseInt(box.style.top) + 0.5 * parseInt(box.clientHeight) + this.settings[type + '_v_offset'] + ]; + horizontal_to.push(line); + for (var l in horizontal_to) { + if (horizontal_to[l][2] > line[2]) { + horizontal_to[l][2] = line[2]; + } + if (vertical_to[0] > horizontal_to[l][2]) { + vertical_to[0] = horizontal_to[l][2]; + vertical_to[2] = horizontal_to[l][2]; + } + if (vertical_to[1] > horizontal_to[l][3]) { + vertical_to[1] = horizontal_to[l][3]; + } + if (vertical_to[3] < horizontal_to[l][3]) { + vertical_to[3] = horizontal_to[l][3]; + } + } + } + var midpoints = [ + [ + (vertical_from[0] + vertical_from[2]) / 2, + (vertical_from[1] + vertical_from[3]) / 2 + ], + [ + (vertical_from[0] + vertical_from[2] + vertical_to[0] + vertical_to[2]) / 4, + (vertical_from[1] + vertical_from[3]) / 2 + ], + [ + (vertical_from[0] + vertical_from[2] + vertical_to[0] + vertical_to[2]) / 4, + (vertical_to[1] + vertical_to[3]) / 2 + ], + [ + (vertical_to[0] + vertical_to[2]) / 2, + (vertical_to[1] + vertical_to[3]) / 2 + ] + ] + for (var l in horizontal_from) { + this.drawLine(ctx, horizontal_from[l]); + } + this.drawLine(ctx, vertical_from); + for (var l in horizontal_to) { + this.drawLine(ctx, horizontal_to[l]); + } + this.drawLine(ctx, vertical_to); + for (var m = 0; m < midpoints.length-1; m++) { + this.drawLine(ctx, [ + midpoints[m][0], midpoints[m][1], midpoints[m+1][0], midpoints[m+1][1] + ]); + } + } + } + } + +} + +playoff.run(); diff --git a/playoff.py b/playoff.py new file mode 100644 index 0000000..e2243d8 --- /dev/null +++ b/playoff.py @@ -0,0 +1,205 @@ +import json, os, shutil, sys +import mysql.connector +from datetime import datetime +from playoff import sql as p_sql +from playoff import template as p_temp + +settings = json.load(open(sys.argv[1])) +teams = settings['teams'] +leaderboard = [None] * len(teams) + +database = mysql.connector.connect( + user=settings['database']['user'], + password=settings['database']['pass'], + host=settings['database']['host'], + port=settings['database']['port'] +) +db_cursor = database.cursor(buffered=True) + +def db_fetch(db, sql, params): + db_cursor.execute(sql.replace('#db#', db), params) + row = db_cursor.fetchone() + return row + +def get_shortname(fullname): + for team in settings['teams']: + if team[0] == fullname: + return team[1] + return fullname + +def get_match_table(match): + rows = '' + for team in match.teams: + rows += p_temp.MATCH_TEAM_ROW % ( + team.name, + ' / '.join([get_shortname(name) for name in team.name.split('
')]), + team.score + ) + html = p_temp.MATCH_TABLE.decode('utf8') % ( + int(settings['page']['width'] * 0.75), + int(settings['page']['width'] * 0.25), + rows + ) + if match.running > 0: + html += p_temp.MATCH_RUNNING % (match.link, match.running) + return html + +def get_match_grid(grid, matches, width, height): + grid_boxes = '' + col_no = 0 + for column in grid: + grid_x = col_no * (settings['page']['width'] + settings['page']['margin']) + grid_header = p_temp.MATCH_GRID_PHASE_RUNNING if len([match for match in column if matches[match].running > 0]) > 0 else p_temp.MATCH_GRID_PHASE + grid_boxes += grid_header % ( + settings['phases'][col_no]['link'], + settings['page']['width'], + grid_x, + settings['phases'][col_no]['title'] + ) + row_no = 0 + column_height = height / len(column) + for match in column: + grid_y = int(row_no * column_height + 0.5 * (column_height - settings['page']['height'])) + grid_boxes += p_temp.MATCH_BOX % ( + grid_x, grid_y, + match, + ' '.join([str(m) for m in matches[match].winner_matches]) if matches[match].winner_matches is not None else '', + ' '.join([str(m) for m in matches[match].loser_matches]) if matches[match].loser_matches is not None else '', + get_match_table(matches[match]) + ) + row_no += 1 + col_no += 1 + return p_temp.MATCH_GRID % (width, height, width, height, grid_boxes) + +def get_leaderboard_table(leaderboard): + position = 1 + rows = '' + for team in [team if team is not None else '' for team in leaderboard]: + rows += p_temp.LEADERBOARD_ROW % (position, team) + position +=1 + html = p_temp.LEADERBOARD.decode('utf8') % (rows) + return html + +class Team: + name = '' + score = 0.0 + +class Match: + teams = None + running = 0 + link = '#' + winner = None + loser = None + winner_matches = None + loser_matches = None + +match_info = {} + +def get_match_info(match): + info = Match() + info.teams = [Team(), Team()] + info.winner_matches = [] + info.loser_matches = [] + for i in range(0, 2): + if 'winner' in match['teams'][i]: + info.winner_matches += match['teams'][i]['winner'] + if 'loser' in match['teams'][i]: + info.loser_matches += match['teams'][i]['loser'] + info.winner_matches = list(set(info.winner_matches)) + info.loser_matches = list(set(info.loser_matches)) + try: + row = db_fetch(match['database'], p_sql.MATCH_RESULTS, (match['table'], match['round'])) + info.teams[0].name = row[0] + info.teams[1].name = row[1] + info.teams[0].score = row[3] + row[5] + info.teams[1].score = row[4] + row[6] + if row[2] > 0: + info.teams[0].score += row[2] + else: + info.teams[1].score -= row[2] + except Exception as e: + for i in range(0, 2): + if isinstance(match['teams'][i], basestring): + info.teams[i].name = match['teams'][i] + else: + teams = [] + if 'winner' in match['teams'][i]: + teams += [ + match_info[winner_match].winner + for winner_match in match['teams'][i]['winner'] + ] + if 'loser' in match['teams'][i]: + teams += [ + match_info[loser_match].loser + for loser_match in match['teams'][i]['loser'] + ] + info.teams[i].name = '
'.join([ + team if team is not None else '??' + for team in teams] + ) if len([team for team in teams if team is not None]) > 0 else '' + + try: + row = db_fetch(match['database'], p_sql.BOARD_COUNT, (match['table'], match['round'])) + if row[1] > 0: + info.running = int(row[1]) + if row[1] == row[0]: + info.running = 0 + info.winner = info.teams[0].name if info.teams[0].score > info.teams[1].score else info.teams[1].name + info.loser = info.teams[1].name if info.teams[0].score > info.teams[1].score else info.teams[0].name + except Exception as e: + pass + return info + +grid = [] +for phase in settings['phases']: + grid.append([]) + for match in phase['matches']: + match_info[match['id']] = get_match_info(match) + match_info[match['id']].link = phase['link'] + grid[-1].append(match['id']) + +leaderboard_teams = {} +for phase in settings['phases']: + for match in phase['matches']: + if 'winner' in match: + winner_key = tuple(match['winner']) + if winner_key not in leaderboard_teams: + leaderboard_teams[winner_key] = [] + leaderboard_teams[winner_key].append(match_info[match['id']].winner) + if 'loser' in match: + loser_key = tuple(match['loser']) + if loser_key not in leaderboard_teams: + leaderboard_teams[loser_key] = [] + leaderboard_teams[loser_key].append(match_info[match['id']].loser) + +for positions, teams in leaderboard_teams.iteritems(): + positions = list(positions) + if len(positions) == len([team for team in teams if team is not None]): + for table_team in settings['teams']: + if table_team[0] in teams: + position = positions.pop(0) + leaderboard[position-1] = table_team[0] + +grid_columns = len(settings['phases']) +grid_rows = max([len(phase['matches']) for phase in settings['phases']]) +grid_height = grid_rows * (settings['page']['height'] + settings['page']['margin']) - settings['page']['margin'] +grid_width = grid_columns * (settings['page']['width'] + settings['page']['margin']) - settings['page']['margin'] + +output = open(settings['output'], 'w') +output.write(( + p_temp.PAGE % ( + p_temp.PAGE_HEAD % ( + p_temp.PAGE_HEAD_REFRESH % (settings['page']['refresh']) if settings['page']['refresh'] > 0 else '', + settings['page']['title'] + ), + p_temp.PAGE_BODY % ( + settings['page']['logoh'], + get_match_grid(grid, match_info, grid_width, grid_height), + get_leaderboard_table(leaderboard), + p_temp.PAGE_BODY_FOOTER.decode('utf8') % (datetime.now().strftime('%Y-%m-%d o %H:%M')) + ) + )).encode('utf8') +) + +shutil.copy(unicode(os.path.join(os.path.dirname(__file__), 'playoff.js')), + unicode(os.path.join(os.path.dirname(settings['output']), 'sklady/playoff.js'))) diff --git a/playoff/__init__.py b/playoff/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/playoff/sql.py b/playoff/sql.py new file mode 100644 index 0000000..0bd2df7 --- /dev/null +++ b/playoff/sql.py @@ -0,0 +1,23 @@ +MATCH_RESULTS = ''' +SELECT t1.fullname, t2.fullname, matches.carry, matches.vph, matches.vpv, matches.corrh, matches.corrv +FROM #db#.matches matches +JOIN #db#.teams t1 + ON t1.id = #db#.matches.homet +JOIN #db#.teams t2 + ON t2.id = #db#.matches.visit +WHERE matches.tabl = %s AND matches.rnd = %s +''' + +BOARD_COUNT = ''' +SELECT segmentsperround*boardspersegment, SUM(sc1.contract IS NOT NULL AND sc2.contract IS NOT NULL) +FROM #db#.scores sc1 +JOIN #db#.scores sc2 + ON sc1.rnd = sc2.rnd + AND sc1.segment = sc2.segment + AND sc1.tabl = sc2.tabl + AND sc1.board = sc2.board + AND sc1.room = 1 + AND sc2.room = 2 +JOIN #db#.admin +WHERE sc1.tabl = %s AND sc1.rnd = %s +''' diff --git a/playoff/template.py b/playoff/template.py new file mode 100644 index 0000000..5fe855c --- /dev/null +++ b/playoff/template.py @@ -0,0 +1,116 @@ +#encoding=utf-8 + +MATCH_TABLE = ''' + + + + + +%s +
  wynik 
+''' + +MATCH_TEAM_ROW = ''' + + %s  + %.1f  + +''' + +MATCH_RUNNING = ''' + + +%d + + +''' + +MATCH_GRID = ''' +
+ +%s + +
+''' + +MATCH_GRID_PHASE = ''' +%s +''' + +MATCH_GRID_RUNNING_PHASE = ''' + + +%s + + +''' + +MATCH_BOX = ''' +
+%s +
+''' + +LEADERBOARD = ''' + + + + + + + + + + + +%s +
KLASYFIKACJA KOŃCOWA
 
 miejsce  drużyna 
+''' + +LEADERBOARD_ROW = ''' + +%d + %s  + +''' + +PAGE_HEAD = ''' + + + + + + +%s +%s + + +''' + +PAGE_HEAD_REFRESH = ''' + +''' + +PAGE_BODY = ''' + +%s +%s +%s +%s +''' + +PAGE_BODY_FOOTER = ''' +

 Admin ©Jan Romański'2005, PlayOff ©Michał Klichowicz'2017, strona wygenerowana %s

+''' + +PAGE = ''' + + + +%s + + +%s + + +''' -- cgit v1.2.3