brackt/app/lib/draft-order.ts
Claude 4cb7424ae4
Address code review feedback on draft order bug fix
- Move buildDraftOrderTeams to app/lib/draft-order.ts so it is importable
  and testable; remove the local copy from the settings component
- Add unit tests for buildDraftOrderTeams covering the empty, full, and
  partial-slot cases
- Tighten the draft slot guard from existingSlots.length > 0 to
  existingSlots.length === currentTeamCount so partial legacy states are
  treated the same as "order not set"
- Condense the 3-line server comment to a single line per project style
- Rename getNumTeamsInSeason → getNumDraftSlotsBySeasonId to reflect what
  the function actually counts, and update its one call site
- Add tests for the server-side slot-creation guard logic

https://claude.ai/code/session_01M3H55gnMxRztJK9KMXqqZo
2026-05-20 01:07:34 +00:00

82 lines
2.4 KiB
TypeScript

/**
* Builds the ordered team-ID list for the draft order UI.
* Slotted teams come first (in their configured order); any teams without a
* slot are appended at the end so all teams are always visible.
*/
export function buildDraftOrderTeams(
slots: { teamId: string }[],
allTeams: { id: string }[]
): string[] {
if (slots.length === 0) return allTeams.map((t) => t.id);
const slottedIds = new Set(slots.map((s) => s.teamId));
const unslotted = allTeams.filter((t) => !slottedIds.has(t.id)).map((t) => t.id);
return [...slots.map((s) => s.teamId), ...unslotted];
}
/**
* Returns the draft slot for a given pick number in a snake draft.
*/
export function getTeamForPick<T extends { draftOrder: number }>(
pickNumber: number,
draftSlots: T[]
): T | undefined {
const totalTeams = draftSlots.length;
if (totalTeams === 0) return undefined;
const round = Math.ceil(pickNumber / totalTeams);
const isEvenRound = round % 2 === 0;
let pickInRound = ((pickNumber - 1) % totalTeams) + 1;
if (isEvenRound) {
pickInRound = totalTeams - pickInRound + 1;
}
return draftSlots.find((slot) => slot.draftOrder === pickInRound);
}
export interface ProjectedPick {
round: number;
pickNumber: number;
picksFromNow: number;
}
export function getProjectedPicks(options: {
draftSlots: Array<{ draftOrder: number; teamId: string }>;
userTeamId: string;
currentPick: number;
totalRounds: number;
existingPicks: Array<{ pickNumber: number; teamId: string }>;
}): ProjectedPick[] {
const { draftSlots, userTeamId, currentPick, totalRounds, existingPicks } = options;
const totalTeams = draftSlots.length;
if (totalTeams === 0) return [];
const userSlot = draftSlots.find((slot) => slot.teamId === userTeamId);
if (!userSlot) return [];
const userDraftOrder = userSlot.draftOrder;
const pickedNumbersForTeam = new Set(
existingPicks
.filter((p) => p.teamId === userTeamId)
.map((p) => p.pickNumber)
);
const result: ProjectedPick[] = [];
for (let round = 1; round <= totalRounds; round++) {
const isEvenRound = round % 2 === 0;
const pickInRound = isEvenRound
? totalTeams - userDraftOrder + 1
: userDraftOrder;
const pickNumber = (round - 1) * totalTeams + pickInRound;
if (pickNumber < currentPick) continue;
if (pickedNumbersForTeam.has(pickNumber)) continue;
result.push({
round,
pickNumber,
picksFromNow: pickNumber - currentPick,
});
}
return result;
}