1
0
mirror of https://github.com/jcwimer/wrestlingApp synced 2026-03-25 01:14:43 +00:00

Added mat assignment rules for the bout board and fixed the bug where a delegate making the tournamnet info public changes them to the owner

This commit is contained in:
2024-11-25 16:25:59 -05:00
parent bb548be81b
commit ad8e486205
19 changed files with 769 additions and 43 deletions

View File

@@ -0,0 +1,82 @@
class MatAssignmentRulesController < ApplicationController
before_action :set_tournament
before_action :check_access_manage
before_action :set_mat_assignment_rule, only: [:edit, :update, :show, :destroy]
def index
@mat_assignment_rules = @tournament.mat_assignment_rules
# Create a hash mapping each Weight ID to its Weight object for quick lookups
@weights_by_id = @tournament.weights.index_by(&:id)
end
def new
@mat_assignment_rule = @tournament.mat_assignment_rules.build
load_form_data
end
def destroy
@mat_assignment_rule.destroy
redirect_to tournament_mat_assignment_rules_path(@tournament), notice: 'Mat assignment rule was successfully deleted.'
end
def create
@mat_assignment_rule = @tournament.mat_assignment_rules.build(mat_assignment_rule_params)
load_form_data
if @mat_assignment_rule.save
redirect_to tournament_mat_assignment_rules_path(@tournament), notice: 'Mat assignment rule created successfully.'
else
render :new
end
end
def edit
load_form_data
end
def update
load_form_data
if @mat_assignment_rule.update(mat_assignment_rule_params)
redirect_to tournament_mat_assignment_rules_path(@tournament), notice: 'Mat assignment rule updated successfully.'
else
render :edit
end
end
private
def set_tournament
@tournament = Tournament.find(params[:tournament_id])
end
def set_mat_assignment_rule
@mat_assignment_rule = @tournament.mat_assignment_rules.find(params[:id])
end
def check_access_manage
authorize! :manage, @tournament
end
def mat_assignment_rule_params
# Set defaults to empty arrays if no checkboxes are selected
# otherwise rails interprets this as "don't modify"
params[:mat_assignment_rule][:weight_classes] ||= []
params[:mat_assignment_rule][:bracket_positions] ||= []
params[:mat_assignment_rule][:rounds] ||= []
# Permit the parameters and convert specific fields to integer arrays
params.require(:mat_assignment_rule).permit(:mat_id, weight_classes: [], bracket_positions: [], rounds: []).tap do |whitelisted|
whitelisted[:weight_classes] = whitelisted[:weight_classes].map(&:to_i)
whitelisted[:bracket_positions] = whitelisted[:bracket_positions].map(&:to_i)
whitelisted[:rounds] = whitelisted[:rounds].map(&:to_i)
end
end
# Load data needed for the form
def load_form_data
@available_mats = Mat.all
@unique_bracket_positions = @tournament.matches.select(:bracket_position).distinct.pluck(:bracket_position)
@unique_rounds = @tournament.matches.select(:round).distinct.pluck(:round)
end
end

View File

@@ -1,6 +1,6 @@
class TournamentsController < ApplicationController
before_action :set_tournament, only: [:calculate_team_scores, :import,:export,:bout_sheets,:swap,:weigh_in_sheet,:error,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:remove_delegate,:school_delegate,:delegate,:matches,:weigh_in,:weigh_in_weight,:create_custom_weights,:show,:edit,:update,:destroy,:up_matches,:no_matches,:team_scores,:brackets,:generate_matches,:bracket,:all_brackets]
before_action :check_access_manage, only: [:calculate_team_scores, :import,:export,:swap,:weigh_in_sheet,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:school_delegate,:weigh_in,:weigh_in_weight,:create_custom_weights,:update,:edit,:generate_matches,:matches]
before_action :set_tournament, only: [:reset_bout_board,:calculate_team_scores, :import,:export,:bout_sheets,:swap,:weigh_in_sheet,:error,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:remove_delegate,:school_delegate,:delegate,:matches,:weigh_in,:weigh_in_weight,:create_custom_weights,:show,:edit,:update,:destroy,:up_matches,:no_matches,:team_scores,:brackets,:generate_matches,:bracket,:all_brackets]
before_action :check_access_manage, only: [:reset_bout_board,:calculate_team_scores, :import,:export,:swap,:weigh_in_sheet,:teampointadjust,:remove_teampointadjust,:remove_school_delegate,:school_delegate,:weigh_in,:weigh_in_weight,:create_custom_weights,:update,:edit,:generate_matches,:matches]
before_action :check_access_destroy, only: [:destroy,:delegate,:remove_delegate]
before_action :check_tournament_errors, only: [:generate_matches]
before_action :check_for_matches, only: [:up_matches,:bracket,:all_brackets]
@@ -248,6 +248,7 @@ class TournamentsController < ApplicationController
redirect_to root_path
end
@tournament = Tournament.new(tournament_params)
@tournament.user_id = current_user.id
respond_to do |format|
if @tournament.save
format.html { redirect_to @tournament, notice: 'Tournament was successfully created.' }
@@ -282,6 +283,11 @@ class TournamentsController < ApplicationController
def error
end
def reset_bout_board
@tournament.reset_and_fill_bout_board
redirect_to tournament_path(@tournament), notice: "Successfully reset the bout board."
end
private
# Use callbacks to share common setup or constraints between actions.
def set_tournament
@@ -290,7 +296,7 @@ class TournamentsController < ApplicationController
# Never trust parameters from the scary internet, only allow the white list through.
def tournament_params
params.require(:tournament).permit(:name, :address, :director, :director_email, :tournament_type, :weigh_in_ref, :user_id, :date, :originalId, :swapId, :is_public)
params.require(:tournament).permit(:name, :address, :director, :director_email, :tournament_type, :weigh_in_ref, :date, :originalId, :swapId, :is_public)
end
#Check for tournament owner

View File

@@ -1,6 +1,7 @@
class Mat < ApplicationRecord
belongs_to :tournament
has_many :matches
has_many :mat_assignment_rules, dependent: :destroy
validates :name, presence: true
@@ -21,11 +22,11 @@ class Mat < ApplicationRecord
end
def assign_next_match
t_matches = tournament.matches.select{|m| m.mat_id == nil && m.finished != 1 && m.bout_number != nil}.sort_by{|m| m.bout_number}
if t_matches.size > 0 and self.unfinished_matches.size < 4
match = t_matches.sort_by{|m| m.bout_number}.first
match = next_eligible_match
if match
match.mat_id = self.id
if match.save
# Invalidate any wrestler caches
if match.w1
match.wrestler1.touch
match.wrestler1.school.touch
@@ -43,6 +44,31 @@ class Mat < ApplicationRecord
end
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.where(finished: [nil, 0]).where(mat_id: nil).where.not(bout_number: nil).order(:bout_number)
# Sequentially apply each rule, narrowing down the matches
mat_assignment_rules.each do |rule|
if rule.weight_classes.any?
filtered_matches = filtered_matches.where(weight_id: rule.weight_classes)
end
if rule.bracket_positions.any?
filtered_matches = filtered_matches.where(bracket_position: rule.bracket_positions)
end
if rule.rounds.any?
filtered_matches = filtered_matches.where(round: rule.rounds)
end
end
# Return the first match in filtered results, or nil if none are left
result = filtered_matches.first
result
end
def unfinished_matches
matches.select{|m| m.finished != 1}.sort_by{|m| m.bout_number}
end

View File

@@ -0,0 +1,4 @@
class MatAssignmentRule < ApplicationRecord
belongs_to :mat
belongs_to :tournament
end

View File

@@ -7,6 +7,7 @@ class Tournament < ApplicationRecord
has_many :wrestlers, through: :weights
has_many :matches, dependent: :destroy
has_many :delegates, class_name: "TournamentDelegate"
has_many :mat_assignment_rules, dependent: :destroy
validates :date, :name, :tournament_type, :address, :director, :director_email , presence: true
@@ -17,25 +18,25 @@ class Tournament < ApplicationRecord
end
def self.search_date_name(pattern)
if pattern.blank? # blank? covers both nil and empty string
all
else
search_functions = []
search_variables = []
search_terms = pattern.split(' ').map{|word| "%#{word.downcase}%"}
search_terms.each do |word|
search_functions << '(LOWER(name) LIKE ? or LOWER(date) LIKE ?)'
# add twice for both ?'s in the function above
search_variables << word
search_variables << word
end
like_patterns = search_functions.join(' and ')
# puts "where(#{like_patterns})"
# puts *search_variables
# example: (LOWER(name LIKE ? or LOWER(date) LIKE ?) and (LOWER(name) LIKE ? or LOWER(date) LIKE ?), %test%, %test%, %2016%, %2016%
where("#{like_patterns}", *search_variables)
end
end
if pattern.blank? # blank? covers both nil and empty string
all
else
search_functions = []
search_variables = []
search_terms = pattern.split(' ').map{|word| "%#{word.downcase}%"}
search_terms.each do |word|
search_functions << '(LOWER(name) LIKE ? or LOWER(date) LIKE ?)'
# add twice for both ?'s in the function above
search_variables << word
search_variables << word
end
like_patterns = search_functions.join(' and ')
# puts "where(#{like_patterns})"
# puts *search_variables
# example: (LOWER(name LIKE ? or LOWER(date) LIKE ?) and (LOWER(name) LIKE ? or LOWER(date) LIKE ?), %test%, %test%, %2016%, %2016%
where("#{like_patterns}", *search_variables)
end
end
def days_until_start
time = (Date.today - self.date).to_i
@@ -188,4 +189,23 @@ end
nil
end
end
def reset_and_fill_bout_board
reset_mats
if mats.any?
4.times do
# Iterate over each mat and assign the next available match
mats.each do |mat|
match_assigned = mat.assign_next_match
# If no more matches are available, exit early
unless match_assigned
puts "No more eligible matches to assign."
return
end
end
end
end
end
end

View File

@@ -16,7 +16,6 @@ class GenerateTournamentMatches
@tournament.curently_generating_matches = 1
@tournament.save
unAssignBouts
unAssignMats
PoolToBracketMatchGeneration.new(@tournament).generatePoolToBracketMatchesWeight(weight) if @tournament.tournament_type == "Pool to bracket"
postMatchCreationActions
PoolToBracketGenerateLoserNames.new(@tournament).assignLoserNamesWeight(weight) if @tournament.tournament_type == "Pool to bracket"
@@ -51,7 +50,7 @@ class GenerateTournamentMatches
def postMatchCreationActions
moveFinalsMatchesToLastRound
assignBouts
assignFirstMatchesToMats
@tournament.reset_and_fill_bout_board
@tournament.curently_generating_matches = nil
@tournament.save!
end
@@ -75,17 +74,6 @@ class GenerateTournamentMatches
end
end
def assignFirstMatchesToMats
matsToAssign = @tournament.mats
if matsToAssign.count > 0
until matsToAssign.sort_by{|m| m.id}.last.matches.count == 4
matsToAssign.sort_by{|m| m.id}.each do |m|
m.assign_next_match
end
end
end
end
def unAssignMats
matches = @tournament.matches.reload
matches.each do |m|

View File

@@ -32,6 +32,8 @@
<li><%= link_to "All Matches" , "/tournaments/#{@tournament.id}/matches" %></li>
<li><%= link_to "Full Screen Bout Board" , "/tournaments/#{@tournament.id}/up_matches?print=true" , target: :_blank %></li>
<li><%= link_to "Deduct Team Points" , "/tournaments/#{@tournament.id}/teampointadjust" %></li>
<li><%= link_to "View All Mat Assignment Rules", tournament_mat_assignment_rules_path(@tournament) %></li>
<li><%= link_to "Reset Bout Board", reset_bout_board_tournament_path(@tournament), method: :post, data: { confirm: "Are you sure you want to reset the bout board?" } %></li>
<% if can? :destroy, @tournament %>
<li><%= link_to "Tournament Delegation" , "/tournaments/#{@tournament.id}/delegate" %></li>
<% end %>

View File

@@ -0,0 +1,61 @@
<%= form_with model: [@tournament, @mat_assignment_rule] do |form| %>
<!-- Mat Selection -->
<div>
<%= form.label :mat_id, "Select Mat" %><br>
<% if @available_mats.any? %>
<%= form.collection_select :mat_id, @available_mats, :id, :name, { prompt: "Choose a Mat" } %>
<% else %>
<p>No mats are available. Please create a mat first.</p>
<% end %>
</div>
<!-- Weight Classes as Checkboxes -->
<div>
<%= form.label :weight_classes, "Allowed Weight Classes" %><br>
<% if @tournament.weights.any? %>
<% @tournament.weights.each do |weight| %>
<div>
<%= check_box_tag "mat_assignment_rule[weight_classes][]", weight.id, @mat_assignment_rule.weight_classes.include?(weight.id) %>
<%= label_tag "mat_assignment_rule_weight_classes_#{weight.id}", weight.max %>
</div>
<% end %>
<% else %>
<p>No weight classes are available. Please create weight classes first.</p>
<% end %>
</div>
<!-- Bracket Positions as Checkboxes -->
<div>
<%= form.label :bracket_positions, "Allowed Bracket Positions" %><br>
<% if @unique_bracket_positions.present? %>
<% @unique_bracket_positions.each do |position| %>
<div>
<%= check_box_tag "mat_assignment_rule[bracket_positions][]", position, @mat_assignment_rule.bracket_positions.include?(position) %>
<%= label_tag "mat_assignment_rule_bracket_positions_#{position}", position %>
</div>
<% end %>
<% else %>
<p>No bracket positions are available. Please ensure matches have bracket positions set.</p>
<% end %>
</div>
<!-- Rounds as Checkboxes -->
<div>
<%= form.label :rounds, "Allowed Rounds" %><br>
<% if @unique_rounds.present? %>
<% @unique_rounds.each do |round| %>
<div>
<%= check_box_tag "mat_assignment_rule[rounds][]", round, @mat_assignment_rule.rounds.include?(round) %>
<%= label_tag "mat_assignment_rule_rounds_#{round}", round %>
</div>
<% end %>
<% else %>
<p>No rounds are available. Please ensure matches have rounds set.</p>
<% end %>
</div>
<!-- Submit Button -->
<div>
<%= form.submit 'Submit', :class=>"btn btn-success" %>
</div>
<% end %>

View File

@@ -0,0 +1,3 @@
<h1>Edit Mat Assignment Rule for <%= @tournament.name %></h1>
<%= render "form", tournament: @tournament, mat_assignment: @mat_assignment_rule, available_mats: @available_mats %>

View File

@@ -0,0 +1,36 @@
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Mat</th>
<th>Weight Classes (Max)</th>
<th>Bracket Positions</th>
<th>Rounds</th>
<th><%= link_to ' New Mat Assignment Rule', new_tournament_mat_assignment_rule_path(@tournament), :class=>"fas fa-plus" %></th>
</tr>
</thead>
<tbody>
<% @mat_assignment_rules.each do |rule| %>
<tr>
<td><%= rule.mat.name %></td>
<!-- Display max values for each weight associated with the rule -->
<td>
<% rule.weight_classes.each do |weight_id| %>
<% weight = @weights_by_id[weight_id] %>
<%= weight ? weight.max : "N/A" %><%= ", " unless weight_id == rule.weight_classes.last %>
<% end %>
</td>
<!-- Display bracket positions and rounds -->
<td><%= rule.bracket_positions.join(", ") %></td>
<td><%= rule.rounds.join(", ") %></td>
<!-- Edit and Delete Actions -->
<td>
<%= link_to '', edit_tournament_mat_assignment_rule_path(@tournament, rule), :class=>"fas fa-edit" %>
<%= link_to '', tournament_mat_assignment_rule_path(@tournament, rule), method: :delete, data: { confirm: "Are you sure?" }, :class=>"fas fa-trash-alt" %>
</td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -0,0 +1,3 @@
<h1>New Mat Assignment Rule for <%= @tournament.name %></h1>
<%= render "form", tournament: @tournament, mat_assignment: @mat_assignment_rule, available_mats: @available_mats %>

View File

@@ -40,7 +40,6 @@
See About page for information on tournament types: <%= link_to "About", "/static_pages/about" %>
<p>For double elimination tournaments, 1-6 places 1st through 6th and 1-8 places 1st through 8th.</p>
</div>
<%= f.hidden_field :user_id, :value => current_user.id %>
<br>
<br>
<div class="field">