Add standard deviation display for predicted ratings
- Calculate and store standard deviation during rating prediction - Add std_dev column to players database table - Display standard deviation tooltip on hover over predicted rating - Show rating range (±std_dev) tooltip on hover over current rating - Update tooltips dynamically when ratings are refreshed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+185
-7
@@ -196,6 +196,25 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #007bff;
|
color: #007bff;
|
||||||
}
|
}
|
||||||
|
.std-dev-tooltip {
|
||||||
|
position: absolute;
|
||||||
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
color: white;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 10000;
|
||||||
|
display: none;
|
||||||
|
white-space: nowrap;
|
||||||
|
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
||||||
|
border: 1px solid rgba(255,255,255,0.2);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
.predicted-value {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
.pdga-number {
|
.pdga-number {
|
||||||
color: #6c757d;
|
color: #6c757d;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -582,18 +601,20 @@
|
|||||||
<td class="pdga-number mobile-hide">#${player.pdgaNumber}</td>
|
<td class="pdga-number mobile-hide">#${player.pdgaNumber}</td>
|
||||||
<td class="rating">
|
<td class="rating">
|
||||||
<div class="refresh-section">
|
<div class="refresh-section">
|
||||||
${player.rating || '<span style="color: #999; font-style: italic;">Click refresh</span>'}
|
<span class="rating-value" data-rating="${player.rating || ''}" data-stddev="${player.stdDev || ''}" data-pdga="${player.pdgaNumber}" style="cursor: help;">${player.rating || '<span style="color: #999; font-style: italic;">Click refresh</span>'}</span>
|
||||||
<i class="fas fa-sync-alt refresh-icon" onclick="refreshPlayer(${player.pdgaNumber})" title="Refresh player data"></i>
|
<i class="fas fa-sync-alt refresh-icon" onclick="refreshPlayer(${player.pdgaNumber})" title="Refresh player data"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="mobile-only rating-change ${ratingChangeClass}" style="font-size: 11px; margin-top: 2px;">${ratingChangeText}</div>
|
<div class="mobile-only rating-change ${ratingChangeClass}" style="font-size: 11px; margin-top: 2px;">${ratingChangeText}</div>
|
||||||
|
<div class="std-dev-tooltip" id="tooltip-rating-${player.pdgaNumber}"></div>
|
||||||
</td>
|
</td>
|
||||||
<td class="rating-change ${ratingChangeClass} mobile-hide">${ratingChangeText}</td>
|
<td class="rating-change ${ratingChangeClass} mobile-hide">${ratingChangeText}</td>
|
||||||
<td class="predicted-rating mobile-hide" id="predicted-${player.pdgaNumber}">
|
<td class="predicted-rating mobile-hide" id="predicted-${player.pdgaNumber}">
|
||||||
<div class="refresh-section">
|
<div class="refresh-section">
|
||||||
${player.predictedRating || 'N/A'}
|
<span class="predicted-value" data-stddev="${player.stdDev || ''}" data-pdga="${player.pdgaNumber}" style="cursor: help;">${player.predictedRating || 'N/A'}</span>
|
||||||
<i class="fas fa-question-circle debug-icon" onclick="showDebugInfo(${player.pdgaNumber})" title="Show calculation details" style="margin-left: 5px; color: #6c757d; cursor: pointer; opacity: 0.6;"></i>
|
<i class="fas fa-question-circle debug-icon" onclick="showDebugInfo(${player.pdgaNumber})" title="Show calculation details" style="margin-left: 5px; color: #6c757d; cursor: pointer; opacity: 0.6;"></i>
|
||||||
<i class="fas fa-sync-alt refresh-icon" onclick="refreshRoundHistory(${player.pdgaNumber})" title="Refresh prediction data"></i>
|
<i class="fas fa-sync-alt refresh-icon" onclick="refreshRoundHistory(${player.pdgaNumber})" title="Refresh prediction data"></i>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="std-dev-tooltip" id="tooltip-stddev-${player.pdgaNumber}"></div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr id="history-${player.pdgaNumber}" class="expanded-content">
|
<tr id="history-${player.pdgaNumber}" class="expanded-content">
|
||||||
@@ -619,6 +640,60 @@
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
tableDiv.innerHTML = tableHTML;
|
tableDiv.innerHTML = tableHTML;
|
||||||
|
|
||||||
|
// Add hover listeners for predicted rating standard deviation tooltips
|
||||||
|
document.querySelectorAll('.predicted-value').forEach(span => {
|
||||||
|
const pdgaNumber = span.dataset.pdga;
|
||||||
|
const stdDev = span.dataset.stddev;
|
||||||
|
const tooltip = document.getElementById(`tooltip-stddev-${pdgaNumber}`);
|
||||||
|
|
||||||
|
if (stdDev && tooltip) {
|
||||||
|
span.addEventListener('mouseenter', (e) => {
|
||||||
|
tooltip.textContent = `Standard Deviation: ±${stdDev}`;
|
||||||
|
tooltip.style.display = 'block';
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
span.addEventListener('mousemove', (e) => {
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
span.addEventListener('mouseleave', () => {
|
||||||
|
tooltip.style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add hover listeners for current rating range tooltips
|
||||||
|
document.querySelectorAll('.rating-value').forEach(span => {
|
||||||
|
const pdgaNumber = span.dataset.pdga;
|
||||||
|
const rating = parseInt(span.dataset.rating);
|
||||||
|
const stdDev = parseInt(span.dataset.stddev);
|
||||||
|
const tooltip = document.getElementById(`tooltip-rating-${pdgaNumber}`);
|
||||||
|
|
||||||
|
if (rating && stdDev && tooltip) {
|
||||||
|
const minRating = rating - stdDev;
|
||||||
|
const maxRating = rating + stdDev;
|
||||||
|
|
||||||
|
span.addEventListener('mouseenter', (e) => {
|
||||||
|
tooltip.textContent = `Rating Range: ${minRating} - ${maxRating} (±${stdDev})`;
|
||||||
|
tooltip.style.display = 'block';
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
span.addEventListener('mousemove', (e) => {
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
span.addEventListener('mouseleave', () => {
|
||||||
|
tooltip.style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -846,8 +921,45 @@
|
|||||||
const ratingChangeClass = data.player.ratingChange > 0 ? 'positive' :
|
const ratingChangeClass = data.player.ratingChange > 0 ? 'positive' :
|
||||||
data.player.ratingChange < 0 ? 'negative' : 'neutral';
|
data.player.ratingChange < 0 ? 'negative' : 'neutral';
|
||||||
|
|
||||||
const refreshSection = ratingCell.querySelector('.refresh-section');
|
// Update rating value
|
||||||
refreshSection.innerHTML = `${data.player.rating || 'N/A'} <i class="fas fa-sync-alt refresh-icon" onclick="refreshPlayer(${pdgaNumber})" title="Refresh player data"></i>`;
|
const ratingValue = ratingCell.querySelector('.rating-value');
|
||||||
|
if (ratingValue) {
|
||||||
|
ratingValue.textContent = data.player.rating || 'N/A';
|
||||||
|
ratingValue.dataset.rating = data.player.rating || '';
|
||||||
|
// stdDev stays the same - only updates with predicted rating refresh
|
||||||
|
|
||||||
|
// Re-attach tooltip listeners if we have both rating and stdDev
|
||||||
|
const stdDev = parseInt(ratingValue.dataset.stddev);
|
||||||
|
const rating = parseInt(data.player.rating);
|
||||||
|
const tooltip = document.getElementById(`tooltip-rating-${pdgaNumber}`);
|
||||||
|
|
||||||
|
if (rating && stdDev && tooltip) {
|
||||||
|
// Remove old listeners by cloning and replacing
|
||||||
|
const newRatingValue = ratingValue.cloneNode(true);
|
||||||
|
ratingValue.parentNode.replaceChild(newRatingValue, ratingValue);
|
||||||
|
|
||||||
|
const minRating = rating - stdDev;
|
||||||
|
const maxRating = rating + stdDev;
|
||||||
|
|
||||||
|
// Add new listeners
|
||||||
|
newRatingValue.addEventListener('mouseenter', (e) => {
|
||||||
|
tooltip.textContent = `Rating Range: ${minRating} - ${maxRating} (±${stdDev})`;
|
||||||
|
tooltip.style.display = 'block';
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
newRatingValue.addEventListener('mousemove', (e) => {
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
newRatingValue.addEventListener('mouseleave', () => {
|
||||||
|
tooltip.style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ratingChangeCell) ratingChangeCell.textContent = ratingChangeText;
|
if (ratingChangeCell) ratingChangeCell.textContent = ratingChangeText;
|
||||||
if (ratingChangeCell) ratingChangeCell.className = `rating-change ${ratingChangeClass} mobile-hide`;
|
if (ratingChangeCell) ratingChangeCell.className = `rating-change ${ratingChangeClass} mobile-hide`;
|
||||||
|
|
||||||
@@ -891,9 +1003,75 @@
|
|||||||
// Update predicted rating if the element exists
|
// Update predicted rating if the element exists
|
||||||
const predictedCell = document.getElementById(`predicted-${pdgaNumber}`);
|
const predictedCell = document.getElementById(`predicted-${pdgaNumber}`);
|
||||||
if (predictedCell) {
|
if (predictedCell) {
|
||||||
const refreshSection = predictedCell.querySelector('.refresh-section');
|
const predictedValue = predictedCell.querySelector('.predicted-value');
|
||||||
if (refreshSection && refreshSection.firstChild) {
|
if (predictedValue) {
|
||||||
refreshSection.firstChild.textContent = data.predictedRating || 'N/A';
|
predictedValue.textContent = data.predictedRating || 'N/A';
|
||||||
|
// Update data attribute for tooltip
|
||||||
|
predictedValue.dataset.stddev = data.stdDev || '';
|
||||||
|
|
||||||
|
// Re-attach tooltip listeners
|
||||||
|
const tooltip = document.getElementById(`tooltip-stddev-${pdgaNumber}`);
|
||||||
|
if (data.stdDev && tooltip) {
|
||||||
|
// Remove old listeners by cloning and replacing
|
||||||
|
const newPredictedValue = predictedValue.cloneNode(true);
|
||||||
|
predictedValue.parentNode.replaceChild(newPredictedValue, predictedValue);
|
||||||
|
|
||||||
|
// Add new listeners
|
||||||
|
newPredictedValue.addEventListener('mouseenter', (e) => {
|
||||||
|
tooltip.textContent = `Standard Deviation: ±${data.stdDev}`;
|
||||||
|
tooltip.style.display = 'block';
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
newPredictedValue.addEventListener('mousemove', (e) => {
|
||||||
|
tooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
tooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
newPredictedValue.addEventListener('mouseleave', () => {
|
||||||
|
tooltip.style.display = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also update the rating value's stddev attribute and tooltip
|
||||||
|
const row = document.getElementById(`row-${pdgaNumber}`);
|
||||||
|
const ratingCell = row.querySelector('.rating');
|
||||||
|
const ratingValue = ratingCell.querySelector('.rating-value');
|
||||||
|
if (ratingValue && data.stdDev) {
|
||||||
|
ratingValue.dataset.stddev = data.stdDev;
|
||||||
|
|
||||||
|
// Re-attach rating tooltip listeners if we have both rating and stdDev
|
||||||
|
const rating = parseInt(ratingValue.dataset.rating);
|
||||||
|
const stdDev = parseInt(data.stdDev);
|
||||||
|
const ratingTooltip = document.getElementById(`tooltip-rating-${pdgaNumber}`);
|
||||||
|
|
||||||
|
if (rating && stdDev && ratingTooltip) {
|
||||||
|
// Remove old listeners by cloning and replacing
|
||||||
|
const newRatingValue = ratingValue.cloneNode(true);
|
||||||
|
ratingValue.parentNode.replaceChild(newRatingValue, ratingValue);
|
||||||
|
|
||||||
|
const minRating = rating - stdDev;
|
||||||
|
const maxRating = rating + stdDev;
|
||||||
|
|
||||||
|
// Add new listeners
|
||||||
|
newRatingValue.addEventListener('mouseenter', (e) => {
|
||||||
|
ratingTooltip.textContent = `Rating Range: ${minRating} - ${maxRating} (±${stdDev})`;
|
||||||
|
ratingTooltip.style.display = 'block';
|
||||||
|
ratingTooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
ratingTooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
newRatingValue.addEventListener('mousemove', (e) => {
|
||||||
|
ratingTooltip.style.left = `${e.clientX + 15}px`;
|
||||||
|
ratingTooltip.style.top = `${e.clientY - 35}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
newRatingValue.addEventListener('mouseleave', () => {
|
||||||
|
ratingTooltip.style.display = 'none';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ function initializeDatabase() {
|
|||||||
|
|
||||||
const hasLastRoundUpdate = columns.some(col => col.name === 'last_round_update');
|
const hasLastRoundUpdate = columns.some(col => col.name === 'last_round_update');
|
||||||
const hasPredictedRating = columns.some(col => col.name === 'predicted_rating');
|
const hasPredictedRating = columns.some(col => col.name === 'predicted_rating');
|
||||||
|
const hasStdDev = columns.some(col => col.name === 'std_dev');
|
||||||
|
|
||||||
if (!hasLastRoundUpdate) {
|
if (!hasLastRoundUpdate) {
|
||||||
console.log('Adding last_round_update column to players table...');
|
console.log('Adding last_round_update column to players table...');
|
||||||
@@ -80,6 +81,19 @@ function initializeDatabase() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasStdDev) {
|
||||||
|
console.log('Adding std_dev column to players table...');
|
||||||
|
db.run(`
|
||||||
|
ALTER TABLE players ADD COLUMN std_dev INTEGER DEFAULT NULL
|
||||||
|
`, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Error adding std_dev column:', err.message);
|
||||||
|
} else {
|
||||||
|
console.log('Successfully added std_dev column');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -533,8 +547,12 @@ async function getPlayerDataFromDB(pdgaNumber) {
|
|||||||
|
|
||||||
// Use stored predicted_rating if available, otherwise calculate it from round history
|
// Use stored predicted_rating if available, otherwise calculate it from round history
|
||||||
let predictedRating = cachedPlayer.predicted_rating;
|
let predictedRating = cachedPlayer.predicted_rating;
|
||||||
|
let stdDev = cachedPlayer.std_dev;
|
||||||
if (!predictedRating || predictedRating === 0) {
|
if (!predictedRating || predictedRating === 0) {
|
||||||
predictedRating = await getPredictedRatingFromDB(pdgaNumber);
|
predictedRating = await getPredictedRatingFromDB(pdgaNumber);
|
||||||
|
// After calculation, re-fetch to get the updated std_dev
|
||||||
|
const updatedPlayer = await getPlayerFromDB(pdgaNumber);
|
||||||
|
stdDev = updatedPlayer?.std_dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -542,7 +560,8 @@ async function getPlayerDataFromDB(pdgaNumber) {
|
|||||||
name: cachedPlayer.name,
|
name: cachedPlayer.name,
|
||||||
rating: cachedPlayer.current_rating,
|
rating: cachedPlayer.current_rating,
|
||||||
ratingChange: cachedPlayer.rating_change,
|
ratingChange: cachedPlayer.rating_change,
|
||||||
predictedRating: predictedRating > 0 ? predictedRating : null
|
predictedRating: predictedRating > 0 ? predictedRating : null,
|
||||||
|
stdDev: stdDev > 0 ? stdDev : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return null; // No data in DB
|
return null; // No data in DB
|
||||||
@@ -653,7 +672,7 @@ async function getPredictedRatingFromDB(pdgaNumber) {
|
|||||||
const result = calculatePredictedRating(roundRatings);
|
const result = calculatePredictedRating(roundRatings);
|
||||||
|
|
||||||
// Save the calculated prediction to database
|
// Save the calculated prediction to database
|
||||||
await savePredictedRatingToDB(pdgaNumber, result.rating);
|
await savePredictedRatingToDB(pdgaNumber, result.rating, result.stdDev);
|
||||||
|
|
||||||
return result.rating;
|
return result.rating;
|
||||||
}
|
}
|
||||||
@@ -664,11 +683,11 @@ async function getPredictedRatingFromDB(pdgaNumber) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function savePredictedRatingToDB(pdgaNumber, predictedRating) {
|
function savePredictedRatingToDB(pdgaNumber, predictedRating, stdDev = null) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
db.run(
|
db.run(
|
||||||
'UPDATE players SET predicted_rating = ? WHERE pdga_number = ?',
|
'UPDATE players SET predicted_rating = ?, std_dev = ? WHERE pdga_number = ?',
|
||||||
[predictedRating, pdgaNumber],
|
[predictedRating, stdDev, pdgaNumber],
|
||||||
function(err) {
|
function(err) {
|
||||||
if (err) reject(err);
|
if (err) reject(err);
|
||||||
else resolve();
|
else resolve();
|
||||||
@@ -1484,14 +1503,18 @@ function calculatePredictedRating(roundRatings) {
|
|||||||
const average = sum / weightedRatings.length;
|
const average = sum / weightedRatings.length;
|
||||||
const finalRating = Math.round(average);
|
const finalRating = Math.round(average);
|
||||||
|
|
||||||
|
// Calculate standard deviation of the weighted ratings
|
||||||
|
const stdDev = calculateStandardDeviation(weightedRatings);
|
||||||
|
|
||||||
debugLog.push('🎯 FINAL CALCULATION:');
|
debugLog.push('🎯 FINAL CALCULATION:');
|
||||||
debugLog.push(` Sum: ${sum}`);
|
debugLog.push(` Sum: ${sum}`);
|
||||||
debugLog.push(` Count: ${weightedRatings.length}`);
|
debugLog.push(` Count: ${weightedRatings.length}`);
|
||||||
debugLog.push(` Average: ${average.toFixed(1)}`);
|
debugLog.push(` Average: ${average.toFixed(1)}`);
|
||||||
|
debugLog.push(` Standard Deviation: ${stdDev.toFixed(1)}`);
|
||||||
debugLog.push(` Final Rating: ${finalRating}`);
|
debugLog.push(` Final Rating: ${finalRating}`);
|
||||||
debugLog.push('=== END PDGA CALCULATION ===');
|
debugLog.push('=== END PDGA CALCULATION ===');
|
||||||
|
|
||||||
return { rating: finalRating, debugLog };
|
return { rating: finalRating, stdDev: Math.round(stdDev), debugLog };
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateStandardDeviation(ratings) {
|
function calculateStandardDeviation(ratings) {
|
||||||
@@ -2773,7 +2796,7 @@ app.post('/api/refresh-round-history/:pdgaNumber', async (req, res) => {
|
|||||||
const result = calculatePredictedRating(roundsForPrediction);
|
const result = calculatePredictedRating(roundsForPrediction);
|
||||||
|
|
||||||
// Save the predicted rating to database for persistence
|
// Save the predicted rating to database for persistence
|
||||||
await savePredictedRatingToDB(pdgaNumber, result.rating);
|
await savePredictedRatingToDB(pdgaNumber, result.rating, result.stdDev);
|
||||||
|
|
||||||
// Count official vs new rounds
|
// Count official vs new rounds
|
||||||
const officialCount = allRounds.filter(r => r.source === 'official').length;
|
const officialCount = allRounds.filter(r => r.source === 'official').length;
|
||||||
@@ -2782,6 +2805,7 @@ app.post('/api/refresh-round-history/:pdgaNumber', async (req, res) => {
|
|||||||
res.json({
|
res.json({
|
||||||
success: true,
|
success: true,
|
||||||
predictedRating: result.rating,
|
predictedRating: result.rating,
|
||||||
|
stdDev: result.stdDev,
|
||||||
debugLog: result.debugLog,
|
debugLog: result.debugLog,
|
||||||
totalRounds: roundsForPrediction.length,
|
totalRounds: roundsForPrediction.length,
|
||||||
officialRounds: officialCount,
|
officialRounds: officialCount,
|
||||||
@@ -3323,6 +3347,7 @@ app.post('/api/predicted-rating/:pdgaNumber', async (req, res) => {
|
|||||||
res.json({
|
res.json({
|
||||||
pdgaNumber: parseInt(pdgaNumber),
|
pdgaNumber: parseInt(pdgaNumber),
|
||||||
predictedRating: result.rating,
|
predictedRating: result.rating,
|
||||||
|
stdDev: result.stdDev,
|
||||||
debugLog: result.debugLog
|
debugLog: result.debugLog
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user