Files
sendou.ink/app/db/tables-json.ts

194 lines
6.2 KiB
TypeScript

/** JSON column payload shapes with no natural feature home; feature-owned ones (e.g. `StoredWidget`) live with their feature. */
import type { DBBoolean } from "~/db/tables";
import type { CalendarFilters } from "~/features/calendar/calendar-types";
import type { ScrimFilters } from "~/features/scrims/scrims-types";
import type { CustomThemeVar } from "~/features/theme/theme-constants";
import type { TeamPickPool } from "~/features/tournament/tournament-constants";
import type * as PickBan from "~/features/tournament-bracket/core/PickBan";
import type * as Progression from "~/features/tournament-bracket/core/Progression";
import type {
ActionType,
WhoSide,
} from "~/features/tournament-bracket/tournament-bracket-constants";
import type {
ObjectPronoun,
SubjectPronoun,
} from "~/features/user-page/user-page-constants";
import type {
MainWeaponId,
ModeShort,
StageId,
} from "~/modules/in-game-lists/types";
export type CustomTheme = Omit<Record<CustomThemeVar, number>, "--_chat-h"> & {
"--_chat-h": number | null;
};
/** Missing means "neutral" */
export type Preference = "AVOID" | "PREFER";
export interface UserMapModePreferences {
modes: Array<{
mode: ModeShort;
/** Users opinion on the mode, `undefined` means neutral */
preference?: Preference;
}>;
pool: Array<{
mode: ModeShort;
stages: StageId[];
}>;
}
export interface WeaponPoolEntry {
weaponSplId: MainWeaponId;
isFavorite: DBBoolean;
}
export interface UserPreferences {
disableBuildAbilitySorting?: boolean;
disallowScrimPickupsFromUntrusted?: boolean;
defaultCalendarFilters?: CalendarFilters;
defaultScrimsFilters?: ScrimFilters;
/** "auto" (default) = browser default */
clockFormat?: "24h" | "12h" | "auto";
/** Hides recent tournament results and scores until revealed */
spoilerFreeMode?: boolean;
weaponReportDefaultOpen?: boolean;
/** Start of the week the schedule sidebar nudge was last dismissed for, so it stays gone until the horizon rolls over. */
scheduleNudgeDismissedWeekStartsAt?: number;
/** Who may see the user's schedule. Missing = everyone. Once set it is an allow-list, so a team joined later stays hidden until added. */
scheduleVisibility?: { friends: boolean; teamIds: Array<number> };
}
export type Pronouns = {
subject: SubjectPronoun;
object: ObjectPronoun;
};
export interface PeakXP {
overall: number;
takoroka: number | null;
tentatek: number | null;
}
export interface TournamentSettings {
bracketProgression: Progression.ParsedBracket[];
/** @deprecated use bracketProgression instead */
teamsPerGroup?: number;
/** @deprecated use bracketProgression instead */
thirdPlaceMatch?: boolean;
isRanked?: boolean;
enableNoScreenToggle?: boolean;
/** Enable the subs tab, default true */
enableSubs?: boolean;
requireInGameNames?: boolean;
isInvitational?: boolean;
/** Can teams add subs on their own while tournament is in progress? */
autonomousSubs?: boolean;
/** Timestamp (SQLite format) when reg closes, if missing then means closes at start time */
regClosesAt?: number;
/** @deprecated use bracketProgression instead */
swiss?: {
groupCount: number;
roundCount: number;
};
minMembersPerTeam?: number;
/** Maximum number of team members that can be registered (only applies to 4v4 tournaments) */
maxMembersPerTeam?: number;
isTest?: boolean;
isDraft?: boolean;
requireSendouQParticipation?: boolean;
/** Is this tournament a league? Leagues are played over many weeks, each starting bracket being a division. */
isLeague?: boolean;
/** Team picked map configuration, always set when `Tournament.mapPickingStyle` is "AUTO". */
teamPick?: TeamPickSettings;
}
export interface TeamPickSettings {
/** Modes teams pick maps for and how many maps for each, unique modes in `modesShort` order, count ≥ 1. */
modes: Array<{ mode: ModeShort; count: number }>;
pool: TeamPickPool;
}
export interface CastedMatchesInfo {
/** Matches locked because they are pending to be casted */
lockedMatches: Array<{ twitchAccount: string; matchId: number }>;
castedMatches: { twitchAccount: string; matchId: number }[];
castedMatchHistory?: Array<{
twitchAccount: string;
matchId: number;
timestamp: number;
}>;
}
export interface SeedingSnapshot {
savedAt: number;
teams: Array<{
teamId: number;
members: Array<{ userId: number; username: string }>;
}>;
}
export interface PreparedMaps {
authorId: number;
createdAt: number;
maps: Array<TournamentRoundMaps & { roundId: number; groupId: number }>;
eliminationTeamCount?: number;
}
export interface TournamentRoundMaps {
list?: Array<{ mode: ModeShort; stageId: StageId }> | null;
/** Fixed mode of each slot of a team picked round with a mode pattern, the maps still come from the teams' picks. `count + 2` long for "BAN_2". */
modes?: ModeShort[] | null;
count: number;
type: "BEST_OF" | "PLAY_ALL";
pickBan?: PickBan.Type | null;
customFlow?: CustomPickBanFlow | null;
}
export interface CustomPickBanStep {
action: ActionType;
side?: WhoSide;
}
export interface CustomPickBanFlow {
preSet: CustomPickBanStep[];
postGame: CustomPickBanStep[];
}
/** When updating this also update `settingsFromFormValues` in calendar-progression-form.ts */
export interface TournamentStageSettings {
// SE
thirdPlaceMatch?: boolean;
// RR
teamsPerGroup?: number;
/** (RR only) When true, teams are split into A and B divisions and matches only pair A-vs-B. Only valid on starting brackets. */
hasAbDivisions?: boolean;
// SWISS
groupCount?: number;
// SWISS
roundCount?: number;
/** (Swiss only) Number of wins required for a team to advance early. When set, teams advance at this win count and are eliminated at (roundCount - advanceThreshold + 1) losses. */
advanceThreshold?: number;
}
export interface TournamentAuditLogMetadata {
bracketIdx?: number;
/** The new in-game name, for `UPDATE_IN_GAME_NAME` events. */
inGameName?: string;
/** The new tournament name, for `UPDATE_TOURNAMENT_NAME` events. `null` = it was cleared. */
tournamentName?: string | null;
}
/** E.g. ["W", "L", null] = won the first set, lost the second, did not play the third. */
export type WinLossParticipationArray = Array<"W" | "L" | null>;
export interface NotificationSubscription {
endpoint: string;
keys: {
auth: string;
p256dh: string;
};
}