mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-07-21 20:31:21 +00:00
Merge pull request #930 from got-feedBack/fix/accuracy-floor-not-round
Some checks are pending
ship-ci / ci (push) Waiting to run
Some checks are pending
ship-ci / ci (push) Waiting to run
fix(v3): floor accuracy percentages so 100% means all notes hit
This commit is contained in:
commit
d364529919
@ -33,7 +33,8 @@
|
||||
// Accuracy badge ramp (design/04-badges.md §C): ≥90% good, 50–89% mid, <50% low.
|
||||
function accuracyBadge(acc) {
|
||||
if (acc == null) return '';
|
||||
const pct = Math.round(acc * 100);
|
||||
// Floor, never round: 100% must mean every note hit.
|
||||
const pct = Math.floor(acc * 100);
|
||||
const color = acc >= 0.9 ? 'bg-fb-good' : (acc >= 0.5 ? 'bg-fb-mid' : 'bg-fb-low');
|
||||
const text = acc >= 0.5 && acc < 0.9 ? 'text-black' : 'text-white';
|
||||
return '<span class="absolute bottom-0 right-0 ' + color + '/90 ' + text +
|
||||
|
||||
@ -74,7 +74,7 @@
|
||||
if (st && st.passed) return '<span class="text-fb-good text-xs font-bold flex items-center gap-1">✓ Passed</span>';
|
||||
if (st && st.best_accuracy != null && st.best_accuracy > 0) {
|
||||
const acc = st.best_accuracy;
|
||||
const pct = Math.round(acc * 100);
|
||||
const pct = Math.floor(acc * 100);
|
||||
const color = acc >= 0.9 ? 'text-fb-good' : (acc >= 0.5 ? 'text-fb-mid' : 'text-fb-low');
|
||||
return '<span class="' + color + ' text-xs font-bold">' + pct + '%</span>';
|
||||
}
|
||||
|
||||
@ -21,7 +21,8 @@
|
||||
function accuracyPct(hits, misses) {
|
||||
const judged = hits + misses;
|
||||
if (judged <= 0) return null;
|
||||
return Math.round((hits / Math.max(1, judged)) * 100);
|
||||
// Floor, never round: 100% must mean every judged note was hit.
|
||||
return Math.floor((hits / Math.max(1, judged)) * 100);
|
||||
}
|
||||
|
||||
function calculateLivePerformanceState({ hits = 0, misses = 0, streak = 0, bestStreak = 0 } = {}) {
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
? ' data-play-fn="' + esc(playFn) + '"' + (arrIdx != null ? ' data-play-arr="' + arrIdx + '"' : '')
|
||||
: '';
|
||||
const acc = (isAlbum && typeof opts.acc === 'number')
|
||||
? '<span class="text-xs font-bold shrink-0 ' + (opts.acc >= 0.9 ? 'text-fb-good' : opts.acc >= 0.5 ? 'text-fb-mid' : 'text-fb-low') + '">' + Math.round(opts.acc * 100) + '%</span>'
|
||||
? '<span class="text-xs font-bold shrink-0 ' + (opts.acc >= 0.9 ? 'text-fb-good' : opts.acc >= 0.5 ? 'text-fb-mid' : 'text-fb-low') + '">' + Math.floor(opts.acc * 100) + '%</span>'
|
||||
: '';
|
||||
const pin = (isAlbum && s.arrangement)
|
||||
? '<span class="ml-2 text-[0.625rem] bg-fb-primary/20 text-fb-primary font-bold px-1.5 py-0.5 rounded-sm" title="Pinned arrangement">' + esc(s.arrangement) + '</span>' : '';
|
||||
|
||||
@ -232,7 +232,7 @@
|
||||
host.innerHTML =
|
||||
'<ol class="space-y-2">' + rows.map((s, i) => {
|
||||
const acc = Number(s.best_accuracy) || 0;
|
||||
const pct = Math.round(acc * 100);
|
||||
const pct = Math.floor(acc * 100);
|
||||
const score = Number(s.best_score) || 0;
|
||||
return '<li data-fn="' + esc(s.filename) + '" class="flex items-center gap-3 cursor-pointer rounded-md px-2 py-1.5 hover:bg-fb-card transition">' +
|
||||
'<span class="w-5 text-center text-fb-textDim font-semibold shrink-0">' + (i + 1) + '</span>' +
|
||||
|
||||
@ -265,7 +265,7 @@
|
||||
const onboarding = st.onboarding || {};
|
||||
if (onboarding.calibration_status === 'completed') return; // raced a 100% run
|
||||
const pending = onboarding.calibration_status === 'pending';
|
||||
const pct = Math.max(0, Math.min(100, Math.round((detail.accuracy || 0) * 100)));
|
||||
const pct = Math.max(0, Math.min(100, Math.floor((detail.accuracy || 0) * 100)));
|
||||
|
||||
const overlay = document.createElement('div');
|
||||
overlay.id = 'v3-calibration-retry';
|
||||
|
||||
@ -482,7 +482,8 @@
|
||||
function accuracyBadge(filename, variant) {
|
||||
const acc = state.accuracy[filename];
|
||||
if (acc == null) return '';
|
||||
const pct = Math.round(acc * 100);
|
||||
// Floor, never round: 100% must mean every note hit.
|
||||
const pct = Math.floor(acc * 100);
|
||||
if (variant === 'tree') {
|
||||
const color = acc >= MASTERY_ACCURACY ? 'text-fb-good' : acc >= 0.5 ? 'text-fb-mid' : 'text-fb-low';
|
||||
return '<span class="fb-acc-badge text-xs font-bold ' + color + '">' + pct + '%</span>';
|
||||
@ -1312,7 +1313,7 @@
|
||||
c.year ? String(c.year) : '']
|
||||
.filter(Boolean).join(' · ');
|
||||
const acc = (typeof c.best_accuracy === 'number')
|
||||
? '<span class="font-bold ' + (c.best_accuracy >= MASTERY_ACCURACY ? 'text-fb-good' : c.best_accuracy >= 0.5 ? 'text-fb-mid' : 'text-fb-low') + '">' + Math.round(c.best_accuracy * 100) + '%</span>'
|
||||
? '<span class="font-bold ' + (c.best_accuracy >= MASTERY_ACCURACY ? 'text-fb-good' : c.best_accuracy >= 0.5 ? 'text-fb-mid' : 'text-fb-low') + '">' + Math.floor(c.best_accuracy * 100) + '%</span>'
|
||||
: '<span class="text-fb-textDim/60">not played</span>';
|
||||
return '<div role="radio" aria-checked="' + (checked ? 'true' : 'false') + '" tabindex="0" data-ch="' + esc(c.filename) + '"' +
|
||||
' title="' + (checked ? esc(prefLabel) : 'Make this the preferred chart') + '"' +
|
||||
|
||||
@ -170,7 +170,8 @@ test('DOM text updates after hit and miss events', () => {
|
||||
runtime.onHit();
|
||||
runtime.onMiss();
|
||||
|
||||
assert.equal(els.percent.textContent, '67%');
|
||||
// Floored, not rounded: 100% must mean every judged note was hit.
|
||||
assert.equal(els.percent.textContent, '66%');
|
||||
assert.equal(els.hits.textContent, 'Hits 2 / 3');
|
||||
assert.equal(els.streak.textContent, 'Streak 0');
|
||||
assert.match(els.state.textContent, /Recovering/);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user