fix(ui): unify tie-for-lead result across lobby + game (shared victory, not a draw)
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Has been skipped
CI / integration (pull_request) Has been skipped
CI / ui (pull_request) Successful in 1m7s
CI / conformance (pull_request) Successful in 9s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m41s

Bring the online lobby badge and the in-game 'you won/lost' text to the
same competition ranking the hotseat seat medals use: in a 3-4 player game
a TIE for the lead is a SHARED victory for the top scorers and a placed
finish for those below — not a full draw for everyone (winner() is -1 on
any tie, so isWinner alone conflated them). An aborted game and a genuine
all-level finish stay a draw; a win by resignation (winner at a not-higher
score) is unchanged.
- result.ts: resultBadge no-winner branch ranks by final score; placeBadge
  helper; resigned seats excluded from the ranking.
- Game.svelte: resultText aligned (shared lead = won, below = lost).
This commit is contained in:
Ilia Denisov
2026-07-07 15:47:34 +02:00
parent 1e087be90a
commit 80cc2a76e8
3 changed files with 45 additions and 10 deletions
+9 -1
View File
@@ -1107,7 +1107,15 @@
if (!view) return '';
const me = view.game.seats[view.seat];
if (me?.isWinner) return t('game.won');
return view.game.seats.some((s) => s.isWinner) ? t('game.lost') : t('game.tied');
if (view.game.endReason === 'aborted') return t('game.tied'); // an abort is a draw for everyone
const myScore = me?.score ?? 0;
// A declared winner (incl. by resignation) that is not me, or anyone who scored higher → a loss.
if (view.game.seats.some((s) => s.isWinner) || view.game.seats.some((s) => !s.resigned && s.score > myScore)) {
return t('game.lost');
}
// No one above me and no declared winner: a tie for the lead is a (shared) win; only an
// all-level finish is a draw.
return view.game.seats.filter((s) => !s.resigned).every((s) => s.score === myScore) ? t('game.tied') : t('game.won');
}
// The finished-game export offers two formats — the GCG file and the server-rendered PNG