1
0
mirror of https://github.com/jcwimer/wrestlingApp synced 2026-03-24 17:04:43 +00:00

Using eager loading in GenerateTournamentMatches and AdvanceWrestler, generating/manipulating in-memory, and doing a single bulk insert or update at the end.

This commit is contained in:
2026-02-24 20:58:36 -05:00
parent ca4d5ce0db
commit 18d39c6c8f
18 changed files with 904 additions and 521 deletions

View File

@@ -156,7 +156,7 @@ class Weight < ApplicationRecord
end
def calculate_bracket_size
num_wrestlers = wrestlers.reload.size
num_wrestlers = wrestlers.size
return nil if num_wrestlers <= 0 # Handle invalid input
# Find the smallest power of 2 greater than or equal to num_wrestlers

View File

@@ -12,21 +12,97 @@ class AdvanceWrestler
end
def advance_raw
@last_match.reload
@wrestler.reload
if @last_match && @last_match.finished?
pool_to_bracket_advancement if @tournament.tournament_type == "Pool to bracket"
ModifiedDoubleEliminationAdvance.new(@wrestler, @last_match).bracket_advancement if @tournament.tournament_type.include? "Modified 16 Man Double Elimination"
DoubleEliminationAdvance.new(@wrestler, @last_match).bracket_advancement if @tournament.tournament_type.include? "Regular Double Elimination"
@last_match = Match.find_by(id: @last_match&.id)
@wrestler = Wrestler.includes(:school, :weight).find_by(id: @wrestler.id)
return unless @last_match && @wrestler && @last_match.finished?
context = preload_advancement_context
matches_to_advance = []
if @tournament.tournament_type == "Pool to bracket"
matches_to_advance.concat(pool_to_bracket_advancement(context))
elsif @tournament.tournament_type.include?("Modified 16 Man Double Elimination")
service = ModifiedDoubleEliminationAdvance.new(@wrestler, @last_match, matches: context[:matches])
service.bracket_advancement
matches_to_advance.concat(service.matches_to_advance)
elsif @tournament.tournament_type.include?("Regular Double Elimination")
service = DoubleEliminationAdvance.new(@wrestler, @last_match, matches: context[:matches])
service.bracket_advancement
matches_to_advance.concat(service.matches_to_advance)
end
persist_advancement_changes(context)
advance_pending_matches(matches_to_advance)
@wrestler.school.calculate_score
end
def pool_to_bracket_advancement
if @wrestler.weight.all_pool_matches_finished(@wrestler.pool) and (@wrestler.finished_bracket_matches.size < 1)
PoolOrder.new(@wrestler.weight.wrestlers_in_pool(@wrestler.pool)).getPoolOrder
def preload_advancement_context
weight = Weight.includes(:matches, :wrestlers).find(@wrestler.weight_id)
{
weight: weight,
matches: weight.matches.to_a,
wrestlers: weight.wrestlers.to_a
}
end
PoolAdvance.new(@wrestler).advanceWrestler
def persist_advancement_changes(context)
persist_matches(context[:matches])
persist_wrestlers(context[:wrestlers])
end
def persist_matches(matches)
timestamp = Time.current
updates = matches.filter_map do |m|
next unless m.changed?
{
id: m.id,
w1: m.w1,
w2: m.w2,
winner_id: m.winner_id,
win_type: m.win_type,
score: m.score,
finished: m.finished,
loser1_name: m.loser1_name,
loser2_name: m.loser2_name,
finished_at: m.finished_at,
updated_at: timestamp
}
end
Match.upsert_all(updates) if updates.any?
end
def persist_wrestlers(wrestlers)
timestamp = Time.current
updates = wrestlers.filter_map do |w|
next unless w.changed?
{
id: w.id,
pool_placement: w.pool_placement,
pool_placement_tiebreaker: w.pool_placement_tiebreaker,
updated_at: timestamp
}
end
Wrestler.upsert_all(updates) if updates.any?
end
def advance_pending_matches(matches_to_advance)
matches_to_advance.uniq(&:id).each do |match|
match.advance_wrestlers
end
end
def pool_to_bracket_advancement(context)
matches_to_advance = []
wrestlers_in_pool = context[:wrestlers].select { |w| w.pool == @wrestler.pool }
if @wrestler.weight.all_pool_matches_finished(@wrestler.pool) && (@wrestler.finished_bracket_matches.size < 1)
PoolOrder.new(wrestlers_in_pool).getPoolOrder
end
service = PoolAdvance.new(@wrestler, @last_match, matches: context[:matches], wrestlers: context[:wrestlers])
service.advanceWrestler
matches_to_advance.concat(service.matches_to_advance)
matches_to_advance
end
end

View File

@@ -1,8 +1,12 @@
class DoubleEliminationAdvance
def initialize(wrestler,last_match)
attr_reader :matches_to_advance
def initialize(wrestler,last_match, matches: nil)
@wrestler = wrestler
@last_match = last_match
@matches = matches || @wrestler.weight.matches.to_a
@matches_to_advance = []
@next_match_position_number = (@last_match.bracket_position_number / 2.0)
end
@@ -48,7 +52,7 @@ class DoubleEliminationAdvance
end
if next_match_bracket_position
next_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?",next_match_bracket_position,next_match_position_number.ceil,@wrestler.weight_id).first
next_match = @matches.find { |m| m.bracket_position == next_match_bracket_position && m.bracket_position_number == next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
end
if next_match
@@ -59,18 +63,16 @@ class DoubleEliminationAdvance
def update_new_match(match, wrestler_number)
if wrestler_number == 2 or (match.loser1_name and match.loser1_name.include? "Loser of")
match.w2 = @wrestler.id
match.save
elsif wrestler_number == 1
match.w1 = @wrestler.id
match.save
end
end
def update_consolation_bye
bout = @wrestler.last_match.bout_number
next_match = Match.where("(loser1_name = ? OR loser2_name = ?) AND weight_id = ?","Loser of #{bout}","Loser of #{bout}",@wrestler.weight_id)
if next_match.size > 0
next_match.first.replace_loser_name_with_bye("Loser of #{bout}")
next_match = @matches.find { |m| m.weight_id == @wrestler.weight_id && (m.loser1_name == "Loser of #{bout}" || m.loser2_name == "Loser of #{bout}") }
if next_match
replace_loser_name_with_bye(next_match, "Loser of #{bout}")
end
end
@@ -84,27 +86,18 @@ class DoubleEliminationAdvance
def losers_bracket_advancement
bout = @last_match.bout_number
next_match = Match.where("(loser1_name = ? OR loser2_name = ?) AND weight_id = ?", "Loser of #{bout}", "Loser of #{bout}", @wrestler.weight_id).first
next_match = @matches.find { |m| m.weight_id == @wrestler.weight_id && (m.loser1_name == "Loser of #{bout}" || m.loser2_name == "Loser of #{bout}") }
if next_match.present?
next_match.replace_loser_name_with_wrestler(@wrestler, "Loser of #{bout}")
next_match.reload
replace_loser_name_with_wrestler(next_match, @wrestler, "Loser of #{bout}")
if next_match.loser1_name == "BYE" || next_match.loser2_name == "BYE"
next_match.winner_id = @wrestler.id
next_match.win_type = "BYE"
next_match.score = ""
next_match.finished = 1
# puts "Before save: winner_id=#{next_match.winner_id}"
# if next_match.save
# puts "Save successful: winner_id=#{next_match.reload.winner_id}"
# else
# puts "Save failed: #{next_match.errors.full_messages}"
# end
next_match.save
next_match.advance_wrestlers
next_match.finished_at = Time.current
@matches_to_advance << next_match
end
end
end
@@ -112,51 +105,69 @@ class DoubleEliminationAdvance
def advance_double_byes
weight = @wrestler.weight
weight.matches.select{|m| m.loser1_name == "BYE" and m.loser2_name == "BYE" and m.finished != 1}.each do |match|
@matches.select{|m| m.weight_id == weight.id && m.loser1_name == "BYE" and m.loser2_name == "BYE" and m.finished != 1}.each do |match|
match.finished = 1
match.finished_at = Time.current
match.score = ""
match.win_type = "BYE"
next_match_position_number = (match.bracket_position_number / 2.0).ceil
after_matches = weight.matches.select{|m| m.round > match.round and m.is_consolation_match == match.is_consolation_match }.sort_by{|m| m.round}
next_matches = weight.matches.select{|m| m.round == after_matches.first.round and m.is_consolation_match == match.is_consolation_match }
this_round_matches = weight.matches.select{|m| m.round == match.round and m.is_consolation_match == match.is_consolation_match }
after_matches = @matches.select{|m| m.weight_id == weight.id && m.round > match.round and m.is_consolation_match == match.is_consolation_match }.sort_by{|m| m.round}
next if after_matches.empty?
next_matches = @matches.select{|m| m.weight_id == weight.id && m.round == after_matches.first.round and m.is_consolation_match == match.is_consolation_match }
this_round_matches = @matches.select{|m| m.weight_id == weight.id && m.round == match.round and m.is_consolation_match == match.is_consolation_match }
next_match = nil
if next_matches.size == this_round_matches.size
next_match = next_matches.select{|m| m.bracket_position_number == match.bracket_position_number}.first
next_match.loser2_name = "BYE"
next_match.save
next_match.loser2_name = "BYE" if next_match
elsif next_matches.size < this_round_matches.size and next_matches.size > 0
next_match = next_matches.select{|m| m.bracket_position_number == next_match_position_number}.first
if next_match.bracket_position_number == next_match_position_number
if next_match && next_match.bracket_position_number == next_match_position_number
next_match.loser2_name = "BYE"
else
elsif next_match
next_match.loser1_name = "BYE"
end
end
next_match.save
match.save
end
end
def set_bye_for_placement
weight = @wrestler.weight
fifth_finals = weight.matches.select{|match| match.bracket_position == '5/6'}.first
seventh_finals = weight.matches.select{|match| match.bracket_position == '7/8'}.first
fifth_finals = @matches.select{|match| match.weight_id == weight.id && match.bracket_position == '5/6'}.first
seventh_finals = @matches.select{|match| match.weight_id == weight.id && match.bracket_position == '7/8'}.first
if seventh_finals
conso_quarter = weight.matches.select{|match| match.bracket_position == 'Conso Quarter'}
conso_quarter = @matches.select{|match| match.weight_id == weight.id && match.bracket_position == 'Conso Quarter'}
conso_quarter.each do |match|
if match.loser1_name == "BYE" or match.loser2_name == "BYE"
seventh_finals.replace_loser_name_with_bye("Loser of #{match.bout_number}")
replace_loser_name_with_bye(seventh_finals, "Loser of #{match.bout_number}")
end
end
end
if fifth_finals
conso_semis = weight.matches.select{|match| match.bracket_position == 'Conso Semis'}
conso_semis = @matches.select{|match| match.weight_id == weight.id && match.bracket_position == 'Conso Semis'}
conso_semis.each do |match|
if match.loser1_name == "BYE" or match.loser2_name == "BYE"
fifth_finals.replace_loser_name_with_bye("Loser of #{match.bout_number}")
replace_loser_name_with_bye(fifth_finals, "Loser of #{match.bout_number}")
end
end
end
end
def replace_loser_name_with_wrestler(match, wrestler, loser_name)
if match.loser1_name == loser_name
match.w1 = wrestler.id
end
if match.loser2_name == loser_name
match.w2 = wrestler.id
end
end
def replace_loser_name_with_bye(match, loser_name)
if match.loser1_name == loser_name
match.loser1_name = "BYE"
end
if match.loser2_name == loser_name
match.loser2_name = "BYE"
end
end
end

View File

@@ -1,8 +1,12 @@
class ModifiedDoubleEliminationAdvance
def initialize(wrestler,last_match)
attr_reader :matches_to_advance
def initialize(wrestler,last_match, matches: nil)
@wrestler = wrestler
@last_match = last_match
@matches = matches || @wrestler.weight.matches.to_a
@matches_to_advance = []
@next_match_position_number = (@last_match.bracket_position_number / 2.0)
end
@@ -25,42 +29,41 @@ class ModifiedDoubleEliminationAdvance
update_consolation_bye
end
if @last_match.bracket_position == "Quarter"
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","Semis",@next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "Semis" && m.bracket_position_number == @next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
update_new_match(new_match, get_wrestler_number)
elsif @last_match.bracket_position == "Semis"
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","1/2",@next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "1/2" && m.bracket_position_number == @next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
update_new_match(new_match, get_wrestler_number)
elsif @last_match.bracket_position == "Conso Semis"
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","5/6",@next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "5/6" && m.bracket_position_number == @next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
update_new_match(new_match, get_wrestler_number)
elsif @last_match.bracket_position == "Conso Quarter"
# it's a special bracket where a semi loser is not dropping down
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","Conso Semis",@next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "Conso Semis" && m.bracket_position_number == @next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
update_new_match(new_match, get_wrestler_number)
elsif @last_match.bracket_position == "Bracket Round of 16"
new_match = Match.where("bracket_position_number = ? and weight_id = ? and round > ? and bracket_position = ?", @next_match_position_number.ceil,@wrestler.weight_id, @last_match.round , "Quarter").sort_by{|m| m.round}.first
new_match = @matches.select { |m| m.bracket_position_number == @next_match_position_number.ceil && m.weight_id == @wrestler.weight_id && m.round > @last_match.round && m.bracket_position == "Quarter" }.sort_by(&:round).first
update_new_match(new_match, get_wrestler_number)
elsif @last_match.bracket_position == "Conso Round of 8"
new_match = Match.where("bracket_position_number = ? and weight_id = ? and round > ? and bracket_position = ?", @last_match.bracket_position_number,@wrestler.weight_id, @last_match.round, "Conso Quarter").sort_by{|m| m.round}.first
new_match = @matches.select { |m| m.bracket_position_number == @last_match.bracket_position_number && m.weight_id == @wrestler.weight_id && m.round > @last_match.round && m.bracket_position == "Conso Quarter" }.sort_by(&:round).first
update_new_match(new_match, get_wrestler_number)
end
end
def update_new_match(match, wrestler_number)
return unless match
if wrestler_number == 2 or (match.loser1_name and match.loser1_name.include? "Loser of")
match.w2 = @wrestler.id
match.save
elsif wrestler_number == 1
match.w1 = @wrestler.id
match.save
end
end
def update_consolation_bye
bout = @wrestler.last_match.bout_number
next_match = Match.where("(loser1_name = ? OR loser2_name = ?) AND weight_id = ?","Loser of #{bout}","Loser of #{bout}",@wrestler.weight_id)
if next_match.size > 0
next_match.first.replace_loser_name_with_bye("Loser of #{bout}")
next_match = @matches.find { |m| m.weight_id == @wrestler.weight_id && (m.loser1_name == "Loser of #{bout}" || m.loser2_name == "Loser of #{bout}") }
if next_match
replace_loser_name_with_bye(next_match, "Loser of #{bout}")
end
end
@@ -74,27 +77,18 @@ class ModifiedDoubleEliminationAdvance
def losers_bracket_advancement
bout = @last_match.bout_number
next_match = Match.where("(loser1_name = ? OR loser2_name = ?) AND weight_id = ?", "Loser of #{bout}", "Loser of #{bout}", @wrestler.weight_id).first
next_match = @matches.find { |m| m.weight_id == @wrestler.weight_id && (m.loser1_name == "Loser of #{bout}" || m.loser2_name == "Loser of #{bout}") }
if next_match.present?
next_match.replace_loser_name_with_wrestler(@wrestler, "Loser of #{bout}")
next_match.reload
replace_loser_name_with_wrestler(next_match, @wrestler, "Loser of #{bout}")
if next_match.loser1_name == "BYE" || next_match.loser2_name == "BYE"
next_match.winner_id = @wrestler.id
next_match.win_type = "BYE"
next_match.score = ""
next_match.finished = 1
# puts "Before save: winner_id=#{next_match.winner_id}"
# if next_match.save
# puts "Save successful: winner_id=#{next_match.reload.winner_id}"
# else
# puts "Save failed: #{next_match.errors.full_messages}"
# end
next_match.save
next_match.advance_wrestlers
next_match.finished_at = Time.current
@matches_to_advance << next_match
end
end
end
@@ -102,43 +96,53 @@ class ModifiedDoubleEliminationAdvance
def advance_double_byes
weight = @wrestler.weight
weight.matches.select{|m| m.loser1_name == "BYE" and m.loser2_name == "BYE" and m.finished != 1}.each do |match|
@matches.select{|m| m.weight_id == weight.id && m.loser1_name == "BYE" and m.loser2_name == "BYE" and m.finished != 1}.each do |match|
match.finished = 1
match.finished_at = Time.current
match.score = ""
match.win_type = "BYE"
next_match_position_number = (match.bracket_position_number / 2.0).ceil
after_matches = weight.matches.select{|m| m.round > match.round and m.is_consolation_match == match.is_consolation_match }.sort_by{|m| m.round}
next_matches = weight.matches.select{|m| m.round == after_matches.first.round and m.is_consolation_match == match.is_consolation_match }
this_round_matches = weight.matches.select{|m| m.round == match.round and m.is_consolation_match == match.is_consolation_match }
after_matches = @matches.select{|m| m.weight_id == weight.id && m.round > match.round and m.is_consolation_match == match.is_consolation_match }.sort_by{|m| m.round}
next if after_matches.empty?
next_matches = @matches.select{|m| m.weight_id == weight.id && m.round == after_matches.first.round and m.is_consolation_match == match.is_consolation_match }
this_round_matches = @matches.select{|m| m.weight_id == weight.id && m.round == match.round and m.is_consolation_match == match.is_consolation_match }
next_match = nil
if next_matches.size == this_round_matches.size
next_match = next_matches.select{|m| m.bracket_position_number == match.bracket_position_number}.first
next_match.loser2_name = "BYE"
next_match.save
next_match.loser2_name = "BYE" if next_match
elsif next_matches.size < this_round_matches.size and next_matches.size > 0
next_match = next_matches.select{|m| m.bracket_position_number == next_match_position_number}.first
if next_match.bracket_position_number == next_match_position_number
if next_match && next_match.bracket_position_number == next_match_position_number
next_match.loser2_name = "BYE"
else
elsif next_match
next_match.loser1_name = "BYE"
end
end
next_match.save
match.save
end
end
def set_bye_for_placement
weight = @wrestler.weight
seventh_finals = weight.matches.select{|match| match.bracket_position == '7/8'}.first
seventh_finals = @matches.select{|match| match.weight_id == weight.id && match.bracket_position == '7/8'}.first
if seventh_finals
conso_quarter = weight.matches.select{|match| match.bracket_position == 'Conso Semis'}
conso_quarter = @matches.select{|match| match.weight_id == weight.id && match.bracket_position == 'Conso Semis'}
conso_quarter.each do |match|
if match.loser1_name == "BYE" or match.loser2_name == "BYE"
seventh_finals.replace_loser_name_with_bye("Loser of #{match.bout_number}")
end
replace_loser_name_with_bye(seventh_finals, "Loser of #{match.bout_number}")
end
end
end
end
def replace_loser_name_with_wrestler(match, wrestler, loser_name)
match.w1 = wrestler.id if match.loser1_name == loser_name
match.w2 = wrestler.id if match.loser2_name == loser_name
end
def replace_loser_name_with_bye(match, loser_name)
match.loser1_name = "BYE" if match.loser1_name == loser_name
match.loser2_name = "BYE" if match.loser2_name == loser_name
end
end

View File

@@ -1,8 +1,13 @@
class PoolAdvance
def initialize(wrestler)
attr_reader :matches_to_advance
def initialize(wrestler, last_match, matches: nil, wrestlers: nil)
@wrestler = wrestler
@last_match = @wrestler.last_match
@last_match = last_match
@matches = matches || @wrestler.weight.matches.to_a
@wrestlers = wrestlers || @wrestler.weight.wrestlers.to_a
@matches_to_advance = []
end
def advanceWrestler
@@ -17,15 +22,15 @@ class PoolAdvance
def poolToBracketAdvancment
pool = @wrestler.pool
# This has to always run because the last match in a pool might not be a pool winner or runner up
winner = Wrestler.where("weight_id = ? and pool_placement = 1 and pool = ?",@wrestler.weight.id, pool).first
runner_up = Wrestler.where("weight_id = ? and pool_placement = 2 and pool = ?",@wrestler.weight.id, pool).first
winner = @wrestlers.find { |w| w.weight_id == @wrestler.weight.id && w.pool_placement == 1 && w.pool == pool }
runner_up = @wrestlers.find { |w| w.weight_id == @wrestler.weight.id && w.pool_placement == 2 && w.pool == pool }
if runner_up
runner_up_match = Match.where("weight_id = ? and (loser1_name = ? or loser2_name = ?)",@wrestler.weight.id, "Runner Up Pool #{pool}", "Runner Up Pool #{pool}").first
runner_up_match.replace_loser_name_with_wrestler(runner_up,"Runner Up Pool #{pool}")
runner_up_match = @matches.find { |m| m.weight_id == @wrestler.weight.id && (m.loser1_name == "Runner Up Pool #{pool}" || m.loser2_name == "Runner Up Pool #{pool}") }
replace_loser_name_with_wrestler(runner_up_match, runner_up, "Runner Up Pool #{pool}") if runner_up_match
end
if winner
winner_match = Match.where("weight_id = ? and (loser1_name = ? or loser2_name = ?)",@wrestler.weight.id, "Winner Pool #{pool}", "Winner Pool #{pool}").first
winner_match.replace_loser_name_with_wrestler(winner,"Winner Pool #{pool}")
winner_match = @matches.find { |m| m.weight_id == @wrestler.weight.id && (m.loser1_name == "Winner Pool #{pool}" || m.loser2_name == "Winner Pool #{pool}") }
replace_loser_name_with_wrestler(winner_match, winner, "Winner Pool #{pool}") if winner_match
end
end
@@ -45,36 +50,40 @@ class PoolAdvance
def winner_advance
if @wrestler.last_match.bracket_position == "Quarter"
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","Semis",@wrestler.next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "Semis" && m.bracket_position_number == @wrestler.next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
updateNewMatch(new_match)
end
if @wrestler.last_match.bracket_position == "Semis"
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","1/2",@wrestler.next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "1/2" && m.bracket_position_number == @wrestler.next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
updateNewMatch(new_match)
end
if @wrestler.last_match.bracket_position == "Conso Semis"
new_match = Match.where("bracket_position = ? AND bracket_position_number = ? AND weight_id = ?","5/6",@wrestler.next_match_position_number.ceil,@wrestler.weight_id).first
new_match = @matches.find { |m| m.bracket_position == "5/6" && m.bracket_position_number == @wrestler.next_match_position_number.ceil && m.weight_id == @wrestler.weight_id }
updateNewMatch(new_match)
end
end
def updateNewMatch(match)
return unless match
if @wrestler.next_match_position_number == @wrestler.next_match_position_number.ceil
match.w2 = @wrestler.id
match.save
end
if @wrestler.next_match_position_number != @wrestler.next_match_position_number.ceil
match.w1 = @wrestler.id
match.save
end
end
def loser_advance
bout = @wrestler.last_match.bout_number
next_match = Match.where("(loser1_name = ? OR loser2_name = ?) AND weight_id = ?","Loser of #{bout}","Loser of #{bout}",@wrestler.weight_id)
if next_match.size > 0
next_match.first.replace_loser_name_with_wrestler(@wrestler,"Loser of #{bout}")
next_match = @matches.find { |m| m.weight_id == @wrestler.weight_id && (m.loser1_name == "Loser of #{bout}" || m.loser2_name == "Loser of #{bout}") }
if next_match
replace_loser_name_with_wrestler(next_match, @wrestler, "Loser of #{bout}")
end
end
def replace_loser_name_with_wrestler(match, wrestler, loser_name)
match.w1 = wrestler.id if match.loser1_name == loser_name
match.w2 = wrestler.id if match.loser2_name == loser_name
end
end

View File

@@ -4,8 +4,6 @@ class PoolOrder
end
def getPoolOrder
# clear caching for weight for bracket page
@wrestlers.first.weight.touch
setOriginalPoints
while checkForTies(@wrestlers) == true
getWrestlersOrderByPoolAdvancePoints.each do |wrestler|
@@ -18,7 +16,6 @@ class PoolOrder
getWrestlersOrderByPoolAdvancePoints.each_with_index do |wrestler, index|
placement = index + 1
wrestler.pool_placement = placement
wrestler.save
end
@wrestlers.sort_by{|w| w.poolAdvancePoints}.reverse!
end
@@ -29,7 +26,6 @@ class PoolOrder
def setOriginalPoints
@wrestlers.each do |w|
matches = w.reload.all_matches
w.pool_placement_tiebreaker = nil
w.pool_placement = nil
w.poolAdvancePoints = w.pool_wins.size

View File

@@ -0,0 +1,55 @@
class CalculateSchoolScore
def initialize(school)
@school = school
end
def calculate
school = preload_school_context
score = calculate_score_value(school)
persist_school_score(school.id, score)
score
end
def calculate_value
school = preload_school_context
calculate_score_value(school)
end
private
def preload_school_context
School
.includes(
:deductedPoints,
wrestlers: [
:deductedPoints,
{ matches_as_w1: :winner },
{ matches_as_w2: :winner },
{ weight: [:matches, { tournament: { weights: :wrestlers } }] }
]
)
.find(@school.id)
end
def calculate_score_value(school)
total_points_scored_by_wrestlers(school) - total_points_deducted(school)
end
def total_points_scored_by_wrestlers(school)
school.wrestlers.sum { |wrestler| CalculateWrestlerTeamScore.new(wrestler).totalScore }
end
def total_points_deducted(school)
school.deductedPoints.sum(&:points)
end
def persist_school_score(school_id, score)
School.upsert_all([
{
id: school_id,
score: score,
updated_at: Time.current
}
])
end
end

View File

@@ -3,33 +3,30 @@ class DoubleEliminationGenerateLoserNames
@tournament = tournament
end
# Entry point: assign loser placeholders and advance any byes
def assign_loser_names
# Compatibility wrapper. Returns transformed rows and does not persist.
def assign_loser_names(match_rows = nil)
rows = match_rows || @tournament.matches.where(tournament_id: @tournament.id).map { |m| m.attributes.symbolize_keys }
@tournament.weights.each do |weight|
# only assign loser names if there's conso matches to be had
if weight.calculate_bracket_size > 2
assign_loser_names_for_weight(weight)
advance_bye_matches_championship(weight)
advance_bye_matches_consolation(weight)
end
next unless weight.calculate_bracket_size > 2
assign_loser_names_in_memory(weight, rows)
assign_bye_outcomes_in_memory(weight, rows)
end
rows
end
private
# Assign loser names for a single weight bracket
def assign_loser_names_for_weight(weight)
def assign_loser_names_in_memory(weight, match_rows)
bracket_size = weight.calculate_bracket_size
matches = weight.matches.reload
return if bracket_size <= 2
rows = match_rows.select { |row| row[:weight_id] == weight.id }
num_placers = @tournament.number_of_placers
# Build dynamic round definitions
champ_rounds = dynamic_championship_rounds(bracket_size)
conso_rounds = dynamic_consolation_rounds(bracket_size)
first_round = { bracket_position: first_round_label(bracket_size) }
champ_full = [first_round] + champ_rounds
# Map championship losers into consolation slots
mappings = []
champ_full[0...-1].each_with_index do |champ_info, i|
map_idx = i.zero? ? 0 : (2 * i - 1)
@@ -43,121 +40,102 @@ class DoubleEliminationGenerateLoserNames
}
end
# Apply loser-name mappings
mappings.each do |map|
champ = matches.select { |m| m.bracket_position == map[:championship_bracket_position] }
.sort_by(&:bracket_position_number)
conso = matches.select { |m| m.bracket_position == map[:consolation_bracket_position] }
.sort_by(&:bracket_position_number)
current_champ_round_index = map[:champ_round_index]
if current_champ_round_index.odd?
conso.reverse!
end
champ = rows.select { |r| r[:bracket_position] == map[:championship_bracket_position] }
.sort_by { |r| r[:bracket_position_number] }
conso = rows.select { |r| r[:bracket_position] == map[:consolation_bracket_position] }
.sort_by { |r| r[:bracket_position_number] }
conso.reverse! if map[:champ_round_index].odd?
idx = 0
# Determine if this mapping is for losers from the first championship round
is_first_champ_round_feed = map[:champ_round_index].zero?
is_first_feed = map[:champ_round_index].zero?
conso.each do |cm|
champ_match1 = champ[idx]
if champ_match1
if is_first_champ_round_feed && ((champ_match1.w1 && champ_match1.w2.nil?) || (champ_match1.w1.nil? && champ_match1.w2))
cm.loser1_name = "BYE"
if is_first_feed && single_competitor_match_row?(champ_match1)
cm[:loser1_name] = "BYE"
else
cm.loser1_name = "Loser of #{champ_match1.bout_number}"
cm[:loser1_name] = "Loser of #{champ_match1[:bout_number]}"
end
else
cm.loser1_name = nil # Should not happen if bracket generation is correct
cm[:loser1_name] = nil
end
if map[:both_wrestlers] # This is true only if is_first_champ_round_feed
idx += 1 # Increment for the second championship match
if map[:both_wrestlers]
idx += 1
champ_match2 = champ[idx]
if champ_match2
# BYE check is only relevant for the first championship round feed
if is_first_champ_round_feed && ((champ_match2.w1 && champ_match2.w2.nil?) || (champ_match2.w1.nil? && champ_match2.w2))
cm.loser2_name = "BYE"
if is_first_feed && single_competitor_match_row?(champ_match2)
cm[:loser2_name] = "BYE"
else
cm.loser2_name = "Loser of #{champ_match2.bout_number}"
cm[:loser2_name] = "Loser of #{champ_match2[:bout_number]}"
end
else
cm.loser2_name = nil # Should not happen
cm[:loser2_name] = nil
end
end
idx += 1 # Increment for the next consolation match or next pair from championship
idx += 1
end
end
# 5th/6th place
if bracket_size >= 5 && num_placers >= 6 && weight.wrestlers.size > 4
conso_semis = matches.select { |m| m.bracket_position == "Conso Semis" }
.sort_by(&:bracket_position_number)
if conso_semis.size >= 2
m56 = matches.find { |m| m.bracket_position == "5/6" }
m56.loser1_name = "Loser of #{conso_semis[0].bout_number}"
m56.loser2_name = "Loser of #{conso_semis[1].bout_number}" if m56
conso_semis = rows.select { |r| r[:bracket_position] == "Conso Semis" }.sort_by { |r| r[:bracket_position_number] }
m56 = rows.find { |r| r[:bracket_position] == "5/6" }
if conso_semis.size >= 2 && m56
m56[:loser1_name] = "Loser of #{conso_semis[0][:bout_number]}"
m56[:loser2_name] = "Loser of #{conso_semis[1][:bout_number]}"
end
end
# 7th/8th place
if bracket_size >= 7 && num_placers >= 8 && weight.wrestlers.size > 6
conso_quarters = matches.select { |m| m.bracket_position == "Conso Quarter" }
.sort_by(&:bracket_position_number)
if conso_quarters.size >= 2
m78 = matches.find { |m| m.bracket_position == "7/8" }
m78.loser1_name = "Loser of #{conso_quarters[0].bout_number}"
m78.loser2_name = "Loser of #{conso_quarters[1].bout_number}" if m78
conso_quarters = rows.select { |r| r[:bracket_position] == "Conso Quarter" }.sort_by { |r| r[:bracket_position_number] }
m78 = rows.find { |r| r[:bracket_position] == "7/8" }
if conso_quarters.size >= 2 && m78
m78[:loser1_name] = "Loser of #{conso_quarters[0][:bout_number]}"
m78[:loser2_name] = "Loser of #{conso_quarters[1][:bout_number]}"
end
end
end
matches.each(&:save!)
end
# Advance first-round byes in championship bracket
def advance_bye_matches_championship(weight)
matches = weight.matches.reload
first_round = matches.map(&:round).min
matches.select { |m| m.round == first_round }
.sort_by(&:bracket_position_number)
.each { |m| handle_bye(m) }
end
# Advance first-round byes in consolation bracket
def advance_bye_matches_consolation(weight)
matches = weight.matches.reload
def assign_bye_outcomes_in_memory(weight, match_rows)
bracket_size = weight.calculate_bracket_size
return if bracket_size <= 2
rows = match_rows.select { |r| r[:weight_id] == weight.id }
first_round = rows.map { |r| r[:round] }.compact.min
rows.select { |r| r[:round] == first_round }.each { |row| apply_bye_to_row(row) }
first_conso = dynamic_consolation_rounds(bracket_size).first
matches.select { |m| m.round == first_conso[:round] && m.bracket_position == first_conso[:bracket_position] }
.sort_by(&:bracket_position_number)
.each { |m| handle_bye(m) }
if first_conso
rows.select { |r| r[:round] == first_conso[:round] && r[:bracket_position] == first_conso[:bracket_position] }
.each { |row| apply_bye_to_row(row) }
end
end
# Mark bye match, set finished, and advance
def handle_bye(match)
if [match.w1, match.w2].compact.size == 1
match.finished = 1
match.win_type = 'BYE'
if match.w1
match.winner_id = match.w1
match.loser2_name = 'BYE'
def apply_bye_to_row(row)
return unless single_competitor_match_row?(row)
row[:finished] = 1
row[:win_type] = "BYE"
if row[:w1]
row[:winner_id] = row[:w1]
row[:loser2_name] = "BYE"
else
match.winner_id = match.w2
match.loser1_name = 'BYE'
end
match.score = ''
match.save!
match.advance_wrestlers
row[:winner_id] = row[:w2]
row[:loser1_name] = "BYE"
end
row[:score] = ""
end
def single_competitor_match_row?(row)
[row[:w1], row[:w2]].compact.size == 1
end
# Helpers for dynamic bracket labels
def first_round_label(size)
case size
when 2 then 'Final'
when 4 then 'Semis'
when 8 then 'Quarter'
when 2 then "Final"
when 4 then "Semis"
when 8 then "Quarter"
else "Bracket Round of #{size}"
end
end
@@ -186,9 +164,9 @@ class DoubleEliminationGenerateLoserNames
def bracket_label(participants)
case participants
when 2 then '1/2'
when 4 then 'Semis'
when 8 then 'Quarter'
when 2 then "1/2"
when 4 then "Semis"
when 8 then "Quarter"
else "Bracket Round of #{participants}"
end
end
@@ -197,12 +175,12 @@ class DoubleEliminationGenerateLoserNames
max_j_for_bracket = (2 * (Math.log2(bracket_size).to_i - 1) - 1)
if participants == 2 && j == max_j_for_bracket
return '3/4'
"3/4"
elsif participants == 4
return j.odd? ? 'Conso Quarter' : 'Conso Semis'
j.odd? ? "Conso Quarter" : "Conso Semis"
else
suffix = j.odd? ? ".1" : ".2"
return "Conso Round of #{participants}#{suffix}"
"Conso Round of #{participants}#{suffix}"
end
end
end

View File

@@ -1,29 +1,33 @@
class DoubleEliminationMatchGeneration
def initialize(tournament)
def initialize(tournament, weights: nil)
@tournament = tournament
@weights = weights
end
def generate_matches
#
# PHASE 1: Generate matches (with local round definitions).
#
@tournament.weights.each do |weight|
generate_matches_for_weight(weight)
build_match_rows
end
#
# PHASE 2: Align all rounds to match the largest brackets definitions.
#
align_all_rounds_to_largest_bracket
def build_match_rows
rows_by_weight_id = {}
generation_weights.each do |weight|
rows_by_weight_id[weight.id] = generate_match_rows_for_weight(weight)
end
align_rows_to_largest_bracket(rows_by_weight_id)
rows_by_weight_id.values.flatten
end
###########################################################################
# PHASE 1: Generate all matches for each bracket, using a single definition.
###########################################################################
def generate_matches_for_weight(weight)
def generate_match_rows_for_weight(weight)
bracket_size = weight.calculate_bracket_size
bracket_info = define_bracket_matches(bracket_size)
return unless bracket_info
return [] unless bracket_info
rows = []
# 1) Round one matchups
bracket_info[:round_one_matchups].each_with_index do |matchup, idx|
@@ -32,7 +36,7 @@ class DoubleEliminationMatchGeneration
bracket_pos_number = idx + 1
round_number = matchup[:round]
create_matchup_from_seed(
rows << create_matchup_from_seed(
seed1,
seed2,
bracket_position,
@@ -49,7 +53,7 @@ class DoubleEliminationMatchGeneration
round_number = round_info[:round]
matches_this_round.times do |i|
create_matchup(
rows << create_matchup(
nil,
nil,
bracket_position,
@@ -67,7 +71,7 @@ class DoubleEliminationMatchGeneration
round_number = round_info[:round]
matches_this_round.times do |i|
create_matchup(
rows << create_matchup(
nil,
nil,
bracket_position,
@@ -79,12 +83,14 @@ class DoubleEliminationMatchGeneration
# 5/6, 7/8 placing logic
if weight.wrestlers.size >= 5 && @tournament.number_of_placers >= 6 && matches_this_round == 1
create_matchup(nil, nil, "5/6", 1, round_number, weight)
rows << create_matchup(nil, nil, "5/6", 1, round_number, weight)
end
if weight.wrestlers.size >= 7 && @tournament.number_of_placers >= 8 && matches_this_round == 1
create_matchup(nil, nil, "7/8", 1, round_number, weight)
rows << create_matchup(nil, nil, "7/8", 1, round_number, weight)
end
end
rows
end
# Single bracket definition dynamically generated for any power-of-two bracket size.
@@ -173,18 +179,18 @@ class DoubleEliminationMatchGeneration
###########################################################################
# PHASE 2: Overwrite rounds in all smaller brackets to match the largest one.
###########################################################################
def align_all_rounds_to_largest_bracket
largest_weight = @tournament.weights.max_by { |w| w.calculate_bracket_size }
def align_rows_to_largest_bracket(rows_by_weight_id)
largest_weight = generation_weights.max_by { |w| w.calculate_bracket_size }
return unless largest_weight
position_to_round = {}
largest_weight.tournament.matches.where(weight_id: largest_weight.id).each do |m|
position_to_round[m.bracket_position] ||= m.round
rows_by_weight_id.fetch(largest_weight.id, []).each do |row|
position_to_round[row[:bracket_position]] ||= row[:round]
end
@tournament.matches.find_each do |match|
if position_to_round.key?(match.bracket_position)
match.update(round: position_to_round[match.bracket_position])
rows_by_weight_id.each_value do |rows|
rows.each do |row|
row[:round] = position_to_round[row[:bracket_position]] if position_to_round.key?(row[:bracket_position])
end
end
end
@@ -192,8 +198,12 @@ class DoubleEliminationMatchGeneration
###########################################################################
# Helper methods
###########################################################################
def generation_weights
@weights || @tournament.weights.to_a
end
def wrestler_with_seed(seed, weight)
Wrestler.where("weight_id = ? AND bracket_line = ?", weight.id, seed).first&.id
weight.wrestlers.find { |w| w.bracket_line == seed }&.id
end
def create_matchup_from_seed(w1_seed, w2_seed, bracket_position, bracket_position_number, round, weight)
@@ -208,14 +218,15 @@ class DoubleEliminationMatchGeneration
end
def create_matchup(w1, w2, bracket_position, bracket_position_number, round, weight)
weight.tournament.matches.create!(
{
w1: w1,
w2: w2,
tournament_id: weight.tournament_id,
weight_id: weight.id,
round: round,
bracket_position: bracket_position,
bracket_position_number: bracket_position_number
)
}
end
# Calculates the sequence of seeds for the first round of a power-of-two bracket.

View File

@@ -10,63 +10,183 @@ class GenerateTournamentMatches
def generate_raw
standardStartingActions
PoolToBracketMatchGeneration.new(@tournament).generatePoolToBracketMatches if @tournament.tournament_type == "Pool to bracket"
ModifiedSixteenManMatchGeneration.new(@tournament).generate_matches if @tournament.tournament_type.include? "Modified 16 Man Double Elimination"
DoubleEliminationMatchGeneration.new(@tournament).generate_matches if @tournament.tournament_type.include? "Regular Double Elimination"
generation_context = preload_generation_context
seed_wrestlers_in_memory(generation_context)
match_rows = build_match_rows(generation_context)
post_process_match_rows_in_memory(generation_context, match_rows)
persist_generation_rows(generation_context, match_rows)
postMatchCreationActions
PoolToBracketMatchGeneration.new(@tournament).assignLoserNames if @tournament.tournament_type == "Pool to bracket"
ModifiedSixteenManGenerateLoserNames.new(@tournament).assign_loser_names if @tournament.tournament_type.include? "Modified 16 Man Double Elimination"
DoubleEliminationGenerateLoserNames.new(@tournament).assign_loser_names if @tournament.tournament_type.include? "Regular Double Elimination"
advance_bye_matches_after_insert
end
def standardStartingActions
@tournament.curently_generating_matches = 1
@tournament.save
WipeTournamentMatches.new(@tournament).setUpMatchGeneration
TournamentSeeding.new(@tournament).set_seeds
end
def preload_generation_context
weights = @tournament.weights.includes(:wrestlers).order(:max).to_a
wrestlers = weights.flat_map(&:wrestlers)
{
weights: weights,
wrestlers: wrestlers,
wrestlers_by_weight_id: wrestlers.group_by(&:weight_id)
}
end
def seed_wrestlers_in_memory(generation_context)
TournamentSeeding.new(@tournament).set_seeds(weights: generation_context[:weights], persist: false)
end
def build_match_rows(generation_context)
return PoolToBracketMatchGeneration.new(
@tournament,
weights: generation_context[:weights],
wrestlers_by_weight_id: generation_context[:wrestlers_by_weight_id]
).generatePoolToBracketMatches if @tournament.tournament_type == "Pool to bracket"
return ModifiedSixteenManMatchGeneration.new(@tournament, weights: generation_context[:weights]).generate_matches if @tournament.tournament_type.include? "Modified 16 Man Double Elimination"
return DoubleEliminationMatchGeneration.new(@tournament, weights: generation_context[:weights]).generate_matches if @tournament.tournament_type.include? "Regular Double Elimination"
[]
end
def persist_generation_rows(generation_context, match_rows)
persist_wrestlers(generation_context[:wrestlers])
persist_matches(match_rows)
end
def post_process_match_rows_in_memory(generation_context, match_rows)
move_finals_rows_to_last_round(match_rows) unless @tournament.tournament_type.include?("Regular Double Elimination")
assign_bouts_in_memory(match_rows, generation_context[:weights])
assign_loser_names_in_memory(generation_context, match_rows)
assign_bye_outcomes_in_memory(generation_context, match_rows)
end
def persist_wrestlers(wrestlers)
return if wrestlers.blank?
timestamp = Time.current
rows = wrestlers.map do |w|
{
id: w.id,
bracket_line: w.bracket_line,
pool: w.pool,
updated_at: timestamp
}
end
Wrestler.upsert_all(rows)
end
def persist_matches(match_rows)
return if match_rows.blank?
timestamp = Time.current
rows_with_timestamps = match_rows.map do |row|
row.to_h.symbolize_keys.merge(created_at: timestamp, updated_at: timestamp)
end
all_keys = rows_with_timestamps.flat_map(&:keys).uniq
normalized_rows = rows_with_timestamps.map do |row|
all_keys.each_with_object({}) { |key, normalized| normalized[key] = row[key] }
end
Match.insert_all!(normalized_rows)
end
def postMatchCreationActions
moveFinalsMatchesToLastRound if ! @tournament.tournament_type.include? "Regular Double Elimination"
assignBouts
@tournament.reset_and_fill_bout_board
@tournament.curently_generating_matches = nil
@tournament.save!
Tournament.broadcast_up_matches_board(@tournament.id)
end
def move_finals_rows_to_last_round(match_rows)
finals_round = match_rows.map { |row| row[:round] }.compact.max
return unless finals_round
match_rows.each do |row|
row[:round] = finals_round if ["1/2", "3/4", "5/6", "7/8"].include?(row[:bracket_position])
end
end
def assign_bouts_in_memory(match_rows, weights)
bout_counts = Hash.new(0)
weight_max_by_id = weights.each_with_object({}) { |w, memo| memo[w.id] = w.max }
match_rows
.sort_by { |row| [row[:round].to_i, weight_max_by_id[row[:weight_id]].to_f, row[:weight_id].to_i, row[:bracket_position_number].to_i] }
.each do |row|
round = row[:round].to_i
row[:bout_number] = round * 1000 + bout_counts[round]
bout_counts[round] += 1
end
end
def assign_loser_names_in_memory(generation_context, match_rows)
if @tournament.tournament_type == "Pool to bracket"
service = PoolToBracketGenerateLoserNames.new(@tournament)
generation_context[:weights].each { |weight| service.assign_loser_names_in_memory(weight, match_rows) }
elsif @tournament.tournament_type.include?("Modified 16 Man Double Elimination")
service = ModifiedSixteenManGenerateLoserNames.new(@tournament)
generation_context[:weights].each { |weight| service.assign_loser_names_in_memory(weight, match_rows) }
elsif @tournament.tournament_type.include?("Regular Double Elimination")
service = DoubleEliminationGenerateLoserNames.new(@tournament)
generation_context[:weights].each { |weight| service.assign_loser_names_in_memory(weight, match_rows) }
end
end
def assign_bye_outcomes_in_memory(generation_context, match_rows)
if @tournament.tournament_type.include?("Modified 16 Man Double Elimination")
service = ModifiedSixteenManGenerateLoserNames.new(@tournament)
generation_context[:weights].each { |weight| service.assign_bye_outcomes_in_memory(weight, match_rows) }
elsif @tournament.tournament_type.include?("Regular Double Elimination")
service = DoubleEliminationGenerateLoserNames.new(@tournament)
generation_context[:weights].each { |weight| service.assign_bye_outcomes_in_memory(weight, match_rows) }
end
end
def advance_bye_matches_after_insert
Match.where(tournament_id: @tournament.id, finished: 1, win_type: "BYE")
.where.not(winner_id: nil)
.find_each(&:advance_wrestlers)
end
def assignBouts
bout_counts = Hash.new(0)
@tournament.matches.reload
@tournament.matches.sort_by{|m| [m.round, m.weight_max]}.each do |m|
m.bout_number = m.round * 1000 + bout_counts[m.round]
bout_counts[m.round] += 1
m.save!
timestamp = Time.current
ordered_matches = Match.joins(:weight)
.where(tournament_id: @tournament.id)
.order("matches.round ASC, weights.max ASC, matches.id ASC")
.pluck("matches.id", "matches.round")
updates = []
ordered_matches.each do |match_id, round|
updates << {
id: match_id,
bout_number: round * 1000 + bout_counts[round],
updated_at: timestamp
}
bout_counts[round] += 1
end
Match.upsert_all(updates) if updates.any?
end
def moveFinalsMatchesToLastRound
finalsRound = @tournament.reload.total_rounds
finalsMatches = @tournament.matches.reload.select{|m| m.bracket_position == "1/2" || m.bracket_position == "3/4" || m.bracket_position == "5/6" || m.bracket_position == "7/8"}
finalsMatches. each do |m|
m.round = finalsRound
m.save
end
@tournament.matches
.where(bracket_position: ["1/2", "3/4", "5/6", "7/8"])
.update_all(round: finalsRound, updated_at: Time.current)
end
def unAssignMats
matches = @tournament.matches.reload
matches.each do |m|
m.mat_id = nil
m.save!
end
@tournament.matches.update_all(mat_id: nil, updated_at: Time.current)
end
def unAssignBouts
bout_counts = Hash.new(0)
@tournament.matches.each do |m|
m.bout_number = nil
m.save!
end
@tournament.matches.update_all(bout_number: nil, updated_at: Time.current)
end
end

View File

@@ -3,93 +3,89 @@ class ModifiedSixteenManGenerateLoserNames
@tournament = tournament
end
def assign_loser_names
matches_by_weight = nil
@tournament.weights.each do |w|
matches_by_weight = @tournament.matches.where(weight_id: w.id)
conso_round_2(matches_by_weight)
conso_round_3(matches_by_weight)
third_fourth(matches_by_weight)
seventh_eighth(matches_by_weight)
save_matches(matches_by_weight)
matches_by_weight = @tournament.matches.where(weight_id: w.id).reload
advance_bye_matches_championship(matches_by_weight)
save_matches(matches_by_weight)
# Compatibility wrapper. Returns transformed rows and does not persist.
def assign_loser_names(match_rows = nil)
rows = match_rows || @tournament.matches.where(tournament_id: @tournament.id).map { |m| m.attributes.symbolize_keys }
@tournament.weights.each do |weight|
assign_loser_names_in_memory(weight, rows)
assign_bye_outcomes_in_memory(weight, rows)
end
rows
end
def assign_loser_names_in_memory(weight, match_rows)
rows = match_rows.select { |row| row[:weight_id] == weight.id }
round_16 = rows.select { |r| r[:bracket_position] == "Bracket Round of 16" }
conso_8 = rows.select { |r| r[:bracket_position] == "Conso Round of 8" }.sort_by { |r| r[:bracket_position_number] }
conso_8.each do |row|
if row[:bracket_position_number] == 1
m1 = round_16.find { |m| m[:bracket_position_number] == 1 }
m2 = round_16.find { |m| m[:bracket_position_number] == 2 }
row[:loser1_name] = "Loser of #{m1[:bout_number]}" if m1
row[:loser2_name] = "Loser of #{m2[:bout_number]}" if m2
elsif row[:bracket_position_number] == 2
m3 = round_16.find { |m| m[:bracket_position_number] == 3 }
m4 = round_16.find { |m| m[:bracket_position_number] == 4 }
row[:loser1_name] = "Loser of #{m3[:bout_number]}" if m3
row[:loser2_name] = "Loser of #{m4[:bout_number]}" if m4
elsif row[:bracket_position_number] == 3
m5 = round_16.find { |m| m[:bracket_position_number] == 5 }
m6 = round_16.find { |m| m[:bracket_position_number] == 6 }
row[:loser1_name] = "Loser of #{m5[:bout_number]}" if m5
row[:loser2_name] = "Loser of #{m6[:bout_number]}" if m6
elsif row[:bracket_position_number] == 4
m7 = round_16.find { |m| m[:bracket_position_number] == 7 }
m8 = round_16.find { |m| m[:bracket_position_number] == 8 }
row[:loser1_name] = "Loser of #{m7[:bout_number]}" if m7
row[:loser2_name] = "Loser of #{m8[:bout_number]}" if m8
end
end
def conso_round_2(matches)
matches.select{|m| m.bracket_position == "Conso Round of 8"}.sort_by{|m| m.bracket_position_number}.each do |match|
if match.bracket_position_number == 1
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 1 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
match.loser2_name = "Loser of #{matches.select{|m| m.bracket_position_number == 2 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
elsif match.bracket_position_number == 2
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 3 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
match.loser2_name = "Loser of #{matches.select{|m| m.bracket_position_number == 4 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
elsif match.bracket_position_number == 3
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 5 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
match.loser2_name = "Loser of #{matches.select{|m| m.bracket_position_number == 6 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
elsif match.bracket_position_number == 4
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 7 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
match.loser2_name = "Loser of #{matches.select{|m| m.bracket_position_number == 8 and m.bracket_position == "Bracket Round of 16"}.first.bout_number}"
quarters = rows.select { |r| r[:bracket_position] == "Quarter" }
conso_quarters = rows.select { |r| r[:bracket_position] == "Conso Quarter" }.sort_by { |r| r[:bracket_position_number] }
conso_quarters.each do |row|
source = case row[:bracket_position_number]
when 1 then quarters.find { |q| q[:bracket_position_number] == 4 }
when 2 then quarters.find { |q| q[:bracket_position_number] == 3 }
when 3 then quarters.find { |q| q[:bracket_position_number] == 2 }
when 4 then quarters.find { |q| q[:bracket_position_number] == 1 }
end
row[:loser1_name] = "Loser of #{source[:bout_number]}" if source
end
semis = rows.select { |r| r[:bracket_position] == "Semis" }
third_fourth = rows.find { |r| r[:bracket_position] == "3/4" }
if third_fourth
third_fourth[:loser1_name] = "Loser of #{semis.first[:bout_number]}" if semis.first
third_fourth[:loser2_name] = "Loser of #{semis.second[:bout_number]}" if semis.second
end
conso_semis = rows.select { |r| r[:bracket_position] == "Conso Semis" }
seventh_eighth = rows.find { |r| r[:bracket_position] == "7/8" }
if seventh_eighth
seventh_eighth[:loser1_name] = "Loser of #{conso_semis.first[:bout_number]}" if conso_semis.first
seventh_eighth[:loser2_name] = "Loser of #{conso_semis.second[:bout_number]}" if conso_semis.second
end
end
def conso_round_3(matches)
matches.select{|m| m.bracket_position == "Conso Quarter"}.sort_by{|m| m.bracket_position_number}.each do |match|
if match.bracket_position_number == 1
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 4 and m.bracket_position == "Quarter"}.first.bout_number}"
elsif match.bracket_position_number == 2
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 3 and m.bracket_position == "Quarter"}.first.bout_number}"
elsif match.bracket_position_number == 3
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 2 and m.bracket_position == "Quarter"}.first.bout_number}"
elsif match.bracket_position_number == 4
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position_number == 1 and m.bracket_position == "Quarter"}.first.bout_number}"
end
end
def assign_bye_outcomes_in_memory(weight, match_rows)
rows = match_rows.select { |r| r[:weight_id] == weight.id && r[:bracket_position] == "Bracket Round of 16" }
rows.each { |row| apply_bye_to_row(row) }
end
def third_fourth(matches)
matches.select{|m| m.bracket_position == "3/4"}.sort_by{|m| m.bracket_position_number}.each do |match|
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position == "Semis"}.first.bout_number}"
match.loser2_name = "Loser of #{matches.select{|m| m.bracket_position == "Semis"}.second.bout_number}"
end
end
def apply_bye_to_row(row)
return unless [row[:w1], row[:w2]].compact.size == 1
def seventh_eighth(matches)
matches.select{|m| m.bracket_position == "7/8"}.sort_by{|m| m.bracket_position_number}.each do |match|
match.loser1_name = "Loser of #{matches.select{|m| m.bracket_position == "Conso Semis"}.first.bout_number}"
match.loser2_name = "Loser of #{matches.select{|m| m.bracket_position == "Conso Semis"}.second.bout_number}"
row[:finished] = 1
row[:win_type] = "BYE"
if row[:w1]
row[:winner_id] = row[:w1]
row[:loser2_name] = "BYE"
else
row[:winner_id] = row[:w2]
row[:loser1_name] = "BYE"
end
row[:score] = ""
end
end
def advance_bye_matches_championship(matches)
matches.select{|m| m.bracket_position == "Bracket Round of 16"}.sort_by{|m| m.bracket_position_number}.each do |match|
if match.w1 == nil or match.w2 == nil
match.finished = 1
match.win_type = "BYE"
if match.w1 != nil
match.winner_id = match.w1
match.loser2_name = "BYE"
match.score = ""
match.save
match.advance_wrestlers
elsif match.w2 != nil
match.winner_id = match.w2
match.loser1_name = "BYE"
match.score = ""
match.save
match.advance_wrestlers
end
end
end
end
def save_matches(matches)
matches.each do |m|
m.save!
end
end
end

View File

@@ -1,70 +1,75 @@
class ModifiedSixteenManMatchGeneration
def initialize( tournament )
def initialize( tournament, weights: nil )
@tournament = tournament
@number_of_placers = @tournament.number_of_placers
@weights = weights
end
def generate_matches
@tournament.weights.each do |weight|
generate_matches_for_weight(weight)
rows = []
generation_weights.each do |weight|
rows.concat(generate_match_rows_for_weight(weight))
end
rows
end
def generate_matches_for_weight(weight)
round_one(weight)
round_two(weight)
round_three(weight)
round_four(weight)
round_five(weight)
def generate_match_rows_for_weight(weight)
rows = []
round_one(weight, rows)
round_two(weight, rows)
round_three(weight, rows)
round_four(weight, rows)
round_five(weight, rows)
rows
end
def round_one(weight)
create_matchup_from_seed(1,16, "Bracket Round of 16", 1, 1,weight)
create_matchup_from_seed(8,9, "Bracket Round of 16", 2, 1,weight)
create_matchup_from_seed(5,12, "Bracket Round of 16", 3, 1,weight)
create_matchup_from_seed(4,14, "Bracket Round of 16", 4, 1,weight)
create_matchup_from_seed(3,13, "Bracket Round of 16", 5, 1,weight)
create_matchup_from_seed(6,11, "Bracket Round of 16", 6, 1,weight)
create_matchup_from_seed(7,10, "Bracket Round of 16", 7, 1,weight)
create_matchup_from_seed(2,15, "Bracket Round of 16", 8, 1,weight)
def round_one(weight, rows)
rows << create_matchup_from_seed(1,16, "Bracket Round of 16", 1, 1,weight)
rows << create_matchup_from_seed(8,9, "Bracket Round of 16", 2, 1,weight)
rows << create_matchup_from_seed(5,12, "Bracket Round of 16", 3, 1,weight)
rows << create_matchup_from_seed(4,14, "Bracket Round of 16", 4, 1,weight)
rows << create_matchup_from_seed(3,13, "Bracket Round of 16", 5, 1,weight)
rows << create_matchup_from_seed(6,11, "Bracket Round of 16", 6, 1,weight)
rows << create_matchup_from_seed(7,10, "Bracket Round of 16", 7, 1,weight)
rows << create_matchup_from_seed(2,15, "Bracket Round of 16", 8, 1,weight)
end
def round_two(weight)
create_matchup(nil,nil,"Quarter",1,2,weight)
create_matchup(nil,nil,"Quarter",2,2,weight)
create_matchup(nil,nil,"Quarter",3,2,weight)
create_matchup(nil,nil,"Quarter",4,2,weight)
create_matchup(nil,nil,"Conso Round of 8",1,2,weight)
create_matchup(nil,nil,"Conso Round of 8",2,2,weight)
create_matchup(nil,nil,"Conso Round of 8",3,2,weight)
create_matchup(nil,nil,"Conso Round of 8",4,2,weight)
def round_two(weight, rows)
rows << create_matchup(nil,nil,"Quarter",1,2,weight)
rows << create_matchup(nil,nil,"Quarter",2,2,weight)
rows << create_matchup(nil,nil,"Quarter",3,2,weight)
rows << create_matchup(nil,nil,"Quarter",4,2,weight)
rows << create_matchup(nil,nil,"Conso Round of 8",1,2,weight)
rows << create_matchup(nil,nil,"Conso Round of 8",2,2,weight)
rows << create_matchup(nil,nil,"Conso Round of 8",3,2,weight)
rows << create_matchup(nil,nil,"Conso Round of 8",4,2,weight)
end
def round_three(weight)
create_matchup(nil,nil,"Semis",1,3,weight)
create_matchup(nil,nil,"Semis",2,3,weight)
create_matchup(nil,nil,"Conso Quarter",1,3,weight)
create_matchup(nil,nil,"Conso Quarter",2,3,weight)
create_matchup(nil,nil,"Conso Quarter",3,3,weight)
create_matchup(nil,nil,"Conso Quarter",4,3,weight)
def round_three(weight, rows)
rows << create_matchup(nil,nil,"Semis",1,3,weight)
rows << create_matchup(nil,nil,"Semis",2,3,weight)
rows << create_matchup(nil,nil,"Conso Quarter",1,3,weight)
rows << create_matchup(nil,nil,"Conso Quarter",2,3,weight)
rows << create_matchup(nil,nil,"Conso Quarter",3,3,weight)
rows << create_matchup(nil,nil,"Conso Quarter",4,3,weight)
end
def round_four(weight)
create_matchup(nil,nil,"Conso Semis",1,4,weight)
create_matchup(nil,nil,"Conso Semis",2,4,weight)
def round_four(weight, rows)
rows << create_matchup(nil,nil,"Conso Semis",1,4,weight)
rows << create_matchup(nil,nil,"Conso Semis",2,4,weight)
end
def round_five(weight)
create_matchup(nil,nil,"1/2",1,5,weight)
create_matchup(nil,nil,"3/4",1,5,weight)
create_matchup(nil,nil,"5/6",1,5,weight)
def round_five(weight, rows)
rows << create_matchup(nil,nil,"1/2",1,5,weight)
rows << create_matchup(nil,nil,"3/4",1,5,weight)
rows << create_matchup(nil,nil,"5/6",1,5,weight)
if @number_of_placers >= 8
create_matchup(nil,nil,"7/8",1,5,weight)
rows << create_matchup(nil,nil,"7/8",1,5,weight)
end
end
def wrestler_with_seed(seed,weight)
wrestler = Wrestler.where("weight_id = ? and bracket_line = ?", weight.id, seed).first
wrestler = weight.wrestlers.find { |w| w.bracket_line == seed }
if wrestler
return wrestler.id
else
@@ -79,13 +84,18 @@ class ModifiedSixteenManMatchGeneration
end
def create_matchup(w1, w2, bracket_position, bracket_position_number,round,weight)
@tournament.matches.create(
{
w1: w1,
w2: w2,
tournament_id: @tournament.id,
weight_id: weight.id,
round: round,
bracket_position: bracket_position,
bracket_position_number: bracket_position_number
)
}
end
def generation_weights
@weights || @tournament.weights.to_a
end
end

View File

@@ -12,18 +12,19 @@ class PoolBracketGeneration
end
def generateBracketMatches()
@rows = []
if @pool_bracket_type == "twoPoolsToSemi"
return twoPoolsToSemi()
twoPoolsToSemi()
elsif @pool_bracket_type == "twoPoolsToFinal"
return twoPoolsToFinal()
twoPoolsToFinal()
elsif @pool_bracket_type == "fourPoolsToQuarter"
return fourPoolsToQuarter()
fourPoolsToQuarter()
elsif @pool_bracket_type == "fourPoolsToSemi"
return fourPoolsToSemi()
fourPoolsToSemi()
elsif @pool_bracket_type == "eightPoolsToQuarter"
return eightPoolsToQuarter()
eightPoolsToQuarter()
end
return []
@rows
end
def twoPoolsToSemi()
@@ -86,14 +87,15 @@ class PoolBracketGeneration
end
def createMatchup(w1_name, w2_name, bracket_position, bracket_position_number)
@tournament.matches.create(
@rows << {
loser1_name: w1_name,
loser2_name: w2_name,
tournament_id: @tournament.id,
weight_id: @weight.id,
round: @round,
bracket_position: bracket_position,
bracket_position_number: bracket_position_number
)
}
end
end

View File

@@ -1,35 +1,46 @@
class PoolGeneration
def initialize(weight)
def initialize(weight, wrestlers: nil)
@weight = weight
@tournament = @weight.tournament
@pool = 1
@wrestlers = wrestlers
end
def generatePools
GeneratePoolNumbers.new(@weight).savePoolNumbers
GeneratePoolNumbers.new(@weight).savePoolNumbers(wrestlers: wrestlers_for_weight, persist: false)
rows = []
pools = @weight.pools
while @pool <= pools
roundRobin
rows.concat(roundRobin)
@pool += 1
end
rows
end
def roundRobin
wrestlers = @weight.wrestlers_in_pool(@pool)
rows = []
wrestlers = wrestlers_for_weight.select { |w| w.pool == @pool }
pool_matches = RoundRobinTournament.schedule(wrestlers).reverse
pool_matches.each_with_index do |b, index|
round = index + 1
bouts = b.map
bouts.each do |bout|
if bout[0] != nil and bout[1] != nil
@tournament.matches.create(
rows << {
w1: bout[0].id,
w2: bout[1].id,
tournament_id: @tournament.id,
weight_id: @weight.id,
bracket_position: "Pool",
round: round)
round: round
}
end
end
end
rows
end
def wrestlers_for_weight
@wrestlers || @weight.wrestlers.to_a
end
end

View File

@@ -3,78 +3,95 @@ class PoolToBracketGenerateLoserNames
@tournament = tournament
end
def assignLoserNamesWeight(weight)
matches_by_weight = @tournament.matches.where(weight_id: weight.id)
if weight.pool_bracket_type == "twoPoolsToSemi"
twoPoolsToSemiLoser(matches_by_weight)
elsif (weight.pool_bracket_type == "fourPoolsToQuarter") or (weight.pool_bracket_type == "eightPoolsToQuarter")
fourPoolsToQuarterLoser(matches_by_weight)
elsif weight.pool_bracket_type == "fourPoolsToSemi"
fourPoolsToSemiLoser(matches_by_weight)
end
saveMatches(matches_by_weight)
# Compatibility wrapper. Returns transformed rows and does not persist.
def assignLoserNamesWeight(weight, match_rows = nil)
rows = match_rows || @tournament.matches.where(weight_id: weight.id).map { |m| m.attributes.symbolize_keys }
assign_loser_names_in_memory(weight, rows)
rows
end
# Compatibility wrapper. Returns transformed rows and does not persist.
def assignLoserNames
matches_by_weight = nil
@tournament.weights.each do |w|
matches_by_weight = @tournament.matches.where(weight_id: w.id)
if w.pool_bracket_type == "twoPoolsToSemi"
twoPoolsToSemiLoser(matches_by_weight)
elsif (w.pool_bracket_type == "fourPoolsToQuarter") or (w.pool_bracket_type == "eightPoolsToQuarter")
fourPoolsToQuarterLoser(matches_by_weight)
elsif w.pool_bracket_type == "fourPoolsToSemi"
fourPoolsToSemiLoser(matches_by_weight)
end
saveMatches(matches_by_weight)
@tournament.weights.each_with_object([]) do |weight, all_rows|
all_rows.concat(assignLoserNamesWeight(weight))
end
end
def twoPoolsToSemiLoser(matches_by_weight)
match1 = matches_by_weight.select{|m| m.loser1_name == "Winner Pool 1"}.first
match2 = matches_by_weight.select{|m| m.loser1_name == "Winner Pool 2"}.first
matchChange = matches_by_weight.select{|m| m.bracket_position == "3/4"}.first
matchChange.loser1_name = "Loser of #{match1.bout_number}"
matchChange.loser2_name = "Loser of #{match2.bout_number}"
end
def fourPoolsToQuarterLoser(matches_by_weight)
quarters = matches_by_weight.select{|m| m.bracket_position == "Quarter"}
consoSemis = matches_by_weight.select{|m| m.bracket_position == "Conso Semis"}
semis = matches_by_weight.select{|m| m.bracket_position == "Semis"}
thirdFourth = matches_by_weight.select{|m| m.bracket_position == "3/4"}.first
seventhEighth = matches_by_weight.select{|m| m.bracket_position == "7/8"}.first
consoSemis.each do |m|
if m.bracket_position_number == 1
m.loser1_name = "Loser of #{quarters.select{|m| m.bracket_position_number == 1}.first.bout_number}"
m.loser2_name = "Loser of #{quarters.select{|m| m.bracket_position_number == 2}.first.bout_number}"
elsif m.bracket_position_number == 2
m.loser1_name = "Loser of #{quarters.select{|m| m.bracket_position_number == 3}.first.bout_number}"
m.loser2_name = "Loser of #{quarters.select{|m| m.bracket_position_number == 4}.first.bout_number}"
end
end
thirdFourth.loser1_name = "Loser of #{semis.select{|m| m.bracket_position_number == 1}.first.bout_number}"
thirdFourth.loser2_name = "Loser of #{semis.select{|m| m.bracket_position_number == 2}.first.bout_number}"
consoSemis = matches_by_weight.select{|m| m.bracket_position == "Conso Semis"}
seventhEighth.loser1_name = "Loser of #{consoSemis.select{|m| m.bracket_position_number == 1}.first.bout_number}"
seventhEighth.loser2_name = "Loser of #{consoSemis.select{|m| m.bracket_position_number == 2}.first.bout_number}"
end
def fourPoolsToSemiLoser(matches_by_weight)
semis = matches_by_weight.select{|m| m.bracket_position == "Semis"}
thirdFourth = matches_by_weight.select{|m| m.bracket_position == "3/4"}.first
consoSemis = matches_by_weight.select{|m| m.bracket_position == "Conso Semis"}
seventhEighth = matches_by_weight.select{|m| m.bracket_position == "7/8"}.first
thirdFourth.loser1_name = "Loser of #{semis.select{|m| m.bracket_position_number == 1}.first.bout_number}"
thirdFourth.loser2_name = "Loser of #{semis.select{|m| m.bracket_position_number == 2}.first.bout_number}"
seventhEighth.loser1_name = "Loser of #{consoSemis.select{|m| m.bracket_position_number == 1}.first.bout_number}"
seventhEighth.loser2_name = "Loser of #{consoSemis.select{|m| m.bracket_position_number == 2}.first.bout_number}"
end
def saveMatches(matches)
matches.each do |m|
m.save!
def assign_loser_names_in_memory(weight, match_rows)
rows = match_rows.select { |row| row[:weight_id] == weight.id }
if weight.pool_bracket_type == "twoPoolsToSemi"
two_pools_to_semi_loser_rows(rows)
elsif (weight.pool_bracket_type == "fourPoolsToQuarter") || (weight.pool_bracket_type == "eightPoolsToQuarter")
four_pools_to_quarter_loser_rows(rows)
elsif weight.pool_bracket_type == "fourPoolsToSemi"
four_pools_to_semi_loser_rows(rows)
end
end
def two_pools_to_semi_loser_rows(rows)
match1 = rows.find { |m| m[:loser1_name] == "Winner Pool 1" }
match2 = rows.find { |m| m[:loser1_name] == "Winner Pool 2" }
match_change = rows.find { |m| m[:bracket_position] == "3/4" }
return unless match1 && match2 && match_change
match_change[:loser1_name] = "Loser of #{match1[:bout_number]}"
match_change[:loser2_name] = "Loser of #{match2[:bout_number]}"
end
def four_pools_to_quarter_loser_rows(rows)
quarters = rows.select { |m| m[:bracket_position] == "Quarter" }
conso_semis = rows.select { |m| m[:bracket_position] == "Conso Semis" }
semis = rows.select { |m| m[:bracket_position] == "Semis" }
third_fourth = rows.find { |m| m[:bracket_position] == "3/4" }
seventh_eighth = rows.find { |m| m[:bracket_position] == "7/8" }
conso_semis.each do |m|
if m[:bracket_position_number] == 1
q1 = quarters.find { |q| q[:bracket_position_number] == 1 }
q2 = quarters.find { |q| q[:bracket_position_number] == 2 }
m[:loser1_name] = "Loser of #{q1[:bout_number]}" if q1
m[:loser2_name] = "Loser of #{q2[:bout_number]}" if q2
elsif m[:bracket_position_number] == 2
q3 = quarters.find { |q| q[:bracket_position_number] == 3 }
q4 = quarters.find { |q| q[:bracket_position_number] == 4 }
m[:loser1_name] = "Loser of #{q3[:bout_number]}" if q3
m[:loser2_name] = "Loser of #{q4[:bout_number]}" if q4
end
end
if third_fourth
s1 = semis.find { |s| s[:bracket_position_number] == 1 }
s2 = semis.find { |s| s[:bracket_position_number] == 2 }
third_fourth[:loser1_name] = "Loser of #{s1[:bout_number]}" if s1
third_fourth[:loser2_name] = "Loser of #{s2[:bout_number]}" if s2
end
if seventh_eighth
c1 = conso_semis.find { |c| c[:bracket_position_number] == 1 }
c2 = conso_semis.find { |c| c[:bracket_position_number] == 2 }
seventh_eighth[:loser1_name] = "Loser of #{c1[:bout_number]}" if c1
seventh_eighth[:loser2_name] = "Loser of #{c2[:bout_number]}" if c2
end
end
def four_pools_to_semi_loser_rows(rows)
semis = rows.select { |m| m[:bracket_position] == "Semis" }
conso_semis = rows.select { |m| m[:bracket_position] == "Conso Semis" }
third_fourth = rows.find { |m| m[:bracket_position] == "3/4" }
seventh_eighth = rows.find { |m| m[:bracket_position] == "7/8" }
if third_fourth
s1 = semis.find { |s| s[:bracket_position_number] == 1 }
s2 = semis.find { |s| s[:bracket_position_number] == 2 }
third_fourth[:loser1_name] = "Loser of #{s1[:bout_number]}" if s1
third_fourth[:loser2_name] = "Loser of #{s2[:bout_number]}" if s2
end
if seventh_eighth
c1 = conso_semis.find { |c| c[:bracket_position_number] == 1 }
c2 = conso_semis.find { |c| c[:bracket_position_number] == 2 }
seventh_eighth[:loser1_name] = "Loser of #{c1[:bout_number]}" if c1
seventh_eighth[:loser2_name] = "Loser of #{c2[:bout_number]}" if c2
end
end
end

View File

@@ -1,41 +1,89 @@
class PoolToBracketMatchGeneration
def initialize( tournament )
def initialize(tournament, weights: nil, wrestlers_by_weight_id: nil)
@tournament = tournament
@weights = weights
@wrestlers_by_weight_id = wrestlers_by_weight_id
end
def generatePoolToBracketMatches
@tournament.weights.order(:max).each do |weight|
PoolGeneration.new(weight).generatePools()
last_match = @tournament.matches.where(weight: weight).order(round: :desc).limit(1).first
highest_round = last_match.round
PoolBracketGeneration.new(weight, highest_round).generateBracketMatches()
end
movePoolSeedsToFinalPoolRound
rows = []
generation_weights.each do |weight|
wrestlers = wrestlers_for_weight(weight)
pool_rows = PoolGeneration.new(weight, wrestlers: wrestlers).generatePools
rows.concat(pool_rows)
highest_round = pool_rows.map { |row| row[:round] }.max || 0
bracket_rows = PoolBracketGeneration.new(weight, highest_round).generateBracketMatches
rows.concat(bracket_rows)
end
def movePoolSeedsToFinalPoolRound
@tournament.weights.each do |w|
setOriginalSeedsToWrestleLastPoolRound(w)
movePoolSeedsToFinalPoolRound(rows)
rows
end
def movePoolSeedsToFinalPoolRound(match_rows)
generation_weights.each do |w|
setOriginalSeedsToWrestleLastPoolRound(w, match_rows)
end
end
def setOriginalSeedsToWrestleLastPoolRound(weight)
def setOriginalSeedsToWrestleLastPoolRound(weight, match_rows)
pool = 1
until pool > weight.pools
wrestler1 = weight.pool_wrestlers_sorted_by_bracket_line(pool).first
wrestler2 = weight.pool_wrestlers_sorted_by_bracket_line(pool).second
match = wrestler1.pool_matches.sort_by{|m| m.round}.last
if match.w1 != wrestler2.id or match.w2 != wrestler2.id
if match.w1 == wrestler1.id
SwapWrestlers.new.swap_wrestlers_bracket_lines(match.w2,wrestler2.id)
elsif match.w2 == wrestler1.id
SwapWrestlers.new.swap_wrestlers_bracket_lines(match.w1,wrestler2.id)
wrestlers = wrestlers_for_weight(weight)
weight_pools = weight.pools
until pool > weight_pools
pool_wrestlers = wrestlers.select { |w| w.pool == pool }.sort_by(&:bracket_line)
wrestler1 = pool_wrestlers.first
wrestler2 = pool_wrestlers.second
if wrestler1 && wrestler2
pool_matches = match_rows.select { |row| row[:weight_id] == weight.id && row[:bracket_position] == "Pool" && (row[:w1] == wrestler1.id || row[:w2] == wrestler1.id) }
match = pool_matches.max_by { |row| row[:round] }
if match && (match[:w1] != wrestler2.id || match[:w2] != wrestler2.id)
if match[:w1] == wrestler1.id
swap_wrestlers_in_memory(match_rows, wrestlers, match[:w2], wrestler2.id)
elsif match[:w2] == wrestler1.id
swap_wrestlers_in_memory(match_rows, wrestlers, match[:w1], wrestler2.id)
end
end
end
pool += 1
end
end
def swap_wrestlers_in_memory(match_rows, wrestlers, wrestler1_id, wrestler2_id)
w1 = wrestlers.find { |w| w.id == wrestler1_id }
w2 = wrestlers.find { |w| w.id == wrestler2_id }
return unless w1 && w2
w1_bracket_line, w1_pool = w1.bracket_line, w1.pool
w1.bracket_line, w1.pool = w2.bracket_line, w2.pool
w2.bracket_line, w2.pool = w1_bracket_line, w1_pool
swap_match_rows(match_rows, wrestler1_id, wrestler2_id)
end
def swap_match_rows(match_rows, wrestler1_id, wrestler2_id)
match_rows.each do |row|
row[:w1] = swap_id(row[:w1], wrestler1_id, wrestler2_id)
row[:w2] = swap_id(row[:w2], wrestler1_id, wrestler2_id)
row[:winner_id] = swap_id(row[:winner_id], wrestler1_id, wrestler2_id)
end
end
def swap_id(value, wrestler1_id, wrestler2_id)
return wrestler2_id if value == wrestler1_id
return wrestler1_id if value == wrestler2_id
value
end
def generation_weights
@weights || @tournament.weights.order(:max).to_a
end
def wrestlers_for_weight(weight)
@wrestlers_by_weight_id&.fetch(weight.id, nil) || weight.wrestlers.to_a
end
def assignLoserNames
PoolToBracketGenerateLoserNames.new(@tournament).assignLoserNames

View File

@@ -3,16 +3,22 @@ class TournamentSeeding
@tournament = tournament
end
def set_seeds
@tournament.weights.each do |weight|
def set_seeds(weights: nil, persist: true)
weights_to_seed = weights || @tournament.weights.includes(:wrestlers)
updated_wrestlers = []
weights_to_seed.each do |weight|
wrestlers = weight.wrestlers
bracket_size = weight.calculate_bracket_size
wrestlers = reset_bracket_line_for_lines_higher_than_bracket_size(wrestlers, bracket_size)
wrestlers = set_original_seed_to_bracket_line(wrestlers)
wrestlers = random_seeding(wrestlers, bracket_size)
wrestlers.each(&:save)
updated_wrestlers.concat(wrestlers)
end
persist_bracket_lines(updated_wrestlers) if persist
updated_wrestlers
end
def random_seeding(wrestlers, bracket_size)
@@ -96,4 +102,19 @@ class TournamentSeeding
end
result
end
def persist_bracket_lines(wrestlers)
return if wrestlers.blank?
timestamp = Time.current
updates = wrestlers.map do |wrestler|
{
id: wrestler.id,
bracket_line: wrestler.bracket_line,
updated_at: timestamp
}
end
Wrestler.upsert_all(updates)
end
end

View File

@@ -3,11 +3,13 @@ class GeneratePoolNumbers
@weight = weight
end
def savePoolNumbers
@weight.wrestlers.each do |wrestler|
def savePoolNumbers(wrestlers: nil, persist: true)
wrestlers_to_update = wrestlers || @weight.wrestlers.to_a
wrestlers_to_update.each do |wrestler|
wrestler.pool = get_wrestler_pool_number(@weight.pools, wrestler.bracket_line)
wrestler.save
end
persist_pool_numbers(wrestlers_to_update) if persist
wrestlers_to_update
end
def get_wrestler_pool_number(number_of_pools, wrestler_seed)
@@ -36,4 +38,20 @@ class GeneratePoolNumbers
pool
end
private
def persist_pool_numbers(wrestlers)
return if wrestlers.blank?
timestamp = Time.current
rows = wrestlers.map do |w|
{
id: w.id,
pool: w.pool,
updated_at: timestamp
}
end
Wrestler.upsert_all(rows)
end
end