ScannerIngestRepository
app/features/scanner-ingest/ScannerIngestRepository.server.ts- Tables
- CalendarEventGroupMatchGroupMatchMapGroupMemberIngestedMatchIngestedMatchLinkReportedWeaponTournamentTournamentMatchTournamentMatchGameResultTournamentMatchGameResultParticipantTournamentOrganizationMemberTournamentStaffTournamentStageTournamentTeamTournamentTeamMemberUser
- Calls
- no other repositories
- Imports
- MatchesScoreboards
- Used by
- 3 loaders1 action1 repository1 routine1 script1 other
Functions & values
Returns the games a user played in a tournament, in chronological order.
export function gamesPlayedByUserInTournament(params: { userId: number; tournamentId: number; })
Games a user played in any tournament since the timestamp, chronological — candidates for Scoreboards.resolveContext.
export function gamesPlayedByUserSince(params: { userId: number; /** database timestamp (seconds) */ since: number; })
Games of a tournament's casted sets (streamed now plus cast history), chronological — candidates for cast footage, whose submitter is staff.
export async function castedGamesInTournament(tournamentId: number)
Reported games of the given tournament matches, chronological — candidates for a live send, which has no sequence to anchor on and must not see the rest of the tournament.
export function gamesInTournamentMatches(tournamentMatchIds: number[])
A SendouQ match's reported games in map order. Unplayed maps are left out: a scan sent before its game's report stays unlinked until a resend.
export function gamesInGroupMatch(groupMatchId: number)
Reported SendouQ games a user played since the timestamp, chronological — candidates for Scoreboards.resolveContext.
export function sendouqGamesPlayedByUserSince(params: { userId: number; /** database timestamp (seconds) */ since: number; })
The tournament match the user was probably playing at at: their team's match whose startedAt is close enough before it. The most recently started wins — a later round of the same event is still within the window and would scope an earlier set's games out of reach.
export async function tournamentActivityAt({ userId, at, }: { userId: number; /** wall-clock ms */ at: number; })
The SendouQ match the user was probably playing at at: their group's non-canceled match created close enough before it. The most recently created wins — queueing again right after a set still falls within the window.
export async function groupMatchIdAt({ userId, at, }: { userId: number; /** wall-clock ms */ at: number; })
Tournaments with a match around at the user helps run (author, organizer/streamer staff, or org admin/organizer/streamer) — candidate contexts for cast footage.
export async function staffTournamentIdsAt({ userId, at, }: { userId: number; /** wall-clock ms */ at: number; }): Promise<number[]>
A tournament match's ingested scoreboards with 0-based map indexes, derived from each game's linked ingests.
export async function findScoreboardsByTournamentMatchId( tournamentMatchId: number, )
A SendouQ match's ingested scoreboards with 0-based map indexes, derived from each map's linked ingests.
export async function findScoreboardsByGroupMatchId(groupMatchId: number)
Stores ingested matches, merging partials: one Matches.isSameMatch recognizes (same POV user scope) enriches the stored row instead of inserting; identical resends are no-ops via the content hash. The resolved context is stamped as tournamentIdHint/groupMatchIdHint (existing hints win, missing ones backfilled even on no-op resends).
export async function addOrMergeMatches({ povUserId, submitterUserId, matches, context, }: { povUserId: number | null; submitterUserId: number | null; matches: ScannerMatch[]; context: IngestContext | null; })
Unit tests (3)
Links ingested matches to their matched game results. A row links to at most one game (re-sends are no-ops); a game collects links from many rows (each POV's scan), one per POV user. A known POV player's weapon (Scoreboards.povWeaponId) is reported as a ReportedWeapon tagged with its ingested match, unless they already have one for that game or the row stays linked to another game.
export async function addLinks({ links, povUserId, }: { links: Array<{ ingestedMatchId: number; match: ScannerMatch; game: IngestableGame; }>; povUserId: number | null; })
Unit tests (6)
Stored matches of the given POV users hinted to the context and played since playedSince that no game links yet, chronological, at most UNLINKED_MATCHES_LIMIT.
export async function findUnlinkedMatchesByHint({ context, playedSince, povUserIds, }: { context: IngestContext; /** database timestamp (seconds) */ playedSince: number; povUserIds: number[]; })
The matches the user stored in the last hour and the size of those stored in the last day, as the ingest quota counts them.
export async function findIngestQuotaUsage({ povUserId, hourStart, dayStart, }: { povUserId: number; /** database timestamp (seconds) */ hourStart: number; /** database timestamp (seconds) */ dayStart: number; })
Deletes stored matches created before the timestamp that could have linked (private battles, unread lobbies) but never did, keeping any a reported weapon still points to.
export function deleteUnlinkedMatchesCreatedBefore( /** database timestamp (seconds) */ createdBefore: number, )
Unlinks every ingested match from a SendouQ map, as when its report is undone.
export async function deleteLinksByGroupMatchMapId( groupMatchMapId: number, trx?: Transaction<DB>, )