mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-07 21:56:33 -05:00
Fix Swiss algorithm not always finding the correct team to give bye to
This commit is contained in:
parent
d0654a3201
commit
5adf4be0eb
|
|
@ -358,6 +358,24 @@ describe("Swiss", () => {
|
|||
|
||||
expect(includesPair(result, 1, 2)).toBe(false);
|
||||
});
|
||||
|
||||
it("prefers giving the bye to the lowest standing team without a previous bye", () => {
|
||||
// five team swiss entering round 4: teams 3, 4 and 5 have already had a
|
||||
// bye, team 3 in the round right before this one. Teams 1 and 2 have not,
|
||||
// and a rematch free pairing where team 2 (the lowest standing team
|
||||
// without a previous bye) gets the bye exists: 1-4, 3-5
|
||||
const result = Swiss.pairUp([
|
||||
{ id: 1, score: 3, avoid: [3, 5, 2] },
|
||||
{ id: 2, score: 2, avoid: [4, 3, 1] },
|
||||
{ id: 4, score: 2, avoid: [2, 5], receivedBye: true },
|
||||
{ id: 3, score: 1, avoid: [1, 2], receivedBye: true },
|
||||
{ id: 5, score: 1, avoid: [1, 4], receivedBye: true },
|
||||
]);
|
||||
|
||||
const bye = result.find((match) => match.opponentTwo === null);
|
||||
|
||||
expect(bye?.opponentOne).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("calculateTeamStatus()", () => {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,16 @@ import { calculateTeamStatus } from "./team-status";
|
|||
*/
|
||||
const REMATCH_PENALTY = 1_000_000;
|
||||
|
||||
/**
|
||||
* Weight added for each team of a pair that has already received a bye, making
|
||||
* previously-byed teams more attractive to pair up. Applied per team (not per pair)
|
||||
* so that a matching leaving a bye-less team unpaired always beats one giving a team
|
||||
* a second bye: with an odd team count exactly one team is left unpaired, so the
|
||||
* matchings differ by exactly one bonus, which is set to dwarf every score-based
|
||||
* weight while staying far below REMATCH_PENALTY.
|
||||
*/
|
||||
const PRIOR_BYE_PAIRING_BONUS = 10_000;
|
||||
|
||||
interface GroupArgs {
|
||||
groupId: number;
|
||||
standings: SwissStanding[];
|
||||
|
|
@ -285,11 +295,11 @@ function generateWeightedPairs({
|
|||
wt -= 10;
|
||||
}
|
||||
|
||||
if (
|
||||
(Object.hasOwn(curr, "receivedBye") && curr.receivedBye) ||
|
||||
(Object.hasOwn(opp, "receivedBye") && opp.receivedBye)
|
||||
) {
|
||||
wt += 40;
|
||||
if (curr.receivedBye) {
|
||||
wt += PRIOR_BYE_PAIRING_BONUS;
|
||||
}
|
||||
if (opp.receivedBye) {
|
||||
wt += PRIOR_BYE_PAIRING_BONUS;
|
||||
}
|
||||
|
||||
wt -= timesPlayed(curr, opp) * REMATCH_PENALTY;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user