fix: resolve 9 MC bugs in HumanFightPage and useHumanChallenge

- BUG-1: Prevent double-tap by locking phase before async submit
- BUG-2: Submit timeout notification to server when timer expires
- BUG-3: Distinct "TIME'S UP!" visual vs "ANSWER SUBMITTED"
- BUG-4: Track consecutive poll failures, show connection lost banner
- BUG-5: Add A-D / 1-4 keyboard shortcuts for MC choices
- BUG-6: Use choice text as v-for key instead of array index
- BUG-7: Deadline-based timer (250ms tick) prevents drift
- BUG-8: Validate choice is in current choices before submit
- BUG-9: Submit empty timeout instead of random choice on expiry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-09 08:39:27 +00:00
co-authored by Claude Opus 4.6
parent 9fdf7a6720
commit c7a1f6cb0b
2 changed files with 121 additions and 46 deletions
+18 -4
View File
@@ -48,10 +48,9 @@ export function useHumanChallenge(
if (humanTimer.value <= 0) {
if (timerHandle) clearInterval(timerHandle)
if (!humanSubmitted.value) {
if (humanChoices.value.length > 0 && !humanAnswer.value.trim()) {
humanAnswer.value = humanChoices.value[Math.floor(Math.random() * humanChoices.value.length)]
}
void submitHumanAnswer()
// BUG-9: Submit empty timeout instead of random choice
humanSubmitted.value = true
void submitTimeout()
}
}
}, 1000)
@@ -76,10 +75,25 @@ export function useHumanChallenge(
}
function submitChoice(choice: string) {
if (humanSubmitted.value) return // Prevent double-tap
humanAnswer.value = choice
humanSubmitted.value = true // Lock immediately before async
void submitHumanAnswer()
}
async function submitTimeout() {
if (!myBotId.value || !humanChallenge.value) return
try {
await fetch(`/api/fights/${fightId.value}/respond/${myBotId.value}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ answer: '', timeout: true }),
})
} catch {
// Server will time out on its own
}
}
async function pollForChallenge() {
if (!myBotId.value) return
try {