mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-04-13 00:26:31 +00:00
Added queues for mats and provided a way for tournament directors to move matches to a mat.
This commit is contained in:
@@ -1,53 +1,50 @@
|
||||
class Mat < ApplicationRecord
|
||||
include ActionView::RecordIdentifier
|
||||
belongs_to :tournament
|
||||
has_many :matches, dependent: :nullify
|
||||
has_many :mat_assignment_rules, dependent: :destroy
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
before_destroy do
|
||||
if tournament.matches.size > 0
|
||||
tournament.reset_mats
|
||||
matsToAssign = tournament.mats.select{|m| m.id != self.id}
|
||||
tournament.assign_mats(matsToAssign)
|
||||
end
|
||||
end
|
||||
|
||||
after_create do
|
||||
if tournament.matches.size > 0
|
||||
tournament.reset_mats
|
||||
matsToAssign = tournament.mats
|
||||
tournament.assign_mats(matsToAssign)
|
||||
end
|
||||
end
|
||||
QUEUE_SLOTS = %w[queue1 queue2 queue3 queue4].freeze
|
||||
|
||||
def assign_next_match
|
||||
slot = first_empty_queue_slot
|
||||
return true unless slot
|
||||
|
||||
match = next_eligible_match
|
||||
self.matches.reload
|
||||
if match and self.unfinished_matches.size < 4
|
||||
match.mat_id = self.id
|
||||
if match.save
|
||||
# Invalidate any wrestler caches
|
||||
if match.w1
|
||||
match.wrestler1.touch
|
||||
match.wrestler1.school.touch
|
||||
return false unless match
|
||||
|
||||
place_match_in_empty_slot!(match, slot)
|
||||
true
|
||||
end
|
||||
|
||||
def advance_queue!(finished_match = nil)
|
||||
self.class.transaction do
|
||||
if finished_match
|
||||
position = queue_position_for_match(finished_match)
|
||||
if position == 1
|
||||
shift_queue_forward!
|
||||
fill_queue_slots!
|
||||
elsif position
|
||||
remove_match_from_queue_and_collapse!(finished_match.id)
|
||||
else
|
||||
fill_queue_slots!
|
||||
end
|
||||
if match.w2
|
||||
match.wrestler2.touch
|
||||
match.wrestler2.school.touch
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
if queue1_match&.finished == 1
|
||||
shift_queue_forward!
|
||||
end
|
||||
fill_queue_slots!
|
||||
end
|
||||
else
|
||||
return true
|
||||
end
|
||||
broadcast_current_match
|
||||
true
|
||||
end
|
||||
|
||||
def next_eligible_match
|
||||
# Start with all matches that are either unfinished (nil or 0), have a bout number, and are ordered by bout_number
|
||||
filtered_matches = tournament.matches
|
||||
filtered_matches = Match.where(tournament_id: tournament_id)
|
||||
.where(finished: [nil, 0]) # finished is nil or 0
|
||||
.where(mat_id: nil) # mat_id is nil
|
||||
.where.not(bout_number: nil) # bout_number is not nil
|
||||
@@ -57,6 +54,11 @@ class Mat < ApplicationRecord
|
||||
filtered_matches = filtered_matches
|
||||
.where("loser1_name != ? OR loser1_name IS NULL", "BYE")
|
||||
.where("loser2_name != ? OR loser2_name IS NULL", "BYE")
|
||||
|
||||
# Filter out matches without a wrestlers
|
||||
filtered_matches = filtered_matches
|
||||
.where("w1 IS NOT NULL")
|
||||
.where("w2 IS NOT NULL")
|
||||
|
||||
# Apply mat assignment rules
|
||||
mat_assignment_rules.each do |rule|
|
||||
@@ -80,9 +82,178 @@ class Mat < ApplicationRecord
|
||||
filtered_matches.first
|
||||
end
|
||||
|
||||
def queue_match_ids
|
||||
QUEUE_SLOTS.map { |slot| public_send(slot) }
|
||||
end
|
||||
|
||||
def queue_matches
|
||||
queue_match_ids.map { |match_id| match_id ? Match.find_by(id: match_id) : nil }
|
||||
end
|
||||
|
||||
def queue1_match
|
||||
queue_match_at(1)
|
||||
end
|
||||
|
||||
def queue2_match
|
||||
queue_match_at(2)
|
||||
end
|
||||
|
||||
def queue3_match
|
||||
queue_match_at(3)
|
||||
end
|
||||
|
||||
def queue4_match
|
||||
queue_match_at(4)
|
||||
end
|
||||
|
||||
def queue_position_for_match(match)
|
||||
return nil unless match
|
||||
return 1 if queue1 == match.id
|
||||
return 2 if queue2 == match.id
|
||||
return 3 if queue3 == match.id
|
||||
return 4 if queue4 == match.id
|
||||
nil
|
||||
end
|
||||
|
||||
def remove_match_from_queue_and_collapse!(match_id)
|
||||
queue_ids = queue_match_ids
|
||||
return if queue_ids.none? { |id| id == match_id }
|
||||
|
||||
queue_ids.map! { |id| id == match_id ? nil : id }
|
||||
queue_ids = queue_ids.compact
|
||||
queue_ids += [nil] * (4 - queue_ids.size)
|
||||
|
||||
update!(
|
||||
queue1: queue_ids[0],
|
||||
queue2: queue_ids[1],
|
||||
queue3: queue_ids[2],
|
||||
queue4: queue_ids[3]
|
||||
)
|
||||
|
||||
fill_queue_slots!
|
||||
broadcast_current_match
|
||||
end
|
||||
|
||||
def assign_match_to_queue!(match, position)
|
||||
position = position.to_i
|
||||
raise ArgumentError, "Queue position must be 1-4" unless (1..4).cover?(position)
|
||||
|
||||
self.class.transaction do
|
||||
match.update!(mat_id: id)
|
||||
remove_match_from_other_mats!(match.id)
|
||||
|
||||
queue_ids = queue_match_ids.map { |id| id == match.id ? nil : id }
|
||||
queue_ids = queue_ids.compact
|
||||
|
||||
queue_ids.insert(position - 1, match.id)
|
||||
bumped_match_id = queue_ids.length > 4 ? queue_ids.pop : nil
|
||||
|
||||
queue_ids += [nil] * (4 - queue_ids.length)
|
||||
|
||||
update!(
|
||||
queue1: queue_ids[0],
|
||||
queue2: queue_ids[1],
|
||||
queue3: queue_ids[2],
|
||||
queue4: queue_ids[3]
|
||||
)
|
||||
|
||||
bumped_match = Match.find_by(id: bumped_match_id)
|
||||
if bumped_match && bumped_match.finished != 1
|
||||
bumped_match.update!(mat_id: nil)
|
||||
end
|
||||
end
|
||||
broadcast_current_match
|
||||
end
|
||||
|
||||
def clear_queue!
|
||||
update!(queue1: nil, queue2: nil, queue3: nil, queue4: nil)
|
||||
end
|
||||
|
||||
def unfinished_matches
|
||||
matches.select{|m| m.finished != 1}.sort_by{|m| m.bout_number}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def queue_match_at(position)
|
||||
match_id = public_send("queue#{position}")
|
||||
match_id ? Match.find_by(id: match_id) : nil
|
||||
end
|
||||
|
||||
def first_empty_queue_slot
|
||||
QUEUE_SLOTS.each_with_index do |slot, index|
|
||||
return index + 1 if public_send(slot).nil?
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def shift_queue_forward!
|
||||
update!(
|
||||
queue1: queue2,
|
||||
queue2: queue3,
|
||||
queue3: queue4,
|
||||
queue4: nil
|
||||
)
|
||||
end
|
||||
|
||||
def fill_queue_slots!
|
||||
queue_ids = queue_match_ids
|
||||
updated = false
|
||||
|
||||
QUEUE_SLOTS.each_with_index do |_slot, index|
|
||||
next if queue_ids[index].present?
|
||||
|
||||
match = next_eligible_match
|
||||
break unless match
|
||||
|
||||
queue_ids[index] = match.id
|
||||
match.update!(mat_id: id)
|
||||
updated = true
|
||||
end
|
||||
|
||||
if updated
|
||||
update!(
|
||||
queue1: queue_ids[0],
|
||||
queue2: queue_ids[1],
|
||||
queue3: queue_ids[2],
|
||||
queue4: queue_ids[3]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def remove_match_from_other_mats!(match_id)
|
||||
self.class.where.not(id: id)
|
||||
.where("queue1 = :match_id OR queue2 = :match_id OR queue3 = :match_id OR queue4 = :match_id", match_id: match_id)
|
||||
.find_each do |mat|
|
||||
mat.remove_match_from_queue_and_collapse!(match_id)
|
||||
end
|
||||
end
|
||||
|
||||
def place_match_in_empty_slot!(match, slot)
|
||||
self.class.transaction do
|
||||
match.update!(mat_id: id)
|
||||
remove_match_from_other_mats!(match.id)
|
||||
update!(slot_key(slot) => match.id)
|
||||
end
|
||||
broadcast_current_match
|
||||
end
|
||||
|
||||
def slot_key(slot)
|
||||
"queue#{slot}"
|
||||
end
|
||||
|
||||
def broadcast_current_match
|
||||
Turbo::StreamsChannel.broadcast_update_to(
|
||||
self,
|
||||
target: dom_id(self, :current_match),
|
||||
partial: "mats/current_match",
|
||||
locals: {
|
||||
mat: self,
|
||||
match: queue1_match,
|
||||
next_match: queue2_match,
|
||||
show_next_bout_button: true
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user