Extracting tournament round building logic
This commit is contained in:
parent
dd06034974
commit
efd2178294
@ -16,105 +16,4 @@ class MashTournament < ActiveRecord::Base
|
|||||||
:conditions => {:number => number}
|
:conditions => {:number => number}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def valid_number_of_contenders?(n_contenders)
|
|
||||||
[8, 16, 32, 64, 128].include?(n_contenders)
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_rounds_for_contenders(n_contenders)
|
|
||||||
if not valid_number_of_contenders?(n_contenders)
|
|
||||||
raise StandardError.new(
|
|
||||||
"The number of contenders must be 8, 16, 32, 64, or 128! " +
|
|
||||||
"Got '#{n_contenders}'"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
round = 1
|
|
||||||
|
|
||||||
while n_contenders > 1
|
|
||||||
create_round(round, n_contenders)
|
|
||||||
n_contenders = n_contenders / 2
|
|
||||||
round += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
self.total_rounds = round - 1
|
|
||||||
end
|
|
||||||
|
|
||||||
def fill_in_next_round
|
|
||||||
self.rounds.sort{ |a,b| a.number <=> b.number}.each do |round|
|
|
||||||
if not round.done?
|
|
||||||
return assign_maps_for_round(round)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def create_round(round_number, n_contenders)
|
|
||||||
round = MashTournamentRound.new(
|
|
||||||
:mash_tournament_id => self.id,
|
|
||||||
:number => round_number,
|
|
||||||
:mash_count => n_contenders / 2
|
|
||||||
)
|
|
||||||
round.save!
|
|
||||||
|
|
||||||
n_contenders.times do
|
|
||||||
Mash.new(
|
|
||||||
:mash_tournament_id => self.id,
|
|
||||||
:mash_tournament_round_id => round.id
|
|
||||||
).save!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def assign_maps_for_round(round)
|
|
||||||
if round.number == 1
|
|
||||||
return assign_maps_for_round_one(round)
|
|
||||||
end
|
|
||||||
|
|
||||||
previous = MashTournamentRound.find_by_mash_tournament_id_and_number(
|
|
||||||
self.id, round.number - 1
|
|
||||||
)
|
|
||||||
previous_winners = previous.mashes.collect(&:winner_id)
|
|
||||||
pool = Map.all(
|
|
||||||
:order => 'RANDOM()',
|
|
||||||
:conditions => ['id in ?', previous_winners]
|
|
||||||
)
|
|
||||||
|
|
||||||
filled_in = []
|
|
||||||
|
|
||||||
round.mashes.each do |mash|
|
|
||||||
mash.map_a = pool.pop.id
|
|
||||||
mash.map_b = pool.pop.id
|
|
||||||
mash.save!
|
|
||||||
|
|
||||||
filled_in << mash
|
|
||||||
end
|
|
||||||
|
|
||||||
filled_in
|
|
||||||
end
|
|
||||||
|
|
||||||
def assign_maps_for_round_one(round)
|
|
||||||
pool = Map.all(
|
|
||||||
:order => 'RANDOM()',
|
|
||||||
:limit => round.mash_count * 2
|
|
||||||
)
|
|
||||||
|
|
||||||
logger.info("Populating mashes from pool: #{pool.inspect}")
|
|
||||||
|
|
||||||
filled_in = []
|
|
||||||
|
|
||||||
round.mashes.each do |mash|
|
|
||||||
map_a = pool.pop
|
|
||||||
map_b = pool.pop
|
|
||||||
logger.info("Assigning `map_a` from #{map_a.inspect}, " +
|
|
||||||
"`map_b` from #{map_b.inspect} to mash #{mash.inspect}")
|
|
||||||
|
|
||||||
mash.map_a = map_a
|
|
||||||
mash.map_b = map_b
|
|
||||||
mash.save!
|
|
||||||
|
|
||||||
filled_in << mash
|
|
||||||
end
|
|
||||||
|
|
||||||
filled_in
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
113
rails/map-mash/lib/mash_tournament_builder.rb
Normal file
113
rails/map-mash/lib/mash_tournament_builder.rb
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
class MashTournamentBuilder
|
||||||
|
attr_accessor :tournament, :tournament_model, :round_model
|
||||||
|
attr_accessor :map_model, :mash_model
|
||||||
|
|
||||||
|
def initialize(tournament, tournament_model, round_model, map_model, mash_model)
|
||||||
|
@tournament = tournament
|
||||||
|
@tournament_model = tournament_model
|
||||||
|
@round_model = round_model
|
||||||
|
@map_model = map_model
|
||||||
|
@mash_model = mash_model
|
||||||
|
end
|
||||||
|
|
||||||
|
def valid_number_of_contenders?(n_contenders)
|
||||||
|
[8, 16, 32, 64, 128].include?(n_contenders)
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_rounds_for_contenders(n_contenders)
|
||||||
|
if not valid_number_of_contenders?(n_contenders)
|
||||||
|
raise StandardError.new(
|
||||||
|
"The number of contenders must be 8, 16, 32, 64, or 128! " +
|
||||||
|
"Got '#{n_contenders}'"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
round = 1
|
||||||
|
|
||||||
|
while n_contenders > 1
|
||||||
|
create_round(round, n_contenders)
|
||||||
|
n_contenders = n_contenders / 2
|
||||||
|
round += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
@tournament.total_rounds = round - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def fill_in_next_round
|
||||||
|
@tournament.rounds.sort{ |a,b| a.number <=> b.number}.each do |round|
|
||||||
|
if not round.done?
|
||||||
|
return assign_maps_for_round(round)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def create_round(round_number, n_contenders)
|
||||||
|
round = @round_model.new(
|
||||||
|
:mash_tournament_id => @tournament.id,
|
||||||
|
:number => round_number,
|
||||||
|
:mash_count => n_contenders / 2
|
||||||
|
)
|
||||||
|
round.save!
|
||||||
|
|
||||||
|
n_contenders.times do
|
||||||
|
@mash_model.new(
|
||||||
|
:mash_tournament_id => @tournament.id,
|
||||||
|
:mash_tournament_round_id => round.id
|
||||||
|
).save!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_maps_for_round(round)
|
||||||
|
if round.number == 1
|
||||||
|
return assign_maps_for_round_one(round)
|
||||||
|
end
|
||||||
|
|
||||||
|
previous = @round_model.find_by_mash_tournament_id_and_number(
|
||||||
|
@tournament.id, round.number - 1
|
||||||
|
)
|
||||||
|
previous_winners = previous.mashes.collect(&:winner_id)
|
||||||
|
pool = @map_model.all(
|
||||||
|
:order => 'RANDOM()',
|
||||||
|
:conditions => ['id in ?', previous_winners]
|
||||||
|
)
|
||||||
|
|
||||||
|
filled_in = []
|
||||||
|
|
||||||
|
round.mashes.each do |mash|
|
||||||
|
mash.map_a = pool.pop.id
|
||||||
|
mash.map_b = pool.pop.id
|
||||||
|
mash.save!
|
||||||
|
|
||||||
|
filled_in << mash
|
||||||
|
end
|
||||||
|
|
||||||
|
filled_in
|
||||||
|
end
|
||||||
|
|
||||||
|
def assign_maps_for_round_one(round)
|
||||||
|
pool = @map_model.all(
|
||||||
|
:order => 'RANDOM()',
|
||||||
|
:limit => round.mash_count * 2
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info("Populating mashes from pool: #{pool.inspect}")
|
||||||
|
|
||||||
|
filled_in = []
|
||||||
|
|
||||||
|
round.mashes.each do |mash|
|
||||||
|
map_a = pool.pop
|
||||||
|
map_b = pool.pop
|
||||||
|
logger.info("Assigning `map_a` from #{map_a.inspect}, " +
|
||||||
|
"`map_b` from #{map_b.inspect} to mash #{mash.inspect}")
|
||||||
|
|
||||||
|
mash.map_a = map_a
|
||||||
|
mash.map_b = map_b
|
||||||
|
mash.save!
|
||||||
|
|
||||||
|
filled_in << mash
|
||||||
|
end
|
||||||
|
|
||||||
|
filled_in
|
||||||
|
end
|
||||||
|
end
|
64
rails/map-mash/spec/lib/mash_tournament_builder_spec.rb
Normal file
64
rails/map-mash/spec/lib/mash_tournament_builder_spec.rb
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe MashTournamentBuilder do
|
||||||
|
let(:subject) do
|
||||||
|
MashTournamentBuilder.new(
|
||||||
|
MashTournament.make(:requester => Requester.make),
|
||||||
|
MashTournament, MashTournamentRound, Map, Mash
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:mock_subject) do
|
||||||
|
@tournament = mock(Object)
|
||||||
|
@tournament_model = mock(Object)
|
||||||
|
@round_model = mock(Object)
|
||||||
|
@map_model = mock(Object)
|
||||||
|
@mash_model = mock(Object)
|
||||||
|
|
||||||
|
MashTournamentBuilder.new(
|
||||||
|
@tournament, @tournament_model,
|
||||||
|
@round_model, @map_model, @mash_model
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'creating rounds' do
|
||||||
|
it 'should reject invalid numbers of contenders' do
|
||||||
|
[11, 24, 40].each do |n|
|
||||||
|
expect do
|
||||||
|
subject.create_rounds_for_contenders(n)
|
||||||
|
end.to raise_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:all) do
|
||||||
|
subject.map_model.destroy_all
|
||||||
|
40.times do
|
||||||
|
subject.map_model.make.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
[[8, 3], [16, 4], [32, 5]].each do |n_contenders,n_rounds|
|
||||||
|
context "for #{n_contenders} total contenders" do
|
||||||
|
it "should create #{n_rounds} rounds" do
|
||||||
|
subject.create_rounds_for_contenders(n_contenders)
|
||||||
|
subject.tournament.total_rounds.should == n_rounds
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'filling in rounds' do
|
||||||
|
before(:each) do
|
||||||
|
subject.id.should_not be_nil
|
||||||
|
subject.create_rounds_for_contenders(8)
|
||||||
|
end
|
||||||
|
|
||||||
|
xit 'should fill in every map for every mash in a given round' do
|
||||||
|
subject.fill_in_next_round
|
||||||
|
subject.round(1).mashes.each do |mash|
|
||||||
|
mash.map_a.should_not be_nil
|
||||||
|
mash.map_b.should_not be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -5,56 +5,7 @@ describe MashTournament do
|
|||||||
@valid_attributes = {:requester_id => 1}
|
@valid_attributes = {:requester_id => 1}
|
||||||
end
|
end
|
||||||
|
|
||||||
before(:each) do
|
|
||||||
@requester = Requester.make
|
|
||||||
@requester.save!
|
|
||||||
subject.requester_id = @requester.id
|
|
||||||
subject.save!
|
|
||||||
subject.reload
|
|
||||||
end
|
|
||||||
|
|
||||||
it "should create a new instance given valid attributes" do
|
it "should create a new instance given valid attributes" do
|
||||||
MashTournament.create!(@valid_attributes)
|
MashTournament.create!(@valid_attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'creating rounds' do
|
|
||||||
it 'should reject invalid numbers of contenders' do
|
|
||||||
[11, 24, 40].each do |n|
|
|
||||||
expect do
|
|
||||||
subject.create_rounds_for_contenders(n)
|
|
||||||
end.to raise_error
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
before(:all) do
|
|
||||||
Map.destroy_all
|
|
||||||
40.times do
|
|
||||||
Map.make.save
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
[[8, 3], [16, 4], [32, 5]].each do |n_contenders,n_rounds|
|
|
||||||
context "for #{n_contenders} total contenders" do
|
|
||||||
it "should create #{n_rounds} rounds" do
|
|
||||||
subject.create_rounds_for_contenders(n_contenders)
|
|
||||||
subject.total_rounds.should == n_rounds
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'filling in rounds' do
|
|
||||||
before(:each) do
|
|
||||||
subject.id.should_not be_nil
|
|
||||||
subject.create_rounds_for_contenders(8)
|
|
||||||
end
|
|
||||||
|
|
||||||
xit 'should fill in every map for every mash in a given round' do
|
|
||||||
subject.fill_in_next_round
|
|
||||||
subject.round(1).mashes.each do |mash|
|
|
||||||
mash.map_a.should_not be_nil
|
|
||||||
mash.map_b.should_not be_nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user