Skip to content

Tournament · Repositories

3 modules · 24 exports · 4 repositories · 23 e2e tests · 12 routes

Every table a function queries, its own helpers included, read or written. Calls to other repositories are listed apart, their tables are on their own page.

SavedCalendarEventRepository

app/features/tournament/SavedCalendarEventRepository.server.ts
Tables
CalendarEventSavedCalendarEvent
Calls
TournamentOrganizationRepositoryTournamentRepository
Imports
ShowcaseTournaments.server
Used by
3 loaders2 actions1 script3 other

Functions & values

function

saveOwn

no JSDoc:6
export function saveOwn(tournamentId: number)
function

unsaveByUserId

no JSDoc:20
export function unsaveByUserId({
	userId,
	tournamentId,
}: {
	userId: number;
	tournamentId: number;
})
function

isSaved

no JSDoc:39
export async function isSaved({
	userId,
	tournamentId,
}: {
	userId: number;
	tournamentId: number;
}): Promise<boolean>
function

countByUserId

no JSDoc:61
export async function countByUserId(userId: number): Promise<number>
function

findAllUpcomingByUserId

no JSDoc:81
export async function findAllUpcomingByUserId(
	userId: number,
): Promise<ShowcaseCalendarEvent[]>
function

deleteByTournamentId

no JSDoc:111
export function deleteByTournamentId(tournamentId: number)

TournamentAuditLogRepository

app/features/tournament/TournamentAuditLogRepository.server.ts
Tables
TournamentAuditLogTournamentTeamTournamentTeamHistoryUserUserSubmittedImage
Calls
no other repositories
Imports
no other modules
Used by
1 loader1 repository1 routine1 script

Functions & values

const

AUDIT_LOG_PAGE_SIZE

no JSDoc:10
export const AUDIT_LOG_PAGE_SIZE = 30;
function

insert

:27

Inserts an audit log event in the caller's transaction, actor from actorId(). Ensures a TournamentTeamHistory row exists so the event stays readable after the team is hard-deleted.

export async function insert(args: InsertArgs, trx: Transaction<DB>)
function

updateTeamHistoryName

:90

Keeps the preserved name current after a rename. No-op without a history row (created on the first audited event).

export function updateTeamHistoryName(
	trx: Transaction<DB>,
	{ tournamentTeamId, name }: { tournamentTeamId: number; name: string },
)
function

findByTournamentId

:107

A page of events, newest first, optionally filtered by type and/or team, with actor, affected member and (preserved) team name.

export function findByTournamentId({
	tournamentId,
	type,
	tournamentTeamHistoryId,
	limit,
	offset,
}: {
	tournamentId: number;
	type?: TournamentAuditLogType;
	tournamentTeamHistoryId?: number;
	limit: number;
	offset: number;
})
function

countByTournamentId

:175

Event count under the same filters as {@link findByTournamentId}, for pagination.

export async function countByTournamentId({
	tournamentId,
	type,
	tournamentTeamHistoryId,
}: {
	tournamentId: number;
	type?: TournamentAuditLogType;
	tournamentTeamHistoryId?: number;
})
function

deleteOld

:206

Deletes audit log events older than three months.

export function deleteOld()
function

findTeamsByTournamentId

:218

Every team (deleted ones included) in the tournament's audit log, for the team filter.

export function findTeamsByTournamentId(tournamentId: number)
Unit tests not about one export (9)

TournamentRepository

app/features/tournament/TournamentRepository.server.ts
Tables
AllTeamBadgeCalendarEventCalendarEventBadgeCalendarEventDateLiveStreamMapPoolMapMapResultPlayerResultSeedingSkillSkillSkillTeamUserTournamentTournamentBadgeOwnerTournamentBracketProgressionOverrideTournamentDivisionTierTournamentMatchTournamentMatchPickBanEventTournamentMatchVodTournamentOrganizationTournamentOrganizationMemberTournamentOrganizationSeriesTournamentResultTournamentStaffTournamentStageTournamentTeamTournamentTeamCheckInTournamentTeamMemberTrophyUnvalidatedUserSubmittedImageUserUserFriendCodeUserSubmittedImage
Calls
TrophyRepository
Imports
Progression
Used by
8 loaders7 actions5 routes3 modules3 routines2 scripts7 other

Types

type

FindById

no JSDoc:55
export type FindById = NonNullable<Unwrapped<typeof findById>>;
type

TeamFull

no JSDoc:494
export type TeamFull = Unwrapped<typeof findTeamsFullByTournamentId>;
type

ForShowcase

no JSDoc:835
export type ForShowcase = Unwrapped<typeof findAllForShowcase>;

Functions & values

function

findStreamsByTournamentId

:402

Live streams of checked-in participants and of the tournament's cast accounts.

export async function findStreamsByTournamentId(tournamentId: number)
function

findParticipatedUserIdsById

:462

User ids of everyone who played at least one map of the tournament. Probes each roster member instead of reading every participant row (members who played can't be removed from the roster).

export async function findParticipatedUserIdsById(tournamentId: number)
function

findTeamsFullByTournamentId

:501

Full rosters of a tournament's teams: per member profile data, map pools and invite codes. Kept out of {@link findById} because the tournament layout ships the lite team shape only — views that render rosters load these separately.

export async function findTeamsFullByTournamentId(tournamentId: number)
function

findParticipantStreamAccounts

:623

Twitch and YouTube accounts of the given tournaments' participants who have not dropped out. Kept out of {@link findById} since only the live stream sync routine needs them.

export async function findParticipantStreamAccounts(tournamentIds: number[])
function

findRulesById

:665

Loads a tournament's rules markdown. Kept out of {@link findById} since it can be large and is only needed on the tournament's rules page.

export async function findRulesById(tournamentId: number)
function

findDescriptionById

:679

Loads a tournament's description markdown. Kept out of {@link findById} since it can be large and is only needed on the tournament's info page.

export async function findDescriptionById(tournamentId: number)
function

findSeedingSnapshotById

:690

Loads a tournament's seeding snapshot.

export async function findSeedingSnapshotById(tournamentId: number)
function

findResultsByTournamentId

:701

Per-user results persisted at finalization time. Empty for tournaments not yet finalized.

export function findResultsByTournamentId(tournamentId: number)
function

findLatestFinalizedLeagueParticipants

:721

Participants of the organization's latest finalized league, with the bracket progression that tells what division (= starting bracket) each played in. Only participants eligible for a division placement: have a result, team did not drop out, played at least one match. Null if the organization has no finalized league.

export async function findLatestFinalizedLeagueParticipants(args: {
	organizationId: number;
	namePrefix: string;
})
function

findTOSetMapPoolById

no JSDoc:769
export async function findTOSetMapPoolById(tournamentId: number)
function

findPreparedMapsById

no JSDoc:788
export async function findPreparedMapsById(tournamentId: number)
function

findRelatedUsersByTournamentIds

no JSDoc:800
export function findRelatedUsersByTournamentIds(tournamentIds: number[])
function

findShowcaseCountsById

:953

Team & participant counts of one tournament as {@link findAllForShowcase} computes them, for refreshing a cached showcase tournament.

export function findShowcaseCountsById(tournamentId: number)
function

findAllBetweenTwoTimestamps

no JSDoc:965
export function findAllBetweenTwoTimestamps({
	startTime,
	endTime,
}: {
	startTime: Date;
	endTime: Date;
})
function

findPendingCheckInsStartingBetween

:995

Members of teams that have not checked in nor dropped out, for every tournament whose first day starts inside the window. One row per member per tournament; the caller narrows the window to the check-in period.

export function findPendingCheckInsStartingBetween({
	startsAfter,
	startsBefore,
}: {
	startsAfter: Date;
	startsBefore: Date;
})
function

findOrganizerPermissionsByTournamentIds

:1076

ORGANIZE and MANAGE_MATCHES holders keyed by tournament id, without loading the tournaments themselves.

export async function findOrganizerPermissionsByTournamentIds(
	tournamentIds: number[],
)
function

findTopThreeResultsByTournamentIds

:1143

Podium placements of the given tournaments, one row per placed player.

export async function findTopThreeResultsByTournamentIds(
	tournamentIds: number[],
)
function

findFriendCodesByTournamentId

no JSDoc:1161
export async function findFriendCodesByTournamentId(tournamentId: number)
function

updateProgression

no JSDoc:1186
export function updateProgression({
	tournamentId,
	bracketProgression,
}: {
	tournamentId: number;
	bracketProgression: TournamentSettings["bracketProgression"];
})
function

overrideTeamBracketProgression

no JSDoc:1255
export function overrideTeamBracketProgression({
	tournamentId,
	tournamentTeamId,
	sourceBracketIdx,
	destinationBracketIdx,
}: {
	tournamentId: number;
	tournamentTeamId: number;
	sourceBracketIdx: number;
	destinationBracketIdx: number;
})
function

setStaff

no JSDoc:1278
export function setStaff({
	tournamentId,
	staff,
}: {
	tournamentId: number;
	staff: Array<{
		userId: number;
		role: Tables["TournamentStaff"]["role"];
	}>;
})
function

upsertPreparedMaps

no JSDoc:1313
export function upsertPreparedMaps({
	bracketIdx,
	maps,
	tournamentId,
}: UpsertPreparedMapsArgs)
function

updateCastAccounts

no JSDoc:1343
export function updateCastAccounts({
	tournamentId,
	castAccounts,
}: {
	tournamentId: number;
	castAccounts: CastAccount[];
})
function

lockMatch

no JSDoc:1373
export function lockMatch({
	matchId,
	tournamentId,
	castAccount,
}: {
	matchId: number;
	tournamentId: number;
	castAccount: StreamAccount;
})
function

unlockMatch

no JSDoc:1406
export function unlockMatch({
	matchId,
	tournamentId,
}: {
	matchId: number;
	tournamentId: number;
})
function

setMatchAsCasted

no JSDoc:1444
export function setMatchAsCasted({
	matchId,
	tournamentId,
	castAccount,
}: {
	matchId: number;
	tournamentId: number;
	castAccount: StreamAccount | null;
})
function

findPickBanEventsByMatchId

no JSDoc:1475
export function findPickBanEventsByMatchId(matchId: number)
function

insertPickBanEvent

no JSDoc:1490
export function insertPickBanEvent(
	values: Insertable<DB["TournamentMatchPickBanEvent"]>,
)
function

reopenTournament

no JSDoc:1496
export function reopenTournament(tournamentId: number)
function

finalize

:1531

Finalizes a tournament, recording the full summary: skills, seeding skills, map/player result deltas, badge owners and placements. See {@link finalizeWithoutSummary} for test tournaments.

Returns false without writing anything if the tournament was already finalized, so that overlapping requests can't apply the additive summary deltas twice.

export function finalize({
	tournamentId,
	summary,
	season,
	badgeReceivers = [],
	trophyReceiver,
}: {
	tournamentId: number;
	summary: TournamentSummary;
	season?: number;
	badgeReceivers?: TournamentBadgeReceivers;
	trophyReceiver?: TournamentTrophyReceiver;
})
function

finalizeWithoutSummary

:1764

Marks a test tournament as finalized without recording any summary stats. See {@link finalize}.

Returns false if the tournament was already finalized.

export function finalizeWithoutSummary(tournamentId: number)
function

searchByName

:1790

Tournaments whose calendar event name contains the query, hidden excluded, most likely matches first.

export async function searchByName({
	query,
	limit,
	minStartTime,
	maxStartTime,
}: {
	query: string;
	limit: number;
	minStartTime?: Date;
	maxStartTime?: Date;
})
function

updateTeamSeeds

no JSDoc:1852
export function updateTeamSeeds({
	tournamentId,
	teamIds,
}: {
	tournamentId: number;
	teamIds: number[];
})
function

findDivisionTiersByTournamentId

:1910

Tier of every league division (starting bracket) of the tournament that has one.

export function findDivisionTiersByTournamentId(tournamentId: number)
function

upsertDivisionTier

:1925

Records the tier of one division (= starting bracket) from its checked-in teams and sets the tournament's own tier to the best of its divisions (the same thing when there is one division).

export async function upsertDivisionTier({
	tournamentId,
	bracketIdx,
	tier,
}: {
	tournamentId: number;
	bracketIdx: number;
	tier: TournamentTierNumber;
})
function

findRunningTournamentIds

no JSDoc:1959
export async function findRunningTournamentIds()

TournamentTeamRepository

app/features/tournament/TournamentTeamRepository.server.ts
Tables
CalendarEventCalendarEventDateMapPoolMapTournamentTournamentMatchGameResultTournamentMatchGameResultParticipantTournamentTeamTournamentTeamCheckInTournamentTeamMemberUnvalidatedUserSubmittedImageUser
Calls
TournamentAuditLogRepository
Imports
no other modules
Used by
3 loaders7 actions4 routes1 repository1 module2 scripts6 other

Functions & values

function

findAllByChatRoomIds

:20

Teams owning the given chat rooms, with their members' user ids and the tournament they belong to.

export async function findAllByChatRoomIds(chatRoomIds: number[])
function

findAllMembersByTeamIds

:55

Members of the given teams, one row per member.

export async function findAllMembersByTeamIds(tournamentTeamIds: number[])
function

setActiveRoster

no JSDoc:68
export function setActiveRoster({
	teamId,
	activeRosterUserIds,
}: {
	teamId: number;
	activeRosterUserIds: number[] | null;
})
function

updateMemberInGameName

no JSDoc:119
export function updateMemberInGameName({
	userId,
	inGameName,
	tournamentTeamId,
}: {
	userId: number;
	inGameName: string;
	tournamentTeamId: number;
})
function

updateOwnMemberInGameNameForNonStarted

:149

Updates the acting user's in-game name in tournaments not yet started, returning the ids of those tournaments.

export async function updateOwnMemberInGameNameForNonStarted(
	inGameName: string,
	trx: Transaction<DB>,
): Promise<number[]>
function

insert

no JSDoc:176
export function insert({
	team,
	avatarImgId = null,
	userId,
	additionalMemberUserIds = [],
	tournamentId,
}: {
	team: Pick<Tables["TournamentTeam"], "name" | "prefersNotToHost" | "teamId">;
	avatarImgId?: number | null;
	/** The user who becomes the team owner. */
	userId: number;
	/** Non-owner members to add to the team on creation. */
	additionalMemberUserIds?: number[];
	tournamentId: number;
})
function

upsertRegistration

:273

Creates a registration or applies a full-state edit to an existing one (tournamentTeamId) in one transaction: name, linked team, owner, members, in-game names, tournament names and counterpick map pool. The caller validates the ops and handles side effects (caches, notifications). Returns the tournament name changes actually applied (values equal to the current one are no-ops), for the caller to log.

export function upsertRegistration({
	tournamentTeamId,
	tournamentId,
	name,
	teamId,
	avatarImgId,
	ownerUserId,
	ownerChange,
	membersToAdd,
	membersToRemove,
	inGameNameUpdates,
	tournamentNameUpdates,
	mapPool,
}: {
	/** Present when editing an existing team, omitted when creating a new one. */
	tournamentTeamId?: number;
	tournamentId: number;
	name: string;
	/** Linked sendou.ink team id, or null for a pickup team. */
	teamId: number | null;
	/** Resolved pickup team logo image id (null for none / linked teams). */
	avatarImgId: number | null;
	/** Roster owner/captain. Assigned the OWNER role when creating a new team. */
	ownerUserId: number;
	/** Owner transfer for an existing team (null when unchanged or when creating). */
	ownerChange: { oldOwnerId: number; newOwnerId: number } | null;
	membersToAdd: number[];
	membersToRemove: number[];
	inGameNameUpdates: Array<{ userId: number; inGameName: string }>;
	/** Organizer-set names shown in every tournament. `null` clears the user's current one. */
	tournamentNameUpdates: Array<{
		userId: number;
		tournamentName: string | null;
	}>;
	/** Counterpick map pool to replace the team's with. Omitted leaves it as is. */
	mapPool?: MapPool;
})
Unit tests (6)
function

update

no JSDoc:554
export function update({
	team,
	avatarImgId,
}: {
	team: Pick<
		Tables["TournamentTeam"],
		"id" | "name" | "prefersNotToHost" | "teamId"
	>;
	/** Resolved logo image id. `null` clears the pickup avatar (e.g. when switching to a linked team). */
	avatarImgId: number | null;
})
function

updateStartingBrackets

no JSDoc:584
export function updateStartingBrackets(
	startingBrackets: {
		tournamentTeamId: number;
		startingBracketIdx: number;
	}[],
)
function

updateAbDivisions

no JSDoc:612
export function updateAbDivisions(
	abDivisions: {
		tournamentTeamId: number;
		abDivision: 0 | 1 | null;
	}[],
)
function

checkIn

:642

Checks a team in to the whole tournament, or to one bracket with bracketIdx. Clears existing check-outs first.

export function checkIn(
	tournamentTeamId: number,
	options?: { bracketIdx?: number },
)
function

checkOut

no JSDoc:686
export function checkOut({
	tournamentTeamId,
	bracketIdx,
}: {
	tournamentTeamId: number;
	bracketIdx: number | null;
})
function

dropOut

no JSDoc:727
export function dropOut({
	tournamentTeamId,
	previewBracketIdxs,
}: {
	tournamentTeamId: number;
	previewBracketIdxs: number[];
})
function

undoDropOut

no JSDoc:759
export function undoDropOut(tournamentTeamId: number)
function

join

:780

@returns user ids whose chat room set changed, for notifyRoomsChanged.

export function join({
	previousTeamIdToDelete,
	newTeamId,
	userId,
	isOrganizerAdded = false,
}: {
	/** Team to delete as the user joins, e.g. a solo team they leave behind. */
	previousTeamIdToDelete?: number;
	newTeamId: number;
	userId: number;
	/** Added by the organizer rather than joining on their own. */
	isOrganizerAdded?: boolean;
}): Promise<number[]>
Unit tests (1)
function

deleteById

:852

@returns user ids whose chat room set changed, for notifyRoomsChanged.

export function deleteById(tournamentTeamId: number): Promise<number[]>
Unit tests (2)
function

isOrganizerAddedMember

:874

Whether the organizer added the user to the team rather than the user joining on their own.

export async function isOrganizerAddedMember({
	tournamentTeamId,
	userId,
}: {
	tournamentTeamId: number;
	userId: number;
})
function

leave

no JSDoc:891
export function leave({ teamId, userId }: { teamId: number; userId: number })
function

upsertCounterpickMaps

no JSDoc:910
export function upsertCounterpickMaps(args: {
	tournamentTeamId: Tables["TournamentTeam"]["id"];
	mapPool: MapPool;
})
function

findAllRegistrationsByUserIds

:975

Registrations of the given users starting within the window, one row per member per event date; dropped-out teams and hidden events excluded. Rows also carry what estimating the tournament's duration needs (settings, registered team count) for availability commitments. excludeTournamentId leaves one tournament out, for "busy elsewhere" views of that tournament.

export function findAllRegistrationsByUserIds({
	userIds,
	startsAt,
	endsAt,
	excludeTournamentId,
}: {
	userIds: Array<number>;
	startsAt: number;
	endsAt: number;
	excludeTournamentId?: number;
})
Unit tests (3)
function

findInviteCodeById

:1033

Invite code of one team, the secret the tournament layout data does not carry.

export async function findInviteCodeById(tournamentTeamId: number)
function

findAllChatRoomIdsByIds

:1044

Chat rooms of the given teams, left out for teams without one (only pickup teams formed via LFG have one).

export async function findAllChatRoomIdsByIds(tournamentTeamIds: number[])
function

isPickupAvatarImgId

:1057

Whether some team of some tournament has this image as its pickup logo; organizers copy those when importing teams.

export async function isPickupAvatarImgId(imgId: number)
Unit tests (1)
function

findByInviteCode

no JSDoc:1067
export function findByInviteCode(inviteCode: string)
function

findMapPoolsByTeamIds

:1076

Map pools of the given tournament teams, keyed by tournament team id.

export async function findMapPoolsByTeamIds(tournamentTeamIds: number[])
function

findRecentlyPlayedMapsByIds

no JSDoc:1106
export async function findRecentlyPlayedMapsByIds({
	teamIds,
	excludeMatchId,
	limit = 5,
}: {
	teamIds: [number, number];
	/** The match the maps are resolved for, left out so its own played games don't change the map list mid-set. */
	excludeMatchId: number;
	/** Recent maps per team, default 5. */
	limit?: number;
}): Promise<Array<{ mode: ModeShort; stageId: StageId }>>
Unit tests (1)