Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | 415x 8992x 8992x 8992x 415x 9x 415x 2507x 2507x 2507x 2507x 2201x 330x 318x 3x 315x 415x 1747x 1747x 1747x 415x 47x 47x 33x 14x 14x 14x 14x 6x 8x 415x 2905x 2905x 135x 134x 7x 2776x 2671x 2671x 2671x 2671x 2184x 532x 487x 150x 47x 52x 103x 52x 62x 52x 415x 5948x 415x 549x 549x 415x 1124x 1124x 1124x 415x 573x 573x 573x 573x 573x 415x 1126x 1126x 1126x 415x 1122x 1122x | import dayjs, { Dayjs } from "dayjs";
import { config } from "shared/config";
import { ProgramItem } from "shared/types/models/programItem";
import { TIMEZONE } from "shared/utils/initializeDayjs";
import { isDirectSignupAlwaysOpen } from "shared/utils/isDirectSignupAlwaysOpen";
import { isPreConventionWeekProgramItem } from "shared/utils/isPreConventionWeekProgramItem";
// Resolve a program item's effective start time, applying the parent override that batches
// several items into a single lottery run
export const getProgramItemStartTime = (programItem: ProgramItem): string => {
const { startTimesByParentIds } = config.event();
const parentStartTime = startTimesByParentIds.get(programItem.parentId);
return parentStartTime ?? programItem.startTime;
};
// Open the whole batch at a fixed hour the previous evening. startOf("day") zeroes the
// minutes/seconds so an item starting at e.g. 09:15 opens at 22:00, not 22:15
const openAtFixedHourPreviousEvening = (
timezoneStartTime: Dayjs,
hour: number,
): Dayjs => timezoneStartTime.subtract(1, "day").startOf("day").hour(hour);
export const getLotterySignupStartTime = (programItem: ProgramItem): Dayjs => {
const { eventStartTime, preSignupStart, fixedLotterySignupTime } =
config.event();
const startTime = getProgramItemStartTime(programItem);
// Set timezone because hour comparison and setting hour value
const timezoneStartTime = fixedLotterySignupTime
? dayjs(fixedLotterySignupTime).tz(TIMEZONE)
: dayjs(startTime).tz(TIMEZONE).subtract(preSignupStart, "minutes");
// If lottery signup starts before event start time, use event start time
if (timezoneStartTime.isBefore(dayjs(eventStartTime))) {
return dayjs(eventStartTime);
}
const startTimeIsTooEarly = timezoneStartTime.hour() <= 6;
if (startTimeIsTooEarly) {
return openAtFixedHourPreviousEvening(timezoneStartTime, 22);
}
return timezoneStartTime;
};
export const getLotterySignupEndTime = (programItem: ProgramItem): Dayjs => {
const { directSignupPhaseStart } = config.event();
const startTime = getProgramItemStartTime(programItem);
return dayjs(startTime).subtract(directSignupPhaseStart, "minutes");
};
export const getRollingDirectSignupStartTime = (
programItem: ProgramItem,
eventStartTime: string,
): Dayjs => {
// Signup starts 4 hours before program item start time
const rollingStartTime = dayjs(programItem.startTime).subtract(4, "hours");
// Earliest start time is event start time
if (rollingStartTime.isBefore(dayjs(eventStartTime))) {
return dayjs(eventStartTime);
}
// If program item starts before 12:00, signup starts 18:00 previous day
Eif (config.event().enableRollingDirectSignupPreviousDay) {
// Set timezone because hour comparison and setting hour value
const timezoneStartTime = dayjs(programItem.startTime).tz(TIMEZONE);
const startTimeIsTooEarly = timezoneStartTime.hour() < 12;
if (startTimeIsTooEarly) {
return openAtFixedHourPreviousEvening(timezoneStartTime, 18);
}
}
return rollingStartTime;
};
export const getDirectSignupStartTime = (programItem: ProgramItem): Dayjs => {
const {
eventStartTime,
preConventionWeekSignupStartTime,
directSignupPhaseStart,
phaseGap,
directSignupWindows,
rollingDirectSignupProgramTypes,
twoPhaseSignupProgramTypes,
} = config.event();
// ** SIGNUP ALWAYS OPEN **
if (isDirectSignupAlwaysOpen(programItem)) {
// Pre-convention week items take place before the event starts, so they have
// their own signup start time instead of the event start time
if (
preConventionWeekSignupStartTime &&
isPreConventionWeekProgramItem(programItem)
) {
return dayjs(preConventionWeekSignupStartTime);
}
return dayjs(eventStartTime);
}
// ** TWO PHASE SIGNUPS **
// 'twoPhaseSignupProgramTypes' signup times are configured with 'directSignupPhaseStart'
if (twoPhaseSignupProgramTypes.includes(programItem.programType)) {
const startTime = getProgramItemStartTime(programItem);
const directSignupStart = dayjs(startTime).subtract(
directSignupPhaseStart,
"minutes",
);
// If event starts at 15:00, 'directSignupPhaseStart' is 2h and 'phaseGap' is 15min
// Start time 15:00 -> signup start 13:00 -> fix to 15:00
// Start time 16:00 -> signup start 14:00 -> fix to 15:00
// Start time 17:00 -> signup start 15:15 -> fix to 15:00
// Start time 18:00 -> signup start 16:15 -> this is fine
const signupsBeforeThisStartAtEventStart = dayjs(eventStartTime).add(
1,
"hour",
);
if (dayjs(directSignupStart).isBefore(signupsBeforeThisStartAtEventStart)) {
return dayjs(eventStartTime);
}
const directSignupStartWithPhaseGap = directSignupStart.add(
phaseGap,
"minutes",
);
return directSignupStartWithPhaseGap;
}
// ** ROLLING DIRECT SIGNUP **
if (rollingDirectSignupProgramTypes.includes(programItem.programType)) {
return getRollingDirectSignupStartTime(programItem, eventStartTime);
}
// ** DIRECT SIGNUP WINDOWS **
// Other program types use "directSignupWindows" config
const signupWindowsForProgramType = directSignupWindows
? directSignupWindows[programItem.programType]
: undefined;
Iif (!signupWindowsForProgramType) {
return dayjs(eventStartTime);
}
const matchingSignupWindow = signupWindowsForProgramType.find(
(signupWindow) =>
dayjs(programItem.startTime).isBetween(
signupWindow.signupWindowStart,
signupWindow.signupWindowClose,
"minutes",
"[)", // Include windowStart, exclude windowClose
),
);
return matchingSignupWindow?.signupWindowStart ?? dayjs(eventStartTime);
};
export const getDirectSignupEndTime = (programItem: ProgramItem): Dayjs => {
return dayjs(programItem.startTime);
};
export const getLotterySignupNotStarted = (
programItem: ProgramItem,
timeNow: Dayjs,
): boolean => {
const lotterySignupStartTime = getLotterySignupStartTime(programItem);
return timeNow.isBefore(lotterySignupStartTime);
};
export const getLotterySignupInProgress = (
programItem: ProgramItem,
timeNow: Dayjs,
): boolean => {
const lotterySignupStartTime = getLotterySignupStartTime(programItem);
const lotterySignupEndTime = getLotterySignupEndTime(programItem);
return (
timeNow.isSameOrAfter(lotterySignupStartTime) &&
timeNow.isSameOrBefore(lotterySignupEndTime)
);
};
export const getPhaseGapInProgress = (
programItem: ProgramItem,
timeNow: Dayjs,
): boolean => {
const { phaseGap } = config.event();
const directSignupStartTime = getDirectSignupStartTime(programItem);
// Delay showing lottery results immediately since lottery is still running
const DELAY_SHOW_AFTER_LOTTERY = 1;
const phaseGapStart = directSignupStartTime.subtract(
phaseGap - DELAY_SHOW_AFTER_LOTTERY,
"minutes",
);
return (
timeNow.isSameOrAfter(phaseGapStart) &&
timeNow.isBefore(directSignupStartTime)
);
};
export const getDirectSignupInProgress = (
programItem: ProgramItem,
timeNow: Dayjs,
): boolean => {
const directSignupStartTime = getDirectSignupStartTime(programItem);
const directSignupEndTime = getDirectSignupEndTime(programItem);
return (
timeNow.isSameOrAfter(directSignupStartTime) &&
timeNow.isSameOrBefore(directSignupEndTime)
);
};
export const getDirectSignupEnded = (
programItem: ProgramItem,
timeNow: Dayjs,
): boolean => {
const directSignupEndTime = getDirectSignupEndTime(programItem);
return timeNow.isAfter(directSignupEndTime);
};
|