Add "Start with SZ" toggleable option on the Preparing Maps page Closes #1887

This commit is contained in:
Kalle
2024-09-22 16:04:54 +03:00
parent 3a5fbeef1e
commit 8eb852f840
2 changed files with 81 additions and 13 deletions

View File

@@ -65,6 +65,7 @@ export function BracketMapListDialog({
})
: untrimmedPreparedMaps;
const [szFirst, setSzFirst] = React.useState(false);
const [eliminationTeamCount, setEliminationTeamCount] = React.useState(() => {
if (preparedMaps?.eliminationTeamCount) {
return preparedMaps.eliminationTeamCount;
@@ -91,6 +92,8 @@ export function BracketMapListDialog({
preparedMaps?.maps[0].type ?? "BEST_OF",
);
const flavor = szFirst ? "SZ_FIRST" : null;
const [maps, setMaps] = React.useState(() => {
if (preparedMaps) {
return new Map(preparedMaps.maps.map((map) => [map.roundId, map]));
@@ -103,6 +106,7 @@ export function BracketMapListDialog({
rounds,
type: bracket.type,
pickBanStyle: null,
flavor,
});
});
const [pickBanStyle, setPickBanStyle] = React.useState(
@@ -271,6 +275,7 @@ export function BracketMapListDialog({
type: bracket.type,
roundsWithPickBan: newRoundsWithPickBan,
pickBanStyle,
flavor,
}),
);
}}
@@ -297,6 +302,7 @@ export function BracketMapListDialog({
type: bracket.type,
roundsWithPickBan,
pickBanStyle,
flavor,
}),
);
setEliminationTeamCount(newCount);
@@ -319,6 +325,7 @@ export function BracketMapListDialog({
type: bracket.type,
roundsWithPickBan,
pickBanStyle,
flavor,
});
setMaps(newMaps);
}}
@@ -330,6 +337,25 @@ export function BracketMapListDialog({
onSetCountType={setCountType}
/>
) : null}
{tournament.ctx.mapPickingStyle === "TO" ? (
<SZFirstToggle
szFirst={szFirst}
setSzFirst={(newSzFirst) => {
setSzFirst(newSzFirst);
setMaps(
generateTournamentRoundMaplist({
mapCounts,
pool: tournament.ctx.toSetMapPool,
rounds,
type: bracket.type,
roundsWithPickBan,
pickBanStyle,
flavor: newSzFirst ? "SZ_FIRST" : null,
}),
);
}}
/>
) : null}
</div>
{tournament.ctx.toSetMapPool.length > 0 ? (
<Button
@@ -345,6 +371,7 @@ export function BracketMapListDialog({
type: bracket.type,
roundsWithPickBan,
pickBanStyle,
flavor,
}),
)
}
@@ -394,6 +421,7 @@ export function BracketMapListDialog({
type: bracket.type,
roundsWithPickBan,
pickBanStyle,
flavor,
});
setMaps(newMaps);
}}
@@ -417,6 +445,7 @@ export function BracketMapListDialog({
type: bracket.type,
roundsWithPickBan: newRoundsWithPickBan,
pickBanStyle,
flavor,
}),
);
}
@@ -678,6 +707,21 @@ function PickBanSelect({
);
}
function SZFirstToggle({
szFirst,
setSzFirst,
}: {
szFirst: boolean;
setSzFirst: (szFirst: boolean) => void;
}) {
return (
<div className="stack items-center">
<Label htmlFor="sz-first">SZ first</Label>
<Toggle id="sz-first" checked={szFirst} setChecked={setSzFirst} />
</div>
);
}
const serializedMapMode = (
map: NonNullable<TournamentRoundMaps["list"]>[number],
) => `${map.mode}-${map.stageId}`;

View File

@@ -1,5 +1,6 @@
/** Map list generation logic for "TO pick" as in the map list is defined beforehand by TO and teams don't pick */
import clone from "just-clone";
import shuffle from "just-shuffle";
import type {
TournamentBracketProgression,
@@ -19,13 +20,14 @@ export type BracketMapCounts = Map<
Map<number, { count: number; type: "BEST_OF" }>
>;
interface GenerateTournamentRoundMaplistArgs {
export interface GenerateTournamentRoundMaplistArgs {
pool: Array<{ mode: ModeShort; stageId: StageId }>;
rounds: Round[];
mapCounts: BracketMapCounts;
type: TournamentBracketProgression[number]["type"];
roundsWithPickBan: Set<number>;
pickBanStyle: TournamentRoundMaps["pickBan"];
flavor: "SZ_FIRST" | null;
}
export type TournamentRoundMapList = ReturnType<
@@ -63,12 +65,13 @@ export function generateTournamentRoundMaplist(
assertUnreachable(args.pickBanStyle);
};
const modes = modeOrder(
amountOfMapsToGenerate(),
args.pool,
const modes = modeOrder({
count: amountOfMapsToGenerate(),
pool: args.pool,
modeFrequency,
iteration,
);
flavor: args.flavor,
});
result.set(round.id, {
count,
@@ -150,12 +153,19 @@ function resolveRoundMapCount(
return count;
}
function modeOrder(
count: number,
pool: GenerateTournamentRoundMaplistArgs["pool"],
modeFrequency: Map<ModeShort, number>,
iteration: number,
) {
function modeOrder({
count,
pool,
modeFrequency,
iteration,
flavor,
}: {
count: number;
pool: GenerateTournamentRoundMaplistArgs["pool"];
modeFrequency: Map<ModeShort, number>;
iteration: number;
flavor: GenerateTournamentRoundMaplistArgs["flavor"];
}) {
const modes = removeDuplicates(pool.map((x) => x.mode));
const shuffledModes = shuffle(modes);
shuffledModes.sort((a, b) => {
@@ -165,7 +175,7 @@ function modeOrder(
return aFreq - bFreq;
});
const biasedModes = modesWithSZBiased(shuffledModes);
const biasedModes = modesWithSZBiased({ modes: shuffledModes, flavor });
const result: ModeShort[] = [];
@@ -182,12 +192,26 @@ function modeOrder(
return result;
}
function modesWithSZBiased(modes: ModeShort[]) {
function modesWithSZBiased({
modes,
flavor,
}: {
modes: ModeShort[];
flavor?: GenerateTournamentRoundMaplistArgs["flavor"];
}) {
// map list without SZ
if (!modes.includes("SZ")) {
return modes;
}
if (flavor === "SZ_FIRST" && modes.includes("SZ")) {
const result: ModeShort[] = clone(modes);
const szIndex = result.indexOf("SZ");
result.splice(szIndex, 1);
result.unshift("SZ");
return result;
}
// not relevant if there are less than 4 modes
if (modes.length < 4) {
return modes;