mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-01 15:48:23 -05:00
Generate bracket reset
This commit is contained in:
@@ -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);
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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++;
|
||||
|
||||
Reference in New Issue
Block a user