/// An exam for the Exam Environment App as designed by the examiners model ExamEnvironmentExam { /// Globally unique exam id id String @id @default(auto()) @map("_id") @db.ObjectId /// All questions for a given exam questionSets ExamEnvironmentQuestionSet[] /// Configuration for exam metadata config ExamEnvironmentConfig /// ObjectIds for required challenges/blocks to take the exam prerequisites String[] @db.ObjectId /// If `deprecated`, the exam should no longer be considered for users deprecated Boolean /// Version of the record /// The default must be incremented by 1, if anything in the schema changes version Int @default(3) // Relations generatedExams ExamEnvironmentGeneratedExam[] examAttempts ExamEnvironmentExamAttempt[] ExamEnvironmentChallenge ExamEnvironmentChallenge[] } /// A grouping of one or more questions of a given type type ExamEnvironmentQuestionSet { /// Unique question type id id String @db.ObjectId type ExamEnvironmentQuestionType /// Content related to all questions in set context String? questions ExamEnvironmentMultipleChoiceQuestion[] } /// A multiple choice question for the Exam Environment App type ExamEnvironmentMultipleChoiceQuestion { /// Unique question id id String @db.ObjectId /// Main question paragraph text String /// Zero or more tags given to categorize a question tags String[] /// Optional audio for a question audio ExamEnvironmentAudio? /// Available possible answers for an exam answers ExamEnvironmentAnswer[] /// TODO Possible "deprecated_time" to remove after all exams could possibly have been taken deprecated Boolean } /// Audio for an Exam Environment App multiple choice question type ExamEnvironmentAudio { /// Optional text for audio captions String? /// URL to audio file /// /// Expected in the format: `#t=,` /// Where `start_time_in_seconds` and `end_time_in_seconds` are optional floats. url String } /// Type of question for the Exam Environment App enum ExamEnvironmentQuestionType { /// Single question with one or more answers MultipleChoice /// Mass text Dialogue } /// Answer for an Exam Environment App multiple choice question type ExamEnvironmentAnswer { /// Unique answer id id String @db.ObjectId /// Whether the answer is correct isCorrect Boolean /// Answer paragraph text String } /// Configuration for an exam in the Exam Environment App type ExamEnvironmentConfig { /// Human-readable exam name name String /// Notes given about exam note String /// Category configuration for question selection tags ExamEnvironmentTagConfig[] /// Total time allocated for exam in seconds totalTimeInS Int /// Configuration for sets of questions questionSets ExamEnvironmentQuestionSetConfig[] /// Duration after exam completion before a retake is allowed in seconds retakeTimeInS Int /// Passing percent for the exam passingPercent Float } /// Configuration for a set of questions in the Exam Environment App type ExamEnvironmentQuestionSetConfig { type ExamEnvironmentQuestionType /// Number of this grouping of questions per exam numberOfSet Int /// Number of multiple choice questions per grouping matching this set config numberOfQuestions Int /// Number of correct answers given per multiple choice question numberOfCorrectAnswers Int /// Number of incorrect answers given per multiple choice question numberOfIncorrectAnswers Int } /// Configuration for tags in the Exam Environment App /// /// This configures the number of questions that should resolve to a given tag set criteria. type ExamEnvironmentTagConfig { /// Group of multiple choice question tags group String[] /// Number of multiple choice questions per exam that should meet the group criteria numberOfQuestions Int } /// An attempt at an exam in the Exam Environment App model ExamEnvironmentExamAttempt { id String @id @default(auto()) @map("_id") @db.ObjectId /// Foriegn key to user userId String @db.ObjectId /// Foreign key to exam examId String @db.ObjectId /// Foreign key to generated exam id generatedExamId String @db.ObjectId questionSets ExamEnvironmentQuestionSetAttempt[] /// Time exam was started startTime DateTime /// Version of the record /// The default must be incremented by 1, if anything in the schema changes version Int @default(3) // Relations user user @relation(fields: [userId], references: [id], onDelete: Cascade) exam ExamEnvironmentExam @relation(fields: [examId], references: [id], onDelete: Cascade) generatedExam ExamEnvironmentGeneratedExam @relation(fields: [generatedExamId], references: [id]) ExamEnvironmentExamModeration ExamEnvironmentExamModeration[] } type ExamEnvironmentQuestionSetAttempt { id String @db.ObjectId questions ExamEnvironmentMultipleChoiceQuestionAttempt[] } type ExamEnvironmentMultipleChoiceQuestionAttempt { /// Foreign key to question id String @db.ObjectId /// An array of foreign keys to answers answers String[] @db.ObjectId /// Time answers to question were submitted /// /// If the question is later revisited, this field is updated submissionTime DateTime } /// A generated exam for the Exam Environment App /// /// This is the user-facing information for an exam. model ExamEnvironmentGeneratedExam { id String @id @default(auto()) @map("_id") @db.ObjectId /// Foreign key to exam examId String @db.ObjectId questionSets ExamEnvironmentGeneratedQuestionSet[] /// If `deprecated`, the generation should not longer be considered for users deprecated Boolean /// Version of the record /// The default must be incremented by 1, if anything in the schema changes version Int @default(1) // Relations exam ExamEnvironmentExam @relation(fields: [examId], references: [id], onDelete: Cascade) EnvExamAttempt ExamEnvironmentExamAttempt[] } type ExamEnvironmentGeneratedQuestionSet { id String @db.ObjectId questions ExamEnvironmentGeneratedMultipleChoiceQuestion[] } type ExamEnvironmentGeneratedMultipleChoiceQuestion { /// Foreign key to question id id String @db.ObjectId /// Each item is a foreign key to an answer answers String[] @db.ObjectId } /// A map between challenge ids and exam ids /// /// This is expected to be used for relating challenge pages AND/OR certifications to exams model ExamEnvironmentChallenge { id String @id @default(auto()) @map("_id") @db.ObjectId examId String @db.ObjectId challengeId String @db.ObjectId version Int @default(1) exam ExamEnvironmentExam @relation(fields: [examId], references: [id], onDelete: Cascade) } model ExamEnvironmentAuthorizationToken { /// An ObjectId is used to provide access to the created timestamp id String @id @default(auto()) @map("_id") @db.ObjectId /// Used to set an `expireAt` index to delete documents expireAt DateTime @db.Date userId String @unique @db.ObjectId version Int @default(1) // Relations user user @relation(fields: [userId], references: [id], onDelete: Cascade) } model ExamEnvironmentExamModeration { id String @id @default(auto()) @map("_id") @db.ObjectId /// Whether or not the item is approved status ExamEnvironmentExamModerationStatus /// Foreign key to exam attempt examAttemptId String @unique @db.ObjectId /// Optional feedback/note about the moderation decision feedback String? /// Date the exam attempt was moderated moderationDate DateTime? /// Foreign key to moderator. This is `null` until the item is moderated. moderatorId String? @db.ObjectId /// Date the exam attempt expired submissionDate DateTime @default(now()) @db.Date /// Whether the `challengeId` for the `ExamEnvironmentChallenge` has been awarded to the user challengesAwarded Boolean @default(false) /// Version of the record /// The default must be incremented by 1, if anything in the schema changes version Int @default(2) // Relations examAttempt ExamEnvironmentExamAttempt @relation(fields: [examAttemptId], references: [id], onDelete: Cascade) } enum ExamEnvironmentExamModerationStatus { /// Attempt is determined to be valid Approved /// Attempt is determined to be invalid Denied /// Attempt has yet to be moderated Pending }