diff --git a/src/interfaces/exam.ts b/src/interfaces/exam.ts index fe919b0b..fa2a7384 100644 --- a/src/interfaces/exam.ts +++ b/src/interfaces/exam.ts @@ -1,4 +1,4 @@ -import { Module } from "."; +import {Module} from "."; export type Exam = ReadingExam | ListeningExam | WritingExam | SpeakingExam | LevelExam; export type Variant = "full" | "partial"; @@ -15,6 +15,7 @@ interface ExamBase { shuffle?: boolean; createdBy?: string; // option as it has been added later createdAt?: string; // option as it has been added later + private?: boolean; } export interface ReadingExam extends ExamBase { module: "reading"; @@ -67,7 +68,7 @@ export interface UserSolution { }; exercise: string; isDisabled?: boolean; - shuffleMaps?: ShuffleMap[] + shuffleMaps?: ShuffleMap[]; } export interface WritingExam extends ExamBase { @@ -99,24 +100,19 @@ export type Exercise = export interface Evaluation { comment: string; overall: number; - task_response: { [key: string]: number | { grade: number; comment: string } }; - misspelled_pairs?: { correction: string | null; misspelled: string }[]; + task_response: {[key: string]: number | {grade: number; comment: string}}; + misspelled_pairs?: {correction: string | null; misspelled: string}[]; } - type InteractivePerfectAnswerKey = `perfect_answer_${number}`; type InteractiveTranscriptKey = `transcript_${number}`; type InteractiveFixedTextKey = `fixed_text_${number}`; -type InteractivePerfectAnswerType = { [key in InteractivePerfectAnswerKey]: { answer: string } }; -type InteractiveTranscriptType = { [key in InteractiveTranscriptKey]?: string }; -type InteractiveFixedTextType = { [key in InteractiveFixedTextKey]?: string }; - -interface InteractiveSpeakingEvaluation extends Evaluation, - InteractivePerfectAnswerType, - InteractiveTranscriptType, - InteractiveFixedTextType { } +type InteractivePerfectAnswerType = {[key in InteractivePerfectAnswerKey]: {answer: string}}; +type InteractiveTranscriptType = {[key in InteractiveTranscriptKey]?: string}; +type InteractiveFixedTextType = {[key in InteractiveFixedTextKey]?: string}; +interface InteractiveSpeakingEvaluation extends Evaluation, InteractivePerfectAnswerType, InteractiveTranscriptType, InteractiveFixedTextType {} interface SpeakingEvaluation extends CommonEvaluation { perfect_answer_1?: string; @@ -189,10 +185,10 @@ export interface InteractiveSpeakingExercise { first_title?: string; second_title?: string; text: string; - prompts: { text: string; video_url: string }[]; + prompts: {text: string; video_url: string}[]; userSolutions: { id: string; - solution: { questionIndex: number; question: string; answer: string }[]; + solution: {questionIndex: number; question: string; answer: string}[]; evaluation?: InteractiveSpeakingEvaluation; }[]; topic?: string; @@ -208,14 +204,14 @@ export interface FillBlanksMCOption { B: string; C: string; D: string; - } + }; } export interface FillBlanksExercise { prompt: string; // *EXAMPLE: "Complete the summary below. Click a blank to select the corresponding word for it." type: "fillBlanks"; id: string; - words: (string | { letter: string; word: string } | FillBlanksMCOption)[]; // *EXAMPLE: ["preserve", "unaware"] + words: (string | {letter: string; word: string} | FillBlanksMCOption)[]; // *EXAMPLE: ["preserve", "unaware"] text: string; // *EXAMPLE: "They tried to {{1}} burning" allowRepetition?: boolean; solutions: { @@ -234,7 +230,7 @@ export interface TrueFalseExercise { id: string; prompt: string; // *EXAMPLE: "Select the appropriate option." questions: TrueFalseQuestion[]; - userSolutions: { id: string; solution: "true" | "false" | "not_given" }[]; + userSolutions: {id: string; solution: "true" | "false" | "not_given"}[]; } export interface TrueFalseQuestion { @@ -263,7 +259,7 @@ export interface MatchSentencesExercise { type: "matchSentences"; id: string; prompt: string; - userSolutions: { question: string; option: string }[]; + userSolutions: {question: string; option: string}[]; sentences: MatchSentenceExerciseSentence[]; allowRepetition: boolean; options: MatchSentenceExerciseOption[]; @@ -286,7 +282,7 @@ export interface MultipleChoiceExercise { id: string; prompt: string; // *EXAMPLE: "Select the appropriate option." questions: MultipleChoiceQuestion[]; - userSolutions: { question: string; option: string }[]; + userSolutions: {question: string; option: string}[]; } export interface MultipleChoiceQuestion { @@ -306,10 +302,10 @@ export interface ShuffleMap { questionID: string; map: { [key: string]: string; - } + }; } export interface Shuffles { exerciseID: string; - shuffles: ShuffleMap[] + shuffles: ShuffleMap[]; } diff --git a/src/utils/exams.be.ts b/src/utils/exams.be.ts index be8d1837..2466c61d 100644 --- a/src/utils/exams.be.ts +++ b/src/utils/exams.be.ts @@ -1,4 +1,4 @@ -import {collection, getDocs, query, where, setDoc, doc, Firestore, getDoc} from "firebase/firestore"; +import {collection, getDocs, query, where, setDoc, doc, Firestore, getDoc, and} from "firebase/firestore"; import {shuffle} from "lodash"; import {Difficulty, Exam, InstructorGender, SpeakingExam, Variant, WritingExam} from "@/interfaces/exam"; import {DeveloperUser, Stat, StudentUser, User} from "@/interfaces/user"; @@ -17,7 +17,7 @@ export const getExams = async ( ): Promise => { const moduleRef = collection(db, module); - const q = query(moduleRef, where("isDiagnostic", "==", false)); + const q = query(moduleRef, and(where("isDiagnostic", "==", false), where("private", "!=", true))); const snapshot = await getDocs(q); const allExams = shuffle(