All checks were successful
Automated Container Build / build-and-push (push) Successful in 1m22s
224 lines
6.5 KiB
Text
224 lines
6.5 KiB
Text
datasource db {
|
|
provider = "sqlite"
|
|
}
|
|
|
|
generator client {
|
|
provider = "prisma-client"
|
|
output = "../src/generated/prisma"
|
|
}
|
|
|
|
model Class {
|
|
id String @id @default(uuid())
|
|
slug String @unique
|
|
name String
|
|
sortOrder Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
|
|
decks Deck[]
|
|
quizSets QuizSet[]
|
|
materialGroups MaterialGroup[]
|
|
spacedRepetitionSets SpacedRepetitionSet[]
|
|
}
|
|
|
|
model Deck {
|
|
id String @id @default(uuid())
|
|
classId String
|
|
name String
|
|
description String?
|
|
sortOrder Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
|
|
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
|
groupId String?
|
|
group MaterialGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
|
|
cards Flashcard[]
|
|
shareLink ShareLink?
|
|
progress StudyProgress[]
|
|
spacedRepetitionMemberships SpacedRepetitionSetDeck[]
|
|
}
|
|
|
|
model Flashcard {
|
|
id String @id @default(uuid())
|
|
deckId String
|
|
front String
|
|
back String
|
|
sortOrder Int @default(0)
|
|
|
|
deck Deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
|
|
spacedRepetitionStates SpacedRepetitionCardState[]
|
|
}
|
|
|
|
model QuizSet {
|
|
id String @id @default(uuid())
|
|
classId String
|
|
name String
|
|
description String?
|
|
sortOrder Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
|
|
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
|
groupId String?
|
|
group MaterialGroup? @relation(fields: [groupId], references: [id], onDelete: SetNull)
|
|
questions Question[]
|
|
attempts QuizAttempt[]
|
|
shareLink ShareLink?
|
|
progress StudyProgress[]
|
|
}
|
|
|
|
model Question {
|
|
id String @id @default(uuid())
|
|
quizSetId String
|
|
type String // "MULTIPLE_CHOICE" | "SATA"
|
|
prompt String
|
|
rationale String
|
|
category String
|
|
sortOrder Int @default(0)
|
|
|
|
quizSet QuizSet @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
|
|
options AnswerOption[]
|
|
}
|
|
|
|
model AnswerOption {
|
|
id String @id @default(uuid())
|
|
questionId String
|
|
text String
|
|
isCorrect Boolean @default(false)
|
|
sortOrder Int @default(0)
|
|
|
|
question Question @relation(fields: [questionId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model StudyProgress {
|
|
id String @id @default(uuid())
|
|
contentType String // "DECK" | "QUIZ"
|
|
deckId String?
|
|
quizSetId String?
|
|
mode String // "SEQUENTIAL" | "SHUFFLED"
|
|
currentIndex Int @default(0)
|
|
orderJson String // JSON array of card/question ids
|
|
answersJson String? // in-progress quiz answers
|
|
cardResultsJson String? // per-card grades for decks
|
|
updatedAt DateTime @updatedAt
|
|
|
|
deck Deck? @relation(fields: [deckId], references: [id], onDelete: Cascade)
|
|
quizSet QuizSet? @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([deckId, mode])
|
|
@@unique([quizSetId, mode])
|
|
}
|
|
|
|
model QuizAttempt {
|
|
id String @id @default(uuid())
|
|
quizSetId String
|
|
score Float
|
|
maxScore Int
|
|
answersJson String
|
|
isPartialRetake Boolean @default(false)
|
|
completedAt DateTime @default(now())
|
|
|
|
quizSet QuizSet @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model ShareLink {
|
|
id String @id @default(uuid())
|
|
targetType String // "DECK" | "QUIZ" | "GROUP"
|
|
deckId String? @unique
|
|
quizSetId String? @unique
|
|
groupId String? @unique
|
|
createdAt DateTime @default(now())
|
|
|
|
deck Deck? @relation(fields: [deckId], references: [id], onDelete: Cascade)
|
|
quizSet QuizSet? @relation(fields: [quizSetId], references: [id], onDelete: Cascade)
|
|
group MaterialGroup? @relation(fields: [groupId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
model AuthSecurity {
|
|
id Int @id @default(1)
|
|
failedAttempts Int @default(0)
|
|
lockedUntil DateTime?
|
|
lastAttemptAt DateTime?
|
|
}
|
|
|
|
model Setting {
|
|
key String @id
|
|
value String
|
|
}
|
|
|
|
model StudyActivity {
|
|
id String @id @default(uuid())
|
|
type String // "FLASHCARD" | "QUIZ_QUESTION"
|
|
occurredAt DateTime @default(now())
|
|
|
|
@@index([occurredAt])
|
|
}
|
|
|
|
model MaterialGroup {
|
|
id String @id @default(uuid())
|
|
classId String
|
|
name String
|
|
type String // "DECK" | "QUIZ"
|
|
sortOrder Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
|
|
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
|
decks Deck[]
|
|
quizSets QuizSet[]
|
|
shareLink ShareLink?
|
|
}
|
|
|
|
model SpacedRepetitionSet {
|
|
id String @id @default(uuid())
|
|
classId String
|
|
name String
|
|
description String?
|
|
newCardsPerDay Int @default(30)
|
|
sortOrder Int @default(0)
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
class Class @relation(fields: [classId], references: [id], onDelete: Cascade)
|
|
decks SpacedRepetitionSetDeck[]
|
|
cardStates SpacedRepetitionCardState[]
|
|
|
|
@@index([classId, sortOrder])
|
|
}
|
|
|
|
model SpacedRepetitionSetDeck {
|
|
setId String
|
|
deckId String
|
|
sortOrder Int @default(0)
|
|
addedAt DateTime @default(now())
|
|
|
|
set SpacedRepetitionSet @relation(fields: [setId], references: [id], onDelete: Cascade)
|
|
deck Deck @relation(fields: [deckId], references: [id], onDelete: Cascade)
|
|
|
|
@@id([setId, deckId])
|
|
@@index([deckId])
|
|
}
|
|
|
|
model SpacedRepetitionCardState {
|
|
id String @id @default(uuid())
|
|
setId String
|
|
flashcardId String
|
|
due DateTime
|
|
stability Float
|
|
difficulty Float
|
|
elapsedDays Int
|
|
scheduledDays Int
|
|
learningSteps Int @default(0)
|
|
reps Int
|
|
lapses Int
|
|
state Int
|
|
firstReviewedAt DateTime @default(now())
|
|
lastReview DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
set SpacedRepetitionSet @relation(fields: [setId], references: [id], onDelete: Cascade)
|
|
flashcard Flashcard @relation(fields: [flashcardId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([setId, flashcardId])
|
|
@@index([setId, due])
|
|
@@index([setId, firstReviewedAt])
|
|
@@index([flashcardId])
|
|
}
|