mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-05-09 20:30:54 -05:00
124 lines
3.3 KiB
TypeScript
124 lines
3.3 KiB
TypeScript
import type { Params } from "@remix-run/react";
|
|
import invariant from "tiny-invariant";
|
|
import type { Tournament, User } from "~/db/types";
|
|
import type { ModeShort } from "~/modules/in-game-lists";
|
|
import { rankedModesShort } from "~/modules/in-game-lists/modes";
|
|
import { databaseTimestampToDate } from "~/utils/dates";
|
|
import type { FindTeamsByTournamentId } from "./queries/findTeamsByTournamentId.server";
|
|
import type {
|
|
TournamentLoaderData,
|
|
TournamentLoaderTeam,
|
|
} from "./routes/to.$id";
|
|
import { TOURNAMENT } from "./tournament-constants";
|
|
import { validate } from "~/utils/remix";
|
|
|
|
export function resolveOwnedTeam({
|
|
teams,
|
|
userId,
|
|
}: {
|
|
teams: Array<TournamentLoaderTeam>;
|
|
userId?: User["id"];
|
|
}) {
|
|
if (typeof userId !== "number") return;
|
|
|
|
return teams.find((team) =>
|
|
team.members.some((member) => member.isOwner && member.userId === userId)
|
|
);
|
|
}
|
|
|
|
export function teamHasCheckedIn(
|
|
team: Pick<TournamentLoaderTeam, "checkedInAt">
|
|
) {
|
|
return Boolean(team.checkedInAt);
|
|
}
|
|
|
|
export function tournamentIdFromParams(params: Params<string>) {
|
|
const result = Number(params["id"]);
|
|
invariant(!Number.isNaN(result), "id is not a number");
|
|
|
|
return result;
|
|
}
|
|
|
|
export function modesIncluded(
|
|
tournament: Pick<Tournament, "mapPickingStyle">
|
|
): ModeShort[] {
|
|
switch (tournament.mapPickingStyle) {
|
|
case "AUTO_SZ": {
|
|
return ["SZ"];
|
|
}
|
|
case "AUTO_TC": {
|
|
return ["TC"];
|
|
}
|
|
case "AUTO_RM": {
|
|
return ["RM"];
|
|
}
|
|
case "AUTO_CB": {
|
|
return ["CB"];
|
|
}
|
|
default: {
|
|
return [...rankedModesShort];
|
|
}
|
|
}
|
|
}
|
|
|
|
export function isOneModeTournamentOf(
|
|
tournament: Pick<Tournament, "mapPickingStyle">
|
|
) {
|
|
return modesIncluded(tournament).length === 1
|
|
? modesIncluded(tournament)[0]!
|
|
: null;
|
|
}
|
|
|
|
export function HACKY_resolvePicture(event: TournamentLoaderData["event"]) {
|
|
if (event.name.includes("In The Zone"))
|
|
return "https://abload.de/img/screenshot2023-04-19a2bfv0.png";
|
|
|
|
return "https://abload.de/img/screenshot2022-12-15ap0ca1.png";
|
|
}
|
|
|
|
// hacky because db query not taking in account possibility of many start times
|
|
// AND always assumed check-in starts 1h before
|
|
export function HACKY_resolveCheckInTime(
|
|
event: Pick<TournamentLoaderData["event"], "startTime">
|
|
) {
|
|
return databaseTimestampToDate(event.startTime - 60 * 60);
|
|
}
|
|
|
|
export function mapPickCountPerMode(event: TournamentLoaderData["event"]) {
|
|
return isOneModeTournamentOf(event)
|
|
? TOURNAMENT.COUNTERPICK_ONE_MODE_TOURNAMENT_MAPS_PER_MODE
|
|
: TOURNAMENT.COUNTERPICK_MAPS_PER_MODE;
|
|
}
|
|
|
|
export function checkInHasStarted(
|
|
event: Pick<TournamentLoaderData["event"], "startTime">
|
|
) {
|
|
return HACKY_resolveCheckInTime(event).getTime() < Date.now();
|
|
}
|
|
|
|
export function checkInHasEnded(
|
|
event: Pick<TournamentLoaderData["event"], "startTime">
|
|
) {
|
|
return databaseTimestampToDate(event.startTime).getTime() < Date.now();
|
|
}
|
|
|
|
export function validateCanCheckIn({
|
|
event,
|
|
team,
|
|
}: {
|
|
event: Pick<TournamentLoaderData["event"], "startTime">;
|
|
team: FindTeamsByTournamentId[number];
|
|
}) {
|
|
validate(checkInHasStarted(event), "Check-in has not started yet");
|
|
validate(
|
|
team.members.length >= TOURNAMENT.TEAM_MIN_MEMBERS_FOR_FULL,
|
|
"Team does not have enough members"
|
|
);
|
|
validate(
|
|
team.mapPool && team.mapPool.length > 0,
|
|
"Team does not have a map pool"
|
|
);
|
|
|
|
return true;
|
|
}
|