73 lines
2.0 KiB
Ruby
73 lines
2.0 KiB
Ruby
module Tournaments
|
|
class GenerateGroupMatches
|
|
def self.call(tournament:, start_at: nil)
|
|
new(tournament, start_at: start_at).call
|
|
end
|
|
|
|
def initialize(tournament, start_at: nil)
|
|
@tournament = tournament
|
|
@start_at = start_at
|
|
end
|
|
|
|
def call
|
|
Tournaments::Entitlements.new(@tournament.club).assert_writable!
|
|
created = []
|
|
cursor = @start_at || Time.zone.local(@tournament.starts_on.year, @tournament.starts_on.month, @tournament.starts_on.day, 9, 0, 0)
|
|
courts = @tournament.court_list
|
|
court_idx = 0
|
|
|
|
@tournament.groups.includes(:participants).order(:position).each do |group|
|
|
pairs = round_robin(group.participants.to_a)
|
|
pairs.each do |home, away|
|
|
next if home.blank? || away.blank?
|
|
|
|
match = Tournaments::ScheduleMatch.call(
|
|
tournament: @tournament,
|
|
attrs: {
|
|
home_participant_id: home.id,
|
|
away_participant_id: away.id,
|
|
tournament_group_id: group.id,
|
|
court: courts[court_idx % courts.size],
|
|
scheduled_at: cursor
|
|
}
|
|
)
|
|
created << match
|
|
court_idx += 1
|
|
if (court_idx % courts.size).zero?
|
|
cursor += 1.hour
|
|
cursor = next_day_morning(cursor) if cursor.to_date > @tournament.ends_on
|
|
end
|
|
end
|
|
end
|
|
created
|
|
end
|
|
|
|
private
|
|
|
|
def round_robin(participants)
|
|
list = participants.dup
|
|
return [] if list.size < 2
|
|
|
|
list << nil if list.size.odd?
|
|
n = list.size
|
|
rounds = n - 1
|
|
pairs = []
|
|
rounds.times do
|
|
(n / 2).times do |i|
|
|
a = list[i]
|
|
b = list[n - 1 - i]
|
|
pairs << [a, b] if a && b
|
|
end
|
|
list = [list[0]] + [list[-1]] + list[1..-2]
|
|
end
|
|
pairs
|
|
end
|
|
|
|
def next_day_morning(time)
|
|
nxt = time.to_date + 1.day
|
|
nxt = @tournament.starts_on if nxt > @tournament.ends_on
|
|
Time.zone.local(nxt.year, nxt.month, nxt.day, 9, 0, 0)
|
|
end
|
|
end
|
|
end
|