class MashTournament < ActiveRecord::Base belongs_to :requester has_many :mashes has_many :rounds, :class_name => 'MashTournamentRound' #after_create :create_rounds #after_save :maybe_fill_in_next_round def next_unplayed_mash self.mashes.unplayed.first end def done? true end def round(number = 0) MashTournamentRound.find_by_mash_tournament_id(self.id, :conditions => {:number => number} ) end private def create_rounds n_contenders = Map.count while n_contenders % 4 != 0 n_contenders -= 1 end round = 0 while n_contenders > 2 create_round(round, n_contenders) n_contenders = n_contenders / 2 round += 1 end assign_maps_for_round_zero self.total_rounds = round - 1 end 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 maybe_fill_in_next_round self.rounds.sort(&:number).each do |round| if not round.done? assign_maps_for_round(round) return end end end def assign_maps_for_round(round) 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] ) round.mashes.each do |mash| mash.update_attributes( :map_a_id => pool.pop.id, :map_b_id => pool.pop.id ) end end def assign_maps_for_round_zero round = MashTournamentRound.for_round(self.id, 0) pool = Map.all( :order => 'RANDOM()', :limit => round.mash_count * 2 ) logger.info("Populating mashes from pool: #{pool.inspect}") 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}") logger.info("`map_a`.`id` = #{map_a.id}, `map_b`.`id` = #{map_b.id} ") mash.update_attributes( :map_a_id => map_a.id, :map_b_id => map_b.id ) end end end