diff --git a/app/services/tournament_services/tournament_seeding.rb b/app/services/tournament_services/tournament_seeding.rb index 0f7c967..f302be5 100644 --- a/app/services/tournament_services/tournament_seeding.rb +++ b/app/services/tournament_services/tournament_seeding.rb @@ -19,14 +19,19 @@ class TournamentSeeding half_of_bracket = bracket_size / 2 available_bracket_lines = (1..bracket_size).to_a first_half_available_bracket_lines = (1..half_of_bracket).to_a + first_line_of_second_half_of_bracket = half_of_bracket + 1 + second_half_available_bracket_lines = (first_line_of_second_half_of_bracket..bracket_size).to_a # remove bracket lines that are taken from available_bracket_lines wrestlers_with_bracket_lines = wrestlers.select{|w| w.bracket_line != nil } wrestlers_with_bracket_lines.each do |wrestler| available_bracket_lines.delete(wrestler.bracket_line) first_half_available_bracket_lines.delete(wrestler.bracket_line) + second_half_available_bracket_lines.delete(wrestler.bracket_line) end + available_bracket_lines_to_use = set_random_seeding_bracket_line_order(first_half_available_bracket_lines, second_half_available_bracket_lines) + wrestlers_without_bracket_lines = wrestlers.select{|w| w.bracket_line == nil } if @tournament.tournament_type == "Pool to bracket" wrestlers_without_bracket_lines.shuffle.each do |wrestler| @@ -38,15 +43,10 @@ class TournamentSeeding else # Iterrate over the list randomly wrestlers_without_bracket_lines.shuffle.each do |wrestler| - if first_half_available_bracket_lines.size > 0 - random_available_bracket_line = first_half_available_bracket_lines.sample - wrestler.bracket_line = random_available_bracket_line - available_bracket_lines.delete(random_available_bracket_line) - first_half_available_bracket_lines.delete(random_available_bracket_line) - else - random_available_bracket_line = available_bracket_lines.sample - wrestler.bracket_line = random_available_bracket_line - available_bracket_lines.delete(random_available_bracket_line) + if available_bracket_lines_to_use.size > 0 + bracket_line_to_use = available_bracket_lines_to_use.first + wrestler.bracket_line = bracket_line_to_use + available_bracket_lines_to_use.delete(bracket_line_to_use) end end end @@ -81,4 +81,35 @@ class TournamentSeeding end return wrestlers end + + private + + def set_random_seeding_bracket_line_order(first_half_lines, second_half_lines) + # This method prevents double BYEs in round 1 + # It also evenly distributes matches from the top half of the bracket to the bottom half + # It does both of these while keeping the randomness of the line assignment + odd_or_even = [0, 1] + odd_or_even_sample = odd_or_even.sample + + # sort by odd or even based on the sample above + if odd_or_even_sample == 1 + # odd numbers first + sorted_first_half_lines = first_half_lines.sort_by { |n| n.even? ? 1 : 0 } + sorted_second_half_lines = second_half_lines.sort_by { |n| n.even? ? 1 : 0 } + else + # even numbers first + sorted_first_half_lines = first_half_lines.sort_by { |n| n.odd? ? 1 : 0 } + sorted_second_half_lines = second_half_lines.sort_by { |n| n.odd? ? 1 : 0 } + end + + # zip requires either even arrays or the receiver to be the bigger list + if first_half_lines.size >= second_half_lines.size + result = sorted_first_half_lines.zip(sorted_second_half_lines).flatten + else + result = sorted_second_half_lines.zip(sorted_first_half_lines).flatten + end + result.compact + result.delete(nil) + result + end end \ No newline at end of file diff --git a/test/integration/random_seeding_test.rb b/test/integration/random_seeding_test.rb new file mode 100644 index 0000000..a13eafb --- /dev/null +++ b/test/integration/random_seeding_test.rb @@ -0,0 +1,36 @@ +require 'test_helper' + +class RandomSeedingTest < ActionDispatch::IntegrationTest + def setup + + end + + def clean_up_original_seeds(tournament) + tournament.wrestlers.select{|w| w.original_seed > 12}.each do |wrestler| + wrestler.original_seed = nil + wrestler.save + end + tournament.wrestlers.reload.each do |wrestler| + wrestler.bracket_line = nil + wrestler.save + end + GenerateTournamentMatches.new(tournament).generate + end + + test "There are no double byes in a double elimination tournament round 1" do + create_double_elim_tournament_single_weight(18, "Regular Double Elimination 1-8") + clean_up_original_seeds(@tournament) + round_one_matches = @tournament.matches.reload.select{|m| m.round == 1} + assert round_one_matches.select{|m| m.w1.nil? and m.w2.nil? }.size == 0 + end + + test "There are the same number of matches in the top half and bottom half of a double elimination tournament in round 1" do + create_double_elim_tournament_single_weight(18, "Regular Double Elimination 1-8") + clean_up_original_seeds(@tournament) + round_one_matches = @tournament.matches.reload.select{|m| m.round == 1} + # 32 man bracket there are 16 matches so top half is bracket_position_number 1-8 and bottom is 9-16 + round_one_top_half = round_one_matches.select{|m| !m.w1.nil? and !m.w2.nil? and m.bracket_position_number < 9} + round_one_bottom_half = round_one_matches.select{|m| !m.w1.nil? and !m.w2.nil? and m.bracket_position_number > 8} + assert round_one_top_half.size == round_one_bottom_half.size + end +end \ No newline at end of file