From 4b4fdc5f52d0a5e0728cf2fe974739ead34c1993 Mon Sep 17 00:00:00 2001 From: Peter Law Date: Sun, 15 Apr 2012 12:32:12 +0100 Subject: [PATCH] Add support for disqualified zones. If a zone is DSQ, then it gets zero league points, and it is removed from contention for any possible tied places. --- bin/scores.py | 42 +++++++++++++++++++++++++++++++++--------- test/test-scores.py | 30 ++++++++++++++++++++++++++---- 2 files changed, 59 insertions(+), 13 deletions(-) diff --git a/bin/scores.py b/bin/scores.py index ff4d6ee..438c258 100644 --- a/bin/scores.py +++ b/bin/scores.py @@ -176,10 +176,11 @@ def check_match(match): if buckets > max_buckets: print('WARNING! Too many buckets in this match! ({0})'.format(buckets)) -def calc_positions(zpoints): +def calc_positions(zpoints, dsq_list): """ A function to work out the placings of zones in a game, given the game points. @param zpoints: a dict of zone number to game points. + @param dsq_list: a list of zones that should be considered below last. @returns: a dict of position to array of zone numbers. """ @@ -187,6 +188,8 @@ def calc_positions(zpoints): points_map = {} for z, p in zpoints.iteritems(): + if z in dsq_list: + p = -1 if not points_map.has_key(p): points_map[p] = [] points_map[p].append(z) @@ -198,16 +201,24 @@ def calc_positions(zpoints): return pos_map -def calc_league_points(pos_map): +def calc_league_points(pos_map, dsq_list): """ A function to work out the league points for each zone, given the rankings within that game. @param pos_map: a dict of position to array of zone numbers. + @param dsq_list: a list of zones that shouldn't be awarded league points. @returns: a dict of zone number to league points. """ lpoints = {} for pos, zones in pos_map.iteritems(): + # remove any that are dsqaulified + # note that we do this before working out the ties, so that any + # dsq tie members are removed from contention + zones = [ z for z in zones if z not in dsq_list ] + if len(zones) == 0: + continue + # max points is 4, add one because pos is 1-indexed points = (4 + 1) - pos # Now that we have the value for this position if it were not a tie, @@ -220,33 +231,46 @@ def calc_league_points(pos_map): for z in zones: lpoints[z] = points + # those that were dsq get 0 + for z in dsq_list: + lpoints[z] = 0.0 + return lpoints -def get_league_points(zpoints): +def get_league_points(zpoints, dsq): """ A function to work out the league points for each zone, given the game points. This is a thin convenience wrapper around `calc_positions` and `calc_league_points`. @param zpoints: a dict of zone number to game points. + @param dsq: a list of zones that shouldn't be awarded league points. @returns: a dict of zone number to league points. """ - pos_map = calc_positions(zpoints) - lpoints = calc_league_points(pos_map) + pos_map = calc_positions(zpoints, dsq) + lpoints = calc_league_points(pos_map, dsq) return lpoints def match_rank(match,sub): - zpoints = _get_zone_points(match) - lpoints = get_league_points(zpoints) + zpoints, dsq = _get_zone_data(match) + lpoints = get_league_points(zpoints, dsq) _store_league_points(match, sub, lpoints) -def _get_zone_points(match): +def _get_zone_data(match): + """ + @returns: A tuple of: + a dict that contains the points for each zone + a list that contains any zones that were disqualified + """ zpoints = dict() + dsq = [] for z in range(4): zone = actor.hgetall('{0}.scores.match.{1}.{2}'.format(BASE,match,z)) if zone != {}: zpoints['{0}'.format(z)] = game_points([match,z,zone['trobot'],zone['tzone'],zone['tbucket'],zone['nbuckets']]) + if zone.get('disqualified', None) == "True": + dsq.append('{0}'.format(z)) else: zpoints['{0}'.format(z)] = -1 - return zpoints + return zpoints, dsq def _store_league_points(match, sub, lpoints): mat = split_match(actor.lindex('{0}.matches'.format(BASE), match)) diff --git a/test/test-scores.py b/test/test-scores.py index 864fa20..d1be00e 100644 --- a/test/test-scores.py +++ b/test/test-scores.py @@ -21,29 +21,51 @@ simple_pos = { 1: ['0'], 2: ['1'], 3: ['2'], 4: ['3'] } simple_points = { '0': 4.0, '1': 3.0, '2': 2.0, '3': 1.0 } +dsq_data = { '0': 3, '1': 2, '2': 1, '3': 0 } +dsq_dsq = [ '0', '2' ] +dsq_pos = { 1: ['1'], 2: ['3'], 3: ['0', '2'] } +dsq_points = { '0': 0.0, '1': 4.0, '2': 0.0, '3': 3.0 } + tie1_data = { '0': 3, '1': 3, '2': 0, '3': 0 } tie1_pos = { 1: ['1', '0'], 3: ['3', '2'] } tie1_points = { '0': 3.5, '1': 3.5, '2': 1.5, '3': 1.5 } +tie2_data = { '0': 3, '1': 3, '2': 0, '3': 0 } +tie2_dsq = [ '0', '2' ] +tie2_pos = { 1: ['1'], 2: ['3'], 3: ['0', '2'] } +tie2_points = { '0': 0.0, '1': 4.0, '2': 0.0, '3': 3.0 } + class PositionsTests(unittest.TestCase): def test_simple(self): - pos = scores.calc_positions(simple_data) + pos = scores.calc_positions(simple_data, []) util.assertEqual(simple_pos, pos, "Wrong positions") def test_tie(self): - pos = scores.calc_positions(tie1_data) + pos = scores.calc_positions(tie1_data, []) util.assertEqual(tie1_pos, pos, "Wrong positions") + def test_dsq(self): + pos = scores.calc_positions(dsq_data, dsq_dsq) + util.assertEqual(dsq_pos, pos, "Wrong positions") + + def test_dsq_tie(self): + pos = scores.calc_positions(tie2_data, tie2_dsq) + util.assertEqual(tie2_pos, pos, "Wrong positions") + class LeaguePointsTests(unittest.TestCase): def test_simple(self): - points = scores.calc_league_points(simple_pos) + points = scores.calc_league_points(simple_pos, []) util.assertEqual(simple_points, points, "Wrong points") def test_tie(self): - points = scores.calc_league_points(tie1_pos) + points = scores.calc_league_points(tie1_pos, []) util.assertEqual(tie1_points, points, "Wrong points") + def test_dsq_tie(self): + points = scores.calc_league_points(tie2_pos, tie2_dsq) + util.assertEqual(tie2_points, points, "Wrong points") + if __name__ == '__main__': unittest.main(buffer=True)