def make_pairs_single_elimination(self, round, ranking): previous_round = round.previous_round if previous_round and previous_round.type == Round.TYPE_SINGLE_ELIM: previous_winners = [m.winner for m in previous_round.matches] # this is expected to return items from ranking... players = [{'player': p} for p in previous_winners] if odd(players): # something's wrong, abort return [] return split(players, 2) else: playoff_rounds_count = (round.tournament.rounds .filter(type=Round.TYPE_SINGLE_ELIM) .count()) player_count = 2 ** playoff_rounds_count players = ranking[:player_count] half = player_count / 2 pairs = zip(players[:half], reversed(players[half:])) for i in range(1, playoff_rounds_count - 1): half = len(pairs) / 2 / i pairs = merge(merge(map( lambda x, y: [x, y], split(pairs, i)[:half], reversed(split(pairs, i)[half:]) ))) return pairs
def _bye_if_odd(self, round, ranking): """ If ranking player count is odd, pops a random player from a group of players with the lowest score and who didn't receive a bye yet, and gives them a bye. Returns odd-length ranking. """ if odd(ranking): bye_candidates = [x for x in ranking if not x['player'].competitor.received_bye] if not bye_candidates: # everyone received a bye -- it's probably messed up # TODO: logging return [] bye_candidates.sort(key=lambda x: x['points']) lowest_points = bye_candidates[0]['points'] lp_group = [x for x in bye_candidates if x['points'] == lowest_points] bye_receiver = pop_random(lp_group) ranking.pop(ranking.index(bye_receiver)) competitor = bye_receiver['player'].competitor competitor.received_bye = True competitor.extra_points = 3 competitor.extra_buchholz = round.index * 3 + 1 competitor.save() return ranking
def make_pairs_swiss(self, round, ranking): ranking = self._bye_if_odd(round, ranking) group = [] pairs = [] points = ranking[0]['points'] def pair(group): assert not odd(group) half = len(group) / 2 return [list(p) for p in zip(group[:half], group[half:])] for player in ranking: if player['points'] == points or odd(group): group.append(player) else: pairs += pair(group) group = [player] points = player['points'] pairs += pair(group) pairs = self._fix_rematches(pairs) return pairs
def pair(group): assert not odd(group) half = len(group) / 2 return [list(p) for p in zip(group[:half], group[half:])]