schema: add canonical tournament & participant tables
Adds tournaments, participants (canonical), tournament_results, and participant_surface_elos (canonical). Adds nullable tournament_id to scoring_events and nullable participant_id to season_participants. Phase 1b of canonical tournament layer migration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ec10c9006c
commit
775b905069
1 changed files with 155 additions and 0 deletions
|
|
@ -150,6 +150,12 @@ export const simulatorTypeEnum = pgEnum("simulator_type", [
|
|||
"llws_bracket",
|
||||
]);
|
||||
|
||||
export const tournamentStatusEnum = pgEnum("tournament_status", [
|
||||
"scheduled",
|
||||
"in_progress",
|
||||
"completed",
|
||||
]);
|
||||
|
||||
export const playoffMatchGameStatusEnum = pgEnum("playoff_match_game_status", [
|
||||
"scheduled",
|
||||
"complete",
|
||||
|
|
@ -378,6 +384,9 @@ export const seasonParticipants = pgTable("season_participants", {
|
|||
sportsSeasonId: uuid("sports_season_id")
|
||||
.notNull()
|
||||
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
|
||||
participantId: uuid("participant_id").references(() => participants.id, {
|
||||
onDelete: "restrict",
|
||||
}),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
shortName: varchar("short_name", { length: 100 }),
|
||||
externalId: varchar("external_id", { length: 255 }),
|
||||
|
|
@ -389,6 +398,96 @@ export const seasonParticipants = pgTable("season_participants", {
|
|||
uniqueIndex("participants_sports_season_name_unique").on(table.sportsSeasonId, table.name),
|
||||
]);
|
||||
|
||||
export const participants = pgTable(
|
||||
"participants",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
sportId: uuid("sport_id")
|
||||
.notNull()
|
||||
.references(() => sports.id, { onDelete: "cascade" }),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
externalKey: varchar("external_key", { length: 255 }),
|
||||
metadata: jsonb("metadata"),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||
},
|
||||
(t) => ({
|
||||
uniqueSportName: uniqueIndex("participants_sport_name_unique").on(
|
||||
t.sportId,
|
||||
t.name,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
export const tournaments = pgTable(
|
||||
"tournaments",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
sportId: uuid("sport_id")
|
||||
.notNull()
|
||||
.references(() => sports.id, { onDelete: "cascade" }),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
year: integer("year").notNull(),
|
||||
startsAt: timestamp("starts_at"),
|
||||
endsAt: timestamp("ends_at"),
|
||||
surface: varchar("surface", { length: 50 }), // tennis only: hard | clay | grass
|
||||
location: varchar("location", { length: 255 }),
|
||||
status: tournamentStatusEnum("status").notNull().default("scheduled"),
|
||||
externalKey: varchar("external_key", { length: 255 }),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||
},
|
||||
(t) => ({
|
||||
uniqueSportNameYear: uniqueIndex("tournaments_sport_name_year_unique").on(
|
||||
t.sportId,
|
||||
t.name,
|
||||
t.year,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
export const tournamentResults = pgTable(
|
||||
"tournament_results",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
tournamentId: uuid("tournament_id")
|
||||
.notNull()
|
||||
.references(() => tournaments.id, { onDelete: "cascade" }),
|
||||
participantId: uuid("participant_id")
|
||||
.notNull()
|
||||
.references(() => participants.id, { onDelete: "cascade" }),
|
||||
placement: integer("placement"),
|
||||
rawScore: decimal("raw_score", { precision: 10, scale: 2 }),
|
||||
createdAt: timestamp("created_at").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||
},
|
||||
(t) => ({
|
||||
uniqueTournamentParticipant: uniqueIndex(
|
||||
"tournament_results_tournament_participant_unique",
|
||||
).on(t.tournamentId, t.participantId),
|
||||
}),
|
||||
);
|
||||
|
||||
export const participantSurfaceElos = pgTable(
|
||||
"participant_surface_elos",
|
||||
{
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
participantId: uuid("participant_id")
|
||||
.notNull()
|
||||
.references(() => participants.id, { onDelete: "cascade" }),
|
||||
worldRanking: integer("world_ranking"),
|
||||
eloHard: integer("elo_hard"),
|
||||
eloClay: integer("elo_clay"),
|
||||
eloGrass: integer("elo_grass"),
|
||||
updatedAt: timestamp("updated_at").defaultNow().notNull(),
|
||||
},
|
||||
(t) => ({
|
||||
uniqueParticipant: uniqueIndex("participant_surface_elos_participant_unique").on(
|
||||
t.participantId,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
export const seasonTemplateSports = pgTable("season_template_sports", {
|
||||
id: uuid("id").primaryKey().defaultRandom(),
|
||||
templateId: uuid("template_id")
|
||||
|
|
@ -435,6 +534,9 @@ export const scoringEvents = pgTable("scoring_events", {
|
|||
sportsSeasonId: uuid("sports_season_id")
|
||||
.notNull()
|
||||
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
|
||||
tournamentId: uuid("tournament_id").references(() => tournaments.id, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
name: varchar("name", { length: 255 }).notNull(), // "2024 Masters", "Super Bowl LIX", etc.
|
||||
eventDate: date("event_date"),
|
||||
eventStartsAt: timestamp("event_starts_at", { withTimezone: true }),
|
||||
|
|
@ -783,6 +885,8 @@ export const teamEvSnapshots = pgTable("team_ev_snapshots", {
|
|||
// Relations
|
||||
export const sportsRelations = relations(sports, ({ many }) => ({
|
||||
sportsSeasons: many(sportsSeasons),
|
||||
tournaments: many(tournaments),
|
||||
participants: many(participants),
|
||||
}));
|
||||
|
||||
export const sportsSeasonsRelations = relations(sportsSeasons, ({ one, many }) => ({
|
||||
|
|
@ -803,10 +907,57 @@ export const seasonParticipantsRelations = relations(seasonParticipants, ({ one,
|
|||
fields: [seasonParticipants.sportsSeasonId],
|
||||
references: [sportsSeasons.id],
|
||||
}),
|
||||
canonicalParticipant: one(participants, {
|
||||
fields: [seasonParticipants.participantId],
|
||||
references: [participants.id],
|
||||
}),
|
||||
results: many(seasonParticipantResults),
|
||||
regularSeasonStandings: many(regularSeasonStandings),
|
||||
}));
|
||||
|
||||
export const participantsRelations = relations(participants, ({ one, many }) => ({
|
||||
sport: one(sports, {
|
||||
fields: [participants.sportId],
|
||||
references: [sports.id],
|
||||
}),
|
||||
seasonParticipants: many(seasonParticipants),
|
||||
tournamentResults: many(tournamentResults),
|
||||
surfaceElo: one(participantSurfaceElos, {
|
||||
fields: [participants.id],
|
||||
references: [participantSurfaceElos.participantId],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const tournamentsRelations = relations(tournaments, ({ one, many }) => ({
|
||||
sport: one(sports, {
|
||||
fields: [tournaments.sportId],
|
||||
references: [sports.id],
|
||||
}),
|
||||
scoringEvents: many(scoringEvents),
|
||||
tournamentResults: many(tournamentResults),
|
||||
}));
|
||||
|
||||
export const tournamentResultsRelations = relations(tournamentResults, ({ one }) => ({
|
||||
tournament: one(tournaments, {
|
||||
fields: [tournamentResults.tournamentId],
|
||||
references: [tournaments.id],
|
||||
}),
|
||||
participant: one(participants, {
|
||||
fields: [tournamentResults.participantId],
|
||||
references: [participants.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const participantSurfaceElosRelations = relations(
|
||||
participantSurfaceElos,
|
||||
({ one }) => ({
|
||||
participant: one(participants, {
|
||||
fields: [participantSurfaceElos.participantId],
|
||||
references: [participants.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const seasonTemplatesRelations = relations(seasonTemplates, ({ many }) => ({
|
||||
seasonTemplateSports: many(seasonTemplateSports),
|
||||
seasons: many(seasons),
|
||||
|
|
@ -943,6 +1094,10 @@ export const scoringEventsRelations = relations(scoringEvents, ({ one, many }) =
|
|||
fields: [scoringEvents.sportsSeasonId],
|
||||
references: [sportsSeasons.id],
|
||||
}),
|
||||
tournament: one(tournaments, {
|
||||
fields: [scoringEvents.tournamentId],
|
||||
references: [tournaments.id],
|
||||
}),
|
||||
eventResults: many(eventResults),
|
||||
playoffMatches: many(playoffMatches),
|
||||
tournamentGroups: many(tournamentGroups),
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue