feat: ranked queue Elo-bracket matchmaking and harder prompts

Elo-bracket matchmaking: prefer ±200, widen by 100 every 15s of waiting.
Add pickRankedChallenge() that filters to creative/open-ended only, never
multiple choice. Show ranked queue status, wait estimate, and "HARDER
PROMPTS" notice on JoinBoutPage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-08 20:18:23 +00:00
co-authored by Claude Opus 4.6
parent e229bfb8fc
commit 156c727f82
3 changed files with 84 additions and 17 deletions
+28
View File
@@ -1011,6 +1011,34 @@ export function pickChallenge(usedTypes: Set<string>, _arenaModifier: string | n
return templateToChallenge(template)
}
/** Ranked challenge: no multiple choice, only harder creative/open-ended prompts */
export function pickRankedChallenge(usedTypes: Set<string>): Challenge {
let available = TEMPLATES.filter(t => !usedTypes.has(t.type))
if (available.length === 0) available = TEMPLATES
// Filter to creative-only (open-ended, harder) — no factual multiple choice
const creative = available.filter(t => t.scoring === 'creative')
const pool = creative.length > 0 ? creative : available
const template = pool[Math.floor(Math.random() * pool.length)]
// Pick a prompt that has no choices array (open-ended)
const openPrompts = template.prompts.filter(p => !p.choices)
const prompts = openPrompts.length > 0 ? openPrompts : template.prompts
const entry = prompts[Math.floor(Math.random() * prompts.length)]
return {
type: template.type,
label: template.label,
prompt: entry.prompt,
answers: entry.answers,
choices: undefined, // Never multiple choice in ranked
timeout_ms: template.timeout_ms,
scoring: template.scoring,
baseDamage: template.baseDamage,
}
}
function templateToChallenge(template: ChallengeTemplate): Challenge {
const entry = template.prompts[Math.floor(Math.random() * template.prompts.length)]