feat: show sensitivity bracket around required average

After the binary search converges, also simulate predicted rating at
required±1 average. Display the three rows in the modal so the user can
see how sharp the requirement is — e.g. whether averaging 1 point lower
costs them 1 point of predicted rating or 5.
This commit is contained in:
Samuel Enocsson
2026-05-22 13:43:25 +02:00
parent 96edc606d3
commit e29bc8ee80
4 changed files with 61 additions and 2 deletions
+21
View File
@@ -360,3 +360,24 @@
gap: 12px;
align-items: flex-start;
}
.target-rating-result .sensitivity {
margin-top: 12px;
padding-top: 12px;
border-top: 1px dashed var(--border);
}
.target-rating-result .sensitivity-heading {
font-size: 0.9em;
color: var(--text-muted);
margin-bottom: 4px;
}
.target-rating-result .sensitivity-row {
font-variant-numeric: tabular-nums;
padding-left: 12px;
}
.target-rating-result .sensitivity-row.is-target {
font-weight: 600;
}
+28
View File
@@ -647,6 +647,10 @@ async function calculateTargetRating(event) {
mutedLine.textContent = 'Across ' + data.rounds + ' synthetic rounds before the next PDGA update.';
summary.appendChild(mutedLine);
if (data.sensitivity) {
renderSensitivity(data.sensitivity, summary);
}
if (data.warning) {
_targetResultMsg(summary, 'warning', data.warning);
}
@@ -666,6 +670,30 @@ function closeTargetRatingModal(event) {
document.getElementById('target-rating-modal').style.display = 'none';
}
function renderSensitivity(sensitivity, container) {
const wrapper = document.createElement('div');
wrapper.className = 'sensitivity';
const heading = document.createElement('div');
heading.className = 'sensitivity-heading';
heading.textContent = 'Sensitivity:';
wrapper.appendChild(heading);
const rows = [
{ row: sensitivity.lower, isTarget: false },
{ row: sensitivity.target, isTarget: true },
{ row: sensitivity.upper, isTarget: false }
];
for (const { row, isTarget } of rows) {
const line = document.createElement('div');
line.className = 'sensitivity-row' + (isTarget ? ' is-target' : '');
line.textContent = 'Average ' + row.average + ' → predicted ' + row.predicted + (isTarget ? ' (target)' : '');
wrapper.appendChild(line);
}
container.appendChild(wrapper);
}
function renderNoHistoryPrompt(pdgaNumber, container) {
const wrapper = document.createElement('div');
wrapper.className = 'no-history-prompt';