Remove redundant "inProgressStages"

This commit is contained in:
Kalle 2024-06-10 18:49:01 +03:00
parent 91bb932b31
commit 5452a30c63
13 changed files with 46 additions and 66 deletions

View File

@ -253,6 +253,7 @@ export interface TournamentStage {
type: "round_robin" | "single_elimination" | "double_elimination";
settings: string; // json
number: number;
createdAt: number | null;
}
/** A group is a logical structure used to group multiple rounds together.

View File

@ -3,7 +3,7 @@ import { json, redirect } from "@remix-run/node";
import { requireUser } from "~/features/auth/core/user.server";
import * as BadgeRepository from "~/features/badges/BadgeRepository.server";
import * as CalendarRepository from "~/features/calendar/CalendarRepository.server";
import { tournamentFromDB } from "~/features/tournament-bracket/core/Tournament.server";
import { tournamentData } from "~/features/tournament-bracket/core/Tournament.server";
import { i18next } from "~/modules/i18n/i18next.server";
import { canEditCalendarEvent } from "~/permissions";
import { validate } from "~/utils/remix";
@ -35,17 +35,15 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
// special tags that are added automatically
const tags = event?.tags?.filter((tag) => tag !== "BADGE");
if (!event?.tournamentId) return { ...event, tags, tournamentCtx: null };
if (!event?.tournamentId) return { ...event, tags, tournament: null };
return {
...event,
tags,
tournamentCtx: (
await tournamentFromDB({
tournamentId: event.tournamentId,
user,
})
).ctx,
tournament: await tournamentData({
tournamentId: event.tournamentId,
user,
}),
};
};
@ -56,11 +54,11 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
// no editing tournament after the start
if (
eventToEdit &&
eventToEdit.tournamentCtx?.inProgressBrackets &&
eventToEdit.tournamentCtx.inProgressBrackets.length > 0
eventToEdit.tournament?.data.stage &&
eventToEdit.tournament.data.stage.length > 0
) {
return redirect(
tournamentBracketsPage({ tournamentId: eventToEdit.tournamentCtx.id }),
tournamentBracketsPage({ tournamentId: eventToEdit.tournament.ctx.id }),
);
}

View File

@ -279,7 +279,7 @@ function DescriptionTextarea({
function RulesTextarea({ supportsMarkdown }: { supportsMarkdown?: boolean }) {
const baseEvent = useBaseEvent();
const [value, setValue] = React.useState(
baseEvent?.tournamentCtx?.rules ?? "",
baseEvent?.tournament?.ctx.rules ?? "",
);
return (
@ -617,10 +617,10 @@ function AvatarImageInput({
if (
baseEvent?.avatarImgId &&
baseEvent?.tournamentCtx?.logoUrl &&
baseEvent?.tournament?.ctx.logoUrl &&
showPrevious
) {
const logoImgUrl = userSubmittedImage(baseEvent.tournamentCtx.logoUrl);
const logoImgUrl = userSubmittedImage(baseEvent.tournament.ctx.logoUrl);
return (
<div className="stack horizontal md flex-wrap">
@ -784,7 +784,7 @@ function TournamentLogoColorInputsWithShowcase({
function RankedToggle() {
const baseEvent = useBaseEvent();
const [isRanked, setIsRanked] = React.useState(
baseEvent?.tournamentCtx?.settings.isRanked ?? true,
baseEvent?.tournament?.ctx.settings.isRanked ?? true,
);
const id = React.useId();
@ -813,7 +813,7 @@ function RankedToggle() {
function EnableNoScreenToggle() {
const baseEvent = useBaseEvent();
const [enableNoScreen, setEnableNoScreen] = React.useState(
baseEvent?.tournamentCtx?.settings.enableNoScreenToggle ?? true,
baseEvent?.tournament?.ctx.settings.enableNoScreenToggle ?? true,
);
const id = React.useId();
@ -840,7 +840,7 @@ function EnableNoScreenToggle() {
function AutonomousSubsToggle() {
const baseEvent = useBaseEvent();
const [autonomousSubs, setAutonomousSubs] = React.useState(
baseEvent?.tournamentCtx?.settings.autonomousSubs ?? true,
baseEvent?.tournament?.ctx.settings.autonomousSubs ?? true,
);
const id = React.useId();
@ -867,7 +867,7 @@ function AutonomousSubsToggle() {
function RequireIGNToggle() {
const baseEvent = useBaseEvent();
const [requireIGNs, setRequireIGNs] = React.useState(
baseEvent?.tournamentCtx?.settings.requireInGameNames ?? false,
baseEvent?.tournament?.ctx.settings.requireInGameNames ?? false,
);
const id = React.useId();
@ -895,7 +895,7 @@ function RequireIGNToggle() {
function InvitationalToggle() {
const baseEvent = useBaseEvent();
const [isInvitational, setIsInvitational] = React.useState(
baseEvent?.tournamentCtx?.settings.isInvitational ?? false,
baseEvent?.tournament?.ctx.settings.isInvitational ?? false,
);
const id = React.useId();
@ -922,7 +922,7 @@ function InvitationalToggle() {
function StrictDeadlinesToggle() {
const baseEvent = useBaseEvent();
const [strictDeadlines, setStrictDeadlines] = React.useState(
baseEvent?.tournamentCtx?.settings.deadlines === "STRICT" ? true : false,
baseEvent?.tournament?.ctx.settings.deadlines === "STRICT" ? true : false,
);
const id = React.useId();
@ -949,11 +949,11 @@ function StrictDeadlinesToggle() {
function RegClosesAtSelect() {
const baseEvent = useBaseEvent();
const [regClosesAt, setRegClosesAt] = React.useState<RegClosesAtOption>(
baseEvent?.tournamentCtx?.settings.regClosesAt
baseEvent?.tournament?.ctx.settings.regClosesAt
? datesToRegClosesAt({
startTime: new Date(baseEvent.tournamentCtx.startTime),
startTime: new Date(baseEvent.tournament.ctx.startTime),
regClosesAt: databaseTimestampToDate(
baseEvent.tournamentCtx.settings.regClosesAt,
baseEvent.tournament.ctx.settings.regClosesAt,
),
})
: "0",
@ -1212,30 +1212,30 @@ function MapPoolValidationStatusMessage({
function TournamentFormatSelector() {
const baseEvent = useBaseEvent();
const [format, setFormat] = React.useState<TournamentFormatShort>(
baseEvent?.tournamentCtx?.settings.bracketProgression
baseEvent?.tournament?.ctx.settings.bracketProgression
? bracketProgressionToShortTournamentFormat(
baseEvent.tournamentCtx.settings.bracketProgression,
baseEvent.tournament.ctx.settings.bracketProgression,
)
: "DE",
);
const [withUndergroundBracket, setWithUndergroundBracket] = React.useState(
baseEvent?.tournamentCtx
? baseEvent.tournamentCtx.settings.bracketProgression.some(
baseEvent?.tournament
? baseEvent.tournament.ctx.settings.bracketProgression.some(
(b) => b.name === BRACKET_NAMES.UNDERGROUND,
)
: false,
);
const [thirdPlaceMatch, setThirdPlaceMatch] = React.useState(
baseEvent?.tournamentCtx?.settings.thirdPlaceMatch ?? true,
baseEvent?.tournament?.ctx.settings.thirdPlaceMatch ?? true,
);
const [teamsPerGroup, setTeamsPerGroup] = React.useState(
baseEvent?.tournamentCtx?.settings.teamsPerGroup ?? 4,
baseEvent?.tournament?.ctx.settings.teamsPerGroup ?? 4,
);
const [swissGroupCount, setSwissGroupCount] = React.useState(
baseEvent?.tournamentCtx?.settings.swiss?.groupCount ?? 1,
baseEvent?.tournament?.ctx.settings.swiss?.groupCount ?? 1,
);
const [swissRoundCount, setSwissRoundCount] = React.useState(
baseEvent?.tournamentCtx?.settings.swiss?.roundCount ?? 5,
baseEvent?.tournament?.ctx.settings.swiss?.roundCount ?? 5,
);
return (
@ -1377,17 +1377,17 @@ function FollowUpBrackets({
}) {
const baseEvent = useBaseEvent();
const [autoCheckInAll, setAutoCheckInAll] = React.useState(
baseEvent?.tournamentCtx?.settings.autoCheckInAll ?? false,
baseEvent?.tournament?.ctx.settings.autoCheckInAll ?? false,
);
const [_brackets, setBrackets] = React.useState<Array<FollowUpBracket>>(
() => {
if (
baseEvent?.tournamentCtx &&
baseEvent?.tournament &&
["round_robin", "swiss"].includes(
baseEvent.tournamentCtx.settings.bracketProgression[0].type,
baseEvent.tournament.ctx.settings.bracketProgression[0].type,
)
) {
return baseEvent.tournamentCtx.settings.bracketProgression
return baseEvent.tournament.ctx.settings.bracketProgression
.slice(1)
.map((b) => ({
name: b.name,

View File

@ -20,7 +20,7 @@ interface CreateBracketArgs {
name: string;
teamsPendingCheckIn?: number[];
tournament: Tournament;
createdAt: number | null;
createdAt?: number | null;
sources?: {
bracketIdx: number;
placements: number[];

View File

@ -17,12 +17,13 @@ export async function tournamentData({
user?: { id: number };
tournamentId: number;
}) {
const data = manager.get.tournamentData(tournamentId);
const ctx = notFoundIfFalsy(
await TournamentRepository.findById(tournamentId),
);
const revealAllMapPools =
ctx.inProgressBrackets.length > 0 ||
data.stage.length > 0 ||
ctx.author.id === user?.id ||
ctx.staff.some(
(staff) => staff.id === user?.id && staff.role === "ORGANIZER",
@ -32,7 +33,7 @@ export async function tournamentData({
: HACKY_resolvePicture(ctx);
return {
data: manager.get.tournamentData(tournamentId),
data,
ctx: {
...ctx,
logoSrc: logo,

View File

@ -32,7 +32,7 @@ export class Tournament {
ctx;
constructor({ data, ctx }: TournamentData) {
const hasStarted = ctx.inProgressBrackets.length > 0;
const hasStarted = data.stage.length > 0;
const teamsInSeedOrder = ctx.teams.sort((a, b) => {
if (a.seed && b.seed) {
@ -91,9 +91,7 @@ export class Tournament {
bracketIdx,
{ type, name, sources },
] of this.ctx.settings.bracketProgression.entries()) {
const inProgressStage = this.ctx.inProgressBrackets.find(
(stage) => stage.name === name,
);
const inProgressStage = data.stage.find((stage) => stage.name === name);
if (inProgressStage) {
const match = data.match.filter(

View File

@ -100,6 +100,7 @@ export class Stage {
settings: JSON.parse(rawStage.settings),
tournament_id: rawStage.tournamentId,
type: rawStage.type,
createdAt: rawStage.createdAt,
};
}

View File

@ -68,12 +68,6 @@ export const testTournament = (
{ name: BRACKET_NAMES.MAIN, type: "double_elimination" },
],
},
inProgressBrackets: data.stage.map((stage) => ({
id: stage.id,
name: stage.name,
type: stage.type,
createdAt: 0,
})),
castedMatchesInfo: null,
teams: nTeams(participant.length, Math.min(...participant)),
author: {

View File

@ -61,18 +61,6 @@ export async function findById(id: number) {
.where("TournamentResult.tournamentId", "=", id)
.select("TournamentResult.tournamentId"),
).as("isFinalized"),
jsonArrayFrom(
eb
.selectFrom("TournamentStage")
.select([
"TournamentStage.id",
"TournamentStage.name",
"TournamentStage.type",
"TournamentStage.createdAt",
])
.where("TournamentStage.tournamentId", "=", id)
.orderBy("TournamentStage.number asc"),
).as("inProgressBrackets"),
jsonArrayFrom(
eb
.selectFrom("TournamentTeam")

View File

@ -106,10 +106,7 @@ export const action: ActionFunction = async ({ request, params }) => {
}
case "CHANGE_TEAM_NAME": {
validateIsTournamentOrganizer();
validate(
tournament.ctx.inProgressBrackets.length === 0,
"Tournament started",
);
validate(!tournament.hasStarted, "Tournament started");
const team = tournament.teamById(data.teamId);
validate(team, "Invalid team id");

View File

@ -91,7 +91,7 @@ export const action: ActionFunction = async ({ request, params }) => {
const event = notFoundIfFalsy(findByIdentifier(tournamentId));
validate(
tournament.ctx.inProgressBrackets.length === 0,
!tournament.hasStarted,
"Tournament has started, cannot make edits to registration",
);

View File

@ -142,7 +142,7 @@ export const loader = async ({ params, request }: LoaderFunctionArgs) => {
const tournament = await tournamentData({ tournamentId, user });
const streams =
tournament.ctx.inProgressBrackets.length > 0
tournament.data.stage.length > 0
? await streamsByTournamentId({
tournamentId,
castTwitchAccounts: tournament.ctx.castTwitchAccounts,

View File

@ -32,6 +32,8 @@ export interface Stage {
/** The number of the stage in its tournament. */
number: number;
createdAt?: number | null;
}
/**