Skip to content

Commit

Permalink
Add Knockout.reorder_participants
Browse files Browse the repository at this point in the history
  • Loading branch information
kostrykin committed Jan 30, 2024
1 parent 2d5bdda commit 5c959cb
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 20 deletions.
13 changes: 13 additions & 0 deletions tournaments/tournaments/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,10 +495,23 @@ def clean(self):
if self.double_elimination:
raise ValidationError('Double elimination is not implemented yet.')

@staticmethod
def reorder_participants(participants):
result = [None] * len(participants)
participants = list(participants)
for pidx in range(len(participants)):
i = pidx // 2
j = pidx % 2
result[pidx] = participants[i if j == 0 else -i - 1]
return result

def create_fixtures(self, participants):
assert len(participants) >= 2
levels = math.ceil(math.log2(len(participants)))

# Re-order the participants so that the first (highest ranked) are matched against the last (lowest ranked).
participants = Knockout.reorder_participants(participants)

# Identify fixtures by their path (which, in a binary tree, corresponds to the index of the node in binary representation, starting from `1` for the root).
remaining_participants = list(participants)
last_fixture_path = len(participants) - 1
Expand Down
47 changes: 27 additions & 20 deletions tournaments/tournaments/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,13 @@ def test_required_confirmations_count(self):

class KnockoutTest(ModeTestBase, TestCase):

def test_reorder_participants(self):
self.assertEqual(Knockout.reorder_participants([1]), [1])
self.assertEqual(Knockout.reorder_participants([1, 2]), [1, 2])
self.assertEqual(Knockout.reorder_participants([1, 2, 3]), [1, 3, 2])
self.assertEqual(Knockout.reorder_participants([1, 2, 3, 4, 5, 6]), [1, 6, 2, 5, 3, 4])
self.assertEqual(Knockout.reorder_participants([1, 2, 3, 4, 5, 6, 7]), [1, 7, 2, 6, 3, 5, 4])

def test_create_fixtures_2participants(self):
mode = Knockout.objects.create(tournament = self.tournament)
mode.create_fixtures(self.participants[:2])
Expand All @@ -711,7 +718,7 @@ def test_create_fixtures_4participants(self):
# Verify fixtures.
actual_fixtures = self.group_fixtures_by_level(mode)
expected_fixtures = {
0: [(4, 3), (2, 1)],
0: [(3, 2), (4, 1)],
1: [(None, None)]
}
self.assertEqual(actual_fixtures, expected_fixtures)
Expand All @@ -723,8 +730,8 @@ def test_create_fixtures_5participants(self):
# Verify fixtures.
actual_fixtures = self.group_fixtures_by_level(mode)
expected_fixtures = {
0: [(2, 1)],
1: [(None, 5), (4, 3)],
0: [(5, 1)],
1: [(None, 3), (4, 2)],
2: [(None, None)]
}
self.assertEqual(actual_fixtures, expected_fixtures)
Expand All @@ -738,8 +745,8 @@ def test_create_fixtures_6participants(self):
# Verify fixtures.
actual_fixtures = self.group_fixtures_by_level(mode)
expected_fixtures = {
0: [(4, 3), (2, 1)],
1: [(None, None), (6, 5)],
0: [(5, 2), (6, 1)],
1: [(None, None), (4, 3)],
2: [(None, None)]
}
self.assertEqual(actual_fixtures, expected_fixtures)
Expand All @@ -764,7 +771,7 @@ def test_propagate(self):
mode = self.test_create_fixtures_5participants()
playoff = mode.current_fixtures.get()

# Propagate play-off (user-2 vs. user-1).
# Propagate play-off (user-5 vs. user-1).
playoff.score = (10, 12)
playoff.save()
propagate_ret = mode.propagate(playoff)
Expand All @@ -773,14 +780,14 @@ def test_propagate(self):
# Verify fixtures after play-off.
actual_fixtures = self.group_fixtures_by_level(mode)
expected_fixtures = {
0: [(2, 1)],
1: [(1, 5), (4, 3)],
0: [(5, 1)],
1: [(1, 3), (4, 2)],
2: [(None, None)]
}
self.assertEqual(actual_fixtures, expected_fixtures)

# Propagate 1st seminfal (user-1 vs. user-5).
semifinal1 = mode.fixtures.get(player1 = User.objects.get(id = 1), player2 = User.objects.get(id = 5))
# Propagate 1st seminfal (user-1 vs. user-3).
semifinal1 = mode.fixtures.get(player1 = User.objects.get(id = 1), player2 = User.objects.get(id = 3))
semifinal1.score = (12, 10)
semifinal1.save()
propagate_ret = mode.propagate(semifinal1)
Expand All @@ -789,14 +796,14 @@ def test_propagate(self):
# Verify fixtures after 1st semifinal.
actual_fixtures = self.group_fixtures_by_level(mode)
expected_fixtures = {
0: [(2, 1)],
1: [(1, 5), (4, 3)],
0: [(5, 1)],
1: [(1, 3), (4, 2)],
2: [(1, None)]
}
self.assertEqual(actual_fixtures, expected_fixtures)

# Propagate 2nd seminfal (user-4 vs. user-3).
semifinal2 = mode.fixtures.get(player1 = User.objects.get(id = 4), player2 = User.objects.get(id = 3))
# Propagate 2nd seminfal (user-4 vs. user-2).
semifinal2 = mode.fixtures.get(player1 = User.objects.get(id = 4), player2 = User.objects.get(id = 2))
semifinal2.score = (12, 10)
semifinal2.save()
propagate_ret = mode.propagate(semifinal2)
Expand All @@ -809,8 +816,8 @@ def test_propagate(self):
# Verify fixtures after 2nd semifinal.
actual_fixtures = self.group_fixtures_by_level(mode)
expected_fixtures = {
0: [(2, 1)],
1: [(1, 5), (4, 3)],
0: [(5, 1)],
1: [(1, 3), (4, 2)],
2: [(1, 4)]
}
self.assertEqual(actual_fixtures, expected_fixtures)
Expand All @@ -836,7 +843,7 @@ def test_current_fixtures(self):
self.assertEqual(mode.current_fixtures.count(), 1)

fixture = mode.current_fixtures.get()
self.assertEqual(fixture.player1.id, 2)
self.assertEqual(fixture.player1.id, 5)
self.assertEqual(fixture.player2.id, 1)

self.confirm_fixture(fixture)
Expand All @@ -847,9 +854,9 @@ def test_current_fixtures(self):

fixtures = mode.current_fixtures.all()
self.assertEqual(fixtures[0].player1.id, 1)
self.assertEqual(fixtures[0].player2.id, 5)
self.assertEqual(fixtures[0].player2.id, 3)
self.assertEqual(fixtures[1].player1.id, 4)
self.assertEqual(fixtures[1].player2.id, 3)
self.assertEqual(fixtures[1].player2.id, 2)

self.confirm_fixture(fixtures[0])
self.assertEqual(mode.current_level, 1)
Expand All @@ -872,7 +879,7 @@ def test_current_fixtures(self):
def test_placements(self):
mode = self.test_propagate()
actual_placements = [user.id for user in mode.placements]
expected_placements = [1, 4, 5, 3, 2]
expected_placements = [1, 4, 3, 2, 5]
self.assertEqual(actual_placements, expected_placements)

def test_placements_empty(self):
Expand Down

0 comments on commit 5c959cb

Please sign in to comment.