Generate bracket reset

This commit is contained in:
Kalle (Sendou)
2021-12-17 18:57:51 +02:00
parent 02af571113
commit 2332456ef2
4 changed files with 57 additions and 23 deletions

View File

@@ -1,9 +1,10 @@
import { suite } from "uvu";
import * as assert from "uvu/assert";
import type { Match, TeamIdentifier } from "./bracket";
import {
eliminationBracket,
fillParticipantsWithNullTillPowerOfTwo,
Match,
TeamIdentifier,
} from "./algorithms";
const AmountOfTeams = suite("Amount of teams");
@@ -21,29 +22,29 @@ AmountOfTeams("Generates right amount of rounds (16 participants - SE)", () => {
AmountOfTeams("Generates right amount of rounds (16 participants - DE)", () => {
const bracket16 = eliminationBracket(16, "DE");
assert.equal(removeMatchesWithByes(bracket16.winners).length, 16); // not incl reset
assert.equal(removeMatchesWithByes(bracket16.winners).length, 17);
assert.equal(removeMatchesWithByes(bracket16.losers).length, 14);
});
AmountOfTeams("Generates right amount of rounds (15 participants - DE)", () => {
const bracket15 = eliminationBracket(15, "DE");
assert.equal(removeMatchesWithByes(bracket15.winners).length, 15); // not incl reset
assert.equal(removeMatchesWithByes(bracket15.winners).length, 16);
assert.equal(removeMatchesWithByes(bracket15.losers).length, 14); // one bye
});
AmountOfTeams("Generates right amount of rounds (17 participants - DE)", () => {
const bracket17 = eliminationBracket(17, "DE");
assert.equal(removeMatchesWithByes(bracket17.winners).length, 17); // not incl reset
assert.equal(removeMatchesWithByes(bracket17.winners).length, 18);
assert.equal(removeMatchesWithByes(bracket17.losers).length, 30);
assert.equal(removeMatchesWithByes(bracket17.winners).length, 17); // not incl reset
assert.equal(removeMatchesWithByes(bracket17.winners).length, 18);
assert.equal(removeMatchesWithByes(bracket17.losers).length, 30);
});
AmountOfTeams("Same amount of rounds as next power of two", () => {
const bracket17 = eliminationBracket(17, "DE");
const bracket32 = eliminationBracket(32, "DE");
assert.equal(bracket17.winners.length, bracket32.winners.length); // not incl reset
assert.equal(bracket17.winners.length, bracket32.winners.length);
assert.equal(bracket17.losers.length, bracket32.losers.length);
});

View File

@@ -132,13 +132,18 @@ export function eliminationBracket(
invariant(match1, "Unexpected no match1 in final match");
invariant(match2, "Unexpected no match2 in final match");
// Add final match
bracket.winners.push(
createMatch({
match1,
match2,
})
);
// Add final match and bracket reset
const grandFinals = createMatch({
match1,
match2,
});
bracket.winners.push(grandFinals);
const bracketReset = createMatch({
match1: grandFinals,
match2: grandFinals,
});
bracket.winners.push(bracketReset);
return bracket;
}

View File

@@ -1,29 +1,48 @@
import { suite } from "uvu";
import * as assert from "uvu/assert";
import { eliminationBracket } from "./algorithms";
import { countRounds } from "./bracket";
import { countRounds, getRoundNames } from "./bracket";
const CountBracketRounds = suite("countRounds()");
const RoundNames = suite("getRoundNames()");
CountBracketRounds("Counts bracket (DE - 38)", () => {
const bracket = eliminationBracket(38, "DE");
const count = countRounds(bracket);
assert.equal(count, { winners: 7, losers: 9 });
assert.equal(count, { winners: 8, losers: 9 });
});
CountBracketRounds("Counts bracket (DE - 10)", () => {
const bracket = eliminationBracket(10, "DE");
const count = countRounds(bracket);
assert.equal(count, { winners: 5, losers: 5 });
assert.equal(count, { winners: 6, losers: 5 });
});
CountBracketRounds("Counts bracket (DE - 16)", () => {
const bracket = eliminationBracket(16, "DE");
const count = countRounds(bracket);
assert.equal(count, { winners: 5, losers: 6 });
assert.equal(count, { winners: 6, losers: 6 });
});
RoundNames("No bracket reset round for SE", () => {
const bracketSE = getRoundNames(eliminationBracket(16, "SE"));
const bracketDE = getRoundNames(eliminationBracket(16, "DE"));
let hasBR = false;
for (const round of bracketDE.winners) {
if (round === "Bracket Reset") hasBR = true;
}
assert.ok(hasBR);
hasBR = false;
for (const round of bracketSE.winners) {
if (round === "Bracket Reset") hasBR = true;
}
assert.not.ok(hasBR);
});
CountBracketRounds.run();
RoundNames.run();

View File

@@ -54,6 +54,7 @@ export function participantCountToRoundsInfo({
const WINNERS_DEFAULT = 5;
const WINNERS_FIRST_TWO_DEFAULT = 3;
const GRAND_FINALS_DEFAULT = 7;
const GRAND_FINALS_RESET_DEFAULT = 7;
const LOSERS_DEFAULT = 3;
const LOSERS_FINALS_DEFAULT = 5;
@@ -67,9 +68,13 @@ export function getRoundsDefaultBestOf(
return {
winners: new Array(winnersRoundCount).fill(null).map((_, i) => {
const isSE = losersRoundCount === 0;
if (i === 0) return WINNERS_FIRST_TWO_DEFAULT;
if (i === 1) return WINNERS_FIRST_TWO_DEFAULT;
if (i === winnersRoundCount - 1) return GRAND_FINALS_DEFAULT;
if (i === winnersRoundCount - 2 + Number(isSE)) {
return GRAND_FINALS_DEFAULT;
}
if (i === winnersRoundCount - 1) return GRAND_FINALS_RESET_DEFAULT;
return WINNERS_DEFAULT;
}),
losers: new Array(losersRoundCount)
@@ -80,15 +85,19 @@ export function getRoundsDefaultBestOf(
};
}
function getRoundNames(bracket: Bracket): EliminationBracket<string[]> {
export function getRoundNames(bracket: Bracket): EliminationBracket<string[]> {
const { winners: winnersRoundCount, losers: losersRoundCount } =
countRounds(bracket);
return {
winners: new Array(winnersRoundCount).fill(null).map((_, i) => {
if (i === winnersRoundCount - 3) return "Winners' Semifinals";
if (i === winnersRoundCount - 2) return "Winners' Finals";
if (i === winnersRoundCount - 1) return "Grand Finals";
const isSE = bracket.losers.length === 0;
if (i === winnersRoundCount - 4 + Number(isSE)) {
return "Winners' Semifinals";
}
if (i === winnersRoundCount - 3 + Number(isSE)) return "Winners' Finals";
if (i === winnersRoundCount - 2 + Number(isSE)) return "Grand Finals";
if (!isSE && i === winnersRoundCount - 1) return "Bracket Reset";
return `Winners' Round ${i + 1}`;
}),
losers: new Array(losersRoundCount)
@@ -100,7 +109,7 @@ function getRoundNames(bracket: Bracket): EliminationBracket<string[]> {
}
export function countRounds(bracket: Bracket): EliminationBracket<number> {
let winners = 1;
let winners = 2;
for (let i = bracket.participantsWithByesCount; i > 1; i /= 2) {
winners++;