Skip to content

Tournament match · Modules

1 module · 15 exports · 1 repository · 0 e2e tests · 2 routes

Who imports who · hover a node
Depends onTournament match modulesUsed byLeagueScheduling15 expo…Loaders2 filesActions1 fileCommitments.serveravail…Components3 filesRoutines1 fileOther5 files

LeagueScheduling

app/features/tournament-match/core/LeagueScheduling.ts

No overview comment at the top of the file.

Imports
no other modules
Used by
2 loaders1 action1 module3 components1 routine5 other

Types

type

Phase

:32

CLOSED = nothing to schedule (no scheduling in the bracket, over, or a team missing), NOT_OPEN = the board opens later, UNSCHEDULED = the teams are agreeing on a time, SCHEDULED_LOCKED = a time is agreed but the round is not playable yet, SCHEDULED = agreed and playable.

export type Phase =
	| "CLOSED"
	| "NOT_OPEN"
	| "UNSCHEDULED"
	| "SCHEDULED_LOCKED"
	| "SCHEDULED";
Only used inside the module
type

ProposalError

no JSDoc:39
export type ProposalError =
	| "NOT_OPEN"
	| "BEFORE_PLAYABLE"
	| "IN_PAST"
	| "TOO_MANY"
	| "ORGANIZER_LOCKED";

Functions & values

const

LEAGUE_SCHEDULING

no JSDoc:6
export const LEAGUE_SCHEDULING = {
	/** Teams can put candidate times up this long before the round becomes playable. */
	OPENS_BEFORE_PLAYABLE_SECONDS: DAY_SECONDS,
	/** Sanity cap on a team's open candidates per set. */
	MAX_OPEN_PROPOSALS_PER_TEAM: 6,
	/** How long before the agreed time a set counts as live while a member streams. */
	LIVE_BEFORE_SECONDS: HOUR_SECONDS / 2,
	/** How long after the agreed time a set without a winner still counts as live. */
	LIVE_AFTER_SECONDS: HOUR_SECONDS,
	/** Length of the busy block a scheduled set puts on its players' schedules. */
	SET_DURATION_SECONDS: HOUR_SECONDS,
	/** Availability is shown until the next round opens, or this long when there is no next round. */
function

phase

:47

Which point of the scheduling flow the set is at; every timestamp in unix seconds.

export function phase({
	hasScheduling,
	isOver,
	hasBothTeams,
	isPlayableAt,
	scheduledAt,
	now,
}: {
	/** False outside leagues and in a league's real-time brackets. */
	hasScheduling: boolean;
	isOver: boolean;
	hasBothTeams: boolean;
	isPlayableAt: number | null;
	scheduledAt: number | null;
	now: number;
}): Phase
Unit tests (1)
function

opensAt

:77

When teams can start putting times on the board: a day before the round is playable, right away without a playable time.

export function opensAt(isPlayableAt: number | null)
Unit tests (2)
function

playableAtFromDate

:84

When a round picked to be playable on date's calendar day (read in local time) opens: the start of that day in UTC+14.

export function playableAtFromDate(date: Date)
Unit tests (1)
function

playableDate

:92

The calendar day a round is playable from, as local midnight, so formatting it shows the organizer's picked date in any time zone.

export function playableDate(isPlayableAt: number)
Unit tests (1)
function

playableAtsAreAscending

:105

Whether no round becomes playable before an earlier round of its section; rounds in play order, those without a time skipped.

export function playableAtsAreAscending(
	rounds: Array<{ section?: string | null; isPlayableAt?: number | null }>,
)
Unit tests (2)
function

validateProposals

:124

Whether a team may replace its candidate times with proposedAts now, and if not, why; times it already has up are not rechecked.

export function validateProposals({
	proposedAts,
	existingProposedAts,
	phase: currentPhase,
	isPlayableAt,
	now,
	setByOrganizer,
}: {
	/** The team's full new set of candidates. */
	proposedAts: Array<number>;
	/** The team's candidates currently on the board. */
	existingProposedAts: Array<number>;
	phase: Phase;
	isPlayableAt: number | null;
	now: number;
	setByOrganizer: boolean;
}): ProposalError | null
Unit tests (1)
function

shouldAnnounceProposals

:164

Whether a team putting up new candidate times gets a chat line. Not when the room's latest message already announces the same team's times recently, so repeated updates can't flood the chat.

export function shouldAnnounceProposals({
	latestMessage,
	teamMemberUserIds,
	now,
}: {
	latestMessage:
		| {
				type: string | null;
				authorUserId: number | null;
				createdAt: number;
		  }
		| undefined;
	teamMemberUserIds: Array<number>;
	now: number;
})
Unit tests (1)
function

isAcceptableProposal

:196

Whether a candidate time can still be picked: it has to be ahead.

export function isAcceptableProposal({
	proposedAt,
	now,
}: {
	proposedAt: number;
	now: number;
})
Unit tests (1)
function

liveWindow

:207

The span around the agreed time in which the set counts as live while somebody streams it.

export function liveWindow(scheduledAt: number): TimeRange
function

isLive

:215

Whether the set is inside its live window and still undecided.

export function isLive({
	scheduledAt,
	hasWinner,
	now,
}: {
	scheduledAt: number;
	hasWinner: boolean;
	now: number;
})
Unit tests (2)
function

busyBlock

:232

The span a scheduled set blocks on its players' schedules.

export function busyBlock(scheduledAt: number): TimeRange
function

availabilityWindow

:243

The span the availability panel covers: from the round becoming playable (or now, once it is) to the next round becoming playable, a week when there is no next round or it opens no later.

export function availabilityWindow({
	now,
	isPlayableAt,
	nextIsPlayableAt,
}: {
	now: number;
	isPlayableAt: number | null;
	nextIsPlayableAt: number | null;
}): TimeRange
Unit tests (5)