datasource db { provider = "postgresql" // TODO: should use same .env system as Next.JS url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" previewFeatures = ["orderByRelation"] } model User { id Int @id @default(autoincrement()) username String discriminator String discordId String @unique discordAvatar String? teamId Int? ladderTeamId Int? patreonTier Int? profile Profile? player Player? builds Build[] submittedRecords SalmonRunRecord[] salmonRunRecords SalmonRunRecord[] @relation("SalmonRunRecordRoster") freeAgentPost FreeAgentPost? team Team? @relation(fields: [teamId], references: [id]) captainedTeam Team? @relation("TeamCaptain") trueSkill LadderPlayerTrueSkill? ladderTeam LadderRegisteredTeam? @relation(fields: [ladderTeamId], references: [id]) ladderMatches LadderMatchPlayer[] plusStatus PlusStatus? vouched PlusStatus? @relation("Voucher") plusSuggestionsMade PlusSuggestion[] plusSuggestionsReceived PlusSuggestion[] @relation("Suggester") votesMade PlusBallot[] votesReceived PlusBallot[] @relation("Voter") votingSummaries PlusVotingSummary[] calendarEvents CalendarEvent[] } model Profile { twitterName String? twitchName String? youtubeId String? country String? sensMotion Float? sensStick Float? bio String? weaponPool String[] updatedAt DateTime @default(now()) @updatedAt customUrlPath String? @unique colors Json? user User @relation(fields: [userId], references: [id]) userId Int @unique } enum RankedMode { SZ TC RM CB } enum Mode { TW SZ TC RM CB } model XRankPlacement { id Int @id @default(autoincrement()) switchAccountId String player Player @relation(fields: [switchAccountId], references: [switchAccountId]) playerName String ranking Int xPower Float weapon String mode RankedMode month Int year Int @@unique([switchAccountId, mode, month, year]) } enum Region { EU NA JP } enum LeagueType { TWIN QUAD } model LeagueSquad { id Int @id @default(autoincrement()) region Region type LeagueType leaguePower Float startTime DateTime members LeagueSquadMember[] @@index([leaguePower, type, region]) } model LeagueSquadMember { squadId Int squad LeagueSquad @relation(fields: [squadId], references: [id]) switchAccountId String player Player @relation(fields: [switchAccountId], references: [switchAccountId]) weapon String @@unique([squadId, switchAccountId]) } model Player { switchAccountId String @unique userId Int? @unique name String? principalId String? isJP Boolean @default(false) placements XRankPlacement[] user User? @relation(fields: [userId], references: [id]) leaguePlacements LeagueSquadMember[] @@index([principalId]) } enum Ability { CB LDE OG T H NS TI RP AD DR SJ OS BDU REC RES ISM ISS MPU QR QSJ RSU SSU SCU SPU SS BRU } model Build { id Int @id @default(autoincrement()) userId Int weapon String title String? description String? modes Mode[] headGear String? headAbilities Ability[] clothingGear String? clothingAbilities Ability[] shoesGear String? shoesAbilities Ability[] abilityPoints Json top500 Boolean jpn Boolean updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id]) @@index(weapon) @@index(userId) @@index(abilityPoints) } model SalmonRunRotation { id Int @unique startTime DateTime endTime DateTime weapons String[] grizzcoWeapon String? stage String records SalmonRunRecord[] } enum SalmonRunRecordCategory { TOTAL TOTAL_NO_NIGHT PRINCESS NT_NORMAL HT_NORMAL LT_NORMAL NT_RUSH HT_RUSH NT_FOG HT_FOG LT_FOG NT_GOLDIE HT_GOLDIE NT_GRILLERS HT_GRILLERS NT_MOTHERSHIP HT_MOTHERSHIP LT_MOTHERSHIP LT_COHOCK } model SalmonRunRecord { id Int @id @default(autoincrement()) rotationId Int submitterId Int goldenEggCount Int approved Boolean category SalmonRunRecordCategory links String[] createdAt DateTime @default(now()) rotation SalmonRunRotation @relation(fields: [rotationId], references: [id]) submitter User @relation(fields: [submitterId], references: [id]) roster User[] @relation("SalmonRunRecordRoster") } enum VoiceChatStatus { YES NO MAYBE } enum Playstyle { FRONTLINE MIDLINE BACKLINE } model FreeAgentPost { id Int @id @default(autoincrement()) playstyles Playstyle[] canVC VoiceChatStatus content String updatedAt DateTime @updatedAt userId Int @unique user User @relation(fields: [userId], references: [id]) likedPosts FreeAgentPost[] @relation("LikedPosts", references: [id]) likersPosts FreeAgentPost[] @relation("LikedPosts", references: [id]) } model Team { id Int @id @default(autoincrement()) name String nameForUrl String @unique twitterName String? bio String? recruitingPost String? inviteCode String @unique captainId Int @unique captain User @relation("TeamCaptain", fields: [captainId], references: [id]) roster User[] } model LadderPlayerTrueSkill { userId Int @id mu Float sigma Float user User @relation(fields: [userId], references: [id]) } model LadderRegisteredTeam { id Int @id @default(autoincrement()) roster User[] inviteCode String @unique ownerId Int @unique } enum Side { ALPHA BRAVO } model LadderMatchPlayer { userId Int matchId Int team Side user User @relation(fields: [userId], references: [id]) match LadderMatch @relation(fields: [matchId], references: [id]) @@id([userId, matchId]) } model LadderMatch { id Int @id @default(autoincrement()) teamAScore Int? teamBScore Int? maplist Json order Int dayId Int players LadderMatchPlayer[] day LadderDay @relation(fields: [dayId], references: [id]) details DetailedMap[] } model LadderDay { id Int @id @default(autoincrement()) date DateTime matches LadderMatch[] } model DetailedMap { id Int @id @default(autoincrement()) order Int stage String mode Mode duration Int winnerScore Int loserScore Int date DateTime? ladderMatchId Int? players DetailedMapPlayer[] ladderMatch LadderMatch? @relation(fields: [ladderMatchId], references: [id]) } enum WinnerLoser { WINNER LOSER } model DetailedMapPlayer { detailedMapId Int status WinnerLoser principalId String name String weapon String mainAbilities Ability[] subAbilities Ability[] kills Int assists Int deaths Int specials Int paint Int gear String[] detailedMap DetailedMap @relation(fields: [detailedMapId], references: [id]) @@unique([detailedMapId, principalId]) } enum PlusRegion { EU NA } model PlusStatus { userId Int @unique voucherId Int? @unique membershipTier Int? vouchTier Int? canVouchFor Int? canVouchAgainAfter DateTime? region PlusRegion nameForVoting String? user User @relation(fields: [userId], references: [id]) voucher User? @relation("Voucher", fields: [voucherId], references: [id]) } model PlusSuggestion { suggestedId Int suggesterId Int tier Int description String isResuggestion Boolean @default(false) createdAt DateTime @default(now()) suggestedUser User @relation(fields: [suggestedId], references: [id]) suggesterUser User @relation("Suggester", fields: [suggesterId], references: [id]) @@unique([tier, suggestedId, suggesterId]) } model PlusBallot { votedId Int voterId Int score Int tier Int isStale Boolean @default(false) votedUser User @relation(fields: [votedId], references: [id]) voterUser User @relation("Voter", fields: [voterId], references: [id]) @@unique([votedId, voterId, isStale]) } model PlusVotingSummary { userId Int tier Int month Int year Int wasVouched Boolean wasSuggested Boolean countsEU Int[] countsNA Int[] user User @relation(fields: [userId], references: [id]) @@unique([userId, tier, month, year]) } enum TournamentFormat { SE DE GROUPS2SE GROUPS2DE SWISS2SE SWISS2DE SWISS OTHER } model CalendarEvent { id Int @id @default(autoincrement()) name String date DateTime description String eventUrl String discordInviteUrl String? tags String[] isTournament Boolean @default(true) format TournamentFormat? posterId Int poster User @relation(fields: [posterId], references: [id]) }