mirror of
https://github.com/jcwimer/wrestlingApp
synced 2026-03-25 01:14:43 +00:00
Added a dynamic score form on the stats page, added stats page form validation on the in js to compliment the validation already in place on the model, and added the wrestler's score in the winner dropdown of the form.
This commit is contained in:
@@ -295,4 +295,8 @@ class Wrestler < ApplicationRecord
|
|||||||
def short_bracket_name
|
def short_bracket_name
|
||||||
return "#{self.name} (#{self.school.abbreviation})"
|
return "#{self.name} (#{self.school.abbreviation})"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def name_with_school
|
||||||
|
return "#{self.name} - #{self.school.name}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<button id="w1-nf2" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N2')">N2 </button>
|
<button id="w1-nf2" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N2')">N2 </button>
|
||||||
<button id="w1-nf3" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N3')">N3</button>
|
<button id="w1-nf3" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N3')">N3</button>
|
||||||
<button id="w1-nf4" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N4')">N4</button>
|
<button id="w1-nf4" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N4')">N4</button>
|
||||||
<button id="w1-nf5" type="button" class="btn btn-success btn-sm" onclick="updateStats(w2,'N5')">N5</button>
|
<button id="w1-nf5" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'N5')">N5</button>
|
||||||
<button id="w1-penalty" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'P1')">P1</button>
|
<button id="w1-penalty" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'P1')">P1</button>
|
||||||
<button id="w1-penalty2" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'P2')">P2</button></td>
|
<button id="w1-penalty2" type="button" class="btn btn-success btn-sm" onclick="updateStats(w1,'P2')">P2</button></td>
|
||||||
<td><%= @wrestler2_name %> Scoring <br><button id="w2-takedown" type="button" class="btn btn-danger btn-sm" onclick="updateStats(w2,'T3')">T3</button>
|
<td><%= @wrestler2_name %> Scoring <br><button id="w2-takedown" type="button" class="btn btn-danger btn-sm" onclick="updateStats(w2,'T3')">T3</button>
|
||||||
@@ -71,7 +71,34 @@
|
|||||||
<button id="w2-caution" type="button" class="btn btn-danger btn-sm" onclick="updateStats(w2,'C')">Caution</button></td>
|
<button id="w2-caution" type="button" class="btn btn-danger btn-sm" onclick="updateStats(w2,'C')">Caution</button></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Match Options <br><button type="button" class="btn btn-primary btn-sm" onclick="updateStats(w2,'|End Period|');updateStats(w1,'|End Period|')">End Period</button></td>
|
<td>Match Options <br><button type="button" class="btn btn-primary btn-sm" onclick="updateStats(w2,'|End Period|'); updateStats(w1,'|End Period|');">End Period</button></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<h5><%= @wrestler1_name %> Timer Controls</h5>
|
||||||
|
Injury Time (90 second max): <span id="w1-injury-time">0 sec</span>
|
||||||
|
<button type="button" onclick="startTimer(w1, 'injury')" class="btn btn-primary btn-sm">Start</button>
|
||||||
|
<button type="button" onclick="stopTimer(w1, 'injury')" class="btn btn-primary btn-sm">Stop</button>
|
||||||
|
<button type="button" onclick="resetTimer(w1, 'injury')" class="btn btn-primary btn-sm">Reset</button>
|
||||||
|
<br><br>
|
||||||
|
Blood Time (600 second max): <span id="w1-blood-time">0 sec</span>
|
||||||
|
<button type="button" onclick="startTimer(w1, 'blood')" class="btn btn-primary btn-sm">Start</button>
|
||||||
|
<button type="button" onclick="stopTimer(w1, 'blood')" class="btn btn-primary btn-sm">Stop</button>
|
||||||
|
<button type="button" onclick="resetTimer(w1, 'blood')" class="btn btn-primary btn-sm">Reset</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<h5><%= @wrestler2_name %> Timer Controls</h5>
|
||||||
|
Injury Time (90 second max): <span id="w2-injury-time">0 sec</span>
|
||||||
|
<button type="button" onclick="startTimer(w2, 'injury')" class="btn btn-primary btn-sm">Start</button>
|
||||||
|
<button type="button" onclick="stopTimer(w2, 'injury')" class="btn btn-primary btn-sm">Stop</button>
|
||||||
|
<button type="button" onclick="resetTimer(w2, 'injury')" class="btn btn-primary btn-sm">Reset</button>
|
||||||
|
<br><br>
|
||||||
|
Blood Time (600 second max): <span id="w2-blood-time">0 sec</span>
|
||||||
|
<button type="button" onclick="startTimer(w2, 'blood')" class="btn btn-primary btn-sm">Start</button>
|
||||||
|
<button type="button" onclick="stopTimer(w2, 'blood')" class="btn btn-primary btn-sm">Stop</button>
|
||||||
|
<button type="button" onclick="resetTimer(w2, 'blood')" class="btn btn-primary btn-sm">Reset</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -92,13 +119,33 @@
|
|||||||
<br>
|
<br>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<%= f.label "Winner" %> Please choose the winner<br>
|
<%= f.label "Winner" %> Please choose the winner<br>
|
||||||
<%= f.collection_select :winner_id, @wrestlers, :id, :name, include_blank: true %>
|
<%= f.collection_select :winner_id, @wrestlers, :id, :name_with_school, include_blank: true %>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
<% if @match.finished && @match.finished == 1 %>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<%= f.label "Final Score" %> For decision, major, or tech fall put the score here in Number-Number format. If pin, put the accumulated pin time in the format MM:SS. If default, injury default, dq, bye, or forfeit, leave blank. Examples: 7-2, 17-2, 0:30, or 2:34.<br>
|
<%= f.label "Final Score" %> For decision, major, or tech fall put the score here in Number-Number format. If pin, put the accumulated pin time in the format MM:SS. If default, injury default, dq, bye, or forfeit, leave blank. Examples: 7-2, 17-2, 0:30, or 2:34.<br>
|
||||||
<%= f.text_field :score %>
|
<%= f.text_field :score %>
|
||||||
</div>
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<div class="field">
|
||||||
|
<%= f.label "Final Score" %>
|
||||||
|
<br>
|
||||||
|
<span id="score-help-text">
|
||||||
|
The input will adjust based on the selected win type.
|
||||||
|
</span>
|
||||||
|
<br>
|
||||||
|
<div id="dynamic-score-input"></div>
|
||||||
|
<p id="pin-time-tip" class="text-muted mt-2" style="display: none;">
|
||||||
|
<strong>Tip:</strong> Pin time is an accumulation over the match, not how much time was left in the current period.
|
||||||
|
<br>For example, if all 3 periods are 2 minutes and a pin happened with 1:27 left in the second period,
|
||||||
|
the pin time would be <strong>2:33</strong> (2 minutes for the first period + 33 seconds elapsed in the second period).
|
||||||
|
</p>
|
||||||
|
<div id="validation-alerts" class="text-danger mt-2"></div>
|
||||||
|
<%= f.hidden_field :score, id: "final-score-field" %>
|
||||||
|
</div>
|
||||||
|
<%= render 'matches/matchstats_variable_score_input' %>
|
||||||
|
<% end %>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<%= f.hidden_field :finished, :value => 1 %>
|
<%= f.hidden_field :finished, :value => 1 %>
|
||||||
@@ -106,173 +153,178 @@
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<%= f.submit onclick: "return confirm('Is the name of the winner ' + document.getElementById('match_winner_id').options[document.getElementById('match_winner_id').selectedIndex].text + '?')", :class=>"btn btn-success" %>
|
<%= f.submit "Update Match", id: "update-match-btn", onclick: "return confirm('Is the name of the winner ' + document.getElementById('match_winner_id').options[document.getElementById('match_winner_id').selectedIndex].text + '?')", class: "btn btn-success" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<%= render 'matches/matchstats_color_change' %>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Localstorage
|
// Get variables
|
||||||
// https://stackoverflow.com/questions/12806198/how-do-i-save-data-on-localstorage-in-ruby-on-rails-3-2-8
|
var tournament = <%= @match.tournament.id %>;
|
||||||
|
var bout = <%= @match.bout_number %>;
|
||||||
|
var match_finsihed = "<%= @match.finished %>";
|
||||||
|
|
||||||
//Create person object
|
// ############### STATS
|
||||||
function Person(stats){
|
// Create person object
|
||||||
this.stats=stats;
|
function Person(stats, name) {
|
||||||
}
|
this.name = name;
|
||||||
|
this.stats = stats;
|
||||||
|
this.updated_at = null; // Track last updated timestamp
|
||||||
|
this.timers = {
|
||||||
|
"injury": { time: 0, startTime: null, interval: null },
|
||||||
|
"blood": { time: 0, startTime: null, interval: null },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
//Declare variables
|
// Declare variables
|
||||||
var w1=new Person("");
|
var w1 = new Person("", "w1");
|
||||||
var w2=new Person("");
|
var w2 = new Person("", "w2");
|
||||||
updatejsvalues();
|
updateJsValues();
|
||||||
|
|
||||||
// Get variables
|
// Generate unique localStorage key
|
||||||
var tournament=<%= @match.tournament.id %>;
|
function generateKey(wrestler_name) {
|
||||||
var bout=<%= @match.bout_number %>;
|
return `${wrestler_name}-${tournament}-${bout}`;
|
||||||
|
}
|
||||||
|
|
||||||
// if localstorage tournament id and bout number are the same and the html stat values are blank
|
// Load values from localStorage
|
||||||
// if the html stat values are not blank we want to honor what came from the db
|
function loadFromLocalStorage(wrestler_name) {
|
||||||
if (localStorage.getItem('wrestler1') && localStorage.tournament == tournament && localStorage.bout == bout && document.getElementById("match_w1_stat").value == "" && document.getElementById("match_w2_stat").value == "") {
|
const key = generateKey(wrestler_name);
|
||||||
w1.stats = localStorage.getItem('wrestler1');
|
const data = localStorage.getItem(key);
|
||||||
w2.stats = localStorage.getItem('wrestler2');
|
return data ? JSON.parse(data) : null;
|
||||||
updatehtmlvalues();
|
}
|
||||||
} else {
|
|
||||||
updateLocalStorage();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Save values to localStorage
|
||||||
|
function saveToLocalStorage(person) {
|
||||||
|
const key = generateKey(person.name);
|
||||||
|
const data = {
|
||||||
|
stats: person.stats,
|
||||||
|
updated_at: person.updated_at,
|
||||||
|
timers: person.timers, // Save all timers
|
||||||
|
};
|
||||||
|
localStorage.setItem(key, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
|
||||||
function updatehtmlvalues(){
|
// Update HTML values
|
||||||
|
function updateHtmlValues() {
|
||||||
document.getElementById("match_w1_stat").value = w1.stats;
|
document.getElementById("match_w1_stat").value = w1.stats;
|
||||||
document.getElementById("match_w2_stat").value = w2.stats;
|
document.getElementById("match_w2_stat").value = w2.stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update JS object values from HTML
|
||||||
|
function updateJsValues() {
|
||||||
|
w1.stats = document.getElementById("match_w1_stat").value;
|
||||||
|
w2.stats = document.getElementById("match_w2_stat").value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update stats and persist to localStorage
|
||||||
|
function updateStats(wrestler, text) {
|
||||||
|
updateJsValues();
|
||||||
|
wrestler.stats += text + " ";
|
||||||
|
wrestler.updated_at = new Date().toISOString(); // Update timestamp
|
||||||
|
updateHtmlValues();
|
||||||
|
|
||||||
|
// Save to localStorage
|
||||||
|
if (wrestler === w1) {
|
||||||
|
saveToLocalStorage(w1);
|
||||||
|
} else if (wrestler === w2) {
|
||||||
|
saveToLocalStorage(w2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize data on page load
|
||||||
|
function initializeTimers(wrestler) {
|
||||||
|
// Iterate over each timer in the wrestler object
|
||||||
|
Object.keys(wrestler.timers).forEach((timerKey) => {
|
||||||
|
const savedData = loadFromLocalStorage(wrestler.name);
|
||||||
|
if (savedData && savedData.timers && savedData.timers[timerKey]) {
|
||||||
|
wrestler.timers[timerKey].time = savedData.timers[timerKey].time || 0;
|
||||||
|
updateTimerDisplay(wrestler, timerKey, wrestler.timers[timerKey].time);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
const localW1 = loadFromLocalStorage("w1");
|
||||||
|
const localW2 = loadFromLocalStorage("w2");
|
||||||
|
|
||||||
|
if (localW1) {
|
||||||
|
w1.stats = localW1.stats || "";
|
||||||
|
w1.updated_at = localW1.updated_at || null;
|
||||||
|
w1.timers = localW1.timers || w1.timers; // Load timer data
|
||||||
|
// set localStorage values to html
|
||||||
|
updateHtmlValues();
|
||||||
|
}
|
||||||
|
if (localW2) {
|
||||||
|
w2.stats = localW2.stats || "";
|
||||||
|
w2.updated_at = localW2.updated_at || null;
|
||||||
|
w2.timers = localW2.timers || w2.timers; // Load timer data
|
||||||
|
// set localStorage values to html
|
||||||
|
updateHtmlValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatejsvalues(){
|
initializeTimers(w1);
|
||||||
w1.stats=document.getElementById("match_w1_stat").value;
|
initializeTimers(w2);
|
||||||
w2.stats=document.getElementById("match_w2_stat").value;
|
updateJsValues()
|
||||||
}
|
}
|
||||||
|
|
||||||
function takedown(wrestler){
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
updateStats(wrestler,"T3")
|
initialize();
|
||||||
}
|
});
|
||||||
|
|
||||||
function updateStats(wrestler,text){
|
// ############### Blood and Injury time timers
|
||||||
updatejsvalues();
|
// Timer storage and interval references
|
||||||
wrestler.stats = wrestler.stats + text + " ";
|
// Start a timer for a wrestler
|
||||||
updatehtmlvalues();
|
function startTimer(wrestler, timerKey) {
|
||||||
updateLocalStorage();
|
const timer = wrestler.timers[timerKey];
|
||||||
}
|
if (timer.interval) return; // Prevent multiple intervals
|
||||||
|
timer.startTime = Date.now(); // Record the start time
|
||||||
|
timer.interval = setInterval(() => {
|
||||||
|
const elapsedSeconds = Math.floor((Date.now() - timer.startTime) / 1000);
|
||||||
|
updateTimerDisplay(wrestler, timerKey, timer.time + elapsedSeconds); // Show total time
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
function updateLocalStorage(){
|
// Stop a timer for a wrestler
|
||||||
localStorage.setItem("wrestler1",w1.stats);
|
function stopTimer(wrestler, timerKey) {
|
||||||
localStorage.setItem("wrestler2",w2.stats);
|
const timer = wrestler.timers[timerKey];
|
||||||
localStorage.setItem("bout", bout);
|
if (!timer.interval || !timer.startTime) return; // Timer not running
|
||||||
localStorage.setItem("tournament", tournament);
|
clearInterval(timer.interval);
|
||||||
}
|
|
||||||
|
|
||||||
//For Changing button colors
|
const elapsedSeconds = Math.floor((Date.now() - timer.startTime) / 1000); // Calculate elapsed time
|
||||||
function changeW1Color(color){
|
timer.time += elapsedSeconds; // Add elapsed time to total
|
||||||
if (color.value == "red") {
|
timer.interval = null;
|
||||||
w1Red();
|
timer.startTime = null;
|
||||||
w2Green();
|
|
||||||
document.getElementById("w2-color").value = "green";
|
|
||||||
}
|
|
||||||
if (color.value == "green") {
|
|
||||||
w1Green();
|
|
||||||
w2Red();
|
|
||||||
document.getElementById("w2-color").value = "red";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeW2Color(color){
|
saveToLocalStorage(wrestler); // Save wrestler data
|
||||||
if (color.value == "red") {
|
updateTimerDisplay(wrestler, timerKey, timer.time); // Update final display
|
||||||
w2Red();
|
updateStatsBox(wrestler, timerKey, elapsedSeconds); // Update wrestler stats
|
||||||
w1Green();
|
}
|
||||||
document.getElementById("w1-color").value = "green";
|
|
||||||
}
|
|
||||||
if (color.value == "green") {
|
|
||||||
w2Green();
|
|
||||||
w1Red();
|
|
||||||
document.getElementById("w1-color").value = "red";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function redColor(id){
|
// Reset a timer for a wrestler
|
||||||
document.getElementById(id).className = "btn btn-danger btn-sm";
|
function resetTimer(wrestler, timerKey) {
|
||||||
}
|
const timer = wrestler.timers[timerKey];
|
||||||
|
stopTimer(wrestler, timerKey); // Stop if running
|
||||||
|
timer.time = 0; // Reset time
|
||||||
|
updateTimerDisplay(wrestler, timerKey, 0); // Update display
|
||||||
|
saveToLocalStorage(wrestler); // Save wrestler data
|
||||||
|
}
|
||||||
|
|
||||||
function greenColor(id){
|
// Update the timer display
|
||||||
document.getElementById(id).className = "btn btn-success btn-sm";
|
function updateTimerDisplay(wrestler, timerKey, totalTime) {
|
||||||
|
const elementId = `${wrestler.name}-${timerKey}-time`; // Construct element ID
|
||||||
|
const element = document.getElementById(elementId);
|
||||||
|
if (element) {
|
||||||
|
element.innerText = `${Math.floor(totalTime / 60)}m ${totalTime % 60}s`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function w1Red(){
|
// Update wrestler stats box with elapsed timer information
|
||||||
redColor("w1-takedown");
|
function updateStatsBox(wrestler, timerKey, elapsedSeconds) {
|
||||||
redColor("w1-escape");
|
const timerType = timerKey.includes("injury") ? "Injury Time" : "Blood Time";
|
||||||
redColor("w1-reversal");
|
const formattedTime = `${Math.floor(elapsedSeconds / 60)}m ${elapsedSeconds % 60}s`;
|
||||||
redColor("w1-penalty");
|
updateStats(wrestler, `${timerType}: ${formattedTime}`);
|
||||||
redColor("w1-penalty2");
|
}
|
||||||
redColor("w1-nf5");
|
|
||||||
redColor("w1-nf4");
|
|
||||||
redColor("w1-nf3");
|
|
||||||
redColor("w1-nf2");
|
|
||||||
redColor("w1-top");
|
|
||||||
redColor("w1-bottom");
|
|
||||||
redColor("w1-neutral");
|
|
||||||
redColor("w1-defer");
|
|
||||||
redColor("w1-stalling");
|
|
||||||
redColor("w1-caution");
|
|
||||||
}
|
|
||||||
|
|
||||||
function w1Green(){
|
|
||||||
greenColor("w1-takedown");
|
|
||||||
greenColor("w1-escape");
|
|
||||||
greenColor("w1-reversal");
|
|
||||||
greenColor("w1-penalty");
|
|
||||||
greenColor("w1-penalty2");
|
|
||||||
greenColor("w1-nf5");
|
|
||||||
greenColor("w1-nf4");
|
|
||||||
greenColor("w1-nf3");
|
|
||||||
greenColor("w1-nf2");
|
|
||||||
greenColor("w1-top");
|
|
||||||
greenColor("w1-bottom");
|
|
||||||
greenColor("w1-neutral");
|
|
||||||
greenColor("w1-defer");
|
|
||||||
greenColor("w1-stalling");
|
|
||||||
greenColor("w1-caution");
|
|
||||||
}
|
|
||||||
|
|
||||||
function w2Red(){
|
|
||||||
redColor("w2-takedown");
|
|
||||||
redColor("w2-escape");
|
|
||||||
redColor("w2-reversal");
|
|
||||||
redColor("w2-penalty");
|
|
||||||
redColor("w2-penalty2");
|
|
||||||
redColor("w2-nf5");
|
|
||||||
redColor("w2-nf4");
|
|
||||||
redColor("w2-nf3");
|
|
||||||
redColor("w2-nf2");
|
|
||||||
redColor("w2-top");
|
|
||||||
redColor("w2-bottom");
|
|
||||||
redColor("w2-neutral");
|
|
||||||
redColor("w2-defer");
|
|
||||||
redColor("w2-stalling");
|
|
||||||
redColor("w2-caution");
|
|
||||||
}
|
|
||||||
|
|
||||||
function w2Green(){
|
|
||||||
greenColor("w2-takedown");
|
|
||||||
greenColor("w2-escape");
|
|
||||||
greenColor("w2-reversal");
|
|
||||||
greenColor("w2-penalty");
|
|
||||||
greenColor("w2-penalty2");
|
|
||||||
greenColor("w2-nf5");
|
|
||||||
greenColor("w2-nf4");
|
|
||||||
greenColor("w2-nf3");
|
|
||||||
greenColor("w2-nf2");
|
|
||||||
greenColor("w2-top");
|
|
||||||
greenColor("w2-bottom");
|
|
||||||
greenColor("w2-neutral");
|
|
||||||
greenColor("w2-defer");
|
|
||||||
greenColor("w2-stalling");
|
|
||||||
greenColor("w2-caution");
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
108
app/views/matches/_matchstats_color_change.html.erb
Normal file
108
app/views/matches/_matchstats_color_change.html.erb
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<script>
|
||||||
|
// ############### Button color change red/green
|
||||||
|
function changeW1Color(color){
|
||||||
|
if (color.value == "red") {
|
||||||
|
w1Red();
|
||||||
|
w2Green();
|
||||||
|
document.getElementById("w2-color").value = "green";
|
||||||
|
}
|
||||||
|
if (color.value == "green") {
|
||||||
|
w1Green();
|
||||||
|
w2Red();
|
||||||
|
document.getElementById("w2-color").value = "red";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeW2Color(color){
|
||||||
|
if (color.value == "red") {
|
||||||
|
w2Red();
|
||||||
|
w1Green();
|
||||||
|
document.getElementById("w1-color").value = "green";
|
||||||
|
}
|
||||||
|
if (color.value == "green") {
|
||||||
|
w2Green();
|
||||||
|
w1Red();
|
||||||
|
document.getElementById("w1-color").value = "red";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function redColor(id){
|
||||||
|
document.getElementById(id).className = "btn btn-danger btn-sm";
|
||||||
|
}
|
||||||
|
|
||||||
|
function greenColor(id){
|
||||||
|
document.getElementById(id).className = "btn btn-success btn-sm";
|
||||||
|
}
|
||||||
|
|
||||||
|
function w1Red(){
|
||||||
|
redColor("w1-takedown");
|
||||||
|
redColor("w1-escape");
|
||||||
|
redColor("w1-reversal");
|
||||||
|
redColor("w1-penalty");
|
||||||
|
redColor("w1-penalty2");
|
||||||
|
redColor("w1-nf5");
|
||||||
|
redColor("w1-nf4");
|
||||||
|
redColor("w1-nf3");
|
||||||
|
redColor("w1-nf2");
|
||||||
|
redColor("w1-top");
|
||||||
|
redColor("w1-bottom");
|
||||||
|
redColor("w1-neutral");
|
||||||
|
redColor("w1-defer");
|
||||||
|
redColor("w1-stalling");
|
||||||
|
redColor("w1-caution");
|
||||||
|
}
|
||||||
|
|
||||||
|
function w1Green(){
|
||||||
|
greenColor("w1-takedown");
|
||||||
|
greenColor("w1-escape");
|
||||||
|
greenColor("w1-reversal");
|
||||||
|
greenColor("w1-penalty");
|
||||||
|
greenColor("w1-penalty2");
|
||||||
|
greenColor("w1-nf5");
|
||||||
|
greenColor("w1-nf4");
|
||||||
|
greenColor("w1-nf3");
|
||||||
|
greenColor("w1-nf2");
|
||||||
|
greenColor("w1-top");
|
||||||
|
greenColor("w1-bottom");
|
||||||
|
greenColor("w1-neutral");
|
||||||
|
greenColor("w1-defer");
|
||||||
|
greenColor("w1-stalling");
|
||||||
|
greenColor("w1-caution");
|
||||||
|
}
|
||||||
|
|
||||||
|
function w2Red(){
|
||||||
|
redColor("w2-takedown");
|
||||||
|
redColor("w2-escape");
|
||||||
|
redColor("w2-reversal");
|
||||||
|
redColor("w2-penalty");
|
||||||
|
redColor("w2-penalty2");
|
||||||
|
redColor("w2-nf5");
|
||||||
|
redColor("w2-nf4");
|
||||||
|
redColor("w2-nf3");
|
||||||
|
redColor("w2-nf2");
|
||||||
|
redColor("w2-top");
|
||||||
|
redColor("w2-bottom");
|
||||||
|
redColor("w2-neutral");
|
||||||
|
redColor("w2-defer");
|
||||||
|
redColor("w2-stalling");
|
||||||
|
redColor("w2-caution");
|
||||||
|
}
|
||||||
|
|
||||||
|
function w2Green(){
|
||||||
|
greenColor("w2-takedown");
|
||||||
|
greenColor("w2-escape");
|
||||||
|
greenColor("w2-reversal");
|
||||||
|
greenColor("w2-penalty");
|
||||||
|
greenColor("w2-penalty2");
|
||||||
|
greenColor("w2-nf5");
|
||||||
|
greenColor("w2-nf4");
|
||||||
|
greenColor("w2-nf3");
|
||||||
|
greenColor("w2-nf2");
|
||||||
|
greenColor("w2-top");
|
||||||
|
greenColor("w2-bottom");
|
||||||
|
greenColor("w2-neutral");
|
||||||
|
greenColor("w2-defer");
|
||||||
|
greenColor("w2-stalling");
|
||||||
|
greenColor("w2-caution");
|
||||||
|
}
|
||||||
|
</script>
|
||||||
216
app/views/matches/_matchstats_variable_score_input.html.erb
Normal file
216
app/views/matches/_matchstats_variable_score_input.html.erb
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
<script>
|
||||||
|
// ############### Score field changer and form validation
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
const winTypeSelect = document.getElementById("match_win_type");
|
||||||
|
const winnerSelect = document.getElementById("match_winner_id");
|
||||||
|
const submitButton = document.getElementById("update-match-btn");
|
||||||
|
const dynamicScoreInput = document.getElementById("dynamic-score-input");
|
||||||
|
const finalScoreField = document.getElementById("final-score-field");
|
||||||
|
const validationAlerts = document.getElementById("validation-alerts");
|
||||||
|
const pinTimeTip = document.getElementById("pin-time-tip");
|
||||||
|
|
||||||
|
// Variables to persist scores across win type changes
|
||||||
|
let storedScores = {
|
||||||
|
winnerScore: "0",
|
||||||
|
loserScore: "0",
|
||||||
|
};
|
||||||
|
|
||||||
|
function updateScoreInput() {
|
||||||
|
const winType = winTypeSelect.value;
|
||||||
|
|
||||||
|
if (winType === "Pin") {
|
||||||
|
if (
|
||||||
|
dynamicScoreInput.querySelector("#minutes") &&
|
||||||
|
dynamicScoreInput.querySelector("#seconds")
|
||||||
|
) {
|
||||||
|
validateForm(); // Trigger validation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear existing form and create Pin inputs
|
||||||
|
dynamicScoreInput.innerHTML = "";
|
||||||
|
pinTimeTip.style.display = "block";
|
||||||
|
|
||||||
|
const minuteInput = createTextInput("minutes", "Minutes (MM)", "Pin Time Minutes");
|
||||||
|
const secondInput = createTextInput("seconds", "Seconds (SS)", "Pin Time Seconds");
|
||||||
|
|
||||||
|
dynamicScoreInput.appendChild(minuteInput);
|
||||||
|
dynamicScoreInput.appendChild(secondInput);
|
||||||
|
|
||||||
|
const updateFinalScore = () => {
|
||||||
|
const minutes = minuteInput.value.padStart(2, "0");
|
||||||
|
const seconds = secondInput.value.padStart(2, "0");
|
||||||
|
finalScoreField.value = `${minutes}:${seconds}`;
|
||||||
|
validateForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
[minuteInput, secondInput].forEach((input) => {
|
||||||
|
input.addEventListener("input", updateFinalScore);
|
||||||
|
});
|
||||||
|
|
||||||
|
updateFinalScore(); // Set initial value
|
||||||
|
validateForm(); // Trigger validation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
winType === "Decision" ||
|
||||||
|
winType === "Major" ||
|
||||||
|
winType === "Tech Fall"
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
dynamicScoreInput.querySelector("#winner-score") &&
|
||||||
|
dynamicScoreInput.querySelector("#loser-score")
|
||||||
|
) {
|
||||||
|
validateForm(); // Trigger validation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear existing form and create Score inputs
|
||||||
|
dynamicScoreInput.innerHTML = "";
|
||||||
|
pinTimeTip.style.display = "none";
|
||||||
|
|
||||||
|
const winnerScoreInput = createTextInput(
|
||||||
|
"winner-score",
|
||||||
|
"Winner's Score",
|
||||||
|
"Enter the winner's score"
|
||||||
|
);
|
||||||
|
const loserScoreInput = createTextInput(
|
||||||
|
"loser-score",
|
||||||
|
"Loser's Score",
|
||||||
|
"Enter the loser's score"
|
||||||
|
);
|
||||||
|
|
||||||
|
dynamicScoreInput.appendChild(winnerScoreInput);
|
||||||
|
dynamicScoreInput.appendChild(loserScoreInput);
|
||||||
|
|
||||||
|
// Restore stored values
|
||||||
|
winnerScoreInput.value = storedScores.winnerScore;
|
||||||
|
loserScoreInput.value = storedScores.loserScore;
|
||||||
|
|
||||||
|
const updateFinalScore = () => {
|
||||||
|
const winnerScore = winnerScoreInput.value || "0";
|
||||||
|
const loserScore = loserScoreInput.value || "0";
|
||||||
|
finalScoreField.value = `${winnerScore}-${loserScore}`;
|
||||||
|
validateForm();
|
||||||
|
};
|
||||||
|
|
||||||
|
[winnerScoreInput, loserScoreInput].forEach((input) => {
|
||||||
|
input.addEventListener("input", (event) => {
|
||||||
|
storedScores[event.target.id === "winner-score" ? "winnerScore" : "loserScore"] =
|
||||||
|
event.target.value || "0";
|
||||||
|
updateFinalScore();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
updateFinalScore(); // Set initial value
|
||||||
|
validateForm(); // Trigger validation
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For other types, clear everything
|
||||||
|
dynamicScoreInput.innerHTML = "";
|
||||||
|
pinTimeTip.style.display = "none";
|
||||||
|
finalScoreField.value = ""; // Clear the final score for other win types
|
||||||
|
validateForm(); // Trigger validation
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateForm() {
|
||||||
|
const winType = winTypeSelect.value;
|
||||||
|
const winner = winnerSelect.value;
|
||||||
|
let isValid = true;
|
||||||
|
let alertMessage = "";
|
||||||
|
|
||||||
|
let winTypeShouldBe = "Decision";
|
||||||
|
|
||||||
|
if (winType === "Decision" || winType === "Major" || winType === "Tech Fall") {
|
||||||
|
const winnerScoreInput = document.getElementById("winner-score");
|
||||||
|
const loserScoreInput = document.getElementById("loser-score");
|
||||||
|
|
||||||
|
if (!winnerScoreInput || !loserScoreInput) return;
|
||||||
|
|
||||||
|
const winnerScore = parseInt(winnerScoreInput.value || "0", 10);
|
||||||
|
const loserScore = parseInt(loserScoreInput.value || "0", 10);
|
||||||
|
const scoreDifference = winnerScore - loserScore;
|
||||||
|
|
||||||
|
if (winnerScore <= loserScore) {
|
||||||
|
isValid = false;
|
||||||
|
alertMessage += "Winner's score must be higher than loser's score.<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scoreDifference < 8) {
|
||||||
|
winTypeShouldBe = "Decision";
|
||||||
|
} else if (scoreDifference >= 8 && scoreDifference < 15) {
|
||||||
|
winTypeShouldBe = "Major";
|
||||||
|
} else if (scoreDifference >= 15) {
|
||||||
|
winTypeShouldBe = "Tech Fall";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (winTypeShouldBe !== winType) {
|
||||||
|
isValid = false;
|
||||||
|
alertMessage += `
|
||||||
|
Win type should be <strong>${winTypeShouldBe}</strong>.
|
||||||
|
Decisions are wins with a score difference less than 8.
|
||||||
|
Majors are wins with a score difference between 8 and 14.
|
||||||
|
Tech Falls are wins with a score difference of 15 or more.<br>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!winner) {
|
||||||
|
isValid = false;
|
||||||
|
alertMessage += "Please select a winner.<br>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValid) {
|
||||||
|
validationAlerts.innerHTML = alertMessage;
|
||||||
|
validationAlerts.style.display = "block";
|
||||||
|
} else {
|
||||||
|
validationAlerts.innerHTML = ""; // Clear alerts
|
||||||
|
validationAlerts.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
submitButton.disabled = !isValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector("form").addEventListener("submit", (event) => {
|
||||||
|
const winType = winTypeSelect.value;
|
||||||
|
|
||||||
|
if (winType === "Pin") {
|
||||||
|
const minuteInput = document.getElementById("minutes");
|
||||||
|
const secondInput = document.getElementById("seconds");
|
||||||
|
|
||||||
|
if (minuteInput && secondInput) {
|
||||||
|
const minutes = minuteInput.value.padStart(2, "0");
|
||||||
|
const seconds = secondInput.value.padStart(2, "0");
|
||||||
|
finalScoreField.value = `${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
winTypeSelect.addEventListener("change", updateScoreInput);
|
||||||
|
winnerSelect.addEventListener("change", validateForm);
|
||||||
|
|
||||||
|
updateScoreInput();
|
||||||
|
validateForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Helper function to create text inputs
|
||||||
|
function createTextInput(id, placeholder, label) {
|
||||||
|
const container = document.createElement("div");
|
||||||
|
container.classList.add("form-group");
|
||||||
|
|
||||||
|
const inputLabel = document.createElement("label");
|
||||||
|
inputLabel.innerText = label;
|
||||||
|
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.type = "text";
|
||||||
|
input.id = id;
|
||||||
|
input.placeholder = placeholder;
|
||||||
|
input.classList.add("form-control", "form-control-sm");
|
||||||
|
|
||||||
|
container.appendChild(inputLabel);
|
||||||
|
container.appendChild(input);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user