feat: target rating calculator (#2) #17
@@ -353,3 +353,10 @@
|
||||
.target-rating-result .loading {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.target-rating-result .no-history-prompt {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
@@ -615,6 +615,10 @@ async function calculateTargetRating(event) {
|
||||
clearResult();
|
||||
|
||||
if (!response.ok || !data.success) {
|
||||
if (response.status === 404 && data.errorType === 'NO_ROUNDS') {
|
||||
renderNoHistoryPrompt(pdgaNumber, result);
|
||||
return;
|
||||
}
|
||||
const msg = data.details ? data.error + ': ' + data.details : (data.error || 'Calculation failed');
|
||||
_targetResultMsg(result, 'error', msg);
|
||||
return;
|
||||
@@ -661,3 +665,61 @@ async function calculateTargetRating(event) {
|
||||
function closeTargetRatingModal(event) {
|
||||
document.getElementById('target-rating-modal').style.display = 'none';
|
||||
}
|
||||
|
||||
function renderNoHistoryPrompt(pdgaNumber, container) {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'no-history-prompt';
|
||||
|
||||
const msg = document.createElement('div');
|
||||
msg.textContent = 'No round-level history is stored for this player yet. Refresh from PDGA to enable the calculation.';
|
||||
wrapper.appendChild(msg);
|
||||
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.className = 'btn btn-confirm';
|
||||
btn.textContent = 'Refresh round history & calculate';
|
||||
btn.addEventListener('click', function () { refreshHistoryThenCalculate(pdgaNumber); });
|
||||
wrapper.appendChild(btn);
|
||||
|
||||
container.appendChild(wrapper);
|
||||
}
|
||||
|
||||
async function refreshHistoryThenCalculate(pdgaNumber) {
|
||||
const result = document.getElementById('target-rating-result');
|
||||
while (result.firstChild) result.removeChild(result.firstChild);
|
||||
_targetResultMsg(result, 'loading', 'Refreshing round history from PDGA — this may take up to 30 seconds...');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/refresh-round-history/' + pdgaNumber, { method: 'POST' });
|
||||
const data = await response.json();
|
||||
while (result.firstChild) result.removeChild(result.firstChild);
|
||||
|
||||
if (response.status === 429) {
|
||||
const hours = data.hoursRemaining ? data.hoursRemaining + ' hour(s)' : 'a while';
|
||||
_targetResultMsg(result, 'error', 'Round history was refreshed recently. Try again in ' + hours + '.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!response.ok || !data.success) {
|
||||
const msg = data.details ? data.error + ': ' + data.details : (data.error || 'Refresh failed');
|
||||
_targetResultMsg(result, 'error', msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.debugLog) cachedDebugInfo[pdgaNumber] = data.debugLog;
|
||||
const predictedCell = document.getElementById('predicted-' + pdgaNumber);
|
||||
if (predictedCell) {
|
||||
const predictedValue = predictedCell.querySelector('.predicted-value');
|
||||
if (predictedValue) {
|
||||
predictedValue.textContent = data.predictedRating || 'N/A';
|
||||
predictedValue.dataset.stddev = data.stdDev || '';
|
||||
}
|
||||
}
|
||||
|
||||
await calculateTargetRating(null);
|
||||
} catch (err) {
|
||||
console.error('Error refreshing round history:', err);
|
||||
while (result.firstChild) result.removeChild(result.firstChild);
|
||||
_targetResultMsg(result, 'error', 'Network error during refresh. Please try again.');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user