Skip to content

Scrims · Modules

2 modules · 22 exports · 4 repositories · 12 e2e tests · 3 routes

Who imports who · hover a node
Depends onScrims modulesUsed byAvailabilityavailabilityMapListmap-list-generatorScrim18 exportsScrimMapByMap4 exportsLoaders2 filesActions2 filesRoutes1 fileRepositories2 filesComponents7 filesRoutines1 fileOther1 file

Scrim

app/features/scrims/core/Scrim.ts

Rules of a scrim post: who takes part and on which side (the post's users are ALPHA, the accepted request's BRAVO), when it starts, which posts the list filters keep, when map-by-map tracking locks and how a team's availability fits a post.

Imports
Availability
Used by
2 loaders2 actions1 route2 repositories6 components1 routine1 other

Types

interface

PickableSlot

:223

A start the new post form offers, from the roster's shared free time.

export interface PickableSlot extends TimeRange {
	tier: PlayableWindowTier;
	/** Members free for the whole slot. */
	userIds: Array<number>;
	/** The part of the slot the whole team is free for, when that is only part of it. */
	fullSpan: TimeRange | null;
	/** What picking the slot fills the post's start and start-time flexibility with. */
	pick: { startsAt: number; rangeEnd: RangeEndOption | null };
}
interface

RosterFit

:283

How a roster's availability fits a post, shown as the fit indicator on the post's card.

export interface RosterFit {
	/** The start the fit is measured at, the best one of those offered. */
	startsAt: number;
	/** The scrim played from that start, its length assumed. */
	window: TimeRange;
	entries: Array<WindowAvailabilityEntry>;
	/** How many of the roster are free for the whole window. */
	availableCount: number;
}

Functions & values

function

isAccepted

:35

Returns true if the original poster has accepted any of the requests.

export function isAccepted(post: ScrimPost)
Unit tests (1)
function

isParticipating

:40

Returns true if the user is participating in the scrim, either in the original post users list or the request.

export function isParticipating(post: ScrimPost, userId: number)
Unit tests (1)
function

resolvePoolCode

:49

The in-game private battle pool both sides join, spread over SC1–SC9 by the post's id so scrims don't share one.

export function resolvePoolCode(postId: number)
Unit tests (1)
function

participantIdsListFromAccepted

:54

Participant ids of an accepted post (one whose scrim page exists).

export function participantIdsListFromAccepted(post: ScrimPost)
Unit tests (4)
Actions/scrims
function

getStartTime

:69

The scrim's actual start: the accepted request's time when the post has a range (rangeEndsAt set), else the post's start.

export function getStartTime(post: ScrimPost): number
Unit tests (1)
function

sideDisplayName

:75

Display name of a scrim side: the team name, else "{ownerUsername}'s pickup".

export function sideDisplayName(side: {
	team: { name: string } | null;
	users: Array<{ username: string; isOwner: boolean }>;
}): string
Unit tests (2)
function

applyFilters

:85

Whether the post passes the list filters: its LUTI div range (when it has one) and its time overlap the filter's, the time compared against the weekday or weekend filter by the post's day.

export function applyFilters(post: ScrimPost, filters: ScrimFilters): boolean
Unit tests (26)
Routes/scrims
function

defaultFilters

:148

No filters set, what the list shows when the user has saved no defaults of their own.

export function defaultFilters(): ScrimFilters
Unit tests (1)
Loaders/scrims
function

filtersAreDefault

:157

Whether no filter is set.

export function filtersAreDefault(filters: ScrimFilters): boolean
Unit tests (1)
Loaders/scrims
Routes/scrims
function

sideOfUser

:162

The user's side in the scrim (post's users are ALPHA, accepted request's are BRAVO), or null when not in the accepted pairing.

export function sideOfUser(post: ScrimPost, userId: number): ScrimSide | null
Unit tests (4)
function

isTrackingLocked

:176

Whether map-by-map tracking is locked: the auto-lock window has elapsed since the last activity (latest reported map, else latest submitted map list). The window only starts running once the scrim is under way. False when no map list has been submitted yet.

export function isTrackingLocked({
	startTime,
	maps = [],
	mapLists = [],
	now = Date.now(),
}: {
	startTime: number;
	maps?: Pick<Tables["ScrimMap"], "reportedAt">[];
	mapLists?: Pick<Tables["ScrimMapList"], "updatedAt">[];
	now?: number;
}): boolean
Unit tests (8)
function

nextMapIndex

:205

The next 0-based map index to insert; existing maps need not be ordered.

export function nextMapIndex(
	maps: Pick<Tables["ScrimMap"], "index">[],
): number
Unit tests (1)
function

lastReportedMap

:213

The most recently reported map (by index), or undefined if none.

export function lastReportedMap<
	T extends Pick<Tables["ScrimMap"], "index" | "reportedAt">,
>(maps: T[]): T | undefined
Unit tests (2)
function

pickableSlots

:234

The roster's shared free time as pickable slots: maximal spans where the team is at most one player short (ONE_SHORT = "grab a sub").

export function pickableSlots({
	members,
	minPlayers,
}: {
	members: Array<MemberAvailability>;
	minPlayers: number;
}): Array<PickableSlot>
Unit tests (6)
function

teamPlayers

:272

The members a scrim is played with: the team's players, or the whole roster when too few players to field a team.

export function teamPlayers<
	T extends { role: MemberRole | null; roleType: MemberRoleType | null },
>(members: Array<T>): Array<T>
Unit tests (2)
function

rosterFit

:297

How well a roster fits a post: the start among starts most of them are free for (ties to the earliest) and how each member relates to it. Null when nobody filled in the post's week.

export function rosterFit({
	starts,
	members,
}: {
	starts: Array<number>;
	members: Array<WindowSchedule>;
}): RosterFit | null
Unit tests (5)

ScrimMapByMap

app/features/scrims/core/ScrimMapByMap.ts

Map-by-map play of a booked scrim: the map pool from both sides' submitted map lists, the next map generated from it, which report can be undone and the win/loss stats of the reported maps.

Imports
MapList
Used by
1 loader1 action1 repository2 components

Functions & values

function

unionPool

:22

Merges the submitted map lists into one deduplicated MapPool.

export function unionPool(lists: ResolvedMapListRow[]): MapPool
Unit tests (2)
function

generateNextMap

:49

The scrim's next map, keeping the pool's mode order stable across calls and avoiding played (mode, stage) pairs.

export function generateNextMap(args: {
	pool: MapPool;
	history: Pick<Tables["ScrimMap"], "mode" | "stageId">[];
}): { mode: ModeShort; stageId: StageId }
Unit tests (5)
function

canUndo

:73

Whether the map is the most recently reported one, and so can be undone.

export function canUndo(
	map: ScrimMapRow | undefined,
	history: ScrimMapRow[],
): boolean
Unit tests (5)
function

stats

:100

Per-mode, per-stage and per-(stage, mode) win/loss counts from the viewer's perspective; unreported maps and ones outside restrictToPool are skipped, empty rows dropped.

export function stats(
	maps: ScrimMapRow[],
	viewerSide: "ALPHA" | "BRAVO",
	opts: { restrictToPool?: MapPool } = {},
): Stats
Unit tests (4)