@tinyweb_dev/oe-exam-sdk 1.0.8 → 1.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/exams/take/components/QuestionRenderer.js +1 -5
- package/dist/components/exams/take/components/question-renderers/ChooseThenAnswerGroupRenderer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversCrossOutWordGroupRenderer.js +24 -10
- package/dist/components/exams/take/components/question-renderers/MoversCrosswordPuzzleRenderer.js +1 -1
- package/dist/components/exams/take/components/question-renderers/MoversFillInBlankGroupRenderer.js +2 -1
- package/dist/components/exams/take/components/speaking/renderers/SpeakingSpontaneousQaGroupRenderer.js +12 -2
- package/dist/components/exams/take/hooks/useSpontaneousQaGroupRendererSetup.js +2 -1
- package/dist/components/exams/take/utils/answer-transformers.js +16 -1
- package/dist/components/exams/take/utils/cross-out-word-group.transformer.js +4 -6
- package/dist/components/exams/take/utils/question-transformers.d.ts +5 -0
- package/dist/components/exams/take/utils/question-transformers.js +6 -0
- package/dist/components/questions/_shared/components/compact/KidChoiceRow.d.ts +12 -0
- package/dist/components/questions/_shared/components/compact/KidChoiceRow.js +33 -0
- package/dist/components/questions/_shared/components/compact/KidInstruction.d.ts +5 -0
- package/dist/components/questions/_shared/components/compact/KidInstruction.js +9 -0
- package/dist/components/questions/_shared/components/compact/KidPrompt.d.ts +5 -0
- package/dist/components/questions/_shared/components/compact/KidPrompt.js +9 -0
- package/dist/components/questions/_shared/components/compact/KidQuestionCard.d.ts +12 -0
- package/dist/components/questions/_shared/components/compact/KidQuestionCard.js +7 -0
- package/dist/components/questions/_shared/components/compact/index.d.ts +4 -0
- package/dist/components/questions/_shared/components/compact/index.js +4 -0
- package/dist/components/questions/_shared/types/answer-the-question-group.type.d.ts +3 -0
- package/dist/components/questions/_shared/types/choose-then-answer-group.type.d.ts +17 -0
- package/dist/components/questions/_shared/types/cross-out-word-group.type.d.ts +1 -0
- package/dist/components/questions/_shared/types/crossword-puzzle.type.d.ts +5 -1
- package/dist/components/questions/_shared/types/spontaneous-qa-group.type.d.ts +17 -0
- package/dist/components/questions/_shared/types/true-false-correct-group.type.d.ts +1 -0
- package/dist/components/questions/_shared/types/true-false-group.type.d.ts +1 -0
- package/dist/components/questions/types/answer-the-question/AnswerTheQuestionClient.js +18 -19
- package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupClient.d.ts +1 -1
- package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupClient.js +16 -17
- package/dist/components/questions/types/answer-the-question-group/AnswerTheQuestionGroupCreator.js +7 -4
- package/dist/components/questions/types/answer-the-question-group/map-answer-the-question-group-data.js +2 -0
- package/dist/components/questions/types/answer-the-question-group/transform.js +12 -5
- package/dist/components/questions/types/arrange-letters-into-words/ArrangeLettersIntoWordsClient.js +17 -11
- package/dist/components/questions/types/choose-correct-adjective/ChooseCorrectAdjectiveClient.js +15 -42
- package/dist/components/questions/types/choose-the-correct-answer/ChooseTheCorrectAnswerClient.js +15 -36
- package/dist/components/questions/types/choose-the-correct-answer-group/ChooseTheCorrectAnswerGroupClient.js +9 -32
- package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupClient.d.ts +1 -1
- package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupClient.js +76 -11
- package/dist/components/questions/types/choose-then-answer-group/ChooseThenAnswerGroupCreator.js +54 -6
- package/dist/components/questions/types/choose-then-answer-group/map-choose-then-answer-group-data.d.ts +4 -1
- package/dist/components/questions/types/choose-then-answer-group/map-choose-then-answer-group-data.js +39 -2
- package/dist/components/questions/types/choose-then-answer-group/transform.js +27 -14
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.d.ts +1 -1
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupClient.js +76 -7
- package/dist/components/questions/types/cross-out-word-group/CrossOutWordGroupCreator.js +24 -44
- package/dist/components/questions/types/cross-out-word-group/index.d.ts +1 -0
- package/dist/components/questions/types/cross-out-word-group/index.js +1 -0
- package/dist/components/questions/types/cross-out-word-group/map-cross-out-word-group-data.js +9 -9
- package/dist/components/questions/types/cross-out-word-group/tokenize.d.ts +2 -0
- package/dist/components/questions/types/cross-out-word-group/tokenize.js +11 -0
- package/dist/components/questions/types/cross-out-word-group/transform.js +2 -4
- package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleClient.d.ts +2 -1
- package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleClient.js +20 -8
- package/dist/components/questions/types/crossword-puzzle/CrosswordPuzzleCreator.js +68 -11
- package/dist/components/questions/types/crossword-puzzle/transform.js +59 -30
- package/dist/components/questions/types/fill-in-blank/FillInBlankClient.js +26 -31
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankAnswerKey.d.ts +6 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankAnswerKey.js +17 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupClient.js +32 -28
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupCreator.js +109 -26
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupMediaField.js +21 -11
- package/dist/components/questions/types/fill-in-blank-group/blank-utils.d.ts +1 -0
- package/dist/components/questions/types/fill-in-blank-group/blank-utils.js +4 -1
- package/dist/components/questions/types/fill-missing-words-in-grid/FillMissingWordsInGridClient.js +32 -31
- package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixClient.d.ts +12 -2
- package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixClient.js +188 -46
- package/dist/components/questions/types/find-words-in-matrix/FindWordsInMatrixCreator.js +6 -2
- package/dist/components/questions/types/find-words-in-matrix/transform.js +5 -0
- package/dist/components/questions/types/label-the-picture/LabelThePictureClient.js +4 -3
- package/dist/components/questions/types/listen-and-choose-from-answer-group/ListenAndChooseFromAnswerGroupClient.js +11 -30
- package/dist/components/questions/types/listen-and-speak-answer/ListenAndSpeakAnswerClient.js +7 -6
- package/dist/components/questions/types/listen-and-speak-compare-images/ListenAndSpeakCompareImagesClient.js +2 -1
- package/dist/components/questions/types/listen-and-speak-image-group/ListenAndSpeakImageGroupClient.js +14 -13
- package/dist/components/questions/types/listen-and-speak-info-exchange/ListenAndSpeakInfoExchangeClient.js +4 -3
- package/dist/components/questions/types/listen-and-speak-odd-one-out/ListenAndSpeakOddOneOutClient.js +4 -3
- package/dist/components/questions/types/listen-and-speak-question-list/ListenAndSpeakQuestionListClient.js +11 -10
- package/dist/components/questions/types/listen-and-speak-with-story-images/ListenAndSpeakWithStoryImagesClient.js +4 -3
- package/dist/components/questions/types/match-by-writing-answer/MatchByWritingAnswerClient.js +13 -11
- package/dist/components/questions/types/match-columns-to-make-sentences/MatchColumnsToMakeSentencesClient.js +17 -14
- package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureClient.js +16 -12
- package/dist/components/questions/types/match-word-to-picture/MatchWordToPictureGroupClient.js +14 -14
- package/dist/components/questions/types/match-word-to-picture-group/MatchWordToPictureGroupClient.js +13 -13
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupClient.js +7 -6
- package/dist/components/questions/types/read-passage-and-answer-questions/ReadPassageAndAnswerQuestionsClient.js +8 -26
- package/dist/components/questions/types/sort-words-into-categories/SortWordsIntoCategoriesClient.js +2 -1
- package/dist/components/questions/types/speaking-conversation/SpeakingConversationPreviewClient.js +6 -5
- package/dist/components/questions/types/speaking-cue-card/SpeakingCueCardClient.js +2 -1
- package/dist/components/questions/types/speaking-describe-image/SpeakingDescribeImageClient.js +5 -4
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.d.ts +1 -1
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupClient.js +54 -11
- package/dist/components/questions/types/spontaneous-qa-group/SpontaneousQaGroupCreator.js +11 -7
- package/dist/components/questions/types/spontaneous-qa-group/creator-helpers.js +8 -2
- package/dist/components/questions/types/spontaneous-qa-group/flatten.d.ts +1 -0
- package/dist/components/questions/types/spontaneous-qa-group/flatten.js +4 -2
- package/dist/components/questions/types/spontaneous-qa-group/map-spontaneous-qa-group-data.js +5 -3
- package/dist/components/questions/types/spontaneous-qa-group/register.js +5 -2
- package/dist/components/questions/types/spontaneous-qa-group/transform.js +6 -2
- package/dist/components/questions/types/true-false/TrueFalseClient.js +5 -54
- package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupClient.d.ts +1 -1
- package/dist/components/questions/types/true-false-correct-group/TrueFalseCorrectGroupClient.js +39 -19
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.d.ts +1 -1
- package/dist/components/questions/types/true-false-group/TrueFalseGroupClient.js +20 -19
- package/dist/components/questions/types/word-fill-paragraph/WordFillParagraphClient.js +76 -81
- package/dist/components/questions/types/word-fill-structured-form/WordFillStructuredFormClient.js +17 -16
- package/dist/components/questions/types/word-order-and-match-group/WordOrderAndMatchGroupClient.js +31 -36
- package/dist/components/questions/types/word-ordering/WordOrderingClient.js +15 -14
- package/dist/components/questions/types/word-ordering-group/WordOrderingGroupClient.js +9 -8
- package/dist/components/questions/types/write-correct-verb-form/WriteCorrectVerbFormClient.js +16 -13
- package/dist/components/questions/viewer/AnswerTheQuestionGroupViewer.d.ts +3 -2
- package/dist/components/questions/viewer/AnswerTheQuestionGroupViewer.js +12 -5
- package/dist/components/questions/viewer/ChooseThenAnswerGroupViewer.d.ts +3 -2
- package/dist/components/questions/viewer/ChooseThenAnswerGroupViewer.js +4 -3
- package/dist/components/questions/viewer/CrossOutWordGroupViewer.d.ts +3 -1
- package/dist/components/questions/viewer/CrossOutWordGroupViewer.js +12 -2
- package/dist/components/questions/viewer/FillInBlankGroupViewer.d.ts +6 -2
- package/dist/components/questions/viewer/FillInBlankGroupViewer.js +13 -7
- package/dist/components/questions/viewer/QuestionViewer.d.ts +9 -1
- package/dist/components/questions/viewer/QuestionViewer.js +23 -10
- package/dist/components/questions/viewer/SpontaneousQaGroupViewer.d.ts +7 -1
- package/dist/components/questions/viewer/SpontaneousQaGroupViewer.js +14 -2
- package/dist/components/questions/viewer/TrueFalseCorrectGroupViewer.d.ts +3 -2
- package/dist/components/questions/viewer/TrueFalseCorrectGroupViewer.js +14 -4
- package/dist/components/questions/viewer/TrueFalseGroupViewer.d.ts +5 -2
- package/dist/components/questions/viewer/TrueFalseGroupViewer.js +14 -4
- package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.d.ts +6 -2
- package/dist/components/questions/viewer/WordOrderAndMatchGroupViewer.js +26 -6
- package/dist/components/results/renderers/ReviewAnswerTheQuestionGroupRenderer.js +1 -1
- package/dist/components/results/renderers/review-question-body-movers.js +1 -1
- package/dist/components/results/review-data.js +8 -1
- package/dist/shared/lib/utils/question-reverse-transform.js +39 -5
- package/dist/shared/types/questions/answer-the-question-group.d.ts +8 -3
- package/dist/shared/types/questions/answer-the-question-group.js +5 -0
- package/dist/shared/types/questions/choose-then-answer-group.d.ts +3 -0
- package/dist/shared/types/questions/crossword-puzzle.d.ts +1 -0
- package/dist/shared/types/questions/find-words-in-matrix.d.ts +1 -0
- package/package.json +1 -1
|
@@ -38,7 +38,7 @@ import { MatchWordToPictureViewer } from './MatchWordToPictureViewer';
|
|
|
38
38
|
import { MatchWordToPictureGroupViewer } from './MatchWordToPictureGroupViewer';
|
|
39
39
|
import { MatchColumnsToMakeSentencesViewer } from './MatchColumnsToMakeSentencesViewer';
|
|
40
40
|
import { WordOrderingGroupViewer } from './WordOrderingGroupViewer';
|
|
41
|
-
export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false, userAnswer, }) {
|
|
41
|
+
export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false, userAnswer, gradeDetails, }) {
|
|
42
42
|
const [selectedAnswer, setSelectedAnswer] = useState(userAnswer || null);
|
|
43
43
|
const [playCount, setPlayCount] = useState(0);
|
|
44
44
|
const audioRef = useRef(null);
|
|
@@ -477,6 +477,19 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
477
477
|
}
|
|
478
478
|
return (_jsxs("div", { className: "space-y-3", children: [content.title ? _jsx("h3", { className: "text-center text-lg font-bold uppercase text-slate-800", children: content.title }) : null, content.imageUrl ? (_jsx("div", { className: "flex justify-center", children: _jsx("img", { src: String(content.imageUrl), alt: "", className: "max-h-[180px] rounded-lg object-contain" }) })) : null, _jsx("div", { className: "space-y-2 text-base leading-relaxed text-slate-800", children: paragraph.split('\n').map((line, li) => (_jsx("div", { className: "flex flex-wrap items-baseline", children: renderLine(line, `wfp-${li}`) }, `wfp-l${li}`))) }), isReviewMode && correctAnswers.length > 0 ? (_jsxs("div", { className: "rounded-lg border border-emerald-200 bg-emerald-50/80 p-2.5 text-sm text-emerald-800", children: [_jsx("span", { className: "font-semibold", children: "\u0110\u00E1p \u00E1n: " }), correctAnswers.map((a, i) => (_jsxs("span", { className: "mr-2", children: ["(", i + 1, ") ", _jsx("span", { className: "font-bold underline", children: a || '—' })] }, `wfp-a${i}`)))] })) : null] }));
|
|
479
479
|
};
|
|
480
|
+
const renderCrosswordPuzzle = () => {
|
|
481
|
+
const raw = userAnswer && typeof userAnswer === 'object' && !Array.isArray(userAnswer)
|
|
482
|
+
? userAnswer
|
|
483
|
+
: {};
|
|
484
|
+
const answers = raw.answers && typeof raw.answers === 'object' && !Array.isArray(raw.answers)
|
|
485
|
+
? raw.answers
|
|
486
|
+
: raw;
|
|
487
|
+
return (_jsx(CrosswordPuzzleClient, { content: question.content, correctAnswer: question.correctAnswer ?? question.answer, isReviewMode: isReviewMode, questionNumber: question.questionNumber, userAnswers: answers, onAnswerChange: isReviewMode
|
|
488
|
+
? undefined
|
|
489
|
+
: (key, value) => {
|
|
490
|
+
onSubmitAnswer?.({ answers: { ...answers, [key]: value } });
|
|
491
|
+
} }));
|
|
492
|
+
};
|
|
480
493
|
const renderQuestion = () => {
|
|
481
494
|
const resolvedType = String(question.type ||
|
|
482
495
|
question.questionType ||
|
|
@@ -488,9 +501,9 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
488
501
|
case 'CHOOSE_THE_CORRECT_ANSWER_GROUP':
|
|
489
502
|
return (_jsx(ChooseTheCorrectAnswerGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
490
503
|
case 'TRUE_FALSE_GROUP':
|
|
491
|
-
return (_jsx(TrueFalseGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
504
|
+
return (_jsx(TrueFalseGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
492
505
|
case 'TRUE_FALSE_CORRECT_GROUP':
|
|
493
|
-
return (_jsx(TrueFalseCorrectGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
506
|
+
return (_jsx(TrueFalseCorrectGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
494
507
|
case 'FILL_IN_BLANK_GROUP':
|
|
495
508
|
return (_jsx(FillInBlankGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
496
509
|
case 'MATCHING_WITH_LINES_GROUP':
|
|
@@ -498,20 +511,20 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
498
511
|
case 'MATCH_COLUMNS_TO_MAKE_SENTENCES':
|
|
499
512
|
return (_jsx(MatchColumnsToMakeSentencesViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
500
513
|
case 'CROSS_OUT_WORD_GROUP':
|
|
501
|
-
return (_jsx(CrossOutWordGroupViewer, { question: question, isReviewMode: isReviewMode }));
|
|
514
|
+
return (_jsx(CrossOutWordGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
502
515
|
case 'ANSWER_THE_QUESTION':
|
|
503
516
|
return (_jsx(AnswerTheQuestionViewer, { question: question, isReviewMode: isReviewMode, userAnswer: typeof userAnswer === 'string' ? userAnswer : undefined, onSubmitAnswer: onSubmitAnswer }));
|
|
504
517
|
case 'ANSWER_THE_QUESTION_GROUP':
|
|
505
|
-
return (_jsx(AnswerTheQuestionGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
518
|
+
return (_jsx(AnswerTheQuestionGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
506
519
|
case 'SPEAKING_CUE_CARD':
|
|
507
520
|
return (_jsx(SpeakingCueCardClient, { questionData: mapQuestionToSpeakingCueCardData(question), isReviewMode: isReviewMode }));
|
|
508
521
|
case 'SPONTANEOUS_QA':
|
|
509
522
|
return (_jsx(SpontaneousQAClient, { questionData: mapQuestionToSpontaneousQAData(question), isReviewMode: isReviewMode }));
|
|
510
523
|
case 'SPONTANEOUS_QA_GROUP':
|
|
511
|
-
return (_jsx(SpontaneousQaGroupViewer, { question: question, isReviewMode: isReviewMode }));
|
|
524
|
+
return (_jsx(SpontaneousQaGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, gradeDetails: gradeDetails, disabled: !onSubmitAnswer }));
|
|
512
525
|
case 'WORD_ORDER_AND_MATCH_GROUP':
|
|
513
526
|
case 'WORD_ORDER_AND_MATCH':
|
|
514
|
-
return (_jsx(WordOrderAndMatchGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
527
|
+
return (_jsx(WordOrderAndMatchGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
515
528
|
case 'WORD_ORDERING_GROUP':
|
|
516
529
|
return (_jsx(WordOrderingGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
517
530
|
case 'MATCH_WORD_TO_PICTURE_GROUP':
|
|
@@ -551,13 +564,13 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
551
564
|
case 'WORD_FILL_STRUCTURED_FORM':
|
|
552
565
|
return (_jsx(WordFillStructuredFormViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
553
566
|
case 'CROSSWORD_PUZZLE':
|
|
554
|
-
return (
|
|
567
|
+
return renderCrosswordPuzzle();
|
|
555
568
|
case 'FIND_WORDS_IN_MATRIX':
|
|
556
|
-
return (_jsx(FindWordsInMatrixClient, { content: question.content, correctAnswer: question.answer, showSolution: isReviewMode }));
|
|
569
|
+
return (_jsx(FindWordsInMatrixClient, { content: question.content, correctAnswer: question.correctAnswer ?? question.answer, showSolution: isReviewMode, userAnswer: userAnswer, onAnswerChange: isReviewMode ? undefined : onSubmitAnswer }));
|
|
557
570
|
case 'SORT_WORDS_INTO_CATEGORIES':
|
|
558
571
|
return (_jsx(SortWordsIntoCategoriesViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
559
572
|
case 'CHOOSE_THEN_ANSWER_GROUP':
|
|
560
|
-
return (_jsx(ChooseThenAnswerGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
573
|
+
return (_jsx(ChooseThenAnswerGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, gradeDetails: gradeDetails, onSubmitAnswer: onSubmitAnswer }));
|
|
561
574
|
default:
|
|
562
575
|
return _jsxs("div", { children: ["Lo\u1EA1i c\u00E2u h\u1ECFi kh\u00F4ng \u0111\u01B0\u1EE3c h\u1ED7 tr\u1EE3: ", question.type] });
|
|
563
576
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { Question } from '../../../shared/types/entities/question.types';
|
|
2
|
-
|
|
2
|
+
import type { SpontaneousQaGroupGradeDetail } from '../_shared/types/spontaneous-qa-group.type';
|
|
3
|
+
export declare function SpontaneousQaGroupViewer({ question, isReviewMode, userAnswer, onItemRecorded, uploadingIndex, gradeDetails, disabled, }: {
|
|
3
4
|
question: Question;
|
|
4
5
|
isReviewMode?: boolean;
|
|
6
|
+
userAnswer?: unknown;
|
|
7
|
+
onItemRecorded?: (flattenIndex: number, blob: Blob) => void;
|
|
8
|
+
uploadingIndex?: number | null;
|
|
9
|
+
gradeDetails?: SpontaneousQaGroupGradeDetail[];
|
|
10
|
+
disabled?: boolean;
|
|
5
11
|
}): import("react").JSX.Element;
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { SpontaneousQaGroupClient } from '../types/spontaneous-qa-group/SpontaneousQaGroupClient';
|
|
4
4
|
import { mapQuestionToSpontaneousQaGroupData } from '../types/spontaneous-qa-group/map-spontaneous-qa-group-data';
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
function readStudentAnswer(value) {
|
|
6
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const keys = value.audioKeys;
|
|
10
|
+
if (!Array.isArray(keys)) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
audioKeys: keys.map((key) => (typeof key === 'string' && key.trim() !== '' ? key : null)),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function SpontaneousQaGroupViewer({ question, isReviewMode = false, userAnswer, onItemRecorded, uploadingIndex, gradeDetails, disabled, }) {
|
|
18
|
+
return (_jsx(SpontaneousQaGroupClient, { questionData: mapQuestionToSpontaneousQaGroupData(question), isReviewMode: isReviewMode, userAnswer: readStudentAnswer(userAnswer), onItemRecorded: isReviewMode ? undefined : onItemRecorded, uploadingIndex: uploadingIndex, gradeDetails: isReviewMode ? undefined : gradeDetails, disabled: disabled }));
|
|
7
19
|
}
|
|
@@ -3,7 +3,8 @@ import type { TrueFalseCorrectStudentItemAnswer } from '../_shared/types/true-fa
|
|
|
3
3
|
type TrueFalseCorrectGroupViewerProps = {
|
|
4
4
|
question: Question;
|
|
5
5
|
isReviewMode?: boolean;
|
|
6
|
-
userAnswer?:
|
|
6
|
+
userAnswer?: unknown;
|
|
7
|
+
onSubmitAnswer?: (answer: TrueFalseCorrectStudentItemAnswer[]) => void;
|
|
7
8
|
};
|
|
8
|
-
export declare function TrueFalseCorrectGroupViewer({ question, isReviewMode, userAnswer, }: TrueFalseCorrectGroupViewerProps): import("react").JSX.Element;
|
|
9
|
+
export declare function TrueFalseCorrectGroupViewer({ question, isReviewMode, userAnswer, onSubmitAnswer, }: TrueFalseCorrectGroupViewerProps): import("react").JSX.Element;
|
|
9
10
|
export {};
|
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { TrueFalseCorrectGroupClient } from '../types/true-false-correct-group/TrueFalseCorrectGroupClient';
|
|
4
4
|
import { mapQuestionToTrueFalseCorrectGroupData } from '../types/true-false-correct-group/map-true-false-correct-group-data';
|
|
5
|
-
|
|
5
|
+
function readStudentAnswers(value) {
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
if (value && typeof value === 'object' && Array.isArray(value.answer)) {
|
|
10
|
+
return value.answer;
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
export function TrueFalseCorrectGroupViewer({ question, isReviewMode = false, userAnswer, onSubmitAnswer, }) {
|
|
6
15
|
const questionData = mapQuestionToTrueFalseCorrectGroupData(question);
|
|
7
|
-
const
|
|
16
|
+
const storedAnswers = readStudentAnswers(userAnswer);
|
|
17
|
+
const reviewAnswers = isReviewMode && !storedAnswers
|
|
8
18
|
? questionData.items.map((item) => ({
|
|
9
19
|
isTrue: item.isTrue,
|
|
10
20
|
correction: item.correction,
|
|
11
21
|
}))
|
|
12
|
-
:
|
|
13
|
-
return (_jsx(TrueFalseCorrectGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: reviewAnswers }));
|
|
22
|
+
: storedAnswers;
|
|
23
|
+
return (_jsx(TrueFalseCorrectGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: reviewAnswers, onAnswerChange: isReviewMode ? undefined : onSubmitAnswer }));
|
|
14
24
|
}
|
|
@@ -2,7 +2,10 @@ import type { Question } from '../../../shared/types/entities/question.types';
|
|
|
2
2
|
type TrueFalseGroupViewerProps = {
|
|
3
3
|
question: Question;
|
|
4
4
|
isReviewMode?: boolean;
|
|
5
|
-
userAnswer?: boolean[]
|
|
5
|
+
userAnswer?: boolean[] | {
|
|
6
|
+
answer?: boolean[];
|
|
7
|
+
};
|
|
8
|
+
onSubmitAnswer?: (answer: boolean[]) => void;
|
|
6
9
|
};
|
|
7
|
-
export declare function TrueFalseGroupViewer({ question, isReviewMode, userAnswer, }: TrueFalseGroupViewerProps): import("react").JSX.Element;
|
|
10
|
+
export declare function TrueFalseGroupViewer({ question, isReviewMode, userAnswer, onSubmitAnswer, }: TrueFalseGroupViewerProps): import("react").JSX.Element;
|
|
8
11
|
export {};
|
|
@@ -2,10 +2,20 @@
|
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
3
|
import { TrueFalseGroupClient } from '../types/true-false-group/TrueFalseGroupClient';
|
|
4
4
|
import { mapQuestionToTrueFalseGroupData } from '../types/true-false-group/map-true-false-group-data';
|
|
5
|
-
|
|
5
|
+
function readBooleanAnswers(value) {
|
|
6
|
+
if (Array.isArray(value)) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
if (value && typeof value === 'object' && Array.isArray(value.answer)) {
|
|
10
|
+
return value.answer;
|
|
11
|
+
}
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
export function TrueFalseGroupViewer({ question, isReviewMode = false, userAnswer, onSubmitAnswer, }) {
|
|
6
15
|
const questionData = mapQuestionToTrueFalseGroupData(question);
|
|
7
|
-
const
|
|
16
|
+
const storedAnswers = readBooleanAnswers(userAnswer);
|
|
17
|
+
const reviewAnswers = isReviewMode && !storedAnswers
|
|
8
18
|
? questionData.items.map((item) => item.correctAnswer)
|
|
9
|
-
:
|
|
10
|
-
return (_jsx(TrueFalseGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: reviewAnswers }));
|
|
19
|
+
: storedAnswers;
|
|
20
|
+
return (_jsx(TrueFalseGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: reviewAnswers, onAnswerChange: isReviewMode ? undefined : onSubmitAnswer }));
|
|
11
21
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Question } from '../../../shared/types/entities/question.types';
|
|
2
|
-
export declare function WordOrderAndMatchGroupViewer({ question, isReviewMode, userAnswer, }: {
|
|
2
|
+
export declare function WordOrderAndMatchGroupViewer({ question, isReviewMode, userAnswer, onSubmitAnswer, }: {
|
|
3
3
|
question: Question;
|
|
4
4
|
isReviewMode?: boolean;
|
|
5
|
-
userAnswer?:
|
|
5
|
+
userAnswer?: unknown;
|
|
6
|
+
onSubmitAnswer?: (answer: Array<{
|
|
7
|
+
orderedPhrase: string;
|
|
8
|
+
matchLabel: string;
|
|
9
|
+
}>) => void;
|
|
6
10
|
}): import("react").JSX.Element;
|
|
@@ -76,20 +76,40 @@ function resolveGroup(question) {
|
|
|
76
76
|
items: itemsRaw.map((item, idx) => mapItem(item, idx, answersRaw[idx])),
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
|
-
|
|
79
|
+
function readMatchAnswers(value) {
|
|
80
|
+
if (Array.isArray(value)) {
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
if (value && typeof value === 'object' && Array.isArray(value.answer)) {
|
|
84
|
+
return value.answer;
|
|
85
|
+
}
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
export function WordOrderAndMatchGroupViewer({ question, isReviewMode = false, userAnswer, onSubmitAnswer, }) {
|
|
80
89
|
const { instruction, matchOptions, items } = resolveGroup(question);
|
|
81
90
|
const questionData = {
|
|
82
91
|
instruction,
|
|
83
92
|
matchOptions,
|
|
84
93
|
items,
|
|
85
94
|
};
|
|
86
|
-
const
|
|
95
|
+
const storedAnswers = readMatchAnswers(userAnswer);
|
|
96
|
+
const autoUserAnswers = isReviewMode && !storedAnswers
|
|
87
97
|
? items.map((item) => ({
|
|
88
98
|
orderedPhrase: item.orderedPhrase,
|
|
89
99
|
matchLabel: item.matchLabel,
|
|
90
100
|
}))
|
|
91
|
-
:
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
: storedAnswers;
|
|
102
|
+
return (_jsx(WordOrderAndMatchGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: autoUserAnswers, onAnswerChange: isReviewMode
|
|
103
|
+
? undefined
|
|
104
|
+
: (itemIndex, next) => {
|
|
105
|
+
const current = items.map((_, index) => {
|
|
106
|
+
const existing = storedAnswers?.[index];
|
|
107
|
+
return {
|
|
108
|
+
orderedPhrase: existing?.orderedPhrase || '',
|
|
109
|
+
matchLabel: existing?.matchLabel || '',
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
current[itemIndex] = next;
|
|
113
|
+
onSubmitAnswer?.(current);
|
|
114
|
+
} }));
|
|
95
115
|
}
|
|
@@ -31,6 +31,6 @@ export function ReviewAnswerTheQuestionGroupRenderer({ partNumber, partName, que
|
|
|
31
31
|
? 'border-red-200 bg-red-50 text-red-800'
|
|
32
32
|
: 'border-gray-200 bg-gray-50 text-gray-700'}`, children: question.isExample
|
|
33
33
|
? (question.exampleAnswer || '(Câu mẫu)')
|
|
34
|
-
: (studentAnswer || '(Chưa trả lời)') }), expectedAnswers.length > 0 && (_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-xs font-medium text-gray-500", children: "\u0110\u00E1p \u00E1n
|
|
34
|
+
: (studentAnswer || '(Chưa trả lời)') }), expectedAnswers.length > 0 && (_jsxs("div", { className: "space-y-1", children: [_jsx("p", { className: "text-xs font-medium text-gray-500", children: "\u0110\u00E1p \u00E1n" }), _jsx("ul", { className: "list-disc space-y-1 pl-5 text-sm text-gray-700", children: expectedAnswers.map((answer) => (_jsx("li", { children: answer }, answer))) })] })), feedback && (_jsx("p", { className: "text-xs text-violet-700", children: feedback }))] })] }, question.id));
|
|
35
35
|
})] }));
|
|
36
36
|
}
|
|
@@ -218,7 +218,7 @@ export function renderMoversReviewBody(ctx) {
|
|
|
218
218
|
case 'CROSSWORD_PUZZLE': {
|
|
219
219
|
const data = transformCrosswordPuzzle(apiQuestions);
|
|
220
220
|
const firstQuestion = apiQuestions[0];
|
|
221
|
-
return (_jsx(MoversCrosswordPuzzleRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, title: data.title, gridSize: data.gridSize, clues: data.clues, answers: answers, correctAnswers: data.correctAnswers, onAnswerChange: handleAnswerChange, isReviewMode: true, caseSensitive: firstQuestion?.correct_answer?.caseSensitive || false }));
|
|
221
|
+
return (_jsx(MoversCrosswordPuzzleRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, title: data.title, gridSize: data.gridSize, markedColumn: data.markedColumn, hiddenWord: data.hiddenWord, clues: data.clues, answers: answers, correctAnswers: data.correctAnswers, onAnswerChange: handleAnswerChange, isReviewMode: true, caseSensitive: data.caseSensitive || firstQuestion?.correct_answer?.caseSensitive || false }));
|
|
222
222
|
}
|
|
223
223
|
default:
|
|
224
224
|
return null;
|
|
@@ -140,13 +140,20 @@ function addCorrectAnswerMaps(result, answer) {
|
|
|
140
140
|
texts.forEach((text, index) => { result.correctAnswerTextMap[`${answer.questionId}-blank-${index}`] = text; });
|
|
141
141
|
if (answer.questionType === 'LABEL_THE_PICTURE' && isRecord(correct.labels))
|
|
142
142
|
Object.entries(correct.labels).forEach(([id, value]) => { result.correctAnswerTextMap[id] = String(value); });
|
|
143
|
-
if (
|
|
143
|
+
if (answer.questionType === 'FILL_MISSING_WORDS_IN_GRID' && isRecord(correct.cells || correct.answers)) {
|
|
144
144
|
const rawCells = (correct.cells || correct.answers);
|
|
145
145
|
result.cellAnswersMap[answer.questionId] = {
|
|
146
146
|
cells: Object.fromEntries(Object.entries(rawCells).map(([k, v]) => [k, { correctAnswer: String(v) }])),
|
|
147
147
|
caseSensitive: correct.caseSensitive === true,
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
|
+
if (answer.questionType === 'CROSSWORD_PUZZLE' && isRecord(correct.cells)) {
|
|
151
|
+
const rawCells = correct.cells;
|
|
152
|
+
result.cellAnswersMap[answer.questionId] = {
|
|
153
|
+
cells: Object.fromEntries(Object.entries(rawCells).map(([k, v]) => [k, { correctAnswer: String(v) }])),
|
|
154
|
+
caseSensitive: correct.caseSensitive === true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
150
157
|
}
|
|
151
158
|
function transformStudentAnswer(questionId, questionType, value) {
|
|
152
159
|
if (value == null)
|
|
@@ -315,6 +315,7 @@ const reverseAnswerTheQuestionGroup = (apiQuestion) => {
|
|
|
315
315
|
items,
|
|
316
316
|
explanation: asString(apiQuestion.explanation),
|
|
317
317
|
points: items.reduce((total, item) => (item.isExample ? total : total + item.points), 0),
|
|
318
|
+
...(meta.gradingType === 'MAPPING' ? { gradingType: 'MAPPING' } : {}),
|
|
318
319
|
},
|
|
319
320
|
};
|
|
320
321
|
};
|
|
@@ -404,6 +405,13 @@ const reverseChooseThenAnswerGroup = (apiQuestion) => {
|
|
|
404
405
|
question: asString(itemContent.question),
|
|
405
406
|
options,
|
|
406
407
|
optionId: asString(rawAnswer.optionId) || options[0]?.id || '',
|
|
408
|
+
expectedAnswers: (() => {
|
|
409
|
+
const raw = asArray(rawAnswer.expectedAnswers)
|
|
410
|
+
.filter((value) => typeof value === 'string')
|
|
411
|
+
.map((value) => value.trim())
|
|
412
|
+
.filter((value) => value !== '');
|
|
413
|
+
return raw.length > 0 ? raw : [''];
|
|
414
|
+
})(),
|
|
407
415
|
isExample,
|
|
408
416
|
points: isExample ? 0 : asNumber(item.points, 1),
|
|
409
417
|
questionNumber: asNumber(item.questionNumber, index + 1),
|
|
@@ -529,18 +537,27 @@ const reverseCrossOutWordGroup = (apiQuestion) => {
|
|
|
529
537
|
const fallback = asRecord(fallbackAnswers[index]);
|
|
530
538
|
const answerRaw = Object.keys(itemAnswer).length > 0 ? itemAnswer : fallback;
|
|
531
539
|
const isExample = item.isExample === true;
|
|
532
|
-
const type = itemContent.type === 'CROSS_OUT_AND_REPLACE'
|
|
533
|
-
answerRaw.type === 'CROSS_OUT_AND_REPLACE'
|
|
540
|
+
const type = itemContent.type === 'CROSS_OUT_AND_REPLACE'
|
|
534
541
|
? 'CROSS_OUT_AND_REPLACE'
|
|
535
|
-
: 'CROSS_OUT'
|
|
542
|
+
: itemContent.type === 'CROSS_OUT'
|
|
543
|
+
? 'CROSS_OUT'
|
|
544
|
+
: answerRaw.type === 'CROSS_OUT_AND_REPLACE'
|
|
545
|
+
? 'CROSS_OUT_AND_REPLACE'
|
|
546
|
+
: 'CROSS_OUT';
|
|
547
|
+
const rawIndex = answerRaw.wordIndex;
|
|
548
|
+
const wordIndex = typeof rawIndex === 'number' && Number.isInteger(rawIndex) && rawIndex >= 0
|
|
549
|
+
? rawIndex
|
|
550
|
+
: null;
|
|
536
551
|
const correctAnswer = type === 'CROSS_OUT_AND_REPLACE'
|
|
537
552
|
? {
|
|
538
553
|
type: 'CROSS_OUT_AND_REPLACE',
|
|
554
|
+
wordIndex,
|
|
539
555
|
crossOut: asString(answerRaw.crossOut),
|
|
540
556
|
replaceWith: asString(answerRaw.replaceWith),
|
|
541
557
|
}
|
|
542
558
|
: {
|
|
543
559
|
type: 'CROSS_OUT',
|
|
560
|
+
wordIndex,
|
|
544
561
|
crossOut: asString(answerRaw.crossOut),
|
|
545
562
|
};
|
|
546
563
|
return {
|
|
@@ -630,12 +647,14 @@ const reverseSpontaneousQaGroup = (apiQuestion) => {
|
|
|
630
647
|
const fallback = asRecord(flattenedAnswers[questionIndex]);
|
|
631
648
|
const expected = asArray(childAnswer.expectedAnswers ?? fallback.expectedAnswers)
|
|
632
649
|
.filter((value) => typeof value === 'string');
|
|
650
|
+
const isExample = child.isExample === true;
|
|
633
651
|
return {
|
|
634
652
|
questionText: asString(childContent.questionText),
|
|
635
653
|
inputType: asString(childContent.inputType, 'TEXT') === 'AUDIO' ? 'AUDIO' : 'TEXT',
|
|
636
654
|
audioUrl: asString(childContent.audioUrl),
|
|
637
655
|
expectedAnswers: expected.length > 0 ? expected : [''],
|
|
638
|
-
|
|
656
|
+
isExample,
|
|
657
|
+
points: isExample ? 0 : asNumber(child.points, 1),
|
|
639
658
|
questionNumber: asNumber(child.questionNumber, questionIndex + 1),
|
|
640
659
|
};
|
|
641
660
|
}),
|
|
@@ -882,6 +901,9 @@ function reverseCrosswordPuzzle(apiQuestion) {
|
|
|
882
901
|
const rows = apiContent.gridSize?.rows || apiContent.rows || 12;
|
|
883
902
|
const cols = apiContent.gridSize?.cols || apiContent.cols || 12;
|
|
884
903
|
const title = apiContent.title || '';
|
|
904
|
+
const type = apiContent.type === 'HIDDEN_WORD' ? 'HIDDEN_WORD' : 'STANDARD';
|
|
905
|
+
const instruction = asString(apiQuestion.instruction, asString(apiContent.instruction));
|
|
906
|
+
const markedColumn = typeof apiContent.markedColumn === 'number' ? apiContent.markedColumn : undefined;
|
|
885
907
|
const across = Array.isArray(apiContent.clues?.across) ? apiContent.clues.across : [];
|
|
886
908
|
const down = Array.isArray(apiContent.clues?.down) ? apiContent.clues.down : [];
|
|
887
909
|
const answers = apiAnswer.answers || {};
|
|
@@ -896,6 +918,7 @@ function reverseCrosswordPuzzle(apiQuestion) {
|
|
|
896
918
|
length: a.length || 1,
|
|
897
919
|
direction: 'across',
|
|
898
920
|
answer: answers[`across-${a.number}`] || '',
|
|
921
|
+
...(a.isExample === true ? { isExample: true } : {}),
|
|
899
922
|
});
|
|
900
923
|
}
|
|
901
924
|
for (const d of down) {
|
|
@@ -908,24 +931,32 @@ function reverseCrosswordPuzzle(apiQuestion) {
|
|
|
908
931
|
length: d.length || 1,
|
|
909
932
|
direction: 'down',
|
|
910
933
|
answer: answers[`down-${d.number}`] || '',
|
|
934
|
+
...(d.isExample === true ? { isExample: true } : {}),
|
|
911
935
|
});
|
|
912
936
|
}
|
|
913
937
|
return {
|
|
914
938
|
content: {
|
|
939
|
+
type,
|
|
915
940
|
title,
|
|
941
|
+
instruction,
|
|
916
942
|
rows,
|
|
917
943
|
cols,
|
|
918
944
|
gridSize: { rows, cols },
|
|
945
|
+
...(type === 'HIDDEN_WORD' && markedColumn ? { markedColumn } : {}),
|
|
919
946
|
clues: { across, down },
|
|
920
947
|
},
|
|
921
948
|
answer: {
|
|
949
|
+
type,
|
|
922
950
|
title,
|
|
951
|
+
instruction,
|
|
923
952
|
rows,
|
|
924
953
|
cols,
|
|
954
|
+
...(type === 'HIDDEN_WORD' && markedColumn ? { markedColumn } : {}),
|
|
955
|
+
hiddenWord: answers['hidden-word'] || '',
|
|
925
956
|
clues,
|
|
926
957
|
answers,
|
|
927
958
|
caseSensitive: apiAnswer.caseSensitive || false,
|
|
928
|
-
explanation: apiQuestion.explanation
|
|
959
|
+
explanation: asString(apiQuestion.explanation),
|
|
929
960
|
},
|
|
930
961
|
};
|
|
931
962
|
}
|
|
@@ -936,6 +967,7 @@ function reverseFindWordsInMatrix(apiQuestion) {
|
|
|
936
967
|
const rows = apiContent.gridSize?.rows || (Array.isArray(apiContent.grid) ? apiContent.grid.length : 14);
|
|
937
968
|
const cols = apiContent.gridSize?.cols || (Array.isArray(apiContent.grid?.[0]) ? apiContent.grid[0].length : 14);
|
|
938
969
|
const title = apiContent.title || '';
|
|
970
|
+
const instruction = typeof apiContent.instruction === 'string' ? apiContent.instruction : '';
|
|
939
971
|
const grid = Array.isArray(apiContent.grid) ? apiContent.grid : [];
|
|
940
972
|
const categories = Array.isArray(apiContent.categories) ? apiContent.categories : [];
|
|
941
973
|
const wordBank = Array.isArray(apiContent.wordBank) ? apiContent.wordBank : [];
|
|
@@ -969,6 +1001,7 @@ function reverseFindWordsInMatrix(apiQuestion) {
|
|
|
969
1001
|
content: {
|
|
970
1002
|
type,
|
|
971
1003
|
title,
|
|
1004
|
+
instruction,
|
|
972
1005
|
rows,
|
|
973
1006
|
cols,
|
|
974
1007
|
gridSize: { rows, cols },
|
|
@@ -981,6 +1014,7 @@ function reverseFindWordsInMatrix(apiQuestion) {
|
|
|
981
1014
|
answer: {
|
|
982
1015
|
type,
|
|
983
1016
|
title,
|
|
1017
|
+
instruction,
|
|
984
1018
|
rows,
|
|
985
1019
|
cols,
|
|
986
1020
|
grid,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export declare const
|
|
1
|
+
export declare const ANSWER_THE_QUESTION_GROUP_GRADING_TYPES: readonly ["AI", "MAPPING"];
|
|
2
|
+
export type AnswerTheQuestionGroupGradingType = (typeof ANSWER_THE_QUESTION_GROUP_GRADING_TYPES)[number];
|
|
3
|
+
/** Default for newly created groups. */
|
|
4
|
+
export declare const ANSWER_THE_QUESTION_GROUP_GRADING_TYPE: AnswerTheQuestionGroupGradingType;
|
|
5
|
+
export declare function resolveAnswerTheQuestionGroupGradingType(value: unknown): AnswerTheQuestionGroupGradingType;
|
|
2
6
|
export interface AnswerTheQuestionGroupItemContent {
|
|
3
7
|
question: string;
|
|
4
8
|
imageUrl?: string | string[];
|
|
@@ -20,8 +24,9 @@ export interface AnswerTheQuestionGroupContent {
|
|
|
20
24
|
passage?: string;
|
|
21
25
|
audioUrl?: string;
|
|
22
26
|
imageUrl?: string | string[];
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
/** AI = LLM short-answer; MAPPING = exact-match expectedAnswers. */
|
|
28
|
+
gradingType: AnswerTheQuestionGroupGradingType;
|
|
29
|
+
isAiGraded: boolean;
|
|
25
30
|
};
|
|
26
31
|
items: AnswerTheQuestionGroupItem[];
|
|
27
32
|
}
|
|
@@ -1 +1,6 @@
|
|
|
1
|
+
export const ANSWER_THE_QUESTION_GROUP_GRADING_TYPES = ['AI', 'MAPPING'];
|
|
2
|
+
/** Default for newly created groups. */
|
|
1
3
|
export const ANSWER_THE_QUESTION_GROUP_GRADING_TYPE = 'AI';
|
|
4
|
+
export function resolveAnswerTheQuestionGroupGradingType(value) {
|
|
5
|
+
return value === 'MAPPING' ? 'MAPPING' : 'AI';
|
|
6
|
+
}
|
|
@@ -4,6 +4,7 @@ export interface ChooseThenAnswerOption {
|
|
|
4
4
|
}
|
|
5
5
|
export interface ChooseThenAnswerItemAnswer {
|
|
6
6
|
optionId: string;
|
|
7
|
+
expectedAnswers?: string[];
|
|
7
8
|
}
|
|
8
9
|
export interface ChooseThenAnswerStudentItemAnswer {
|
|
9
10
|
optionId: string;
|
|
@@ -27,6 +28,8 @@ export interface ChooseThenAnswerGroupContent {
|
|
|
27
28
|
meta?: {
|
|
28
29
|
instruction?: string;
|
|
29
30
|
title?: string;
|
|
31
|
+
gradingType?: 'AI';
|
|
32
|
+
isAiGraded?: boolean;
|
|
30
33
|
};
|
|
31
34
|
items: ChooseThenAnswerGroupItem[];
|
|
32
35
|
}
|