app/models/league/division.rb
require 'tournament_driver'
class League
class Division < ApplicationRecord
belongs_to :league, inverse_of: :divisions
has_many :rosters, inverse_of: :division, class_name: 'Roster', dependent: :destroy
has_many :matches, through: :rosters, source: :home_team_matches, class_name: 'Match', dependent: :destroy
has_many :transfer_requests, through: :rosters, class_name: 'Roster::TransferRequest'
validates :name, presence: true, length: { in: 1..64 }
TOURNAMENT_SYSTEMS = [:swiss, :round_robin, :single_elimination, :double_elimination, :page_playoffs].freeze
SWISS_PAIRERS = [:dutch].freeze
class GenerationError < StandardError
end
# TODO: Replace messy handling here with normal models
def generate_matches(system, match_options, options = {})
return unless TOURNAMENT_SYSTEMS.include?(system)
send("generate_#{system}", match_options, options)
@driver&.created_matches
end
private
def new_driver(match_options, options = {})
@driver = ::TournamentDriver.new(self, match_options, options)
end
def generate_swiss(match_options, options)
unless matches.where.not(status: :confirmed).empty? || options[:allow_unconfirmed_matches]
raise GenerationError, 'Not all matches in division confirmed'
end
pairer = options[:pairer].to_sym
raise GenerationError, 'Unknown pairing system' unless SWISS_PAIRERS.include?(pairer)
send("generate_swiss_#{pairer}", match_options, options)
end
def generate_swiss_dutch(match_options, options)
options[:pair_options] ||= {}
pair_options = {
allow_duplicates: options[:pair_options].fetch(:allow_duplicates, false),
push_byes_to: options[:pair_options].fetch(:push_byes_to, :bottom_half).to_sym,
}
tournament_options = { pairer: TournamentSystem::Swiss::Dutch, pair_options: pair_options }
TournamentSystem::Swiss.generate new_driver(match_options), tournament_options
end
def generate_round_robin(match_options, _)
TournamentSystem::RoundRobin.generate new_driver(match_options)
end
def generate_single_elimination(match_options, options)
match_options[:has_winner] = true
match_options[:allow_round_draws] = false
driver_options = options.slice(:teams_limit, :starting_round)
TournamentSystem::SingleElimination.generate new_driver(match_options, driver_options)
end
def generate_double_elimination(match_options, options)
match_options[:has_winner] = true
match_options[:allow_round_draws] = false
driver_options = options.slice(:teams_limit, :starting_round)
TournamentSystem::DoubleElimination.generate new_driver(match_options, driver_options)
end
def generate_page_playoffs(match_options, options)
match_options[:has_winner] = true
match_options[:allow_round_draws] = false
driver_options = options.slice(:starting_round)
driver_options[:teams_limit] = 4
tournament_options = options.slice(:bronze_match)
TournamentSystem::PagePlayoff.generate new_driver(match_options, driver_options), tournament_options
end
end
end