feat(db): add tournament_admin role and ownership fields to schema

This commit is contained in:
2026-03-29 19:25:02 -07:00
parent 025b195800
commit 8f1f2bf196
4 changed files with 503 additions and 173 deletions
@@ -0,0 +1,232 @@
-- CreateTable
CREATE TABLE "players" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"rating" INTEGER NOT NULL DEFAULT 0,
"currentElo" INTEGER NOT NULL DEFAULT 1000,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "users" (
"id" TEXT NOT NULL PRIMARY KEY,
"email" TEXT NOT NULL,
"emailVerified" BOOLEAN NOT NULL DEFAULT false,
"name" TEXT,
"image" TEXT,
"role" TEXT NOT NULL DEFAULT 'player',
"playerId" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "users_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "players" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "events" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"event_id" INTEGER,
"name" TEXT NOT NULL,
"description" TEXT,
"eventDate" DATETIME,
"eventType" TEXT NOT NULL DEFAULT 'tournament',
"format" TEXT NOT NULL DEFAULT 'round_robin',
"status" TEXT NOT NULL DEFAULT 'planned',
"maxParticipants" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateTable
CREATE TABLE "event_participants" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER NOT NULL,
"playerId" INTEGER NOT NULL,
"teamId" INTEGER,
"seed" INTEGER,
"status" TEXT NOT NULL DEFAULT 'registered',
"registrationDate" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "event_participants_teamId_fkey" FOREIGN KEY ("teamId") REFERENCES "teams" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "event_participants_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "event_participants_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "teams" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER NOT NULL,
"teamName" TEXT,
"player1Id" INTEGER NOT NULL,
"player2Id" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "teams_player2Id_fkey" FOREIGN KEY ("player2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "teams_player1Id_fkey" FOREIGN KEY ("player1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "teams_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "tournament_rounds" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER NOT NULL,
"roundNumber" INTEGER NOT NULL,
"status" TEXT NOT NULL DEFAULT 'pending',
"scheduledStart" DATETIME,
"actualStart" DATETIME,
"completedAt" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "tournament_rounds_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "bracket_matchups" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"roundId" INTEGER NOT NULL,
"eventId" INTEGER NOT NULL,
"team1Id" INTEGER,
"team2Id" INTEGER,
"matchId" INTEGER,
"tableNumber" INTEGER,
"bracketPosition" INTEGER,
"winnerTeamId" INTEGER,
"loserTeamId" INTEGER,
"status" TEXT NOT NULL DEFAULT 'pending',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "bracket_matchups_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "matches" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_team2Id_fkey" FOREIGN KEY ("team2Id") REFERENCES "teams" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_team1Id_fkey" FOREIGN KEY ("team1Id") REFERENCES "teams" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "bracket_matchups_roundId_fkey" FOREIGN KEY ("roundId") REFERENCES "tournament_rounds" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "matches" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER,
"playedAt" DATETIME,
"team1P1Id" INTEGER NOT NULL,
"team1P2Id" INTEGER NOT NULL,
"team2P1Id" INTEGER NOT NULL,
"team2P2Id" INTEGER NOT NULL,
"team1Score" INTEGER NOT NULL,
"team2Score" INTEGER NOT NULL,
"status" TEXT NOT NULL DEFAULT 'completed',
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "matches_team2P2Id_fkey" FOREIGN KEY ("team2P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team2P1Id_fkey" FOREIGN KEY ("team2P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P2Id_fkey" FOREIGN KEY ("team1P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P1Id_fkey" FOREIGN KEY ("team1P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "elo_snapshots" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"playerId" INTEGER NOT NULL,
"matchId" INTEGER NOT NULL,
"ratingBefore" INTEGER NOT NULL,
"ratingAfter" INTEGER NOT NULL,
"ratingChange" INTEGER NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "elo_snapshots_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "matches" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "elo_snapshots_playerId_fkey" FOREIGN KEY ("playerId") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "partnership_games" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"player1Id" INTEGER NOT NULL,
"player2Id" INTEGER NOT NULL,
"matchId" INTEGER NOT NULL,
"teamNumber" INTEGER,
"wonMatch" INTEGER,
"player1EloChange" INTEGER,
"player2EloChange" INTEGER,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT "partnership_games_matchId_fkey" FOREIGN KEY ("matchId") REFERENCES "matches" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "partnership_games_player2Id_fkey" FOREIGN KEY ("player2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "partnership_games_player1Id_fkey" FOREIGN KEY ("player1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "partnership_stats" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"player1Id" INTEGER NOT NULL,
"player2Id" INTEGER NOT NULL,
"gamesPlayed" INTEGER NOT NULL DEFAULT 0,
"wins" INTEGER NOT NULL DEFAULT 0,
"losses" INTEGER NOT NULL DEFAULT 0,
"totalEloChange" INTEGER NOT NULL DEFAULT 0,
"lastPlayed" DATETIME,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "partnership_stats_player2Id_fkey" FOREIGN KEY ("player2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "partnership_stats_player1Id_fkey" FOREIGN KEY ("player1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "session" (
"id" TEXT NOT NULL PRIMARY KEY,
"expiresAt" DATETIME NOT NULL,
"token" TEXT NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
"ipAddress" TEXT,
"userAgent" TEXT,
"userId" TEXT NOT NULL,
CONSTRAINT "session_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "account" (
"id" TEXT NOT NULL PRIMARY KEY,
"accountId" TEXT NOT NULL,
"providerId" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"accessToken" TEXT,
"refreshToken" TEXT,
"idToken" TEXT,
"accessTokenExpiresAt" DATETIME,
"refreshTokenExpiresAt" DATETIME,
"scope" TEXT,
"password" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "account_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
-- CreateTable
CREATE TABLE "verification" (
"id" TEXT NOT NULL PRIMARY KEY,
"identifier" TEXT NOT NULL,
"value" TEXT NOT NULL,
"expiresAt" DATETIME NOT NULL,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
-- CreateIndex
CREATE UNIQUE INDEX "players_name_key" ON "players"("name");
-- CreateIndex
CREATE UNIQUE INDEX "users_email_key" ON "users"("email");
-- CreateIndex
CREATE UNIQUE INDEX "users_playerId_key" ON "users"("playerId");
-- CreateIndex
CREATE INDEX "session_userId_idx" ON "session"("userId");
-- CreateIndex
CREATE UNIQUE INDEX "session_token_key" ON "session"("token");
-- CreateIndex
CREATE INDEX "account_userId_idx" ON "account"("userId");
-- CreateIndex
CREATE INDEX "verification_identifier_idx" ON "verification"("identifier");
@@ -0,0 +1,61 @@
-- RedefineTables
PRAGMA defer_foreign_keys=ON;
PRAGMA foreign_keys=OFF;
CREATE TABLE "new_events" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"event_id" INTEGER,
"name" TEXT NOT NULL,
"description" TEXT,
"eventDate" DATETIME,
"eventType" TEXT NOT NULL DEFAULT 'tournament',
"format" TEXT NOT NULL DEFAULT 'round_robin',
"status" TEXT NOT NULL DEFAULT 'planned',
"maxParticipants" INTEGER,
"ownerId" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "events_ownerId_fkey" FOREIGN KEY ("ownerId") REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_events" ("createdAt", "description", "eventDate", "eventType", "event_id", "format", "id", "maxParticipants", "name", "status", "updatedAt") SELECT "createdAt", "description", "eventDate", "eventType", "event_id", "format", "id", "maxParticipants", "name", "status", "updatedAt" FROM "events";
DROP TABLE "events";
ALTER TABLE "new_events" RENAME TO "events";
CREATE TABLE "new_matches" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"eventId" INTEGER,
"playedAt" DATETIME,
"team1P1Id" INTEGER NOT NULL,
"team1P2Id" INTEGER NOT NULL,
"team2P1Id" INTEGER NOT NULL,
"team2P2Id" INTEGER NOT NULL,
"team1Score" INTEGER NOT NULL,
"team2Score" INTEGER NOT NULL,
"status" TEXT NOT NULL DEFAULT 'completed',
"createdById" TEXT,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL,
CONSTRAINT "matches_team2P2Id_fkey" FOREIGN KEY ("team2P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team2P1Id_fkey" FOREIGN KEY ("team2P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P2Id_fkey" FOREIGN KEY ("team1P2Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_team1P1Id_fkey" FOREIGN KEY ("team1P1Id") REFERENCES "players" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT "matches_eventId_fkey" FOREIGN KEY ("eventId") REFERENCES "events" ("id") ON DELETE SET NULL ON UPDATE CASCADE,
CONSTRAINT "matches_createdById_fkey" FOREIGN KEY ("createdById") REFERENCES "users" ("id") ON DELETE SET NULL ON UPDATE CASCADE
);
INSERT INTO "new_matches" ("createdAt", "eventId", "id", "playedAt", "status", "team1P1Id", "team1P2Id", "team1Score", "team2P1Id", "team2P2Id", "team2Score", "updatedAt") SELECT "createdAt", "eventId", "id", "playedAt", "status", "team1P1Id", "team1P2Id", "team1Score", "team2P1Id", "team2P2Id", "team2Score", "updatedAt" FROM "matches";
DROP TABLE "matches";
ALTER TABLE "new_matches" RENAME TO "matches";
CREATE TABLE "new_players" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" TEXT NOT NULL,
"rating" INTEGER NOT NULL DEFAULT 0,
"currentElo" INTEGER NOT NULL DEFAULT 1000,
"gamesPlayed" INTEGER NOT NULL DEFAULT 0,
"wins" INTEGER NOT NULL DEFAULT 0,
"losses" INTEGER NOT NULL DEFAULT 0,
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" DATETIME NOT NULL
);
INSERT INTO "new_players" ("createdAt", "currentElo", "id", "name", "rating", "updatedAt") SELECT "createdAt", "currentElo", "id", "name", "rating", "updatedAt" FROM "players";
DROP TABLE "players";
ALTER TABLE "new_players" RENAME TO "players";
PRAGMA foreign_keys=ON;
PRAGMA defer_foreign_keys=OFF;
+3
View File
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (e.g., Git)
provider = "sqlite"
+207 -173
View File
@@ -1,5 +1,3 @@
// EuchreCamp Database Schema
// Generated from existing Ruby/ROM implementation
generator client { generator client {
provider = "prisma-client-js" provider = "prisma-client-js"
@@ -10,192 +8,185 @@ datasource db {
url = env("DATABASE_URL") url = env("DATABASE_URL")
} }
// Player Model - Tracks individual player information
model Player { model Player {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
name String @unique name String
rating Int @default(0) rating Int @default(0) // Historical rating (used for rankings)
currentElo Int @default(1000) currentElo Int @default(1000) // Current Elo rating
createdAt DateTime @default(now()) gamesPlayed Int @default(0) // Total games played
updatedAt DateTime @updatedAt wins Int @default(0) // Total wins
losses Int @default(0) // Total losses
// Relationships createdAt DateTime @default(now())
users User[] updatedAt DateTime @updatedAt
eventParticipants EventParticipant[]
teamsAsPlayer1 Team[] @relation("TeamPlayer1")
teamsAsPlayer2 Team[] @relation("TeamPlayer2")
matchesAsP1 Match[] @relation("MatchPlayer1")
matchesAsP2 Match[] @relation("MatchPlayer2")
matchesAsP3 Match[] @relation("MatchPlayer3")
matchesAsP4 Match[] @relation("MatchPlayer4")
eloSnapshots EloSnapshot[] eloSnapshots EloSnapshot[]
partnershipGames PartnershipGame[] @relation("PartnershipPlayer1") eventParticipants EventParticipant[]
partnershipGames2 PartnershipGame[] @relation("PartnershipPlayer2") matchesAsP4 Match[] @relation("MatchPlayer4")
partnershipStats PartnershipStat[] @relation("StatPlayer1") matchesAsP3 Match[] @relation("MatchPlayer3")
partnershipStats2 PartnershipStat[] @relation("StatPlayer2") matchesAsP2 Match[] @relation("MatchPlayer2")
matchesAsP1 Match[] @relation("MatchPlayer1")
partnershipGames2 PartnershipGame[] @relation("PartnershipPlayer2")
partnershipGames PartnershipGame[] @relation("PartnershipPlayer1")
partnershipStats2 PartnershipStat[] @relation("StatPlayer2")
partnershipStats PartnershipStat[] @relation("StatPlayer1")
teamsAsPlayer2 Team[] @relation("TeamPlayer2")
teamsAsPlayer1 Team[] @relation("TeamPlayer1")
user User?
@@map("players") @@map("players")
} }
// User Model - Authentication and authorization
model User { model User {
id Int @id @default(autoincrement()) id String @id @default(cuid())
playerId Int @unique email String @unique
email String @unique emailVerified Boolean @default(false)
passwordDigest String name String?
role String @default("player") image String?
confirmed Boolean @default(false) role String @default("player") // player, tournament_admin, club_admin
confirmationToken String?
confirmationSentAt DateTime? // Session and account references for Better Auth
resetPasswordToken String? sessions Session[]
resetPasswordSentAt DateTime? accounts Account[]
failedLoginAttempts Int @default(0)
lockedUntil DateTime? // Link to EuchreCamp player (optional)
lastLoginAt DateTime? playerId Int? @unique
lastLoginIp String? player Player? @relation(fields: [playerId], references: [id])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt // Tournaments owned by this user
ownedTournaments Event[] @relation("TournamentOwner")
player Player @relation(fields: [playerId], references: [id])
// Matches created by this user
createdMatches Match[] @relation("MatchCreator")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@map("users") @@map("users")
} }
// Event (Tournament) Model
model Event { model Event {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
event_id Int? event_id Int?
name String name String
description String? description String?
eventDate DateTime? eventDate DateTime?
eventType String @default("tournament") eventType String @default("tournament")
format String @default("round_robin") format String @default("round_robin")
status String @default("planned") status String @default("planned")
maxParticipants Int? maxParticipants Int?
createdAt DateTime @default(now()) ownerId String? // User ID of the tournament owner (for tournament_admin)
updatedAt DateTime @updatedAt createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// Relationships bracketMatchups BracketMatchup[]
participants EventParticipant[] participants EventParticipant[]
teams Team[] matches Match[]
rounds TournamentRound[] teams Team[]
bracketMatchups BracketMatchup[] rounds TournamentRound[]
matches Match[] owner User? @relation("TournamentOwner", fields: [ownerId], references: [id])
@@map("events") @@map("events")
} }
// EventParticipant Model
model EventParticipant { model EventParticipant {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
eventId Int eventId Int
playerId Int playerId Int
teamId Int? teamId Int?
seed Int? seed Int?
status String @default("registered") status String @default("registered")
registrationDate DateTime? registrationDate DateTime?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
team Team? @relation(fields: [teamId], references: [id])
event Event @relation(fields: [eventId], references: [id]) player Player @relation(fields: [playerId], references: [id])
player Player @relation(fields: [playerId], references: [id]) event Event @relation(fields: [eventId], references: [id])
team Team? @relation(fields: [teamId], references: [id])
@@map("event_participants") @@map("event_participants")
} }
// Team Model
model Team { model Team {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
eventId Int eventId Int
teamName String? teamName String?
player1Id Int player1Id Int
player2Id Int player2Id Int
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
bracketMatchups2 BracketMatchup[] @relation("BracketTeam2")
// Relationships bracketMatchups1 BracketMatchup[] @relation("BracketTeam1")
event Event @relation(fields: [eventId], references: [id]) eventParticipants EventParticipant[]
player1 Player @relation("TeamPlayer1", fields: [player1Id], references: [id]) player2 Player @relation("TeamPlayer2", fields: [player2Id], references: [id])
player2 Player @relation("TeamPlayer2", fields: [player2Id], references: [id]) player1 Player @relation("TeamPlayer1", fields: [player1Id], references: [id])
eventParticipants EventParticipant[] event Event @relation(fields: [eventId], references: [id])
bracketMatchups1 BracketMatchup[] @relation("BracketTeam1")
bracketMatchups2 BracketMatchup[] @relation("BracketTeam2")
@@map("teams") @@map("teams")
} }
// TournamentRound Model
model TournamentRound { model TournamentRound {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
eventId Int eventId Int
roundNumber Int roundNumber Int
status String @default("pending") status String @default("pending")
scheduledStart DateTime? scheduledStart DateTime?
actualStart DateTime? actualStart DateTime?
completedAt DateTime? completedAt DateTime?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
event Event @relation(fields: [eventId], references: [id])
bracketMatchups BracketMatchup[] bracketMatchups BracketMatchup[]
event Event @relation(fields: [eventId], references: [id])
@@map("tournament_rounds") @@map("tournament_rounds")
} }
// BracketMatchup Model
model BracketMatchup { model BracketMatchup {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
roundId Int roundId Int
eventId Int eventId Int
team1Id Int? team1Id Int?
team2Id Int? team2Id Int?
matchId Int? matchId Int?
tableNumber Int? tableNumber Int?
bracketPosition Int? bracketPosition Int?
winnerTeamId Int? winnerTeamId Int?
loserTeamId Int? loserTeamId Int?
status String @default("pending") status String @default("pending")
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
match Match? @relation(fields: [matchId], references: [id])
round TournamentRound @relation(fields: [roundId], references: [id]) team2 Team? @relation("BracketTeam2", fields: [team2Id], references: [id])
event Event @relation(fields: [eventId], references: [id]) team1 Team? @relation("BracketTeam1", fields: [team1Id], references: [id])
team1 Team? @relation("BracketTeam1", fields: [team1Id], references: [id]) event Event @relation(fields: [eventId], references: [id])
team2 Team? @relation("BracketTeam2", fields: [team2Id], references: [id]) round TournamentRound @relation(fields: [roundId], references: [id])
match Match? @relation(fields: [matchId], references: [id])
@@map("bracket_matchups") @@map("bracket_matchups")
} }
// Match Model
model Match { model Match {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
eventId Int? eventId Int?
playedAt DateTime? playedAt DateTime?
team1P1Id Int team1P1Id Int
team1P2Id Int team1P2Id Int
team2P1Id Int team2P1Id Int
team2P2Id Int team2P2Id Int
team1Score Int team1Score Int
team2Score Int team2Score Int
status String @default("completed") status String @default("completed")
createdAt DateTime @default(now()) createdById String? // User ID of the match creator (for tournament_admin)
updatedAt DateTime @updatedAt createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
event Event? @relation(fields: [eventId], references: [id]) bracketMatchups BracketMatchup[]
team1P1 Player @relation("MatchPlayer1", fields: [team1P1Id], references: [id]) eloSnapshots EloSnapshot[]
team1P2 Player @relation("MatchPlayer2", fields: [team1P2Id], references: [id]) team2P2 Player @relation("MatchPlayer4", fields: [team2P2Id], references: [id])
team2P1 Player @relation("MatchPlayer3", fields: [team2P1Id], references: [id]) team2P1 Player @relation("MatchPlayer3", fields: [team2P1Id], references: [id])
team2P2 Player @relation("MatchPlayer4", fields: [team2P2Id], references: [id]) team1P2 Player @relation("MatchPlayer2", fields: [team1P2Id], references: [id])
eloSnapshots EloSnapshot[] team1P1 Player @relation("MatchPlayer1", fields: [team1P1Id], references: [id])
event Event? @relation(fields: [eventId], references: [id])
partnershipGames PartnershipGame[] partnershipGames PartnershipGame[]
bracketMatchups BracketMatchup[] createdBy User? @relation("MatchCreator", fields: [createdById], references: [id])
@@map("matches") @@map("matches")
} }
// EloSnapshot Model
model EloSnapshot { model EloSnapshot {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
playerId Int playerId Int
@@ -204,47 +195,90 @@ model EloSnapshot {
ratingAfter Int ratingAfter Int
ratingChange Int ratingChange Int
createdAt DateTime @default(now()) createdAt DateTime @default(now())
match Match @relation(fields: [matchId], references: [id])
player Player @relation(fields: [playerId], references: [id]) player Player @relation(fields: [playerId], references: [id])
match Match @relation(fields: [matchId], references: [id])
@@map("elo_snapshots") @@map("elo_snapshots")
} }
// PartnershipGame Model - Tracks each game played by a partnership
model PartnershipGame { model PartnershipGame {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
player1Id Int player1Id Int
player2Id Int player2Id Int
matchId Int matchId Int
teamNumber Int? teamNumber Int?
wonMatch Int? wonMatch Int?
player1EloChange Int? player1EloChange Int?
player2EloChange Int? player2EloChange Int?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
match Match @relation(fields: [matchId], references: [id])
player1 Player @relation("PartnershipPlayer1", fields: [player1Id], references: [id]) player2 Player @relation("PartnershipPlayer2", fields: [player2Id], references: [id])
player2 Player @relation("PartnershipPlayer2", fields: [player2Id], references: [id]) player1 Player @relation("PartnershipPlayer1", fields: [player1Id], references: [id])
match Match @relation(fields: [matchId], references: [id])
@@map("partnership_games") @@map("partnership_games")
} }
// PartnershipStat Model - Aggregated partnership statistics
model PartnershipStat { model PartnershipStat {
id Int @id @default(autoincrement()) id Int @id @default(autoincrement())
player1Id Int player1Id Int
player2Id Int player2Id Int
gamesPlayed Int @default(0) gamesPlayed Int @default(0)
wins Int @default(0) wins Int @default(0)
losses Int @default(0) losses Int @default(0)
totalEloChange Int @default(0) totalEloChange Int @default(0)
lastPlayed DateTime? lastPlayed DateTime?
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
player2 Player @relation("StatPlayer2", fields: [player2Id], references: [id])
player1 Player @relation("StatPlayer1", fields: [player1Id], references: [id]) player1 Player @relation("StatPlayer1", fields: [player1Id], references: [id])
player2 Player @relation("StatPlayer2", fields: [player2Id], references: [id])
@@map("partnership_stats") @@map("partnership_stats")
} }
model Session {
id String @id
expiresAt DateTime
token String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
ipAddress String?
userAgent String?
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([token])
@@index([userId])
@@map("session")
}
model Account {
id String @id
accountId String
providerId String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
accessToken String?
refreshToken String?
idToken String?
accessTokenExpiresAt DateTime?
refreshTokenExpiresAt DateTime?
scope String?
password String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
@@map("account")
}
model Verification {
id String @id
identifier String
value String
expiresAt DateTime
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([identifier])
@@map("verification")
}