sendou.ink/app/features/tournament-bracket/core/rounds.ts
Kalle dd4f68158d
Linked third place match (#2133)
* Initial

* Done

* fix
2025-03-07 22:36:10 +02:00

118 lines
3.2 KiB
TypeScript

import type { TournamentManagerDataSet } from "~/modules/brackets-manager/types";
import { removeDuplicates } from "~/utils/arrays";
import { TOURNAMENT } from "../../tournament/tournament-constants";
export function getRounds(args: {
bracketData: TournamentManagerDataSet;
type: "winners" | "losers" | "single";
}) {
const groupIds = args.bracketData.group.flatMap((group) => {
if (args.type === "winners" && group.number === 2) return [];
if (args.type === "losers" && group.number !== 2) return [];
return group.id;
});
let showingBracketReset = args.bracketData.round.length > 1;
const rounds = args.bracketData.round
.flatMap((round) => {
if (
typeof round.group_id === "number" &&
!groupIds.includes(round.group_id)
) {
return [];
}
return round;
})
.filter((round, i, rounds) => {
const isBracketReset = args.type === "winners" && i === rounds.length - 1;
const grandFinalsMatch =
args.type === "winners"
? args.bracketData.match.find(
(match) => match.round_id === rounds[rounds.length - 2]?.id,
)
: undefined;
if (isBracketReset && grandFinalsMatch?.opponent1?.result === "win") {
showingBracketReset = false;
return false;
}
const matches = args.bracketData.match.filter(
(match) => match.round_id === round.id,
);
const atLeastOneNonByeMatch = matches.some(
(m) => m.opponent1 && m.opponent2,
);
return atLeastOneNonByeMatch;
});
const hasThirdPlaceMatch =
args.type === "single" &&
removeDuplicates(args.bracketData.match.map((m) => m.group_id)).length > 1;
const namedRounds = rounds.map((round, i) => {
const name = () => {
if (
showingBracketReset &&
args.type === "winners" &&
i === rounds.length - 2
) {
return TOURNAMENT.ROUND_NAMES.GRAND_FINALS;
}
if (hasThirdPlaceMatch && i === rounds.length - 2) {
return TOURNAMENT.ROUND_NAMES.FINALS;
}
if (hasThirdPlaceMatch && i === rounds.length - 1) {
return TOURNAMENT.ROUND_NAMES.THIRD_PLACE_MATCH;
}
if (args.type === "winners" && i === rounds.length - 1) {
return showingBracketReset
? TOURNAMENT.ROUND_NAMES.BRACKET_RESET
: TOURNAMENT.ROUND_NAMES.GRAND_FINALS;
}
const namePrefix =
args.type === "winners" ? "WB " : args.type === "losers" ? "LB " : "";
const finalsOffSet = () => {
if (args.type !== "winners") return 1;
if (showingBracketReset) return 3;
return 2;
};
const isFinals = i === rounds.length - finalsOffSet();
const semisOffSet = () => {
if (args.type !== "winners") return hasThirdPlaceMatch ? 3 : 2;
if (showingBracketReset) return 4;
return 3;
};
const isSemis = i === rounds.length - semisOffSet();
return `${namePrefix}${
isFinals ? "Finals" : isSemis ? "Semis" : `Round ${i + 1}`
}`;
};
return {
...round,
name: name(),
};
});
return adjustRoundNumbers(namedRounds);
}
// adjusting losers bracket round numbers to start from 1, can sometimes start with 2 if byes are certain way
export function adjustRoundNumbers<T extends { number: number }>(rounds: T[]) {
if (rounds.at(0)?.number === 1) {
return rounds;
}
return rounds.map((round) => ({ ...round, number: round.number - 1 }));
}