Merge pull request #30 from turniere/ticket/TURNIERE-149
Fix missing stage when creating tournament with odd amount of teams
This commit is contained in:
commit
80d480bee4
|
|
@ -6,9 +6,16 @@ class MatchService
|
||||||
# @param teams [Array] the teams to generate matches with
|
# @param teams [Array] the teams to generate matches with
|
||||||
# @return [Array] the generated matches
|
# @return [Array] the generated matches
|
||||||
def self.generate_matches(teams)
|
def self.generate_matches(teams)
|
||||||
if teams.size < 2
|
if teams.empty?
|
||||||
# should be prevented by controller
|
# should be prevented by controller
|
||||||
return
|
raise 'Cannot generate Matches without teams'
|
||||||
|
end
|
||||||
|
|
||||||
|
if teams.size == 1
|
||||||
|
matches = []
|
||||||
|
match = Match.new state: :single_team, position: 1, match_scores: [MatchScore.create(team: teams.first)]
|
||||||
|
matches << match
|
||||||
|
return matches
|
||||||
end
|
end
|
||||||
|
|
||||||
# normal_games = number of matches with two teams attending
|
# normal_games = number of matches with two teams attending
|
||||||
|
|
@ -37,9 +44,11 @@ class MatchService
|
||||||
matches << match
|
matches << match
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# the start point is to compensate for all the teams that are already within a "normal" match
|
||||||
|
startpoint = matches.size
|
||||||
until matches.size >= needed_games
|
until matches.size >= needed_games
|
||||||
# while we do not have enough matches in general we need to fill the array with "single team" matches
|
# while we do not have enough matches in general we need to fill the array with "single team" matches
|
||||||
i = matches.size
|
i = matches.size + startpoint
|
||||||
match = Match.new state: :single_team, position: i, match_scores: [MatchScore.create(team: teams[i])]
|
match = Match.new state: :single_team, position: i, match_scores: [MatchScore.create(team: teams[i])]
|
||||||
matches << match
|
matches << match
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,12 @@ class PlayoffStageService
|
||||||
# @param number_of_teams [Integer] the teams number of teams to calculate amount of stages
|
# @param number_of_teams [Integer] the teams number of teams to calculate amount of stages
|
||||||
# @return [Integer] amount of required stages
|
# @return [Integer] amount of required stages
|
||||||
def self.calculate_required_stage_count(number_of_teams)
|
def self.calculate_required_stage_count(number_of_teams)
|
||||||
if number_of_teams.zero? || number_of_teams == 1
|
if number_of_teams == 1
|
||||||
0
|
1
|
||||||
else
|
else
|
||||||
# black voodoo magic
|
# black voodoo magic
|
||||||
stage_count = Math.log(Utils.previous_power_of_two(number_of_teams)) / Math.log(2)
|
stage_count = Math.log(Utils.next_power_of_two(number_of_teams)) / Math.log(2)
|
||||||
|
stage_count -= 1 if Utils.po2?(number_of_teams)
|
||||||
stage_count.to_int
|
stage_count.to_int
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
RSpec.describe MatchService do
|
RSpec.describe MatchService do
|
||||||
describe '#generate_matches' do
|
describe 'generates' do
|
||||||
[
|
[
|
||||||
{ team_size: 2 },
|
{ team_size: 2 },
|
||||||
{ team_size: 4 },
|
{ team_size: 4 },
|
||||||
|
|
@ -11,7 +11,7 @@ RSpec.describe MatchService do
|
||||||
{ team_size: 64 }
|
{ team_size: 64 }
|
||||||
].each do |parameters|
|
].each do |parameters|
|
||||||
result = parameters[:team_size] / 2
|
result = parameters[:team_size] / 2
|
||||||
it "generates #{result} matches from #{parameters[:team_size]} teams" do
|
it "#{result} matches from #{parameters[:team_size]} teams" do
|
||||||
teams = build_list(:team, parameters[:team_size], tournament: create(:tournament))
|
teams = build_list(:team, parameters[:team_size], tournament: create(:tournament))
|
||||||
generated_matches = MatchService.generate_matches teams
|
generated_matches = MatchService.generate_matches teams
|
||||||
expect(generated_matches.size).to eq(result)
|
expect(generated_matches.size).to eq(result)
|
||||||
|
|
@ -54,7 +54,7 @@ RSpec.describe MatchService do
|
||||||
{ team_size: 256 }
|
{ team_size: 256 }
|
||||||
|
|
||||||
].each do |parameters|
|
].each do |parameters|
|
||||||
it "matches the right teams for powers of 2 (#{parameters[:team_size]})" do
|
it "the right matchups for powers of 2 (#{parameters[:team_size]})" do
|
||||||
teams = build_list(:team, parameters[:team_size], tournament: create(:tournament))
|
teams = build_list(:team, parameters[:team_size], tournament: create(:tournament))
|
||||||
generated_matches = MatchService.generate_matches teams
|
generated_matches = MatchService.generate_matches teams
|
||||||
generated_matches.each_index do |index|
|
generated_matches.each_index do |index|
|
||||||
|
|
@ -67,7 +67,30 @@ RSpec.describe MatchService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: matches right teams for !powers of 2
|
[
|
||||||
|
{ team_size: 3 },
|
||||||
|
{ team_size: 5 },
|
||||||
|
{ team_size: 7 },
|
||||||
|
{ team_size: 9 },
|
||||||
|
{ team_size: 19 },
|
||||||
|
{ team_size: 41 },
|
||||||
|
{ team_size: 52 },
|
||||||
|
{ team_size: 111 }
|
||||||
|
|
||||||
|
].each do |parameters|
|
||||||
|
it "the right matchups for team numbers that are not powers of 2 (#{parameters[:team_size]})" do
|
||||||
|
team_size = parameters[:team_size]
|
||||||
|
teams = build_list(:team, team_size, tournament: create(:tournament))
|
||||||
|
generated_matches = MatchService.generate_matches teams
|
||||||
|
team_order = []
|
||||||
|
generated_matches.each do |match|
|
||||||
|
match.match_scores.each do |score|
|
||||||
|
team_order << score.team
|
||||||
|
end
|
||||||
|
end
|
||||||
|
expect(team_order).to match_array(teams)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
[
|
[
|
||||||
{ team_size: 3, single_team_matches: 1 },
|
{ team_size: 3, single_team_matches: 1 },
|
||||||
|
|
@ -91,12 +114,8 @@ RSpec.describe MatchService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'generates no matches for 0 teams' do
|
it 'raises an exception for for 0 teams' do
|
||||||
expect(MatchService.generate_matches([])). to eq(nil)
|
expect { MatchService.generate_matches([]) }. to raise_error 'Cannot generate Matches without teams'
|
||||||
end
|
|
||||||
|
|
||||||
it 'generates no matches for 1 team' do
|
|
||||||
expect(MatchService.generate_matches(build_list(:team, 1))). to eq(nil)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
RSpec.describe PlayoffStageService do
|
RSpec.describe PlayoffStageService do
|
||||||
describe '#generate_empty_matches' do
|
describe 'generates' do
|
||||||
[
|
[
|
||||||
{ amount: 1 },
|
{ amount: 1 },
|
||||||
{ amount: 3 },
|
{ amount: 3 },
|
||||||
|
|
@ -12,7 +12,7 @@ RSpec.describe PlayoffStageService do
|
||||||
{ amount: 82 },
|
{ amount: 82 },
|
||||||
{ amount: 359 }
|
{ amount: 359 }
|
||||||
].each do |parameters|
|
].each do |parameters|
|
||||||
it "generates #{parameters[:amount]} empty matches" do
|
it "#{parameters[:amount]} empty matches" do
|
||||||
amount = parameters[:amount]
|
amount = parameters[:amount]
|
||||||
generated_matches = PlayoffStageService.generate_empty_matches amount
|
generated_matches = PlayoffStageService.generate_empty_matches amount
|
||||||
generated_matches.each_index do |i|
|
generated_matches.each_index do |i|
|
||||||
|
|
@ -24,7 +24,7 @@ RSpec.describe PlayoffStageService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#generate_stages_with_empty_matches' do
|
describe 'generates' do
|
||||||
[
|
[
|
||||||
{ stages: 1 },
|
{ stages: 1 },
|
||||||
{ stages: 2 },
|
{ stages: 2 },
|
||||||
|
|
@ -37,7 +37,7 @@ RSpec.describe PlayoffStageService do
|
||||||
{ stages: 9 },
|
{ stages: 9 },
|
||||||
{ stages: 10 }
|
{ stages: 10 }
|
||||||
].each do |parameters|
|
].each do |parameters|
|
||||||
it "generates #{parameters[:stages]} stages with matches provided by #generate_empty_matches" do
|
it "#{parameters[:stages]} stages with matches provided by #generate_empty_matches" do
|
||||||
amount_of_empty_stages = parameters[:stages]
|
amount_of_empty_stages = parameters[:stages]
|
||||||
empty_stages = PlayoffStageService.generate_stages_with_empty_matches(amount_of_empty_stages)
|
empty_stages = PlayoffStageService.generate_stages_with_empty_matches(amount_of_empty_stages)
|
||||||
expect(empty_stages.size).to eq(amount_of_empty_stages)
|
expect(empty_stages.size).to eq(amount_of_empty_stages)
|
||||||
|
|
@ -51,17 +51,22 @@ RSpec.describe PlayoffStageService do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#generate_playoffs' do
|
describe 'generates playoff stages for' do
|
||||||
[
|
[
|
||||||
|
{ team_size: 1, expected_amount_of_playoff_stages: 1 },
|
||||||
|
{ team_size: 2, expected_amount_of_playoff_stages: 1 },
|
||||||
|
{ team_size: 3, expected_amount_of_playoff_stages: 2 },
|
||||||
{ team_size: 4, expected_amount_of_playoff_stages: 2 },
|
{ team_size: 4, expected_amount_of_playoff_stages: 2 },
|
||||||
{ team_size: 8, expected_amount_of_playoff_stages: 3 },
|
{ team_size: 8, expected_amount_of_playoff_stages: 3 },
|
||||||
|
{ team_size: 9, expected_amount_of_playoff_stages: 4 },
|
||||||
|
{ team_size: 10, expected_amount_of_playoff_stages: 4 },
|
||||||
{ team_size: 16, expected_amount_of_playoff_stages: 4 },
|
{ team_size: 16, expected_amount_of_playoff_stages: 4 },
|
||||||
{ team_size: 24, expected_amount_of_playoff_stages: 4 },
|
{ team_size: 24, expected_amount_of_playoff_stages: 5 },
|
||||||
{ team_size: 32, expected_amount_of_playoff_stages: 5 },
|
{ team_size: 32, expected_amount_of_playoff_stages: 5 },
|
||||||
{ team_size: 64, expected_amount_of_playoff_stages: 6 },
|
{ team_size: 64, expected_amount_of_playoff_stages: 6 },
|
||||||
{ team_size: 111, expected_amount_of_playoff_stages: 6 }
|
{ team_size: 111, expected_amount_of_playoff_stages: 7 }
|
||||||
].each do |parameters|
|
].each do |parameters|
|
||||||
it "generates playoff stages for #{parameters[:team_size]} teams" do
|
it "#{parameters[:team_size]} teams" do
|
||||||
amount_of_teams = parameters[:team_size]
|
amount_of_teams = parameters[:team_size]
|
||||||
expected_amount_of_playoff_stages = parameters[:expected_amount_of_playoff_stages]
|
expected_amount_of_playoff_stages = parameters[:expected_amount_of_playoff_stages]
|
||||||
teams = build_list(:team, amount_of_teams)
|
teams = build_list(:team, amount_of_teams)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue