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",
|
"llws_bracket",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
export const tournamentStatusEnum = pgEnum("tournament_status", [
|
||||||
|
"scheduled",
|
||||||
|
"in_progress",
|
||||||
|
"completed",
|
||||||
|
]);
|
||||||
|
|
||||||
export const playoffMatchGameStatusEnum = pgEnum("playoff_match_game_status", [
|
export const playoffMatchGameStatusEnum = pgEnum("playoff_match_game_status", [
|
||||||
"scheduled",
|
"scheduled",
|
||||||
"complete",
|
"complete",
|
||||||
|
|
@ -378,6 +384,9 @@ export const seasonParticipants = pgTable("season_participants", {
|
||||||
sportsSeasonId: uuid("sports_season_id")
|
sportsSeasonId: uuid("sports_season_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
|
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
|
||||||
|
participantId: uuid("participant_id").references(() => participants.id, {
|
||||||
|
onDelete: "restrict",
|
||||||
|
}),
|
||||||
name: varchar("name", { length: 255 }).notNull(),
|
name: varchar("name", { length: 255 }).notNull(),
|
||||||
shortName: varchar("short_name", { length: 100 }),
|
shortName: varchar("short_name", { length: 100 }),
|
||||||
externalId: varchar("external_id", { length: 255 }),
|
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),
|
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", {
|
export const seasonTemplateSports = pgTable("season_template_sports", {
|
||||||
id: uuid("id").primaryKey().defaultRandom(),
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
templateId: uuid("template_id")
|
templateId: uuid("template_id")
|
||||||
|
|
@ -435,6 +534,9 @@ export const scoringEvents = pgTable("scoring_events", {
|
||||||
sportsSeasonId: uuid("sports_season_id")
|
sportsSeasonId: uuid("sports_season_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
.references(() => sportsSeasons.id, { onDelete: "cascade" }),
|
.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.
|
name: varchar("name", { length: 255 }).notNull(), // "2024 Masters", "Super Bowl LIX", etc.
|
||||||
eventDate: date("event_date"),
|
eventDate: date("event_date"),
|
||||||
eventStartsAt: timestamp("event_starts_at", { withTimezone: true }),
|
eventStartsAt: timestamp("event_starts_at", { withTimezone: true }),
|
||||||
|
|
@ -783,6 +885,8 @@ export const teamEvSnapshots = pgTable("team_ev_snapshots", {
|
||||||
// Relations
|
// Relations
|
||||||
export const sportsRelations = relations(sports, ({ many }) => ({
|
export const sportsRelations = relations(sports, ({ many }) => ({
|
||||||
sportsSeasons: many(sportsSeasons),
|
sportsSeasons: many(sportsSeasons),
|
||||||
|
tournaments: many(tournaments),
|
||||||
|
participants: many(participants),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const sportsSeasonsRelations = relations(sportsSeasons, ({ one, many }) => ({
|
export const sportsSeasonsRelations = relations(sportsSeasons, ({ one, many }) => ({
|
||||||
|
|
@ -803,10 +907,57 @@ export const seasonParticipantsRelations = relations(seasonParticipants, ({ one,
|
||||||
fields: [seasonParticipants.sportsSeasonId],
|
fields: [seasonParticipants.sportsSeasonId],
|
||||||
references: [sportsSeasons.id],
|
references: [sportsSeasons.id],
|
||||||
}),
|
}),
|
||||||
|
canonicalParticipant: one(participants, {
|
||||||
|
fields: [seasonParticipants.participantId],
|
||||||
|
references: [participants.id],
|
||||||
|
}),
|
||||||
results: many(seasonParticipantResults),
|
results: many(seasonParticipantResults),
|
||||||
regularSeasonStandings: many(regularSeasonStandings),
|
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 }) => ({
|
export const seasonTemplatesRelations = relations(seasonTemplates, ({ many }) => ({
|
||||||
seasonTemplateSports: many(seasonTemplateSports),
|
seasonTemplateSports: many(seasonTemplateSports),
|
||||||
seasons: many(seasons),
|
seasons: many(seasons),
|
||||||
|
|
@ -943,6 +1094,10 @@ export const scoringEventsRelations = relations(scoringEvents, ({ one, many }) =
|
||||||
fields: [scoringEvents.sportsSeasonId],
|
fields: [scoringEvents.sportsSeasonId],
|
||||||
references: [sportsSeasons.id],
|
references: [sportsSeasons.id],
|
||||||
}),
|
}),
|
||||||
|
tournament: one(tournaments, {
|
||||||
|
fields: [scoringEvents.tournamentId],
|
||||||
|
references: [tournaments.id],
|
||||||
|
}),
|
||||||
eventResults: many(eventResults),
|
eventResults: many(eventResults),
|
||||||
playoffMatches: many(playoffMatches),
|
playoffMatches: many(playoffMatches),
|
||||||
tournamentGroups: many(tournamentGroups),
|
tournamentGroups: many(tournamentGroups),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue