diff --git a/server/routes/games.ts b/server/routes/games.ts index 258186e..d3c456f 100755 --- a/server/routes/games.ts +++ b/server/routes/games.ts @@ -60,7 +60,12 @@ const processTies = (players: Player[]): boolean => { /* Sort the players into buckets based on their * order, and their current roll. If a resulting * roll array has more than one element, then there - * is a tie that must be resolved */ + * is a tie that must be resolved. To ensure that + * earlier rolls remain more significant across + * subsequent tie-break rounds, we pad singleton + * players' numeric `order` when ties are detected so + * their earlier digits don't get outranked by extra + * digits appended to tied players. */ let slots: Player[][] = []; players.forEach((player: Player) => { if (!slots[player.order]) { @@ -87,6 +92,37 @@ const processTies = (players: Player[]): boolean => { } }; + // First detect whether any ties exist at all. If so, we need to pad + // singleton players' `order` values (multiply by 6) so that their + // existing rolls remain more significant than any additional digits + // that will be appended by tied players when they re-roll. + for (const slot of slots) { + if (slot && slot.length > 1) { + ties = true; + break; + } + } + + if (ties) { + // Pad singleton players by shifting their order a digit left in base-6 + players.forEach((player: Player) => { + const slot = slots[player.order]; + if (slot && slot.length === 1) { + player.order = (player.order || 0) * 6; + } + }); + + // Rebuild slots based on the newly padded orders so we can assign + // positions correctly below. + slots = []; + players.forEach((player: Player) => { + if (!slots[player.order]) { + slots[player.order] = []; + } + slots[player.order]!.push(player); + }); + } + /* Reverse from high to low */ const rev = slots.slice().reverse(); for (const slot of rev) {