Aggiunge i tornei con hub, pagina pubblica e tabellone per semifinali e finali.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
module Tournaments
|
||||
class ProposeKnockout
|
||||
def self.call(tournament)
|
||||
new(tournament).call
|
||||
end
|
||||
|
||||
def initialize(tournament)
|
||||
@tournament = tournament
|
||||
end
|
||||
|
||||
def call
|
||||
Tournaments::Entitlements.new(@tournament.club).assert_writable!
|
||||
first_round = @tournament.rounds.order(:position).first
|
||||
return [] unless first_round
|
||||
|
||||
pairs = pair_qualified
|
||||
slots = first_round.matches.order(:scheduled_at, :created_at).to_a
|
||||
slots = create_slots!(first_round, [pairs.size, 1].max) if slots.empty?
|
||||
|
||||
updated = []
|
||||
slots.each_with_index do |match, idx|
|
||||
home, away = pairs[idx]
|
||||
next if home.blank? && away.blank?
|
||||
|
||||
match.update!(home_participant: home, away_participant: away)
|
||||
updated << match
|
||||
end
|
||||
updated.concat(seed_later_rounds!(slots))
|
||||
updated
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def pair_qualified
|
||||
groups = @tournament.groups.order(:position).to_a
|
||||
ranked = groups.map { |group| Tournaments::Standings.call(group).map(&:participant) }
|
||||
return ranked.flatten.each_slice(2).to_a if groups.size < 2
|
||||
|
||||
pairs = []
|
||||
first = ranked[0] || []
|
||||
second = ranked[1] || []
|
||||
pairs << [first[0], second[1]] if first[0] || second[1]
|
||||
pairs << [second[0], first[1]] if second[0] || first[1]
|
||||
leftover = (first.drop(2) + second.drop(2) + ranked.drop(2).flatten)
|
||||
pairs.concat(leftover.each_slice(2).to_a)
|
||||
pairs
|
||||
end
|
||||
|
||||
def seed_later_rounds!(first_round_matches)
|
||||
prev = first_round_matches
|
||||
created = []
|
||||
@tournament.rounds.order(:position).offset(1).each do |round|
|
||||
needed = [prev.size / 2, 1].max
|
||||
slots = round.matches.order(:scheduled_at, :created_at).to_a
|
||||
last_at = prev.map(&:scheduled_at).compact.max
|
||||
start = last_at&.+(1.hour)
|
||||
slots = create_slots!(round, needed, start: start) if slots.empty?
|
||||
|
||||
slots.each_with_index do |match, idx|
|
||||
home_src = prev[idx * 2]
|
||||
away_src = prev[idx * 2 + 1]
|
||||
attrs = {}
|
||||
if home_src && match.home_source_match_id.blank?
|
||||
attrs[:home_source_kind] = "winner_match"
|
||||
attrs[:home_source_match_id] = home_src.id
|
||||
end
|
||||
if away_src && match.away_source_match_id.blank?
|
||||
attrs[:away_source_kind] = "winner_match"
|
||||
attrs[:away_source_match_id] = away_src.id
|
||||
end
|
||||
match.update!(attrs) if attrs.any?
|
||||
created << match
|
||||
end
|
||||
prev = slots
|
||||
end
|
||||
created
|
||||
end
|
||||
|
||||
def create_slots!(round, n, start: nil)
|
||||
count = [n, 1].max
|
||||
day = @tournament.ends_on
|
||||
start ||= Time.zone.local(day.year, day.month, day.day, 18, 0, 0)
|
||||
Array.new(count) do |i|
|
||||
Tournaments::ScheduleMatch.call(
|
||||
tournament: @tournament,
|
||||
attrs: {
|
||||
tournament_round_id: round.id,
|
||||
court: @tournament.court_list.first,
|
||||
scheduled_at: start + i.hours
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user