mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-03-24 17:04:43 +00:00
Use websockets on stats page to determine which match to stat.
This commit is contained in:
@@ -1,22 +1,21 @@
|
|||||||
class MatsController < ApplicationController
|
class MatsController < ApplicationController
|
||||||
before_action :set_mat, only: [:show, :edit, :update, :destroy, :assign_next_match]
|
before_action :set_mat, only: [:show, :edit, :update, :destroy, :assign_next_match]
|
||||||
before_action :check_access, only: [:new,:create,:update,:destroy,:edit,:show, :assign_next_match]
|
before_action :check_access, only: [:new,:create,:update,:destroy,:edit,:show, :assign_next_match]
|
||||||
before_action :check_for_matches, only: [:show]
|
|
||||||
|
|
||||||
# GET /mats/1
|
# GET /mats/1
|
||||||
# GET /mats/1.json
|
# GET /mats/1.json
|
||||||
def show
|
def show
|
||||||
bout_number_param = params[:bout_number] # Read the bout_number from the URL params
|
bout_number_param = params[:bout_number]
|
||||||
|
@queue_matches = @mat.queue_matches
|
||||||
if bout_number_param
|
@match = if bout_number_param
|
||||||
@show_next_bout_button = false
|
@queue_matches.compact.find { |m| m.bout_number == bout_number_param.to_i }
|
||||||
@match = @mat.queue_matches.compact.find { |m| m.bout_number == bout_number_param.to_i }
|
|
||||||
else
|
else
|
||||||
@show_next_bout_button = true
|
@queue_matches[0]
|
||||||
@match = @mat.queue1_match
|
|
||||||
end
|
end
|
||||||
|
# If a requested bout is no longer queued, fall back to queue1.
|
||||||
@next_match = @mat.queue2_match # Second match on the mat
|
@match ||= @queue_matches[0]
|
||||||
|
@next_match = @queue_matches[1]
|
||||||
|
@show_next_bout_button = false
|
||||||
|
|
||||||
@wrestlers = []
|
@wrestlers = []
|
||||||
if @match
|
if @match
|
||||||
@@ -142,11 +141,4 @@ class MatsController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def check_for_matches
|
|
||||||
if @mat
|
|
||||||
if @mat.tournament.matches.empty?
|
|
||||||
redirect_to "/tournaments/#{@tournament.id}/no_matches"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ class Mat < ApplicationRecord
|
|||||||
|
|
||||||
def clear_queue!
|
def clear_queue!
|
||||||
update!(queue1: nil, queue2: nil, queue3: nil, queue4: nil)
|
update!(queue1: nil, queue2: nil, queue3: nil, queue4: nil)
|
||||||
|
broadcast_current_match
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfinished_matches
|
def unfinished_matches
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ class Tournament < ApplicationRecord
|
|||||||
|
|
||||||
def destroy_all_matches
|
def destroy_all_matches
|
||||||
matches.destroy_all
|
matches.destroy_all
|
||||||
|
mats.each(&:clear_queue!)
|
||||||
end
|
end
|
||||||
|
|
||||||
def matches_by_round(round)
|
def matches_by_round(round)
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ class WipeTournamentMatches
|
|||||||
end
|
end
|
||||||
|
|
||||||
def wipeMatches
|
def wipeMatches
|
||||||
@tournament.matches.destroy_all
|
@tournament.destroy_all_matches
|
||||||
end
|
end
|
||||||
|
|
||||||
def resetSchoolScores
|
def resetSchoolScores
|
||||||
@tournament.schools.update_all("score = 0.0")
|
@tournament.schools.update_all("score = 0.0")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -18,8 +18,19 @@
|
|||||||
|
|
||||||
<div id="cable-status-indicator" data-match-data-target="statusIndicator" class="alert alert-secondary" style="padding: 5px; margin-bottom: 10px; border-radius: 4px;"></div>
|
<div id="cable-status-indicator" data-match-data-target="statusIndicator" class="alert alert-secondary" style="padding: 5px; margin-bottom: 10px; border-radius: 4px;"></div>
|
||||||
<h4>Bout <strong><%= @match.bout_number %></strong></h4>
|
<h4>Bout <strong><%= @match.bout_number %></strong></h4>
|
||||||
<% if @show_next_bout_button && @next_match %>
|
<% if @mat %>
|
||||||
<%= link_to "Skip to Next Match for Mat #{@mat.name}", mat_path(@mat, bout_number: @next_match.bout_number), class: "btn btn-primary" %>
|
<% queue_matches = @queue_matches || @mat.queue_matches %>
|
||||||
|
<div style="margin-bottom: 10px;">
|
||||||
|
<% queue_matches.each_with_index do |queue_match, index| %>
|
||||||
|
<% queue_label = "Queue #{index + 1}" %>
|
||||||
|
<% if queue_match %>
|
||||||
|
<% button_class = queue_match.id == @match.id ? "btn btn-success btn-sm" : "btn btn-primary btn-sm" %>
|
||||||
|
<%= link_to "#{queue_label}: Bout #{queue_match.bout_number}", mat_path(@mat, bout_number: queue_match.bout_number), class: button_class %>
|
||||||
|
<% else %>
|
||||||
|
<button type="button" class="btn btn-default btn-sm" disabled><%= "#{queue_label}: Not assigned" %></button>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<h4>Bracket Position: <strong><%= @match.bracket_position %></strong></h4>
|
<h4>Bracket Position: <strong><%= @match.bracket_position %></strong></h4>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<% @mat = mat %>
|
<% @mat = mat %>
|
||||||
<% @match = local_assigns[:match] || mat.queue1_match %>
|
<% @queue_matches = local_assigns[:queue_matches] || mat.queue_matches %>
|
||||||
<% @next_match = local_assigns[:next_match] || mat.queue2_match %>
|
<% @match = local_assigns[:match] || @queue_matches[0] %>
|
||||||
|
<% @match ||= @queue_matches[0] %>
|
||||||
|
<% @next_match = local_assigns[:next_match] || @queue_matches[1] %>
|
||||||
<% @show_next_bout_button = local_assigns.key?(:show_next_bout_button) ? local_assigns[:show_next_bout_button] : true %>
|
<% @show_next_bout_button = local_assigns.key?(:show_next_bout_button) ? local_assigns[:show_next_bout_button] : true %>
|
||||||
|
|
||||||
<% @wrestlers = [] %>
|
<% @wrestlers = [] %>
|
||||||
|
|||||||
@@ -259,6 +259,62 @@ class MatsControllerTest < ActionController::TestCase
|
|||||||
assert_match /#{bout_number}/, response.body, "The bout_number should be rendered on the page"
|
assert_match /#{bout_number}/, response.body, "The bout_number should be rendered on the page"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "mat show renders queue buttons for all four queue slots" do
|
||||||
|
sign_in_owner
|
||||||
|
|
||||||
|
available_matches = @tournament.matches.where(mat_id: nil).limit(3).to_a
|
||||||
|
@mat.assign_match_to_queue!(available_matches[0], 2) if available_matches[0]
|
||||||
|
@mat.assign_match_to_queue!(available_matches[1], 3) if available_matches[1]
|
||||||
|
@mat.assign_match_to_queue!(available_matches[2], 4) if available_matches[2]
|
||||||
|
|
||||||
|
get :show, params: { id: @mat.id }
|
||||||
|
assert_response :success
|
||||||
|
|
||||||
|
assert_includes response.body, "Queue 1: Bout"
|
||||||
|
assert_includes response.body, "Queue 2:"
|
||||||
|
assert_includes response.body, "Queue 3:"
|
||||||
|
assert_includes response.body, "Queue 4:"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "mat show highlights selected queue button and keeps bout_number links working" do
|
||||||
|
sign_in_owner
|
||||||
|
|
||||||
|
queue2_match = @mat.queue2_match
|
||||||
|
unless queue2_match
|
||||||
|
assignable = @tournament.matches.where(mat_id: nil).first
|
||||||
|
@mat.assign_match_to_queue!(assignable, 2) if assignable
|
||||||
|
queue2_match = @mat.reload.queue2_match
|
||||||
|
end
|
||||||
|
assert queue2_match, "Expected queue2 match to be present"
|
||||||
|
|
||||||
|
get :show, params: { id: @mat.id, bout_number: queue2_match.bout_number, foo: "bar" }
|
||||||
|
assert_response :success
|
||||||
|
|
||||||
|
assert_includes response.body, "Queue 2: Bout #{queue2_match.bout_number}"
|
||||||
|
assert_match(/btn btn-success btn-sm/, response.body)
|
||||||
|
assert_includes response.body, "bout_number=#{queue2_match.bout_number}"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "mat show falls back to queue1 when requested bout number is not currently queued" do
|
||||||
|
sign_in_owner
|
||||||
|
|
||||||
|
queue1 = @mat.reload.queue1_match
|
||||||
|
assert queue1, "Expected queue1 to be present"
|
||||||
|
|
||||||
|
get :show, params: { id: @mat.id, bout_number: 999999 }
|
||||||
|
assert_response :success
|
||||||
|
assert_includes response.body, "Bout <strong>#{queue1.bout_number}</strong>"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "mat show renders no matches assigned when queue is empty" do
|
||||||
|
sign_in_owner
|
||||||
|
|
||||||
|
@mat.clear_queue!
|
||||||
|
get :show, params: { id: @mat.id }
|
||||||
|
assert_response :success
|
||||||
|
assert_includes response.body, "No matches assigned to this mat."
|
||||||
|
end
|
||||||
|
|
||||||
test "logged in tournament owner should redirect back to the first unfinished bout on a mat after submitting a match with a bout number param" do
|
test "logged in tournament owner should redirect back to the first unfinished bout on a mat after submitting a match with a bout number param" do
|
||||||
sign_in_owner
|
sign_in_owner
|
||||||
|
|
||||||
@@ -287,11 +343,12 @@ class MatsControllerTest < ActionController::TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
#TESTS THAT NEED MATCHES PUT ABOVE THIS
|
#TESTS THAT NEED MATCHES PUT ABOVE THIS
|
||||||
test "redirect show if no matches" do
|
test "show renders when no matches" do
|
||||||
sign_in_owner
|
sign_in_owner
|
||||||
wipe
|
wipe
|
||||||
show
|
show
|
||||||
no_matches
|
success
|
||||||
|
assert_includes response.body, "No matches assigned to this mat."
|
||||||
end
|
end
|
||||||
|
|
||||||
# Assign Next Match Permissions
|
# Assign Next Match Permissions
|
||||||
|
|||||||
@@ -50,6 +50,29 @@ class UpMatchesCacheTest < ActionController::TestCase
|
|||||||
assert_operator cache_writes(third_events), :>, 0, "Expected queue change to invalidate and rewrite at least one row fragment"
|
assert_operator cache_writes(third_events), :>, 0, "Expected queue change to invalidate and rewrite at least one row fragment"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "up_matches row fragments hit cache after queue clear rewrite" do
|
||||||
|
first_events = cache_events_for_up_matches do
|
||||||
|
get :up_matches, params: { id: @tournament.id }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
assert_operator cache_writes(first_events), :>, 0, "Expected initial render to write row fragments"
|
||||||
|
|
||||||
|
mat = @tournament.mats.first
|
||||||
|
clear_events = cache_events_for_up_matches do
|
||||||
|
mat.clear_queue!
|
||||||
|
get :up_matches, params: { id: @tournament.id }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
assert_operator cache_writes(clear_events), :>, 0, "Expected queue clear to invalidate and rewrite at least one row fragment"
|
||||||
|
|
||||||
|
repeat_events = cache_events_for_up_matches do
|
||||||
|
get :up_matches, params: { id: @tournament.id }
|
||||||
|
assert_response :success
|
||||||
|
end
|
||||||
|
assert_equal 0, cache_writes(repeat_events), "Expected subsequent render after queue clear rewrite to reuse cached row fragments"
|
||||||
|
assert_operator cache_hits(repeat_events), :>, 0, "Expected cache hits after queue clear rewrite"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def cache_events_for_up_matches
|
def cache_events_for_up_matches
|
||||||
|
|||||||
37
test/integration/mat_stats_live_updates_test.rb
Normal file
37
test/integration/mat_stats_live_updates_test.rb
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
require "test_helper"
|
||||||
|
|
||||||
|
class MatStatsLiveUpdatesTest < ActionDispatch::IntegrationTest
|
||||||
|
include ActionView::RecordIdentifier
|
||||||
|
|
||||||
|
test "destroying all matches broadcasts no-match state for mat stats stream" do
|
||||||
|
create_double_elim_tournament_single_weight_1_6(4)
|
||||||
|
mat = @tournament.mats.create!(name: "Mat 1")
|
||||||
|
@tournament.reset_and_fill_bout_board
|
||||||
|
stream = stream_name_for(mat)
|
||||||
|
|
||||||
|
clear_streams(stream)
|
||||||
|
@tournament.destroy_all_matches
|
||||||
|
|
||||||
|
assert_operator broadcasts_for(stream).size, :>, 0
|
||||||
|
payload = broadcasts_for(stream).last
|
||||||
|
assert_includes payload, dom_id(mat, :current_match)
|
||||||
|
assert_includes payload, "No matches assigned to this mat."
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def broadcasts_for(stream)
|
||||||
|
ActionCable.server.pubsub.broadcasts(stream)
|
||||||
|
end
|
||||||
|
|
||||||
|
def clear_streams(*streams)
|
||||||
|
ActionCable.server.pubsub.clear
|
||||||
|
streams.each do |stream|
|
||||||
|
broadcasts_for(stream).clear
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stream_name_for(streamable)
|
||||||
|
Turbo::StreamsChannel.send(:stream_name_from, [streamable])
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -49,6 +49,38 @@ class MatchBroadcastTest < ActiveSupport::TestCase
|
|||||||
assert_includes broadcasts_for(stream).last, dom_id(mat, :current_match)
|
assert_includes broadcasts_for(stream).last, dom_id(mat, :current_match)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "destroy_all_matches clears mats and broadcasts no matches assigned" do
|
||||||
|
create_double_elim_tournament_single_weight_1_6(4)
|
||||||
|
mat = @tournament.mats.create!(name: "Mat 1")
|
||||||
|
@tournament.reset_and_fill_bout_board
|
||||||
|
stream = stream_name_for(mat)
|
||||||
|
|
||||||
|
clear_streams(stream)
|
||||||
|
@tournament.destroy_all_matches
|
||||||
|
|
||||||
|
assert_operator broadcasts_for(stream).size, :>, 0
|
||||||
|
payload = broadcasts_for(stream).last
|
||||||
|
assert_includes payload, dom_id(mat, :current_match)
|
||||||
|
assert_includes payload, "No matches assigned to this mat."
|
||||||
|
assert_equal [nil, nil, nil, nil], mat.reload.queue_match_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
test "wipe tournament matches service clears mats and broadcasts no matches assigned" do
|
||||||
|
create_double_elim_tournament_single_weight_1_6(4)
|
||||||
|
mat = @tournament.mats.create!(name: "Mat 1")
|
||||||
|
@tournament.reset_and_fill_bout_board
|
||||||
|
stream = stream_name_for(mat)
|
||||||
|
|
||||||
|
clear_streams(stream)
|
||||||
|
WipeTournamentMatches.new(@tournament).setUpMatchGeneration
|
||||||
|
|
||||||
|
assert_operator broadcasts_for(stream).size, :>, 0
|
||||||
|
payload = broadcasts_for(stream).last
|
||||||
|
assert_includes payload, dom_id(mat, :current_match)
|
||||||
|
assert_includes payload, "No matches assigned to this mat."
|
||||||
|
assert_equal [nil, nil, nil, nil], mat.reload.queue_match_ids
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def broadcasts_for(stream)
|
def broadcasts_for(stream)
|
||||||
|
|||||||
@@ -26,6 +26,21 @@ class UpMatchesBroadcastTest < ActiveSupport::TestCase
|
|||||||
assert_up_matches_replace_payload(broadcasts_for(stream).last)
|
assert_up_matches_replace_payload(broadcasts_for(stream).last)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "mat clear_queue broadcasts up matches board update" do
|
||||||
|
tournament = tournaments(:one)
|
||||||
|
mat = mats(:one)
|
||||||
|
match = matches(:tournament_1_bout_2000)
|
||||||
|
stream = stream_name_for(tournament)
|
||||||
|
|
||||||
|
mat.update!(queue1: match.id)
|
||||||
|
clear_streams(stream)
|
||||||
|
|
||||||
|
mat.clear_queue!
|
||||||
|
|
||||||
|
assert_operator broadcasts_for(stream).size, :>, 0
|
||||||
|
assert_up_matches_replace_payload(broadcasts_for(stream).last)
|
||||||
|
end
|
||||||
|
|
||||||
test "match mat assignment change broadcasts up matches board update" do
|
test "match mat assignment change broadcasts up matches board update" do
|
||||||
tournament = tournaments(:one)
|
tournament = tournaments(:one)
|
||||||
mat = mats(:one)
|
mat = mats(:one)
|
||||||
@@ -39,6 +54,21 @@ class UpMatchesBroadcastTest < ActiveSupport::TestCase
|
|||||||
assert_up_matches_replace_payload(broadcasts_for(stream).last)
|
assert_up_matches_replace_payload(broadcasts_for(stream).last)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "match mat unassignment broadcasts up matches board update" do
|
||||||
|
tournament = tournaments(:one)
|
||||||
|
mat = mats(:one)
|
||||||
|
match = matches(:tournament_1_bout_2001)
|
||||||
|
stream = stream_name_for(tournament)
|
||||||
|
|
||||||
|
match.update!(mat_id: mat.id)
|
||||||
|
clear_streams(stream)
|
||||||
|
|
||||||
|
match.update!(mat_id: nil)
|
||||||
|
|
||||||
|
assert_operator broadcasts_for(stream).size, :>, 0
|
||||||
|
assert_up_matches_replace_payload(broadcasts_for(stream).last)
|
||||||
|
end
|
||||||
|
|
||||||
test "mat update without queue slot changes does not broadcast up matches board update" do
|
test "mat update without queue slot changes does not broadcast up matches board update" do
|
||||||
tournament = tournaments(:one)
|
tournament = tournaments(:one)
|
||||||
mat = mats(:one)
|
mat = mats(:one)
|
||||||
|
|||||||
Reference in New Issue
Block a user