From 0a82554530e1ded937eadb8e9a28c23940672242 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Mon, 4 Mar 2024 21:36:00 +0200 Subject: [PATCH] Host tournaments as unranked Closes #1681 --- app/db/tables.ts | 1 + .../calendar/CalendarRepository.server.ts | 3 ++ .../calendar/calendar-schemas.server.ts | 1 + app/features/calendar/routes/calendar.new.tsx | 37 ++++++++++++++++++- .../tournament-bracket/core/Tournament.ts | 5 ++- .../routes/to.$id.brackets.tsx | 2 +- 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/db/tables.ts b/app/db/tables.ts index 55f01a95d..c080f9286 100644 --- a/app/db/tables.ts +++ b/app/db/tables.ts @@ -386,6 +386,7 @@ export interface TournamentSettings { bracketProgression: TournamentBracketProgression; teamsPerGroup?: number; thirdPlaceMatch?: boolean; + isRanked?: boolean; } export interface CastedMatchesInfo { diff --git a/app/features/calendar/CalendarRepository.server.ts b/app/features/calendar/CalendarRepository.server.ts index 24c7ef861..2ca885019 100644 --- a/app/features/calendar/CalendarRepository.server.ts +++ b/app/features/calendar/CalendarRepository.server.ts @@ -386,6 +386,7 @@ type CreateArgs = Pick< bracketProgression: TournamentSettings["bracketProgression"] | null; teamsPerGroup?: number; thirdPlaceMatch?: boolean; + isRanked?: boolean; }; export async function create(args: CreateArgs) { return db.transaction().execute(async (trx) => { @@ -396,6 +397,7 @@ export async function create(args: CreateArgs) { bracketProgression: args.bracketProgression, teamsPerGroup: args.teamsPerGroup, thirdPlaceMatch: args.thirdPlaceMatch, + isRanked: args.isRanked, }; tournamentId = ( @@ -465,6 +467,7 @@ export async function update(args: UpdateArgs) { bracketProgression: args.bracketProgression, teamsPerGroup: args.teamsPerGroup, thirdPlaceMatch: args.thirdPlaceMatch, + isRanked: args.isRanked, }; await trx diff --git a/app/features/calendar/calendar-schemas.server.ts b/app/features/calendar/calendar-schemas.server.ts index 44178106b..e8c7a233c 100644 --- a/app/features/calendar/calendar-schemas.server.ts +++ b/app/features/calendar/calendar-schemas.server.ts @@ -70,6 +70,7 @@ export const newCalendarEventActionSchema = z pool: z.string().optional(), toToolsEnabled: z.preprocess(checkboxValueToBoolean, z.boolean()), toToolsMode: z.enum(["ALL", "SZ", "TC", "RM", "CB"]).optional(), + isRanked: z.preprocess(checkboxValueToBoolean, z.boolean().nullish()), // // tournament format related fields // diff --git a/app/features/calendar/routes/calendar.new.tsx b/app/features/calendar/routes/calendar.new.tsx index 6c443a56a..5b74e60ab 100644 --- a/app/features/calendar/routes/calendar.new.tsx +++ b/app/features/calendar/routes/calendar.new.tsx @@ -117,6 +117,7 @@ export const action: ActionFunction = async ({ request }) => { bracketProgression: formValuesToBracketProgression(data), teamsPerGroup: data.teamsPerGroup ?? undefined, thirdPlaceMatch: data.thirdPlaceMatch ?? undefined, + isRanked: data.isRanked ?? undefined, }; validate( !commonArgs.toToolsEnabled || commonArgs.bracketProgression, @@ -253,6 +254,12 @@ export default function CalendarNewEventPage() { + {isTournament ? ( + <> + Tournament settings + + + ) : null} {/* can't edit as participants might have chosen maps and changing this might cause impossible states */} {isTournament && !eventToEdit ? ( @@ -607,6 +614,33 @@ function BadgesAdder() { ); } +function RankedToggle() { + const data = useLoaderData(); + const [isRanked, setIsRanked] = React.useState( + data.tournamentCtx?.settings.isRanked ?? true, + ); + const id = React.useId(); + + return ( +
+ + + + Ranked tournaments affect SP. Tournaments that don't have open + registration (skill capped) or "gimmick tournaments" must + always be hosted as unranked. Any tournament hosted during off-season is + always unranked no matter what is chosen here. + +
+ ); +} + const mapPickingStyleToShort: Record< Tables["Tournament"]["mapPickingStyle"], "ALL" | RankedModeShort @@ -822,7 +856,7 @@ function TournamentFormatSelector() { ); return ( -
+
Tournament format
@@ -866,6 +900,7 @@ function TournamentFormatSelector() { setChecked={setThirdPlaceMatch} name="thirdPlaceMatch" id="thirdPlaceMatch" + tiny />
) : null} diff --git a/app/features/tournament-bracket/core/Tournament.ts b/app/features/tournament-bracket/core/Tournament.ts index 1e38c67ba..9458a5448 100644 --- a/app/features/tournament-bracket/core/Tournament.ts +++ b/app/features/tournament-bracket/core/Tournament.ts @@ -266,7 +266,10 @@ export class Tournament { } get ranked() { - return Boolean(currentSeason(this.ctx.startTime)); + const seasonIsActive = Boolean(currentSeason(this.ctx.startTime)); + if (!seasonIsActive) return false; + + return this.ctx.settings.isRanked ?? true; } get logoSrc() { diff --git a/app/features/tournament-bracket/routes/to.$id.brackets.tsx b/app/features/tournament-bracket/routes/to.$id.brackets.tsx index 74f816860..6977eb5ed 100644 --- a/app/features/tournament-bracket/routes/to.$id.brackets.tsx +++ b/app/features/tournament-bracket/routes/to.$id.brackets.tsx @@ -140,7 +140,7 @@ export const action: ActionFunction = async ({ params, request }) => { teams: tournament.ctx.teams, finalStandings: _finalStandings, results, - calculateSeasonalStats: typeof season === "number", + calculateSeasonalStats: tournament.ranked, queryCurrentTeamRating: (identifier) => queryCurrentTeamRating({ identifier, season: season! }).rating, queryCurrentUserRating: (userId) =>