feat: add draft pick, queue, and timer models with database schema updates
This commit is contained in:
parent
6e19a23e35
commit
469a85a0f8
9 changed files with 1896 additions and 0 deletions
65
app/models/draft-pick.ts
Normal file
65
app/models/draft-pick.ts
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { database } from "~/database/context";
|
||||||
|
import * as schema from "~/database/schema";
|
||||||
|
import { eq, and } from "drizzle-orm";
|
||||||
|
|
||||||
|
export async function createDraftPick(data: {
|
||||||
|
seasonId: string;
|
||||||
|
teamId: string;
|
||||||
|
participantId: string;
|
||||||
|
pickNumber: number;
|
||||||
|
round: number;
|
||||||
|
pickInRound: number;
|
||||||
|
pickedByUserId: string;
|
||||||
|
pickedByType: "owner" | "commissioner" | "auto";
|
||||||
|
timeUsed: number;
|
||||||
|
}) {
|
||||||
|
const db = database();
|
||||||
|
const [pick] = await db.insert(schema.draftPicks).values(data).returning();
|
||||||
|
return pick;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDraftPicks(seasonId: string) {
|
||||||
|
const db = database();
|
||||||
|
return await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftPicks)
|
||||||
|
.where(eq(schema.draftPicks.seasonId, seasonId))
|
||||||
|
.orderBy(schema.draftPicks.pickNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDraftPickByNumber(seasonId: string, pickNumber: number) {
|
||||||
|
const db = database();
|
||||||
|
const [pick] = await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftPicks)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(schema.draftPicks.seasonId, seasonId),
|
||||||
|
eq(schema.draftPicks.pickNumber, pickNumber)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return pick;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTeamDraftPicks(teamId: string) {
|
||||||
|
const db = database();
|
||||||
|
return await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftPicks)
|
||||||
|
.where(eq(schema.draftPicks.teamId, teamId))
|
||||||
|
.orderBy(schema.draftPicks.pickNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isParticipantDrafted(seasonId: string, participantId: string) {
|
||||||
|
const db = database();
|
||||||
|
const [pick] = await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftPicks)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(schema.draftPicks.seasonId, seasonId),
|
||||||
|
eq(schema.draftPicks.participantId, participantId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return !!pick;
|
||||||
|
}
|
||||||
76
app/models/draft-queue.ts
Normal file
76
app/models/draft-queue.ts
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { database } from "~/database/context";
|
||||||
|
import * as schema from "~/database/schema";
|
||||||
|
import { eq, and, asc } from "drizzle-orm";
|
||||||
|
|
||||||
|
export async function addToQueue(data: {
|
||||||
|
seasonId: string;
|
||||||
|
teamId: string;
|
||||||
|
participantId: string;
|
||||||
|
queuePosition: number;
|
||||||
|
}) {
|
||||||
|
const db = database();
|
||||||
|
const [item] = await db.insert(schema.draftQueue).values(data).returning();
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeFromQueue(queueId: string) {
|
||||||
|
const db = database();
|
||||||
|
await db.delete(schema.draftQueue).where(eq(schema.draftQueue.id, queueId));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTeamQueue(teamId: string) {
|
||||||
|
const db = database();
|
||||||
|
return await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftQueue)
|
||||||
|
.where(eq(schema.draftQueue.teamId, teamId))
|
||||||
|
.orderBy(asc(schema.draftQueue.queuePosition));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function clearTeamQueue(teamId: string) {
|
||||||
|
const db = database();
|
||||||
|
await db.delete(schema.draftQueue).where(eq(schema.draftQueue.teamId, teamId));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function reorderQueue(teamId: string, participantIds: string[]) {
|
||||||
|
// Delete existing queue
|
||||||
|
await clearTeamQueue(teamId);
|
||||||
|
|
||||||
|
// Get season ID from first queue item (or we need to pass it)
|
||||||
|
// For now, we'll need to pass seasonId
|
||||||
|
return participantIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function reorderQueueWithSeason(
|
||||||
|
seasonId: string,
|
||||||
|
teamId: string,
|
||||||
|
participantIds: string[]
|
||||||
|
) {
|
||||||
|
// Delete existing queue
|
||||||
|
await clearTeamQueue(teamId);
|
||||||
|
|
||||||
|
// Insert new queue in order
|
||||||
|
const items = participantIds.map((participantId, index) => ({
|
||||||
|
seasonId,
|
||||||
|
teamId,
|
||||||
|
participantId,
|
||||||
|
queuePosition: index + 1,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (items.length > 0) {
|
||||||
|
const db = database();
|
||||||
|
await db.insert(schema.draftQueue).values(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeParticipantFromQueue(teamId: string, participantId: string) {
|
||||||
|
const db = database();
|
||||||
|
await db
|
||||||
|
.delete(schema.draftQueue)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(schema.draftQueue.teamId, teamId),
|
||||||
|
eq(schema.draftQueue.participantId, participantId)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
46
app/models/draft-timer.ts
Normal file
46
app/models/draft-timer.ts
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { database } from "~/database/context";
|
||||||
|
import * as schema from "~/database/schema";
|
||||||
|
import { eq } from "drizzle-orm";
|
||||||
|
|
||||||
|
export async function initializeDraftTimers(seasonId: string, teams: { id: string }[], initialTime: number) {
|
||||||
|
const timerData = teams.map((team) => ({
|
||||||
|
seasonId,
|
||||||
|
teamId: team.id,
|
||||||
|
timeRemaining: initialTime,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const db = database();
|
||||||
|
await db.insert(schema.draftTimers).values(timerData);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTeamTimer(teamId: string) {
|
||||||
|
const db = database();
|
||||||
|
const [timer] = await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftTimers)
|
||||||
|
.where(eq(schema.draftTimers.teamId, teamId));
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getSeasonTimers(seasonId: string) {
|
||||||
|
const db = database();
|
||||||
|
return await db
|
||||||
|
.select()
|
||||||
|
.from(schema.draftTimers)
|
||||||
|
.where(eq(schema.draftTimers.seasonId, seasonId));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateTeamTimer(teamId: string, timeRemaining: number) {
|
||||||
|
const db = database();
|
||||||
|
const [timer] = await db
|
||||||
|
.update(schema.draftTimers)
|
||||||
|
.set({ timeRemaining, updatedAt: new Date() })
|
||||||
|
.where(eq(schema.draftTimers.teamId, teamId))
|
||||||
|
.returning();
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteSeasonTimers(seasonId: string) {
|
||||||
|
const db = database();
|
||||||
|
await db.delete(schema.draftTimers).where(eq(schema.draftTimers.seasonId, seasonId));
|
||||||
|
}
|
||||||
160
app/models/draft-utils.ts
Normal file
160
app/models/draft-utils.ts
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
import { database } from "~/database/context";
|
||||||
|
import * as schema from "~/database/schema";
|
||||||
|
import { eq, and, notInArray, desc } from "drizzle-orm";
|
||||||
|
import { getTeamQueue } from "./draft-queue";
|
||||||
|
import { isParticipantDrafted } from "./draft-pick";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-pick for a team when their timer runs out
|
||||||
|
* 1. Check queue - pick first item if available
|
||||||
|
* 2. If queue empty, pick highest EV participant not drafted
|
||||||
|
*/
|
||||||
|
export async function autoPickForTeam(seasonId: string, teamId: string) {
|
||||||
|
// Check queue first
|
||||||
|
const queue = await getTeamQueue(teamId);
|
||||||
|
|
||||||
|
if (queue.length > 0) {
|
||||||
|
// Pick first item from queue
|
||||||
|
const firstInQueue = queue[0];
|
||||||
|
|
||||||
|
// Verify participant is not already drafted
|
||||||
|
const isDrafted = await isParticipantDrafted(seasonId, firstInQueue.participantId);
|
||||||
|
if (!isDrafted) {
|
||||||
|
return firstInQueue.participantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If first item was drafted, try next items in queue
|
||||||
|
for (const item of queue.slice(1)) {
|
||||||
|
const isDrafted = await isParticipantDrafted(seasonId, item.participantId);
|
||||||
|
if (!isDrafted) {
|
||||||
|
return item.participantId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Queue is empty or all queued players drafted - pick highest EV available
|
||||||
|
return await getTopAvailableParticipant(seasonId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the highest EV participant that hasn't been drafted yet
|
||||||
|
*/
|
||||||
|
export async function getTopAvailableParticipant(seasonId: string) {
|
||||||
|
const db = database();
|
||||||
|
|
||||||
|
// Get all drafted participant IDs
|
||||||
|
const draftedPicks = await db
|
||||||
|
.select({ participantId: schema.draftPicks.participantId })
|
||||||
|
.from(schema.draftPicks)
|
||||||
|
.where(eq(schema.draftPicks.seasonId, seasonId));
|
||||||
|
|
||||||
|
const draftedIds = draftedPicks.map((p: { participantId: string }) => p.participantId);
|
||||||
|
|
||||||
|
// Get all participants from season sports
|
||||||
|
const seasonSportsData = await db
|
||||||
|
.select({ sportsSeasonId: schema.seasonSports.sportsSeasonId })
|
||||||
|
.from(schema.seasonSports)
|
||||||
|
.where(eq(schema.seasonSports.seasonId, seasonId));
|
||||||
|
|
||||||
|
const sportsSeasonIds = seasonSportsData.map((s: { sportsSeasonId: string }) => s.sportsSeasonId);
|
||||||
|
|
||||||
|
if (sportsSeasonIds.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get top available participant by EV
|
||||||
|
let query = db
|
||||||
|
.select()
|
||||||
|
.from(schema.participants)
|
||||||
|
.where(eq(schema.participants.sportsSeasonId, sportsSeasonIds[0]))
|
||||||
|
.orderBy(desc(schema.participants.expectedValue), schema.participants.name);
|
||||||
|
|
||||||
|
// Filter out drafted participants if any exist
|
||||||
|
if (draftedIds.length > 0) {
|
||||||
|
query = db
|
||||||
|
.select()
|
||||||
|
.from(schema.participants)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(schema.participants.sportsSeasonId, sportsSeasonIds[0]),
|
||||||
|
notInArray(schema.participants.id, draftedIds)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.orderBy(desc(schema.participants.expectedValue), schema.participants.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle multiple sports seasons
|
||||||
|
if (sportsSeasonIds.length > 1) {
|
||||||
|
// For simplicity, we'll query all and sort in memory
|
||||||
|
// In production, might want to optimize this
|
||||||
|
const allParticipants = [];
|
||||||
|
|
||||||
|
for (const sportsSeasonId of sportsSeasonIds) {
|
||||||
|
let participantQuery = db
|
||||||
|
.select()
|
||||||
|
.from(schema.participants)
|
||||||
|
.where(eq(schema.participants.sportsSeasonId, sportsSeasonId));
|
||||||
|
|
||||||
|
if (draftedIds.length > 0) {
|
||||||
|
participantQuery = db
|
||||||
|
.select()
|
||||||
|
.from(schema.participants)
|
||||||
|
.where(
|
||||||
|
and(
|
||||||
|
eq(schema.participants.sportsSeasonId, sportsSeasonId),
|
||||||
|
notInArray(schema.participants.id, draftedIds)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const seasonParticipants = await participantQuery;
|
||||||
|
allParticipants.push(...seasonParticipants);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by EV desc, then name
|
||||||
|
allParticipants.sort((a, b) => {
|
||||||
|
if (b.expectedValue !== a.expectedValue) {
|
||||||
|
return b.expectedValue - a.expectedValue;
|
||||||
|
}
|
||||||
|
return a.name.localeCompare(b.name);
|
||||||
|
});
|
||||||
|
|
||||||
|
return allParticipants[0]?.id || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [topParticipant] = await query;
|
||||||
|
return topParticipant?.id || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the current pick based on draft order and round
|
||||||
|
*/
|
||||||
|
export function calculatePickInfo(
|
||||||
|
pickNumber: number,
|
||||||
|
teamCount: number
|
||||||
|
): { round: number; pickInRound: number; teamIndex: number } {
|
||||||
|
const round = Math.ceil(pickNumber / teamCount);
|
||||||
|
const pickInRound = ((pickNumber - 1) % teamCount) + 1;
|
||||||
|
|
||||||
|
// Snake draft: odd rounds go forward, even rounds go backward
|
||||||
|
const isOddRound = round % 2 === 1;
|
||||||
|
const teamIndex = isOddRound ? pickInRound - 1 : teamCount - pickInRound;
|
||||||
|
|
||||||
|
return { round, pickInRound, teamIndex };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the team ID for a given pick number based on draft order
|
||||||
|
*/
|
||||||
|
export function getTeamForPick(
|
||||||
|
pickNumber: number,
|
||||||
|
draftOrder: { teamId: string; draftOrder: number }[]
|
||||||
|
): string | null {
|
||||||
|
const sortedOrder = [...draftOrder].sort((a, b) => a.draftOrder - b.draftOrder);
|
||||||
|
const teamCount = sortedOrder.length;
|
||||||
|
|
||||||
|
if (teamCount === 0) return null;
|
||||||
|
|
||||||
|
const { teamIndex } = calculatePickInfo(pickNumber, teamCount);
|
||||||
|
return sortedOrder[teamIndex]?.teamId || null;
|
||||||
|
}
|
||||||
|
|
@ -12,3 +12,7 @@ export * from "./season-template-sport";
|
||||||
export * from "./season-sport";
|
export * from "./season-sport";
|
||||||
export * from "./participant-result";
|
export * from "./participant-result";
|
||||||
export * from "./draft-slot";
|
export * from "./draft-slot";
|
||||||
|
export * from "./draft-pick";
|
||||||
|
export * from "./draft-queue";
|
||||||
|
export * from "./draft-timer";
|
||||||
|
export * from "./draft-utils";
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,12 @@ export const scoringTypeEnum = pgEnum("scoring_type", [
|
||||||
"majors",
|
"majors",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const pickedByTypeEnum = pgEnum("picked_by_type", [
|
||||||
|
"owner",
|
||||||
|
"commissioner",
|
||||||
|
"auto",
|
||||||
|
]);
|
||||||
|
|
||||||
export const leagues = pgTable("leagues", {
|
export const leagues = pgTable("leagues", {
|
||||||
id: uuid("id").primaryKey().defaultRandom(),
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
name: varchar("name", { length: 255 }).notNull(),
|
name: varchar("name", { length: 255 }).notNull(),
|
||||||
|
|
@ -70,6 +76,11 @@ export const seasons = pgTable("seasons", {
|
||||||
draftRounds: integer("draft_rounds").notNull().default(20),
|
draftRounds: integer("draft_rounds").notNull().default(20),
|
||||||
flexSpots: integer("flex_spots").notNull().default(0),
|
flexSpots: integer("flex_spots").notNull().default(0),
|
||||||
draftDateTime: timestamp("draft_date_time"),
|
draftDateTime: timestamp("draft_date_time"),
|
||||||
|
draftInitialTime: integer("draft_initial_time").notNull().default(120), // seconds
|
||||||
|
draftIncrementTime: integer("draft_increment_time").notNull().default(30), // seconds
|
||||||
|
currentPickNumber: integer("current_pick_number").default(1),
|
||||||
|
draftStartedAt: timestamp("draft_started_at"),
|
||||||
|
draftPaused: boolean("draft_paused").notNull().default(false),
|
||||||
inviteCode: varchar("invite_code", { length: 20 }).notNull().unique(),
|
inviteCode: varchar("invite_code", { length: 20 }).notNull().unique(),
|
||||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||||
|
|
@ -100,6 +111,54 @@ export const draftSlots = pgTable("draft_slots", {
|
||||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const draftPicks = pgTable("draft_picks", {
|
||||||
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
|
seasonId: uuid("season_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => seasons.id, { onDelete: "cascade" }),
|
||||||
|
teamId: uuid("team_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => teams.id, { onDelete: "cascade" }),
|
||||||
|
participantId: uuid("participant_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => participants.id, { onDelete: "cascade" }),
|
||||||
|
pickNumber: integer("pick_number").notNull(),
|
||||||
|
round: integer("round").notNull(),
|
||||||
|
pickInRound: integer("pick_in_round").notNull(),
|
||||||
|
pickedByUserId: varchar("picked_by_user_id", { length: 255 }).notNull(), // Clerk user ID
|
||||||
|
pickedByType: pickedByTypeEnum("picked_by_type").notNull(),
|
||||||
|
timeUsed: integer("time_used").notNull().default(0), // seconds
|
||||||
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const draftQueue = pgTable("draft_queue", {
|
||||||
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
|
seasonId: uuid("season_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => seasons.id, { onDelete: "cascade" }),
|
||||||
|
teamId: uuid("team_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => teams.id, { onDelete: "cascade" }),
|
||||||
|
participantId: uuid("participant_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => participants.id, { onDelete: "cascade" }),
|
||||||
|
queuePosition: integer("queue_position").notNull(),
|
||||||
|
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||||
|
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const draftTimers = pgTable("draft_timers", {
|
||||||
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
|
seasonId: uuid("season_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => seasons.id, { onDelete: "cascade" }),
|
||||||
|
teamId: uuid("team_id")
|
||||||
|
.notNull()
|
||||||
|
.references(() => teams.id, { onDelete: "cascade" }),
|
||||||
|
timeRemaining: integer("time_remaining").notNull(), // seconds
|
||||||
|
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||||
|
});
|
||||||
|
|
||||||
export const commissioners = pgTable("commissioners", {
|
export const commissioners = pgTable("commissioners", {
|
||||||
id: uuid("id").primaryKey().defaultRandom(),
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
leagueId: uuid("league_id")
|
leagueId: uuid("league_id")
|
||||||
|
|
|
||||||
85
drizzle/0017_calm_zarda.sql
Normal file
85
drizzle/0017_calm_zarda.sql
Normal file
|
|
@ -0,0 +1,85 @@
|
||||||
|
CREATE TYPE "public"."picked_by_type" AS ENUM('owner', 'commissioner', 'auto');--> statement-breakpoint
|
||||||
|
CREATE TABLE IF NOT EXISTS "draft_picks" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"season_id" uuid NOT NULL,
|
||||||
|
"team_id" uuid NOT NULL,
|
||||||
|
"participant_id" uuid NOT NULL,
|
||||||
|
"pick_number" integer NOT NULL,
|
||||||
|
"round" integer NOT NULL,
|
||||||
|
"pick_in_round" integer NOT NULL,
|
||||||
|
"picked_by_user_id" varchar(255) NOT NULL,
|
||||||
|
"picked_by_type" "picked_by_type" NOT NULL,
|
||||||
|
"time_used" integer DEFAULT 0 NOT NULL,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE IF NOT EXISTS "draft_queue" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"season_id" uuid NOT NULL,
|
||||||
|
"team_id" uuid NOT NULL,
|
||||||
|
"participant_id" uuid NOT NULL,
|
||||||
|
"queue_position" integer NOT NULL,
|
||||||
|
"created_at" timestamp DEFAULT now() NOT NULL,
|
||||||
|
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
CREATE TABLE IF NOT EXISTS "draft_timers" (
|
||||||
|
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
"season_id" uuid NOT NULL,
|
||||||
|
"team_id" uuid NOT NULL,
|
||||||
|
"time_remaining" integer NOT NULL,
|
||||||
|
"updated_at" timestamp DEFAULT now() NOT NULL
|
||||||
|
);
|
||||||
|
--> statement-breakpoint
|
||||||
|
ALTER TABLE "seasons" ADD COLUMN "draft_initial_time" integer DEFAULT 120 NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "seasons" ADD COLUMN "draft_increment_time" integer DEFAULT 30 NOT NULL;--> statement-breakpoint
|
||||||
|
ALTER TABLE "seasons" ADD COLUMN "current_pick_number" integer DEFAULT 1;--> statement-breakpoint
|
||||||
|
ALTER TABLE "seasons" ADD COLUMN "draft_started_at" timestamp;--> statement-breakpoint
|
||||||
|
ALTER TABLE "seasons" ADD COLUMN "draft_paused" boolean DEFAULT false NOT NULL;--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_picks" ADD CONSTRAINT "draft_picks_season_id_seasons_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."seasons"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_picks" ADD CONSTRAINT "draft_picks_team_id_teams_id_fk" FOREIGN KEY ("team_id") REFERENCES "public"."teams"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_picks" ADD CONSTRAINT "draft_picks_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_queue" ADD CONSTRAINT "draft_queue_season_id_seasons_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."seasons"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_queue" ADD CONSTRAINT "draft_queue_team_id_teams_id_fk" FOREIGN KEY ("team_id") REFERENCES "public"."teams"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_queue" ADD CONSTRAINT "draft_queue_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_timers" ADD CONSTRAINT "draft_timers_season_id_seasons_id_fk" FOREIGN KEY ("season_id") REFERENCES "public"."seasons"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
|
--> statement-breakpoint
|
||||||
|
DO $$ BEGIN
|
||||||
|
ALTER TABLE "draft_timers" ADD CONSTRAINT "draft_timers_team_id_teams_id_fk" FOREIGN KEY ("team_id") REFERENCES "public"."teams"("id") ON DELETE cascade ON UPDATE no action;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN duplicate_object THEN null;
|
||||||
|
END $$;
|
||||||
1394
drizzle/meta/0017_snapshot.json
Normal file
1394
drizzle/meta/0017_snapshot.json
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -120,6 +120,13 @@
|
||||||
"when": 1760590495868,
|
"when": 1760590495868,
|
||||||
"tag": "0016_majestic_roulette",
|
"tag": "0016_majestic_roulette",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 17,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1760599350154,
|
||||||
|
"tag": "0017_calm_zarda",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Loading…
Add table
Reference in a new issue