jM¬<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="chrome-extension://lbjapbcmmceacocpimbpbidpgmlmoaao/content.js"></script>
<title>Golf Scorecard with Signatures</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 5;
display: flex;
justify-content: center;
background-color: #f4f4f4;
height: 100vh;
overflow-y: auto;
}
/* Ensure .framed-page is responsive and allows flexbox to work */
.framed-page {
width: 100%; /* Ensure it is responsive */
max-width: 1200px;
padding: 20px;
border: 3px solid #2a9d8f;
border-radius: 10px;
background-color: #fff;
box-shadow: 0px 8px 16px rgba(0, 0, 0, 0.2);
margin: 20px 0;
box-sizing: border-box;
display: flex;
flex-direction: column;
align-items: center;
height: 300px; /* Allow height to adjust based on content */
/*overflow-x: visible; /* Ensure no hidden overflow */
}
/* Ensure scrolling behavior for smaller screens */
@media (max-width: 768px) {
.scoring-array {
flex-wrap: nowrap; /* Prevent wrapping on smaller screens */
overflow-x: auto; /* Ensure horizontal scrolling */
padding: 0 10px; /* Ensure padding on mobile */
}
.scoring-array input {
flex: 0 0 50px; /* Fixed width for input fields on smaller screens */
}
}
/* Scoreboard section below the scorecard */
#scoreboardSection {
margin-top: 20px; /* Space between scorecard and scoreboard */
padding: 20px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 4px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
}
/* Table styling for both the scorecard and scoreboard */
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
}
th, td {
padding: 1px;
text-align: center;
border: 1px solid #ccc;
}
th {
background-color: #005f5f;
color: white;
}
td {
background-color: #f4f4f4;
}
/* Input fields inside scorecard */
input[type="text"], input[type="date"] {
width: 15%;
padding: 12px;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 8px;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Remove arrows from number inputs in Firefox */
input[type="number"] {
-moz-appearance: textfield;
}
/* Set the width of the number input */
input[type="number"] {
width: 25px; /* Adjust width as needed */
}
/* Hide the difficulty row if needed */
#difficultyRow {
display: none;
}
/* Styling for the scoreboard table */
#leaderboardTable {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
#leaderboardTable th, #leaderboardTable td {
padding: 8px;
text-align: center;
border-bottom: 1px solid #ddd;
}
#leaderboardTable th {
background-color: #005f5f;
color: white;
}
#scoreboardSection {
display: none; /* Initially hidden */
margin-top: 20px;
padding: 15px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
}
.action-bar {
display: flex;
align-items: center; /* Vertically aligns elements */
gap: 10px; /* Space between elements */
}
button {
padding: 5px 10px; /* Adjust the padding to make the buttons smaller */
}
label, select {
margin-left: 10px; /* Add space between the label/select and buttons */
}
select {
padding: 5px; /* Adjust padding to reduce size */
}
</style>
</head>
<body>
<div class="framed-page">
<header>
<div style="display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; width: 100%;">
<header>
<div style="display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; width: 100%;">
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="playerName" placeholder="Player Name" style="width: 100%;">
</div>
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="memberNum" placeholder="Member Num" maxlength="7" style="width: 100%;">
</div>
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="competitionInput" value="TOUR" placeholder="Competition" style="width: 100%; max-width: 100px; text-align: left; box-sizing: border-box;">
</div>
<div style="flex: 1; margin-right: 10px;">
<input type="number" id="handicap" placeholder="Handicap" style="width: 100%;" value="0">
</div>
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="countryCode" placeholder="Country Code (e.g., 064)" style="width: 100%;">
</div>
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="clubCode" placeholder="Club Code (e.g., 271)" style="width: 100%;">
</div>
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="teeInput" placeholder="Tee Type (e.g., whitetee)" style="width: 100%;">
</div>
<!-- New Team Input Field -->
<div style="flex: 1; margin-right: 10px;">
<input type="text" id="teamInput" placeholder="Team Name" style="width: 100%;">
</div>
</div>
</header>
</div>
</header>
<table>
<thead>
<tr>
<th>Hole</th>
<!-- Hole numbers -->
<th>1</th> <th>2</th> <th>3</th> <th>4</th> <th>5</th> <th>6</th> <th>7</th> <th>8</th> <th>9</th> <th>ST</th>
<th>10</th> <th>11</th> <th>12</th> <th>13</th> <th>14</th> <th>15</th> <th>16</th> <th>17</th> <th>18</th> <th>ST</th>
</tr>
</thead>
<tbody>
<tr id="difficultyRow">
<th>Stroke</th>
<!-- Stroke values (empty for now) -->
<td id="diff1"></td> <td id="diff2"></td> <td id="diff3"></td> <td id="diff4"></td> <td id="diff5"></td> <td id="diff6"></td> <td id="diff7"></td> <td id="diff8"></td> <td id="diff9"></td> <td></td>
<td id="diff10"></td> <td id="diff11"></td> <td id="diff12"></td> <td id="diff13"></td> <td id="diff14"></td> <td id="diff15"></td> <td id="diff16"></td> <td id="diff17"></td> <td id="diff18"></td> <td></td>
</tr>
<!-- Row for Par values -->
<tr id="parRow">
<th>Par</th>
<td id="par1"></td> <td id="par2"></td> <td id="par3"></td> <td id="par4"></td> <td id="par5"></td> <td id="par6"></td> <td id="par7"></td> <td id="par8"></td> <td id="par9"></td> <td></td>
<td id="par10"></td> <td id="par11"></td> <td id="par12"></td> <td id="par13"></td> <td id="par14"></td> <td id="par15"></td> <td id="par16"></td> <td id="par17"></td> <td id="par18"></td> <td></td>
</tr>
<!-- Row for Scores input -->
<tr class="input-row">
<th>Score</th>
<td><input type="number" id="hole1" oninput="calculateTotals()"></td>
<td><input type="number" id="hole2" oninput="calculateTotals()"></td>
<td><input type="number" id="hole3" oninput="calculateTotals()"></td>
<td><input type="number" id="hole4" oninput="calculateTotals()"></td>
<td><input type="number" id="hole5" oninput="calculateTotals()"></td>
<td><input type="number" id="hole6" oninput="calculateTotals()"></td>
<td><input type="number" id="hole7" oninput="calculateTotals()"></td>
<td><input type="number" id="hole8" oninput="calculateTotals()"></td>
<td><input type="number" id="hole9" oninput="calculateTotals()"></td>
<td><input type="number" id="st1" readonly></td>
<td><input type="number" id="hole10" oninput="calculateTotals()"></td>
<td><input type="number" id="hole11" oninput="calculateTotals()"></td>
<td><input type="number" id="hole12" oninput="calculateTotals()"></td>
<td><input type="number" id="hole13" oninput="calculateTotals()"></td>
<td><input type="number" id="hole14" oninput="calculateTotals()"></td>
<td><input type="number" id="hole15" oninput="calculateTotals()"></td>
<td><input type="number" id="hole16" oninput="calculateTotals()"></td>
<td><input type="number" id="hole17" oninput="calculateTotals()"></td>
<td><input type="number" id="hole18" oninput="calculateTotals()"></td>
<td><input type="number" id="st2" readonly></td>
</tr>
<!-- Row for Stableford scores -->
<tr>
<th>Sford</th>
<td><input type="number" id="sford1" readonly></td> <td><input type="number" id="sford2" readonly></td> <td><input type="number" id="sford3" readonly></td> <td><input type="number" id="sford4" readonly></td>
<td><input type="number" id="sford5" readonly></td> <td><input type="number" id="sford6" readonly></td> <td><input type="number" id="sford7" readonly></td> <td><input type="number" id="sford8" readonly></td>
<td><input type="number" id="sford9" readonly></td> <td><input type="number" id="sf1" readonly></td>
<td><input type="number" id="sford10" readonly></td> <td><input type="number" id="sford11" readonly></td> <td><input type="number" id="sford12" readonly></td>
<td><input type="number" id="sford13" readonly></td> <td><input type="number" id="sford14" readonly></td> <td><input type="number" id="sford15" readonly></td> <td><input type="number" id="sford16" readonly></td>
<td><input type="number" id="sford17" readonly></td> <td><input type="number" id="sford18" readonly></td> <td><input type="number" id="sf2" readonly></td>
</tr>
</tbody>
</table>
<!-- Totals and Buttons Section -->
<div style="display: flex; justify-content: space-between; align-items: center; width: 100%; margin-bottom: 20px;">
<div>Gross: <span id="gross">0</span></div>
<div>Nett: <span id="net">0</span></div>
<div>Stableford: <span id="stablefordTotal">0</span></div>
<button id="startGameButton">Start Game</button>
<button id="saveButton">Save</button>
<button id="loadButton">Load</button><input type="file" id="fileInput" style="display: none;">
<button id="clearButton">Clear</button>
<button id="updateButton">Update</button>
<button id="scoreboardButton">Scoreboard</button>
</div>
<!-- Add the text area for both sending and displaying messages -->
<div style="width: 100%; margin-bottom: 20px;">
<textarea id="messageTextArea" rows="3" style="width: 100%;" placeholder="Enter your message here..."></textarea>
</div>
<div class="action-bar">
<button id="sendToAllButton">Send to All</button>
<button id="sendToRecipientButton" disabled>Send to Selected Recipient</button>
<label for="recipientSelect">Recipient:</label>
<select id="recipientSelect" disabled>
<option value="">--No recipient selected--</option>
<!-- The selected recipient will be dynamically populated here -->
</select>
<button id="getMessageButton">Get Message</button>
</div>
<!-- Scoreboard Section -->
<div id="scoreboardSection">
<h2>Scoreboard</h2>
<table id="leaderboardTable" style="width: 100%;">
<thead>
<tr>
<th>Player</th>
<th>Handicap</th>
<th id="sortByGross">Gross</th> <!-- ID for Gross -->
<th id="sortByNett">Nett</th> <!-- ID for Nett -->
<th id="sortBySford">Stableford</th> <!-- ID for Stableford -->
<th>Action</th>
</tr>
</thead>
<tbody id="leaderboardBody">
<!-- Player rows will be dynamically inserted here -->
</tbody>
</table>
</div>
<script>
// Function to update the scorecard with fetched par, stroke, and distance data
function updateScorecard(parArray, strokeArray, distanceArray) {
// Update the par, stroke, and distance rows in the table
for (let i = 1; i <= 18; i++) {
document.getElementById(`par${i}`).innerText = parArray[i - 1];
document.getElementById(`diff${i}`).innerText = strokeArray[i - 1];
// You can update distance if required on the UI
}
}
// Function to reset the array based on fetched data and display intermediate arrays
function resetArray(handicap) {
const parArray = JSON.parse(sessionStorage.getItem('ParArray')) || [];
const strokeArray = JSON.parse(sessionStorage.getItem('StrokeArray')) || [];
const distanceArray = JSON.parse(sessionStorage.getItem('DistanceArray')) || [];
const resetArray = Array(18).fill(0);
const PParArray = [];
const Hdp1 = Array(18).fill(0);
const Hdp2 = Array(18).fill(0);
const Hdp3 = Array(18).fill(0);
// Reorder based on difficulty
const reorderedHoles = parArray.map((par, index) => ({
holeNumber: index + 1,
difficulty: strokeArray[index],
par: par,
distance: distanceArray[index]
})).sort((a, b) => a.difficulty - b.difficulty);
// Apply positive or negative handicap distribution logic
if (handicap < 0) {
let numNegativeStrokes = Math.min(-handicap, 6);
reorderedHoles.forEach((hole, index) => {
if (index < 18 - numNegativeStrokes) {
PParArray.push(hole.par);
} else {
PParArray.push(hole.par - 1);
}
});
} else {
for (let i = 0; i < handicap; i++) {
if (i < 18) Hdp1[i % 18]++;
else if (i < 36) Hdp2[i % 18]++;
else Hdp3[i % 18]++;
}
reorderedHoles.forEach((hole, index) => {
PParArray.push(hole.par + Hdp1[index] + Hdp2[index] + Hdp3[index]);
});
}
strokeArray.forEach((difficulty, index) => {
resetArray[index] = PParArray[difficulty - 1];
});
sessionStorage.setItem('ResetArray', JSON.stringify(resetArray));
return resetArray;
}
// Function to calculate and display gross, nett, and stableford totals along with subtotals
function calculateTotals() {
const resetArray = JSON.parse(sessionStorage.getItem('ResetArray')) || [];
const parArray = JSON.parse(sessionStorage.getItem('ParArray')) || []; // Use fetched ParArray from session
let totalGross = 0, totalNett = 0, totalStableford = 0;
let front9Gross = 0, back9Gross = 0;
let front9Nett = 0, back9Nett = 0;
let front9Stableford = 0, back9Stableford = 0;
for (let i = 1; i <= 18; i++) {
const grossScore = parseInt(document.getElementById(`hole${i}`).value) || 0;
totalGross += grossScore;
const personalPar = resetArray[i - 1]; // Adjusted personal par (Reset Par)
const coursePar = parArray[i - 1]; // Standard par fetched from JSON
// Nett score logic: Nett = Gross - (Reset Par - Course Par)
const nettScore = grossScore - (personalPar - coursePar);
totalNett += nettScore;
// Stableford logic: Only calculate if gross score is entered
const stablefordScore = grossScore > 0 ? Math.max(personalPar - grossScore + 2, 0) : 0;
document.getElementById(`sford${i}`).value = stablefordScore;
totalStableford += stablefordScore;
// Subtotals for front 9 (holes 1-9) and back 9 (holes 10-18)
if (i <= 9) {
front9Gross += grossScore;
front9Nett += nettScore;
front9Stableford += stablefordScore;
} else {
back9Gross += grossScore;
back9Nett += nettScore;
back9Stableford += stablefordScore;
}
}
// Log calculated totals
console.log('Total Gross:', totalGross);
console.log('Total Nett:', totalNett);
console.log('Total Stableford:', totalStableford);
// Save totals in session storage
sessionStorage.setItem('totalGross', totalGross);
sessionStorage.setItem('totalNett', totalNett);
sessionStorage.setItem('totalStableford', totalStableford);
// Update total values in the UI
document.getElementById('gross').innerText = totalGross;
document.getElementById('net').innerText = totalNett;
document.getElementById('stablefordTotal').innerText = totalStableford;
// Update subtotals for front 9 and back 9
document.getElementById('st1').value = front9Gross;
document.getElementById('sf1').value = front9Stableford;
document.getElementById('st2').value = back9Gross;
document.getElementById('sf2').value = back9Stableford;
// Log subtotals for front 9 and back 9
console.log('Front 9 Gross:', front9Gross);
console.log('Back 9 Gross:', back9Gross);
}
// Function to save the scorecard data to a JSON file
function saveCollectedData(data) {
const dataStr = JSON.stringify(data, null, 2); // Format the JSON data with indentation
const dataBlob = new Blob([dataStr], { type: 'application/json' });
const url = window.URL.createObjectURL(dataBlob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = `${data.playerName}_scorecard.json`; // File name based on player name
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}
// Function to save the collected data as a JSON file
function saveCollectedData(data) {
// Convert the scoreData object to JSON
const scoreDataJson = JSON.stringify(data, null, 2);
// Create a blob object for the data
const blob = new Blob([scoreDataJson], { type: 'application/json' });
// Clean up the player's name for the filename (remove spaces and special characters)
const cleanPlayerName = data.playerName.replace(/[^a-zA-Z0-9]/g, '_');
const fileName = `${cleanPlayerName}_${data.date}.json`;
// Create a link element to trigger the download
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName; // The file name for the download based on name and date
// Trigger the download by clicking the link
a.click();
}
// Function to populate the form with loaded data Done
function populateFormWithData(data) {
// Populate header information
document.getElementById('playerName').value = data.playerName || '';
document.getElementById('memberNum').value = data.memberNum || '';
document.getElementById('competitionInput').value = data.competition || ''; // Add competition input
document.getElementById('handicap').value = data.handicap || '';
document.getElementById('countryCode').value = data.countryCode || '';
document.getElementById('clubCode').value = data.clubCode || '';
document.getElementById('teeInput').value = data.teeType || '';
document.getElementById('gameDate').value = data.date || '';
// Populate scores
for (let i = 1; i <= 18; i++) {
document.getElementById(`hole${i}`).value = data.scores[i - 1] || '';
}
// Populate Gross, Nett, and Stableford totals
document.getElementById('gross').innerText = data.totalGross || 0;
document.getElementById('net').innerText = data.totalNett || 0;
document.getElementById('stablefordTotal').innerText = data.totalStableford || 0;
// Store loaded data in sessionStorage for further use
sessionStorage.setItem('playerName', data.playerName);
sessionStorage.setItem('memberNum', data.memberNum);
sessionStorage.setItem('competition', data.competition); // Store competition input
sessionStorage.setItem('handicap', data.handicap);
sessionStorage.setItem('countryCode', data.countryCode);
sessionStorage.setItem('clubCode', data.clubCode);
sessionStorage.setItem('teeType', data.teeType);
sessionStorage.setItem('gameDate', data.date);
sessionStorage.setItem('scores', JSON.stringify(data.scores));
// Save totals in sessionStorage
sessionStorage.setItem('totalGross', data.totalGross || 0);
sessionStorage.setItem('totalNett', data.totalNett || 0);
sessionStorage.setItem('totalStableford', data.totalStableford || 0);
}
// Add the event listener for the "Scoreboard" button
document.getElementById('scoreboardButton').addEventListener('click', function() {
const scoreboardSection = document.getElementById('scoreboardSection');
// Toggle the display of the scoreboard section
if (scoreboardSection.style.display === 'none' || scoreboardSection.style.display === '') {
scoreboardSection.style.display = 'block'; // Show the scoreboard
fetchPlayerTotals(); // Fetch and display the player data
} else {
scoreboardSection.style.display = 'none'; // Hide the scoreboard
}
});
// Add event listeners to the column headers for sorting
document.getElementById('sortByGross').addEventListener('click', sortByGross);
document.getElementById('sortByNett').addEventListener('click', sortByNett);
document.getElementById('sortBySford').addEventListener('click', sortBySford);
// Declare global variable to store player data
let playersData = [];
// Function to fetch player totals and store in playersData, then display leaderboard
function fetchPlayerTotals() {
fetch('https://bsvgolf.com/fetch-totals') // Replace this URL with your actual API endpoint
.then(response => response.json())
.then(playerTotals => {
if (playerTotals && playerTotals.length) {
playersData = playerTotals; // Assign the fetched data to playersData
displayLeaderboard(playersData); // Display the leaderboard with totals
} else {
console.error('No player data received.');
}
})
.catch(error => {
console.error('Error fetching player totals:', error);
});
}
// Function to handle selecting a recipient from the scoreboard
function selectRecipient(playerID, playerName) {
// Set the recipient dropdown to show the selected player
const recipientSelect = document.getElementById('recipientSelect');
recipientSelect.innerHTML = `<option value="${playerID}">${playerName}</option>`; // Dynamically populate the dropdown
recipientSelect.disabled = false; // Enable the dropdown to show selection
document.getElementById('sendToRecipientButton').disabled = false; // Enable the "Send to Selected Recipient" button
}
// Example of the scoreboard HTML structure (Make sure you populate the buttons with this function)
function displayLeaderboard(players) {
let html = '';
players.forEach(player => {
html += `<tr>
<td>${player.playerName}</td>
<td>${player.handicap}</td>
<td>${player.totalGross}</td>
<td>${player.totalNett}</td>
<td>${player.totalStableford}</td>
<td>
<button onclick="selectRecipient(${player.playerID}, '${player.playerName}')">Send To</button>
</td>
</tr>`;
});
document.getElementById('leaderboardBody').innerHTML = html;
}
// Sorting by Gross
function sortByGross() {
if (playersData && Array.isArray(playersData)) {
playersData.sort((a, b) => a.totalGross - b.totalGross);
displayLeaderboard(playersData); // Re-populate the table after sorting
} else {
console.error('playersData is not available for sorting.');
}
}
// Sorting by Nett
function sortByNett() {
if (playersData && Array.isArray(playersData)) {
playersData.sort((a, b) => a.totalNett - b.totalNett);
displayLeaderboard(playersData); // Re-populate the table after sorting
} else {
console.error('playersData is not available for sorting.');
}
}
// Sorting by Stableford in descending order (highest to lowest)
function sortBySford() {
if (playersData && Array.isArray(playersData)) {
playersData.sort((a, b) => b.totalStableford - a.totalStableford); // Sort in descending order
displayLeaderboard(playersData); // Re-populate the table after sorting
} else {
console.error('playersData is not available for sorting.');
}
}
// Function to send a message to the server (memory) and save to the directory (file storage)
function sendMessageToServer(message, recipient = 'all', countryCode = '064', clubCode = '271') {
// First, send the message to in-memory storage (send-message endpoint)
fetch('https://bsvgolf.com/send-message', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ text: message, recipient: recipient })
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Message sent to memory successfully:', data);
// After sending the message to memory, save the message to the directory
return fetch('https://bsvgolf.com/save-to-dir', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: message,
recipient: recipient,
countryCode: countryCode, // Pass countryCode for directory structure
clubCode: clubCode // Pass clubCode for directory structure
})
});
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json();
})
.then(data => {
console.log('Message saved to directory successfully:', data);
// Clear the textarea only after the message is successfully sent to both
const messageTextArea = document.getElementById('messageTextArea');
if (messageTextArea) {
messageTextArea.value = ''; // Clear the textarea after successful send
}
})
.catch(error => {
console.error('Error sending or saving message:', error);
});
}
// Function to handle recipient selection and enable/disable the send button
function handleRecipientSelection() {
const recipientSelect = document.getElementById('recipientSelect');
const sendToRecipientButton = document.getElementById('sendToRecipientButton');
// Enable the "Send to Selected Recipient" button if a recipient is selected
if (recipientSelect.value !== '') {
sendToRecipientButton.disabled = false;
} else {
sendToRecipientButton.disabled = true;
}
}
// Function to fetch and display the latest message from the server in the text area
function receiveMessagesFromServer() {
fetch('https://bsvgolf.com/receive-message')
.then(response => response.json())
.then(data => {
const messageTextArea = document.getElementById('messageTextArea');
if (messageTextArea && data.text) { // Only update if data.text is non-empty
messageTextArea.value = data.text; // Update the text area with the received message
console.log('Updated message text area with:', data.text);
} else {
console.log('No new message received');
}
})
.catch(error => {
console.error('Error receiving message:', error);
});
}
// Function to fetch and display the latest message from the server in the text area
function receiveMessagesFromServer() {
fetch('https://bsvgolf.com/receive-message')
.then(response => response.json())
.then(data => {
const messageTextArea = document.getElementById('messageTextArea');
if (messageTextArea && data.text) { // Only update if data.text is non-empty
messageTextArea.value = data.text; // Update the text area with the received message
console.log('Updated message text area with:', data.text);
} else {
console.log('No new message received');
}
})
.catch(error => {
console.error('Error receiving message:', error);
});
}
// Add the event listener for the "Get Message" button
document.getElementById('getMessageButton').addEventListener('click', function() {
receiveMessagesFromServer(); // Manually fetch messages when the button is clicked
});
// The DOMContentLoaded event listener
document.addEventListener('DOMContentLoaded', function() {
// Poll every 60 seconds for new messages
setInterval(receiveMessagesFromServer, 60000);
const sendToAllButton = document.getElementById('sendToAllButton');
const sendToRecipientButton = document.getElementById('sendToRecipientButton');
const messageTextArea = document.getElementById('messageTextArea');
const recipientSelect = document.getElementById('recipientSelect');
// Send to "All" when the "Send to All" button is clicked
sendToAllButton.addEventListener('click', () => {
const message = messageTextArea.value;
if (message.trim()) {
sendMessageToServer(message); // Send to all (default recipient = 'all')
messageTextArea.value = ''; // Clear the text area after sending
} else {
alert("Please enter a message.");
}
});
document.getElementById('sendToRecipientButton').addEventListener('click', () => {
const message = messageTextArea.value;
const recipient = recipientSelect.value;
if (message.trim() && recipient) {
sendMessageToServer(message, recipient); // Send to the selected recipient
messageTextArea.value = ''; // Clear the text area after sending
} else {
alert("Please enter a message and select a recipient.");
}
});
document.getElementById('startGameButton').addEventListener('click', function() {
// Get user inputs
const countryCode = document.getElementById('countryCode').value.trim();
const courseCode = document.getElementById('clubCode').value.trim();
const teeType = document.getElementById('teeInput').value.trim();
// Input validation
if (!countryCode || !courseCode || !teeType) {
alert('Please provide valid inputs for Country Code, Club Code, and Tee Type.');
return; // Stop the function if inputs are invalid
}
// Construct the URL and add .json to tee type
const teeUrl = `https://bsvgolf.com/${countryCode}/${courseCode}/${teeType}.json`;
// Check if the .json file exists by sending a HEAD request
fetch(teeUrl, { method: 'HEAD' })
.then(response => {
if (!response.ok) {
throw new Error(`Tee file does not exist: ${teeType}.json`);
}
// Proceed with fetching the data if the file exists
return fetch(teeUrl);
})
.then(response => {
if (!response.ok) {
throw new Error(`Unable to fetch tee data. Status: ${response.status}`);
}
return response.json();
})
.then(data => {
const parArray = data.Par; // Fetch the par values from the JSON
const strokeArray = data.Difficulty; // Fetch the difficulty values from the JSON
const distanceArray = data.Distance; // Fetch the distance values from the JSON
// Store fetched data in session for further calculations
sessionStorage.setItem('ParArray', JSON.stringify(parArray));
sessionStorage.setItem('StrokeArray', JSON.stringify(strokeArray));
sessionStorage.setItem('DistanceArray', JSON.stringify(distanceArray));
// Update the scorecard with the fetched data
updateScorecard(parArray, strokeArray, distanceArray);
// Call resetArray function to calculate intermediate arrays
resetArray(parseInt(document.getElementById('handicap').value));
})
.catch(error => {
console.error('Error:', error);
alert(`Error fetching tee data: ${error.message}`);
});
});
// Handle file input change (when a file is selected)
document.getElementById('fileInput').addEventListener('change', function(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = function(e) {
const fileContent = e.target.result;
const loadedData = JSON.parse(fileContent);
populateFormWithData(loadedData); // Populate the form with the loaded data
};
reader.readAsText(file);
}
});
// Function to update player scores
function updatePlayerScores() {
// Gather the necessary data from session storage
const playerName = sessionStorage.getItem('playerName') || 'Unknown_Player';
const playerNumber = sessionStorage.getItem('playerNumber') || ''; // Retrieve player number
const memberNum = sessionStorage.getItem('memberNum') || '';
const handicap = sessionStorage.getItem('handicap') || '';
const countryCode = sessionStorage.getItem('countryCode') || '';
const clubCode = sessionStorage.getItem('clubCode') || '';
const teeType = sessionStorage.getItem('teeType') || '';
const competition = sessionStorage.getItem('competition') || 'Unknown_Competition'; // Include competition
const teamName = document.getElementById('teamInput').value || 'No Team'; // New team field
const tournamentType = "Stroke Play"; // System-generated Tournament Type (you can update this logic as needed)
const gameDate = new Date().toISOString().split('T')[0]; // System-generated current date
const scores = JSON.parse(sessionStorage.getItem('scores')) || [];
// Read totals from session storage
const totalGross = sessionStorage.getItem('totalGross') || 0;
const totalNett = sessionStorage.getItem('totalNett') || 0;
const totalStableford = sessionStorage.getItem('totalStableford') || 0;
// Create a data object to send, now including Tournament Type and Team
const scoreData = {
playerName,
playerNumber, // Include player number
memberNum,
competition, // Include competition in the data object
handicap,
countryCode,
clubCode,
teeType,
tournamentType, // Include the system-generated Tournament Type
teamName, // Include the Team Name
date: gameDate, // System-generated current date
scores,
totalGross,
totalNett,
totalStableford
};
// Send the data to the server
fetch('https://bsvgolf.com/update', { // Replace with your domain name and endpoint
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(scoreData)
})
.then(response => {
if (response.ok) {
console.log('Player score updated successfully!');
} else {
console.error('Failed to update the score. Please try again.');
}
})
.catch(error => {
console.error('Error updating the score:', error);
});
}
// Add the event listener for the "Update" button
document.getElementById('updateButton').addEventListener('click', function() {
updatePlayerScores(); // Call the function when the button is clicked
});
// Automatically update every 15 minutes (900,000 milliseconds)
setInterval(function() {
updatePlayerScores(); // Call the function every 15 minutes
}, 900000); // 900000 milliseconds = 15 minutes
// Save scores, stablefords, and nett arrays to session storage
for (let i = 1; i <= 18; i++) {
// Event listener for score inputs
document.getElementById(`hole${i}`).addEventListener('input', function() {
const scores = JSON.parse(sessionStorage.getItem('scores')) || [];
scores[i - 1] = this.value;
sessionStorage.setItem('scores', JSON.stringify(scores));
});
// Event listener for Stableford inputs
document.getElementById(`sford${i}`).addEventListener('input', function() {
const stablefords = JSON.parse(sessionStorage.getItem('stablefords')) || [];
stablefords[i - 1] = this.value;
sessionStorage.setItem('stablefords', JSON.stringify(stablefords));
});
// You can similarly handle the Nett array if needed.
}
// Function to save the collected data as a JSON file
document.getElementById('saveButton').addEventListener('click', function() {
// Read necessary data from session storage
const playerName = sessionStorage.getItem('playerName') || 'Unknown_Player';
const memberNum = sessionStorage.getItem('memberNum') || 'Unknown_Member'; // Default to 'Unknown_Member' if not provided
const competition = sessionStorage.getItem('competition') || 'Unknown_Competition'; // Use competition for the file name
const handicap = sessionStorage.getItem('handicap') || '';
const countryCode = sessionStorage.getItem('countryCode') || '';
const clubCode = sessionStorage.getItem('clubCode') || '';
const teeType = sessionStorage.getItem('teeType') || '';
const teamName = document.getElementById('teamInput').value || 'No Team'; // Default to "No Team" if not provided
// System-generated tournament type
const tournamentType = "Stroke Play"; // Example system-generated value; replace with your logic
const scores = JSON.parse(sessionStorage.getItem('scores')) || [];
// Read Gross, Nett, and Stableford totals from session storage
const totalGross = sessionStorage.getItem('totalGross') || 0;
const totalNett = sessionStorage.getItem('totalNett') || 0;
const totalStableford = sessionStorage.getItem('totalStableford') || 0;
// Construct the JSON object, now including the system-generated tournament type
const scoreData = {
playerName,
memberNum,
competition, // Use competition for the filename
handicap,
countryCode,
clubCode,
teeType,
tournamentType, // Include system-generated Tournament Type
teamName, // Include the new team field
scores,
totalGross,
totalNett,
totalStableford
};
// Create the filename using CompetitionName_PlayerName_MemberNumber.json format
const competitionName = competition.replace(/\s+/g, '_'); // Replace spaces with underscores in competition name
const fileName = `${competitionName}_${playerName.replace(/\s+/g, '_')}_${memberNum}.json`;
// Convert the scoreData object to JSON
const scoreDataJson = JSON.stringify(scoreData, null, 2);
// Create a blob object for the data
const blob = new Blob([scoreDataJson], { type: 'application/json' });
// Create a link element to trigger the download
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName; // Use the generated file name for the download
// Trigger the download by clicking the link
a.click();
console.log(`Player data saved as ${fileName}`);
});
// Load button event listener
document.getElementById('loadButton').addEventListener('click', function() {
// Trigger the file input to open
document.getElementById('fileInput').click();
});
// Save header info to session storage
document.getElementById('playerName').addEventListener('input', function() {
sessionStorage.setItem('playerName', this.value);
});
document.getElementById('memberNum').addEventListener('input', function() {
sessionStorage.setItem('memberNum', this.value);
});
document.getElementById('competitionInput').addEventListener('input', function() {
sessionStorage.setItem('competition', this.value);
});
document.getElementById('handicap').addEventListener('input', function() {
sessionStorage.setItem('handicap', this.value);
});
document.getElementById('countryCode').addEventListener('input', function() {
sessionStorage.setItem('countryCode', this.value);
});
document.getElementById('clubCode').addEventListener('input', function() {
sessionStorage.setItem('clubCode', this.value);
});
document.getElementById('teeInput').addEventListener('input', function() {
sessionStorage.setItem('teeType', this.value);
});
document.getElementById('gameDate').addEventListener('input', function() {
sessionStorage.setItem('gameDate', this.value);
});
// Clear button event listener with confirmation
document.getElementById('clearButton').addEventListener('click', function() {
// Provide a warning before clearing the scorecard
const confirmClear = confirm("Are you sure you want to clear the scorecard? This action cannot be undone.");
if (confirmClear) {
// Clear all header input fields
document.getElementById('playerName').value = '';
document.getElementById('memberNum').value = '';
document.getElementById('competitionInput').value = ''; // Clear competition input field
document.getElementById('handicap').value = '';
document.getElementById('countryCode').value = '';
document.getElementById('clubCode').value = '';
document.getElementById('teeInput').value = '';
document.getElementById('teamInput').value = ''; // Clear team input field
// Clear score, Stableford, and Nett inputs for all 18 holes
for (let i = 1; i <= 18; i++) {
let holeInput = document.getElementById(`hole${i}`);
let sfordInput = document.getElementById(`sford${i}`);
let nettInput = document.getElementById(`nett${i}`);
// Ensure the input fields exist before trying to clear them
if (holeInput) {
holeInput.value = '';
}
if (sfordInput) {
sfordInput.value = '';
}
if (nettInput) {
nettInput.value = '';
}
}
// Clear session storage, including new fields like competition and team
sessionStorage.clear();
console.log('Scorecard cleared and ready for a new game.');
} else {
// If user cancels, log that clearing was cancelled
console.log('Scorecard clearing cancelled by user.');
}
});
// Initialization code
setInterval(receiveMessagesFromServer, 60000);
});
</script>
</body>
</html>
https://whatsonchain.com/tx/2dcf8dd26f2a2208af9ed0612798617e1f6f4687eaa0ca3d38d9f05ac71b0c76