1
0
mirror of https://github.com/jcwimer/wrestlingApp synced 2026-04-07 14:57:48 +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

@@ -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
num_placers = @tournament.number_of_placers
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
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)
@@ -37,128 +34,109 @@ class DoubleEliminationGenerateLoserNames
mappings << {
championship_bracket_position: champ_info[:bracket_position],
consolation_bracket_position: conso_rounds[map_idx][:bracket_position],
both_wrestlers: i.zero?,
champ_round_index: i
consolation_bracket_position: conso_rounds[map_idx][:bracket_position],
both_wrestlers: i.zero?,
champ_round_index: i
}
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
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
first_conso = dynamic_consolation_rounds(bracket_size).first
return if bracket_size <= 2
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) }
end
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) }
# 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'
else
match.winner_id = match.w2
match.loser1_name = 'BYE'
end
match.score = ''
match.save!
match.advance_wrestlers
first_conso = dynamic_consolation_rounds(bracket_size).first
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
# Helpers for dynamic bracket labels
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
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
def first_round_label(size)
case size
when 2 then 'Final'
when 4 then 'Semis'
when 8 then 'Quarter'
else "Bracket Round of #{size}"
when 2 then "Final"
when 4 then "Semis"
when 8 then "Quarter"
else "Bracket Round of #{size}"
end
end
@@ -173,36 +151,36 @@ class DoubleEliminationGenerateLoserNames
def dynamic_consolation_rounds(size)
total_log2 = Math.log2(size).to_i
return [] if total_log2 <= 1
max_j_val = (2 * (total_log2 - 1) - 1)
(1..max_j_val).map do |j|
current_participants = size / (2**((j.to_f / 2).ceil))
{
{
bracket_position: consolation_label(current_participants, j, size),
round: j
round: j
}
end
end
def bracket_label(participants)
case participants
when 2 then '1/2'
when 4 then 'Semis'
when 8 then 'Quarter'
else "Bracket Round of #{participants}"
when 2 then "1/2"
when 4 then "Semis"
when 8 then "Quarter"
else "Bracket Round of #{participants}"
end
end
def consolation_label(participants, j, bracket_size)
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
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
#
# PHASE 2: Align all rounds to match the largest brackets definitions.
#
align_all_rounds_to_largest_bracket
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

@@ -1,95 +1,91 @@
class ModifiedSixteenManGenerateLoserNames
def initialize( tournament )
@tournament = tournament
def initialize(tournament)
@tournament = tournament
end
# 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 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)
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
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}"
end
end
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
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
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 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 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}"
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 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
def apply_bye_to_row(row)
return unless [row[:w1], row[:w2]].compact.size == 1
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

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
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

@@ -1,80 +1,97 @@
class PoolToBracketGenerateLoserNames
def initialize( tournament )
@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)
def initialize(tournament)
@tournament = tournament
end
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)
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}"
# 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
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}"
# Compatibility wrapper. Returns transformed rows and does not persist.
def assignLoserNames
@tournament.weights.each_with_object([]) do |weight, all_rows|
all_rows.concat(assignLoserNamesWeight(weight))
end
end
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
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}"
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 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}"
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
def saveMatches(matches)
matches.each do |m|
m.save!
end
end
end
end

View File

@@ -1,44 +1,92 @@
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()
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
movePoolSeedsToFinalPoolRound
movePoolSeedsToFinalPoolRound(rows)
rows
end
def movePoolSeedsToFinalPoolRound
@tournament.weights.each do |w|
setOriginalSeedsToWrestleLastPoolRound(w)
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)
end
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
end
end
end

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
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