Scrim
app/features/scrims/core/Scrim.tsRules 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
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 }; }
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
Returns true if the original poster has accepted any of the requests.
export function isAccepted(post: ScrimPost)
Unit tests (1)
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)
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)
Participant ids of an accepted post (one whose scrim page exists).
export function participantIdsListFromAccepted(post: ScrimPost)
Unit tests (4)
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)
- $why× 3
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)
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)
- with no filters › returns true when all filters are null
- division filters › returns
- true when post has no divs but filter has divs
- true when only filter min is set and post max is at or above filter min
- false when only filter min is set and post max is below filter min
- true when only filter max is set and post min is at or below filter max
- false when only filter max is set and post min is above filter max
- true when post divs overlap with filter divs
- true when post divs exactly match filter divs
- false when post divs are too high for filter
- false when post divs are too low for filter
- weekday time filters › returns
- true when post time overlaps with weekday time filter
- false when post time is before weekday time filter
- false when post time is after weekday time filter
- true when post time range overlaps with weekday time filter
- false when post time range does not overlap with weekday time filter
- true when post time range ends exactly at the filter start edge
- true when a post time range crossing midnight overlaps the filter
- true when a filter crossing midnight covers the post time
- weekend time filters › returns
- weekend time filters › ignores weekday time filter on weekends
- combined filters › returns
No filters set, what the list shows when the user has saved no defaults of their own.
export function defaultFilters(): ScrimFilters
Unit tests (1)
Whether no filter is set.
export function filtersAreDefault(filters: ScrimFilters): boolean
Unit tests (1)
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)
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)
- returns
- false when no map list submitted yet
- false just inside the auto-lock window from list submission
- true just past the auto-lock window from list submission
- false when the map list was submitted long before a scrim that just started
- true once the auto-lock window has elapsed since the start time
- false for a scrim that has not started yet
- uses
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)
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)
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)
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)
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