| import math
|
| import random
|
|
|
| # make random results consistent between runs
|
| random.seed(42)
|
|
|
|
|
| def generate_players(n_players, min_rank, max_rank):
|
| ndigits = int(math.log10(n_players)) + 1
|
| print(ndigits)
|
| return [(f"Player{N:0{ndigits}d}", random.randint(min_rank, max_rank)) for N in range(n_players)]
|
|
|
|
|
| def sort_players(player_list):
|
| # the `key` here means we will sort using the rank value
|
| # the result is a list of players from low to high ranks
|
| return sorted(player_list, key=lambda pair: pair[1])
|
|
|
|
|
|
|
| def rank_diffs(left, mid, right):
|
| right_diff = abs(right[1] - mid[1])
|
| if left:
|
| left_diff = abs(left[1] - mid[1])
|
| else:
|
| left_diff = float('inf')
|
|
|
| return left_diff, right_diff
|
|
|
|
|
| def match_players(player_list, max_rank_diff=50):
|
| players = player_list.copy()
|
| matches = []
|
|
|
| while len(players) >= 2:
|
| right_player = players.pop()
|
| mid_player = players.pop()
|
|
|
| if players:
|
| # if there are at least three players in the list, we need to look
|
| # on either side of the 'middle' player
|
| left_player = players.pop()
|
| else:
|
| # we're looking at the last two players in this list
|
| left_player = None
|
|
|
| left_diff, right_diff = rank_diffs(left_player, mid_player, right_player)
|
|
|
|
|
| #
|
| # |---| |---| |---|
|
| # | L | ----- | M | ----- | R |
|
| # |---| | |---| | |---|
|
| # | |
|
| # left_diff right_diff
|
|
|
| if left_diff < right_diff:
|
| lo = left_player
|
| hi = mid_player
|
| diff = left_diff
|
|
|
| if right_diff <= max_rank_diff:
|
| # right player might match someone else, put them back in the pool
|
| players.append(right_player)
|
| else:
|
| # right player will not match with anyone
|
| matches.append((right_player, None))
|
| else:
|
| # left_diff >= right_diff
|
| # right player wins the tie when left_diff == right_diff
|
| lo = mid_player
|
| hi = right_player
|
| diff = right_diff
|
|
|
| if left_player:
|
| # left player exists and may match someone else, put them back in the pool
|
| players.append(left_player)
|
|
|
| #
|
| # |----| |----|
|
| # | lo | ----- | hi |
|
| # |----| | |----|
|
| # |
|
| # diff
|
|
|
| if diff <= max_rank_diff:
|
| matches.append((lo, hi))
|
| else:
|
| # hi player will not match with anyone
|
| matches.append((hi, None))
|
| # lo player might match someone else, put them back
|
| players.append(lo)
|
|
|
| return matches
|
|
|
|
|
| if __name__ == "__main__":
|
| print("generating players")
|
| unsorted_players = generate_players(25, min_rank=1000, max_rank=2000)
|
| # unsorted_players = [
|
| # ("Player1", 2000),
|
| # ("Player2", 2015),
|
| # ("Player3", 2020),
|
| # ("Player4", 2030),
|
| # ]
|
| print("unsorted players:")
|
| print(unsorted_players)
|
| print("---\n")
|
|
|
| print("sorting players")
|
| sorted_players = sort_players(unsorted_players)
|
| print("sorted players:")
|
| print(sorted_players)
|
| print("---\n")
|
|
|
| print("creating match pairs")
|
| matches = match_players(sorted_players)
|
| for left_player, right_player in matches:
|
| if right_player is None:
|
| print(f"{left_player!r} is unmatched")
|
| else:
|
| left_rank = left_player[1]
|
| right_rank = right_player[1]
|
| rank_diff = abs(left_rank - right_rank)
|
| print(f"{left_player!r} plays {right_player!r} (rank difference is {rank_diff})")
|
| $ python3 theWhisper_.py
|
| generating players
|
| 2
|
| unsorted players:
|
| [('Player00', 1654), ('Player01', 1114), ('Player02', 1025), ('Player03', 1759), ('Player04', 1281), ('Player05', 1250), ('Player06', 1228), ('Player07', 1142), ('Player08', 1754), ('Player09', 1104), ('Player10', 1692), ('Player11', 1758), ('Player12', 1913), ('Player13', 1558), ('Player14', 1089), ('Player15', 1604), ('Player16', 1432), ('Player17', 1032), ('Player18', 1030), ('Player19', 1095), ('Player20', 1223), ('Player21', 1238), ('Player22', 1517), ('Player23', 1616), ('Player24', 1027)]
|
| ---
|
|
|
| sorting players
|
| sorted players:
|
| [('Player02', 1025), ('Player24', 1027), ('Player18', 1030), ('Player17', 1032), ('Player14', 1089), ('Player19', 1095), ('Player09', 1104), ('Player01', 1114), ('Player07', 1142), ('Player20', 1223), ('Player06', 1228), ('Player21', 1238), ('Player05', 1250), ('Player04', 1281), ('Player16', 1432), ('Player22', 1517), ('Player13', 1558), ('Player15', 1604), ('Player23', 1616), ('Player00', 1654), ('Player10', 1692), ('Player08', 1754), ('Player11', 1758), ('Player03', 1759), ('Player12', 1913)]
|
| ---
|
|
|
| creating match pairs
|
| ('Player12', 1913) is unmatched
|
| ('Player11', 1758) plays ('Player03', 1759) (rank difference is 1)
|
| ('Player08', 1754) is unmatched
|
| ('Player00', 1654) plays ('Player10', 1692) (rank difference is 38)
|
| ('Player15', 1604) plays ('Player23', 1616) (rank difference is 12)
|
| ('Player22', 1517) plays ('Player13', 1558) (rank difference is 41)
|
| ('Player16', 1432) is unmatched
|
| ('Player05', 1250) plays ('Player04', 1281) (rank difference is 31)
|
| ('Player20', 1223) plays ('Player06', 1228) (rank difference is 5)
|
| ('Player21', 1238) is unmatched
|
| ('Player01', 1114) plays ('Player07', 1142) (rank difference is 28)
|
| ('Player14', 1089) plays ('Player19', 1095) (rank difference is 6)
|
| ('Player09', 1104) is unmatched
|
| ('Player18', 1030) plays ('Player17', 1032) (rank difference is 2)
|
| ('Player02', 1025) plays ('Player24', 1027) (rank difference is 2)
|