datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" output = "../src/generated/client" } enum Role { ADMIN GUEST TEACHER } enum Difficulty { EASY MEDIUM HARD } enum Locale { en zh } enum Language { c cpp } enum Protocol { ws wss } enum Status { PD // PENDING QD // QUEUED CP // COMPILING CE // Compilation Error CS // Compilation Success RU // RUNNING TLE // Time Limit Exceeded MLE // Memory Limit Exceeded RE // Runtime Error AC // Accepted WA // Wrong Answer SE // System Error } enum ProblemContentType { TITLE DESCRIPTION SOLUTION } enum CourseEnrollmentRole { STUDENT } model User { id String @id @default(cuid()) name String? email String @unique password String? emailVerified DateTime? image String? role Role @default(GUEST) accounts Account[] sessions Session[] // Optional for WebAuthn support Authenticator Authenticator[] problems Problem[] submissions Submission[] teachingCourses Course[] @relation("CourseTeacher") courseEnrollments CourseEnrollment[] createdAssignments Assignment[] @relation("AssignmentCreator") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Problem { id String @id @default(cuid()) displayId Int @unique difficulty Difficulty @default(EASY) isPublished Boolean @default(false) isTrim Boolean @default(false) timeLimit Int @default(1000) memoryLimit Int @default(134217728) localizations ProblemLocalization[] templates Template[] testcases Testcase[] submissions Submission[] assignmentProblems AssignmentProblem[] userId String? user User? @relation(fields: [userId], references: [id], onDelete: SetNull) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model ProblemLocalization { problemId String locale Locale type ProblemContentType content String problem Problem @relation(fields: [problemId], references: [id], onDelete: Cascade) @@id([problemId, locale, type]) } model Template { problemId String language Language content String problem Problem @relation(fields: [problemId], references: [id], onDelete: Cascade) @@id([problemId, language]) } model Submission { id String @id @default(cuid()) language Language content String status Status message String? timeUsage Int? memoryUsage Int? testcaseResults TestcaseResult[] codeAnalysis CodeAnalysis? userId String problemId String assignmentId String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) problem Problem @relation(fields: [problemId], references: [id], onDelete: Cascade) assignment Assignment? @relation(fields: [assignmentId], references: [id], onDelete: SetNull) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([assignmentId, userId, problemId]) @@index([assignmentId, problemId, status]) @@index([userId, problemId]) @@index([createdAt]) } model Course { id String @id @default(cuid()) title String description String? archived Boolean @default(false) teacherId String teacher User @relation("CourseTeacher", fields: [teacherId], references: [id], onDelete: Cascade) enrollments CourseEnrollment[] assignments Assignment[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([teacherId]) } model CourseEnrollment { id String @id @default(cuid()) role CourseEnrollmentRole @default(STUDENT) courseId String userId String course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) @@unique([courseId, userId]) @@index([courseId]) @@index([userId]) } model Assignment { id String @id @default(cuid()) title String description String? opensAt DateTime? dueAt DateTime? published Boolean @default(false) courseId String createdById String course Course @relation(fields: [courseId], references: [id], onDelete: Cascade) createdBy User @relation("AssignmentCreator", fields: [createdById], references: [id], onDelete: Cascade) problems AssignmentProblem[] submissions Submission[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([courseId]) @@index([createdById]) } model AssignmentProblem { assignmentId String problemId String maxPoints Int @default(100) order Int? assignment Assignment @relation(fields: [assignmentId], references: [id], onDelete: Cascade) problem Problem @relation(fields: [problemId], references: [id], onDelete: Cascade) @@id([assignmentId, problemId]) @@index([assignmentId]) @@index([problemId]) } enum AnalysisStatus { PENDING QUEUED PROCESSING COMPLETED FAILED } model CodeAnalysis { id String @id @default(cuid()) submissionId String @unique status AnalysisStatus @default(PENDING) timeComplexity String? spaceComplexity String? overallScore Int? styleScore Int? readabilityScore Int? efficiencyScore Int? correctnessScore Int? feedback String? submission Submission @relation(fields: [submissionId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Testcase { id String @id @default(cuid()) expectedOutput String inputs TestcaseInput[] testcaseResults TestcaseResult[] problemId String problem Problem @relation(fields: [problemId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model TestcaseInput { id String @id @default(cuid()) index Int name String value String testcaseId String testcase Testcase @relation(fields: [testcaseId], references: [id], onDelete: Cascade) } model TestcaseResult { id String @id @default(cuid()) isCorrect Boolean output String? timeUsage Int? memoryUsage Int? submissionId String testcaseId String submission Submission @relation(fields: [submissionId], references: [id], onDelete: Cascade) testcase Testcase @relation(fields: [testcaseId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model DockerConfig { language Language @id image String tag String workingDir String compileOutputLimit Int @default(1048576) runOutputLimit Int @default(1048576) } model LanguageServerConfig { language Language @id protocol Protocol hostname String port Int? path String? } model Account { userId String type String provider String providerAccountId String refresh_token String? access_token String? expires_at Int? token_type String? scope String? id_token String? session_state String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@id([provider, providerAccountId]) } model Session { sessionToken String @unique userId String expires DateTime user User @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model VerificationToken { identifier String token String expires DateTime @@id([identifier, token]) } // Optional for WebAuthn support model Authenticator { credentialID String @unique userId String providerAccountId String credentialPublicKey String counter Int credentialDeviceType String credentialBackedUp Boolean transports String? user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@id([userId, credentialID]) }