Skip to content

fix(race): make challenge-link races unrated (no Elo) - #304

Merged
C0derTang merged 1 commit into
mainfrom
issue/302-unrated-challenge-races
Jul 25, 2026
Merged

fix(race): make challenge-link races unrated (no Elo)#304
C0derTang merged 1 commit into
mainfrom
issue/302-unrated-challenge-races

Conversation

@C0derTang

Copy link
Copy Markdown
Owner

Closes #302

What changed

src/lib/race/finish.ts only:

  • Added const rated = race.challengeToken === null; read off the atomic claim's RETURNING row (right after the claim, before the Elo block).
  • Gated the Elo block: if (p2Id)if (rated && p2Id). Challenge-link races (challengeToken !== null) still finish (claim update runs, outcome/winner recorded, race_finished published), but skip the user load, applyResult, and the entire db.batch — no user Elo/racesPlayed updates, no elo_history inserts, no eloDeltaP1/eloDeltaP2 write. Deltas stay NULL in the DB; d1/d2 stay 0, so the publish carries eloDeltas: {p1: 0, p2: 0} (fine — clients treat the event as a refetch hint and read real, possibly-NULL, deltas from the snapshot; already null-safe per the issue).
  • Updated the file-header doc comment and the FinishRaceInput.outcome doc to state Elo only applies to rated races.
  • Did not touch the atomic claim / walkover logic. The readyWalkover claim requires non-null readyDeadlineAt (always matchmade ⇒ always rated, since matchmade races always have challengeToken === null), so it's unaffected — added a contrast test proving this.

How verified

  • pnpm exec eslint . — clean.
  • pnpm exec tsc --noEmit — clean.
  • pnpm exec vitest run — 997/997 tests passed across 85 files (full suite, not just this file).
  • tests/race-finish.test.ts: all pre-existing fixtures (makeRace() defaults challengeToken: null) pass unchanged (still rated). Added describe("finishRace — unrated challenge races (issue #302)") with:
    1. challengeToken: "abc123" + p1_win ⇒ finished (claim ran, outcome/winner set), zero db.batch calls, zero inserts, zero user selects, publish called exactly once with eloDeltas: {"user-p1": 0, "user-p2": 0}.
    2. Same shape for draw.
    3. Contrast test: challengeToken: null + readyDeadlineAt non-null (matchmade shape) still applies full Elo (batch of 4, 1 insert, 1 select) — pins that the discriminator is the token, not the deadline.

Notes for reviewers

  • racesPlayed is deliberately not incremented for unrated races (it drives provisional K-factor in src/lib/elo.ts and leaderboard inclusion in src/lib/leaderboard.ts) — this falls out naturally from skipping the whole batch, no separate logic needed.
  • No UI changes — out of scope per the issue; result screens (ResultCard.tsx:295, RaceEndOverlay.tsx:119) are already null-safe for missing deltas.
  • No schema changes.

Deviations

None from the issue spec.

finishRace now reads rated = race.challengeToken === null off the atomic
claim's RETURNING row and gates the Elo block on it. Challenge races still
finish and publish race_finished normally, but skip the user load,
applyResult, and the entire db.batch (Elo updates, racesPlayed increments,
elo_history inserts, eloDeltaP1/P2 write) -- deltas stay NULL in the DB.
Matchmade races are unaffected since they always have challengeToken null.

Closes #302

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cph2h Ready Ready Preview, Comment Jul 25, 2026 11:44pm

@C0derTang
C0derTang merged commit c7c9cdc into main Jul 25, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Challenge-link races must be unrated (no Elo)

1 participant