@tinyweb_dev/oe-exam-sdk 0.2.5 → 0.2.6
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/ExamTakingPageContainer.js +6 -0
- package/dist/components/exams/take/components/QuestionRenderer.js +10 -2
- package/dist/components/exams/take/components/question-renderers/MoversFillInBlankGroupRenderer.d.ts +22 -0
- package/dist/components/exams/take/components/question-renderers/MoversFillInBlankGroupRenderer.js +60 -0
- package/dist/components/exams/take/components/question-renderers/MoversMatchingWithLinesGroupRenderer.d.ts +13 -0
- package/dist/components/exams/take/components/question-renderers/MoversMatchingWithLinesGroupRenderer.js +31 -0
- package/dist/components/exams/take/components/question-renderers/index.d.ts +2 -0
- package/dist/components/exams/take/components/question-renderers/index.js +2 -0
- package/dist/components/exams/take/utils/answer-transformers.js +16 -0
- package/dist/components/exams/take/utils/question-transformers.d.ts +45 -1
- package/dist/components/exams/take/utils/question-transformers.js +90 -0
- package/dist/components/questions/_shared/config/question-types.config.js +12 -0
- package/dist/components/questions/_shared/types/fill-in-blank-group.type.d.ts +50 -0
- package/dist/components/questions/_shared/types/fill-in-blank-group.type.js +2 -0
- package/dist/components/questions/_shared/types/index.d.ts +2 -0
- package/dist/components/questions/_shared/types/index.js +2 -0
- package/dist/components/questions/_shared/types/matching-with-lines-group.type.d.ts +40 -0
- package/dist/components/questions/_shared/types/matching-with-lines-group.type.js +1 -0
- package/dist/components/questions/components/QuestionSearchDropdown.js +4 -0
- package/dist/components/questions/components/QuestionTypeSelector.js +2 -0
- package/dist/components/questions/creator/question-type-registry.js +4 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupClient.d.ts +2 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupClient.js +64 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupCreator.js +158 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupMediaField.d.ts +7 -0
- package/dist/components/questions/types/fill-in-blank-group/FillInBlankGroupMediaField.js +30 -0
- package/dist/components/questions/types/fill-in-blank-group/blank-utils.d.ts +20 -0
- package/dist/components/questions/types/fill-in-blank-group/blank-utils.js +99 -0
- package/dist/components/questions/types/fill-in-blank-group/index.d.ts +5 -0
- package/dist/components/questions/types/fill-in-blank-group/index.js +5 -0
- package/dist/components/questions/types/fill-in-blank-group/map-fill-in-blank-group-data.d.ts +4 -0
- package/dist/components/questions/types/fill-in-blank-group/map-fill-in-blank-group-data.js +102 -0
- package/dist/components/questions/types/fill-in-blank-group/register.d.ts +3 -0
- package/dist/components/questions/types/fill-in-blank-group/register.js +37 -0
- package/dist/components/questions/types/fill-in-blank-group/transform.d.ts +2 -0
- package/dist/components/questions/types/fill-in-blank-group/transform.js +68 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesBoard.d.ts +20 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesBoard.js +109 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupClient.d.ts +2 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupClient.js +30 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupCreator.d.ts +2 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesGroupCreator.js +180 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesImageField.d.ts +6 -0
- package/dist/components/questions/types/matching-with-lines-group/MatchingWithLinesImageField.js +26 -0
- package/dist/components/questions/types/matching-with-lines-group/index.d.ts +4 -0
- package/dist/components/questions/types/matching-with-lines-group/index.js +4 -0
- package/dist/components/questions/types/matching-with-lines-group/map-matching-with-lines-group-data.d.ts +8 -0
- package/dist/components/questions/types/matching-with-lines-group/map-matching-with-lines-group-data.js +104 -0
- package/dist/components/questions/types/matching-with-lines-group/register.d.ts +3 -0
- package/dist/components/questions/types/matching-with-lines-group/register.js +37 -0
- package/dist/components/questions/types/matching-with-lines-group/transform.d.ts +2 -0
- package/dist/components/questions/types/matching-with-lines-group/transform.js +44 -0
- package/dist/components/questions/viewer/FillInBlankGroupViewer.d.ts +10 -0
- package/dist/components/questions/viewer/FillInBlankGroupViewer.js +14 -0
- package/dist/components/questions/viewer/MatchingWithLinesGroupViewer.d.ts +7 -0
- package/dist/components/questions/viewer/MatchingWithLinesGroupViewer.js +48 -0
- package/dist/components/questions/viewer/QuestionViewer.js +6 -0
- package/dist/components/questions/viewer/index.d.ts +2 -0
- package/dist/components/questions/viewer/index.js +2 -0
- package/dist/components/results/renderers/review-question-body-movers.js +37 -2
- package/dist/components/results/review-data.js +37 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/shared/constants/question-skills.js +4 -0
- package/dist/shared/lib/utils/question-reverse-transform.js +86 -0
- package/dist/shared/lib/utils/question-transform.js +4 -0
- package/dist/shared/types/common.types.d.ts +1 -1
- package/dist/shared/types/questions/fill-in-blank-group.d.ts +45 -0
- package/dist/shared/types/questions/fill-in-blank-group.js +1 -0
- package/dist/shared/types/questions/index.d.ts +2 -0
- package/dist/shared/types/questions/index.js +4 -0
- package/dist/shared/types/questions/matching-with-lines-group.d.ts +39 -0
- package/dist/shared/types/questions/matching-with-lines-group.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { MATCHING_WITH_LINES_GROUP_DEFAULT_INSTRUCTION } from '../../_shared/types/matching-with-lines-group.type';
|
|
2
|
+
function sumGradablePoints(items) {
|
|
3
|
+
return items.reduce((total, item) => {
|
|
4
|
+
if (item.isExample)
|
|
5
|
+
return total;
|
|
6
|
+
const points = typeof item.points === 'number' ? item.points : 1;
|
|
7
|
+
return total + points;
|
|
8
|
+
}, 0);
|
|
9
|
+
}
|
|
10
|
+
export const transformMatchingWithLinesGroup = (question) => {
|
|
11
|
+
const answerData = question.answer;
|
|
12
|
+
const items = Array.isArray(answerData?.items) ? answerData.items : [];
|
|
13
|
+
const rightItems = Array.isArray(answerData?.rightItems) ? answerData.rightItems : [];
|
|
14
|
+
if (items.length === 0) {
|
|
15
|
+
return { apiContent: { rightItems: [], items: [] }, apiCorrectAnswer: { answer: [] } };
|
|
16
|
+
}
|
|
17
|
+
const apiItems = items.map((item, index) => ({
|
|
18
|
+
...(item.isExample ? { isExample: true } : {}),
|
|
19
|
+
content: {
|
|
20
|
+
imageUrl: item.imageUrl || '',
|
|
21
|
+
},
|
|
22
|
+
correctAnswer: { answer: item.correctAnswer || '' },
|
|
23
|
+
points: item.isExample ? 0 : (typeof item.points === 'number' ? item.points : 1),
|
|
24
|
+
questionNumber: item.questionNumber || index + 1,
|
|
25
|
+
}));
|
|
26
|
+
const title = typeof answerData?.title === 'string' ? answerData.title.trim() : '';
|
|
27
|
+
return {
|
|
28
|
+
apiContent: {
|
|
29
|
+
meta: {
|
|
30
|
+
instruction: answerData?.instruction || MATCHING_WITH_LINES_GROUP_DEFAULT_INSTRUCTION,
|
|
31
|
+
...(title ? { title } : {}),
|
|
32
|
+
},
|
|
33
|
+
rightItems: rightItems.map((item) => ({
|
|
34
|
+
id: item.id || '',
|
|
35
|
+
text: item.text || '',
|
|
36
|
+
})),
|
|
37
|
+
items: apiItems,
|
|
38
|
+
},
|
|
39
|
+
apiCorrectAnswer: {
|
|
40
|
+
answer: apiItems.map((item) => item.correctAnswer.answer),
|
|
41
|
+
},
|
|
42
|
+
totalPoints: sumGradablePoints(items),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Question } from '../../../shared/types/entities/question.types';
|
|
2
|
+
import type { FillInBlankGroupStudentItemAnswer } from '../_shared/types/fill-in-blank-group.type';
|
|
3
|
+
type FillInBlankGroupViewerProps = {
|
|
4
|
+
question: Question;
|
|
5
|
+
isReviewMode?: boolean;
|
|
6
|
+
userAnswer?: FillInBlankGroupStudentItemAnswer[];
|
|
7
|
+
onSubmitAnswer?: (answer: FillInBlankGroupStudentItemAnswer[]) => void;
|
|
8
|
+
};
|
|
9
|
+
export declare function FillInBlankGroupViewer({ question, isReviewMode, userAnswer, onSubmitAnswer, }: FillInBlankGroupViewerProps): import("react").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { FillInBlankGroupClient } from '../types/fill-in-blank-group/FillInBlankGroupClient';
|
|
4
|
+
import { mapQuestionToFillInBlankGroupData } from '../types/fill-in-blank-group/map-fill-in-blank-group-data';
|
|
5
|
+
export function FillInBlankGroupViewer({ question, isReviewMode = false, userAnswer, onSubmitAnswer, }) {
|
|
6
|
+
const questionData = mapQuestionToFillInBlankGroupData(question);
|
|
7
|
+
const studentAnswers = Array.isArray(userAnswer) ? userAnswer : undefined;
|
|
8
|
+
const reviewAnswers = isReviewMode && !studentAnswers
|
|
9
|
+
? questionData.items.map((item) => ({
|
|
10
|
+
answers: item.answers.map((alts) => alts[0] || ''),
|
|
11
|
+
}))
|
|
12
|
+
: studentAnswers;
|
|
13
|
+
return (_jsx(FillInBlankGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: reviewAnswers, onAnswerChange: isReviewMode ? undefined : onSubmitAnswer }));
|
|
14
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Question } from '../../../shared/types/entities/question.types';
|
|
2
|
+
export declare function MatchingWithLinesGroupViewer({ question, isReviewMode, userAnswer, onSubmitAnswer, }: {
|
|
3
|
+
question: Question;
|
|
4
|
+
isReviewMode?: boolean;
|
|
5
|
+
userAnswer?: unknown;
|
|
6
|
+
onSubmitAnswer?: (answer: string[]) => void;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from 'react';
|
|
4
|
+
import { MatchingWithLinesGroupClient } from '../types/matching-with-lines-group/MatchingWithLinesGroupClient';
|
|
5
|
+
import { mapQuestionToMatchingWithLinesGroupData } from '../types/matching-with-lines-group/map-matching-with-lines-group-data';
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
8
|
+
}
|
|
9
|
+
function emptyAnswers(length) {
|
|
10
|
+
return Array.from({ length }, () => '');
|
|
11
|
+
}
|
|
12
|
+
function parseMatchingAnswers(value, length) {
|
|
13
|
+
const source = Array.isArray(value)
|
|
14
|
+
? value
|
|
15
|
+
: isRecord(value) && Array.isArray(value.answer)
|
|
16
|
+
? value.answer
|
|
17
|
+
: null;
|
|
18
|
+
if (!source)
|
|
19
|
+
return undefined;
|
|
20
|
+
return Array.from({ length }, (_, index) => typeof source[index] === 'string' ? source[index] : '');
|
|
21
|
+
}
|
|
22
|
+
export function MatchingWithLinesGroupViewer({ question, isReviewMode = false, userAnswer, onSubmitAnswer, }) {
|
|
23
|
+
const questionData = mapQuestionToMatchingWithLinesGroupData(question);
|
|
24
|
+
const itemCount = questionData.items.length;
|
|
25
|
+
const parsedUser = parseMatchingAnswers(userAnswer, itemCount);
|
|
26
|
+
const questionKey = `${question.id}:${question.type}:${itemCount}:${questionData.rightItems
|
|
27
|
+
.map((item) => `${item.id}:${item.text}`)
|
|
28
|
+
.join(',')}`;
|
|
29
|
+
const [cachedKey, setCachedKey] = useState(questionKey);
|
|
30
|
+
const [localAnswers, setLocalAnswers] = useState(() => parsedUser ?? emptyAnswers(itemCount));
|
|
31
|
+
if (cachedKey !== questionKey) {
|
|
32
|
+
setCachedKey(questionKey);
|
|
33
|
+
setLocalAnswers(parsedUser ?? emptyAnswers(itemCount));
|
|
34
|
+
}
|
|
35
|
+
const userAnswers = isReviewMode && !parsedUser
|
|
36
|
+
? questionData.items.map((item) => item.correctAnswer)
|
|
37
|
+
: parsedUser ?? localAnswers;
|
|
38
|
+
const handleAnswersChange = (next) => {
|
|
39
|
+
const padded = questionData.items.map((item, index) => {
|
|
40
|
+
if (item.isExample)
|
|
41
|
+
return item.correctAnswer || '';
|
|
42
|
+
return typeof next[index] === 'string' ? next[index] : '';
|
|
43
|
+
});
|
|
44
|
+
setLocalAnswers(padded);
|
|
45
|
+
onSubmitAnswer?.(padded);
|
|
46
|
+
};
|
|
47
|
+
return (_jsx(MatchingWithLinesGroupClient, { questionData: questionData, isReviewMode: isReviewMode, userAnswers: userAnswers, onAnswersChange: isReviewMode ? undefined : handleAnswersChange }));
|
|
48
|
+
}
|
|
@@ -26,6 +26,8 @@ import { WordFillStructuredFormViewer } from './WordFillStructuredFormViewer';
|
|
|
26
26
|
import { ChooseTheCorrectAnswerGroupViewer } from './ChooseTheCorrectAnswerGroupViewer';
|
|
27
27
|
import { TrueFalseGroupViewer } from './TrueFalseGroupViewer';
|
|
28
28
|
import { TrueFalseCorrectGroupViewer } from './TrueFalseCorrectGroupViewer';
|
|
29
|
+
import { FillInBlankGroupViewer } from './FillInBlankGroupViewer';
|
|
30
|
+
import { MatchingWithLinesGroupViewer } from './MatchingWithLinesGroupViewer';
|
|
29
31
|
import { CrossOutWordGroupViewer } from './CrossOutWordGroupViewer';
|
|
30
32
|
import { SpontaneousQaGroupViewer } from './SpontaneousQaGroupViewer';
|
|
31
33
|
import { WordOrderAndMatchGroupViewer } from './WordOrderAndMatchGroupViewer';
|
|
@@ -635,6 +637,10 @@ export function QuestionViewer({ question, onSubmitAnswer, isReviewMode = false,
|
|
|
635
637
|
return (_jsx(TrueFalseGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
636
638
|
case 'TRUE_FALSE_CORRECT_GROUP':
|
|
637
639
|
return (_jsx(TrueFalseCorrectGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer }));
|
|
640
|
+
case 'FILL_IN_BLANK_GROUP':
|
|
641
|
+
return (_jsx(FillInBlankGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
642
|
+
case 'MATCHING_WITH_LINES_GROUP':
|
|
643
|
+
return (_jsx(MatchingWithLinesGroupViewer, { question: question, isReviewMode: isReviewMode, userAnswer: userAnswer, onSubmitAnswer: onSubmitAnswer }));
|
|
638
644
|
case 'CROSS_OUT_WORD_GROUP':
|
|
639
645
|
return (_jsx(CrossOutWordGroupViewer, { question: question, isReviewMode: isReviewMode }));
|
|
640
646
|
case 'ANSWER_THE_QUESTION_GROUP':
|
|
@@ -4,6 +4,8 @@ export { WordFillStructuredFormViewer } from './WordFillStructuredFormViewer';
|
|
|
4
4
|
export { ChooseTheCorrectAnswerGroupViewer } from './ChooseTheCorrectAnswerGroupViewer';
|
|
5
5
|
export { TrueFalseGroupViewer } from './TrueFalseGroupViewer';
|
|
6
6
|
export { TrueFalseCorrectGroupViewer } from './TrueFalseCorrectGroupViewer';
|
|
7
|
+
export { FillInBlankGroupViewer } from './FillInBlankGroupViewer';
|
|
8
|
+
export { MatchingWithLinesGroupViewer } from './MatchingWithLinesGroupViewer';
|
|
7
9
|
export { CrossOutWordGroupViewer } from './CrossOutWordGroupViewer';
|
|
8
10
|
export { SpontaneousQaGroupViewer } from './SpontaneousQaGroupViewer';
|
|
9
11
|
export { WordOrderAndMatchGroupViewer } from './WordOrderAndMatchGroupViewer';
|
|
@@ -4,6 +4,8 @@ export { WordFillStructuredFormViewer } from './WordFillStructuredFormViewer';
|
|
|
4
4
|
export { ChooseTheCorrectAnswerGroupViewer } from './ChooseTheCorrectAnswerGroupViewer';
|
|
5
5
|
export { TrueFalseGroupViewer } from './TrueFalseGroupViewer';
|
|
6
6
|
export { TrueFalseCorrectGroupViewer } from './TrueFalseCorrectGroupViewer';
|
|
7
|
+
export { FillInBlankGroupViewer } from './FillInBlankGroupViewer';
|
|
8
|
+
export { MatchingWithLinesGroupViewer } from './MatchingWithLinesGroupViewer';
|
|
7
9
|
export { CrossOutWordGroupViewer } from './CrossOutWordGroupViewer';
|
|
8
10
|
export { SpontaneousQaGroupViewer } from './SpontaneousQaGroupViewer';
|
|
9
11
|
export { WordOrderAndMatchGroupViewer } from './WordOrderAndMatchGroupViewer';
|
|
@@ -4,8 +4,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
4
4
|
* Movers fallback review cases (isReviewMode=true).
|
|
5
5
|
* Source: oe-exam-fe ReviewQuestionRenderer.tsx
|
|
6
6
|
*/
|
|
7
|
-
import { MoversAnswerTheQuestionRenderer, MoversFillWordHintRenderer, MoversGridFillRenderer, MoversLabelThePictureRenderer, MoversMatchByWritingAnswerRenderer, MoversMatchWordToPictureRenderer, MoversPictureChooseRenderer, MoversPictureFillBlankChooseRenderer, MoversReadingPassageRenderer, MoversTrueFalseRenderer, MoversTrueFalseCorrectGroupRenderer, MoversCrossOutWordGroupRenderer, MoversWordFillParagraphRenderer, MoversWordFillStructuredFormRenderer, MoversWordOrderingRenderer, MoversWriteSentencesRenderer, MoversWritingRenderer, MoversCrosswordPuzzleRenderer, } from '../../../components/exams/take/components/question-renderers';
|
|
8
|
-
import { transformAnswerTheQuestion, transformFillWordHint, transformGridFill, transformLabelPicture, transformMatchByWritingAnswer, transformMatchWordToPicture, transformPictureChoose, transformPictureFillBlankChoose, transformReadingPassage, transformTrueFalse, transformTrueFalseCorrectGroup, transformWordFillParagraph, transformWordFillStructuredForm, transformWordOrdering, transformWriteSentences, transformWriteShortLetter, transformCrosswordPuzzle, } from '../../../components/exams/take/utils/question-transformers';
|
|
7
|
+
import { MoversAnswerTheQuestionRenderer, MoversFillWordHintRenderer, MoversGridFillRenderer, MoversLabelThePictureRenderer, MoversMatchByWritingAnswerRenderer, MoversMatchWordToPictureRenderer, MoversPictureChooseRenderer, MoversPictureFillBlankChooseRenderer, MoversReadingPassageRenderer, MoversTrueFalseRenderer, MoversTrueFalseCorrectGroupRenderer, MoversFillInBlankGroupRenderer, MoversMatchingWithLinesGroupRenderer, MoversCrossOutWordGroupRenderer, MoversWordFillParagraphRenderer, MoversWordFillStructuredFormRenderer, MoversWordOrderingRenderer, MoversWriteSentencesRenderer, MoversWritingRenderer, MoversCrosswordPuzzleRenderer, } from '../../../components/exams/take/components/question-renderers';
|
|
8
|
+
import { transformAnswerTheQuestion, transformFillWordHint, transformGridFill, transformLabelPicture, transformMatchByWritingAnswer, transformMatchWordToPicture, transformPictureChoose, transformPictureFillBlankChoose, transformReadingPassage, transformTrueFalse, transformTrueFalseCorrectGroup, transformFillInBlankGroup, transformMatchingWithLinesGroup, transformWordFillParagraph, transformWordFillStructuredForm, transformWordOrdering, transformWriteSentences, transformWriteShortLetter, transformCrosswordPuzzle, } from '../../../components/exams/take/utils/question-transformers';
|
|
9
9
|
import { normalizeCrossOutWordGroupAnswer, transformCrossOutWordGroup, } from '../../../components/exams/take/utils/cross-out-word-group.transformer';
|
|
10
10
|
function asApiQuestions(questions) {
|
|
11
11
|
return questions;
|
|
@@ -142,6 +142,41 @@ export function renderMoversReviewBody(ctx) {
|
|
|
142
142
|
});
|
|
143
143
|
return (_jsx(MoversTrueFalseCorrectGroupRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, questions: data.questions, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true, correctAnswerMap: correctAnswerMap }));
|
|
144
144
|
}
|
|
145
|
+
case 'FILL_IN_BLANK_GROUP': {
|
|
146
|
+
const data = transformFillInBlankGroup(apiQuestions);
|
|
147
|
+
const correctAnswerMap = {};
|
|
148
|
+
const parent = apiQuestions[0];
|
|
149
|
+
const rawCorrect = parent?.id ? rawCorrectAnswerMap[parent.id] : undefined;
|
|
150
|
+
const rawCorrectRecord = rawCorrect && typeof rawCorrect === 'object' && !Array.isArray(rawCorrect)
|
|
151
|
+
? rawCorrect
|
|
152
|
+
: undefined;
|
|
153
|
+
const correctArr = Array.isArray(rawCorrectRecord?.answer)
|
|
154
|
+
? rawCorrectRecord.answer
|
|
155
|
+
: Array.isArray(parent?.correct_answer?.answer)
|
|
156
|
+
? parent.correct_answer.answer
|
|
157
|
+
: [];
|
|
158
|
+
data.questions.forEach((question, index) => {
|
|
159
|
+
const rawItem = correctArr[index];
|
|
160
|
+
if (!rawItem || typeof rawItem !== 'object' || Array.isArray(rawItem)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const obj = rawItem;
|
|
164
|
+
if (!Array.isArray(obj.answers)) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
correctAnswerMap[question.id] = {
|
|
168
|
+
answers: obj.answers.map((blank) => (Array.isArray(blank)
|
|
169
|
+
? blank.map((alt) => String(alt ?? '').trim()).filter(Boolean)
|
|
170
|
+
: [String(blank ?? '').trim()].filter(Boolean))),
|
|
171
|
+
caseSensitive: obj.caseSensitive === true,
|
|
172
|
+
};
|
|
173
|
+
});
|
|
174
|
+
return (_jsx(MoversFillInBlankGroupRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: data.questions.filter((question) => !question.isExample).length, audioUrl: data.audioUrl, imageUrl: data.imageUrl, showHints: data.showHints, hints: data.hints, questions: data.questions, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true, correctAnswerMap: correctAnswerMap }));
|
|
175
|
+
}
|
|
176
|
+
case 'MATCHING_WITH_LINES_GROUP': {
|
|
177
|
+
const data = transformMatchingWithLinesGroup(apiQuestions);
|
|
178
|
+
return (_jsx(MoversMatchingWithLinesGroupRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, data: data, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true }));
|
|
179
|
+
}
|
|
145
180
|
case 'TRUE_FALSE': {
|
|
146
181
|
const data = transformTrueFalse(apiQuestions);
|
|
147
182
|
return (_jsx(MoversTrueFalseRenderer, { partNumber: partNo, partName: part.name, instruction: part.instructions || data.instruction, questionCount: questionCount, imageUrl: data.imageUrl, questions: data.questions, answers: answers, onAnswerChange: handleAnswerChange, isReviewMode: true, correctAnswerTextMap: correctAnswerTextMap }));
|
|
@@ -9,6 +9,8 @@ const FLATTENED_ANSWER_TYPES = new Set([
|
|
|
9
9
|
'ANSWER_THE_QUESTION_GROUP',
|
|
10
10
|
'CROSS_OUT_WORD_GROUP',
|
|
11
11
|
'TRUE_FALSE_CORRECT_GROUP',
|
|
12
|
+
'FILL_IN_BLANK_GROUP',
|
|
13
|
+
'MATCHING_WITH_LINES_GROUP',
|
|
12
14
|
]);
|
|
13
15
|
export function transformResultAnswersForReview(answers, templateParts = []) {
|
|
14
16
|
const groups = groupAnswers(answers);
|
|
@@ -205,6 +207,41 @@ function transformStudentAnswer(questionId, questionType, value) {
|
|
|
205
207
|
return [`${questionId}-item-${index}`, { isTrue: null, correction: '' }];
|
|
206
208
|
}));
|
|
207
209
|
}
|
|
210
|
+
if (questionType === 'FILL_IN_BLANK_GROUP') {
|
|
211
|
+
const answer = Array.isArray(record.answer)
|
|
212
|
+
? record.answer
|
|
213
|
+
: Array.isArray(value)
|
|
214
|
+
? value
|
|
215
|
+
: [];
|
|
216
|
+
return Object.fromEntries(answer.map((item, index) => {
|
|
217
|
+
if (item && typeof item === 'object' && !Array.isArray(item) && Array.isArray(item.answers)) {
|
|
218
|
+
return [
|
|
219
|
+
`${questionId}-item-${index}`,
|
|
220
|
+
{
|
|
221
|
+
answers: item.answers.map((value) => String(value ?? '')),
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
}
|
|
225
|
+
if (Array.isArray(item)) {
|
|
226
|
+
return [`${questionId}-item-${index}`, { answers: item.map((value) => String(value ?? '')) }];
|
|
227
|
+
}
|
|
228
|
+
if (typeof item === 'string') {
|
|
229
|
+
return [`${questionId}-item-${index}`, { answers: [item] }];
|
|
230
|
+
}
|
|
231
|
+
return [`${questionId}-item-${index}`, { answers: [] }];
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
if (questionType === 'MATCHING_WITH_LINES_GROUP') {
|
|
235
|
+
const answer = Array.isArray(record.answer)
|
|
236
|
+
? record.answer
|
|
237
|
+
: Array.isArray(value)
|
|
238
|
+
? value
|
|
239
|
+
: [];
|
|
240
|
+
return Object.fromEntries(answer.map((item, index) => [
|
|
241
|
+
`${questionId}-item-${index}`,
|
|
242
|
+
typeof item === 'string' ? item : '',
|
|
243
|
+
]));
|
|
244
|
+
}
|
|
208
245
|
if (questionType === 'CHOOSE_THE_CORRECT_ANSWER' || questionType === 'CHOOSE_CORRECT_ADJECTIVE') {
|
|
209
246
|
const rawAns = record.answer ?? record.optionId ?? record.optionIds;
|
|
210
247
|
const ids = getOptionIds(questionId, rawAns);
|
package/dist/index.d.ts
CHANGED
|
@@ -26,4 +26,4 @@ export { validateQuestion } from './components/questions/_shared/utils/question-
|
|
|
26
26
|
export { buildAnswerPayload } from './components/questions/_shared/utils/answer-builder';
|
|
27
27
|
export type { QuestionFormState } from './components/questions/_shared/hooks/useQuestionFormState';
|
|
28
28
|
export * from './components/questions/_shared/types';
|
|
29
|
-
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, TrueFalseCorrectGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, AnswerTheQuestionGroupViewer, MatchWordToPictureViewer, MatchWordToPictureGroupViewer, } from './components/questions/viewer';
|
|
29
|
+
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, TrueFalseCorrectGroupViewer, FillInBlankGroupViewer, MatchingWithLinesGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, AnswerTheQuestionGroupViewer, MatchWordToPictureViewer, MatchWordToPictureGroupViewer, } from './components/questions/viewer';
|
package/dist/index.js
CHANGED
|
@@ -21,4 +21,4 @@ export { QUESTION_TYPE_CONFIG, QUESTION_TYPES_WITH_DEDICATED_COMPONENTS } from '
|
|
|
21
21
|
export { validateQuestion } from './components/questions/_shared/utils/question-validation';
|
|
22
22
|
export { buildAnswerPayload } from './components/questions/_shared/utils/answer-builder';
|
|
23
23
|
export * from './components/questions/_shared/types';
|
|
24
|
-
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, TrueFalseCorrectGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, AnswerTheQuestionGroupViewer, MatchWordToPictureViewer, MatchWordToPictureGroupViewer, } from './components/questions/viewer';
|
|
24
|
+
export { QuestionViewer, QuestionGroupViewer, WordFillStructuredFormViewer, ChooseTheCorrectAnswerGroupViewer, TrueFalseGroupViewer, TrueFalseCorrectGroupViewer, FillInBlankGroupViewer, MatchingWithLinesGroupViewer, CrossOutWordGroupViewer, SpontaneousQaGroupViewer, WordOrderAndMatchGroupViewer, AnswerTheQuestionGroupViewer, MatchWordToPictureViewer, MatchWordToPictureGroupViewer, } from './components/questions/viewer';
|
|
@@ -45,6 +45,7 @@ export const QUESTION_TYPE_SKILLS = {
|
|
|
45
45
|
'CHOOSE_THE_CORRECT_ANSWER_GROUP': SkillEnum.READING,
|
|
46
46
|
'CHOOSE_CORRECT_ADJECTIVE': SkillEnum.READING,
|
|
47
47
|
'FILL_IN_BLANK': SkillEnum.READING,
|
|
48
|
+
'FILL_IN_BLANK_GROUP': SkillEnum.READING,
|
|
48
49
|
'FILL_MISSING_WORDS_IN_GRID': SkillEnum.READING,
|
|
49
50
|
'READ_PASSAGE_AND_ANSWER_QUESTIONS': SkillEnum.READING,
|
|
50
51
|
'ANSWER_THE_QUESTION': SkillEnum.READING,
|
|
@@ -53,6 +54,7 @@ export const QUESTION_TYPE_SKILLS = {
|
|
|
53
54
|
'WORD_FILL_PARAGRAPH': SkillEnum.READING,
|
|
54
55
|
'MATCH_BY_WRITING_ANSWER': SkillEnum.READING,
|
|
55
56
|
'MATCH_WORD_TO_PICTURE': SkillEnum.READING,
|
|
57
|
+
'MATCHING_WITH_LINES_GROUP': SkillEnum.READING,
|
|
56
58
|
// Visual-based reading questions
|
|
57
59
|
'LABEL_THE_PICTURE': SkillEnum.READING,
|
|
58
60
|
'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER': SkillEnum.READING,
|
|
@@ -177,6 +179,7 @@ export const QUESTION_TYPE_LABELS = {
|
|
|
177
179
|
'CHOOSE_THE_CORRECT_ANSWER_GROUP': 'Chọn đáp án đúng (nhóm)',
|
|
178
180
|
'CHOOSE_CORRECT_ADJECTIVE': 'Chọn tính từ',
|
|
179
181
|
'FILL_IN_BLANK': 'Điền vào chỗ trống',
|
|
182
|
+
'FILL_IN_BLANK_GROUP': 'Điền chỗ trống (nhóm)',
|
|
180
183
|
'FILL_MISSING_WORDS_IN_GRID': 'Điền từ vào lưới',
|
|
181
184
|
'READ_PASSAGE_AND_ANSWER_QUESTIONS': 'Đọc hiểu - Trả lời',
|
|
182
185
|
'LABEL_THE_PICTURE': 'Gắn nhãn hình ảnh',
|
|
@@ -209,6 +212,7 @@ export const QUESTION_TYPE_LABELS = {
|
|
|
209
212
|
'WORD_FILL_PARAGRAPH': 'Điền từ vào đoạn văn',
|
|
210
213
|
'MATCH_BY_WRITING_ANSWER': 'Ghép đáp án bằng cách viết',
|
|
211
214
|
'MATCH_WORD_TO_PICTURE': 'Nối từ với tranh',
|
|
215
|
+
'MATCHING_WITH_LINES_GROUP': 'Nối bằng đường kẻ (nhóm)',
|
|
212
216
|
'WORD_FILL_STRUCTURED_FORM': 'Điền từ vào biểu mẫu có cấu trúc',
|
|
213
217
|
'CROSSWORD_PUZZLE': 'Giải ô chữ (Crossword)',
|
|
214
218
|
'FIND_WORDS_IN_MATRIX': 'Tìm từ trong ma trận (Word Search)',
|
|
@@ -308,6 +308,90 @@ const reverseTrueFalseCorrectGroup = (apiQuestion) => {
|
|
|
308
308
|
},
|
|
309
309
|
};
|
|
310
310
|
};
|
|
311
|
+
const reverseFillInBlankGroup = (apiQuestion) => {
|
|
312
|
+
const content = asRecord(apiQuestion.content);
|
|
313
|
+
const answer = readAnswer(apiQuestion);
|
|
314
|
+
const fallbackAnswers = asArray(answer.answer);
|
|
315
|
+
const meta = asRecord(content.meta);
|
|
316
|
+
const items = asArray(content.items).map((rawItem, index) => {
|
|
317
|
+
const item = asRecord(rawItem);
|
|
318
|
+
const itemContent = asRecord(item.content);
|
|
319
|
+
const itemAnswer = asRecord(item.correctAnswer);
|
|
320
|
+
const fallback = asRecord(fallbackAnswers[index]);
|
|
321
|
+
const isExample = item.isExample === true;
|
|
322
|
+
const question = asString(itemContent.question, '{0}');
|
|
323
|
+
const rawAnswers = itemAnswer.answers ?? fallback.answers;
|
|
324
|
+
const answers = asArray(rawAnswers).map((blank) => {
|
|
325
|
+
const alts = Array.isArray(blank)
|
|
326
|
+
? blank.map((alt) => String(alt ?? '').trim()).filter(Boolean)
|
|
327
|
+
: [String(blank ?? '').trim()].filter(Boolean);
|
|
328
|
+
return alts.length > 0 ? alts : [''];
|
|
329
|
+
});
|
|
330
|
+
return {
|
|
331
|
+
question,
|
|
332
|
+
answers: answers.length > 0 ? answers : [['']],
|
|
333
|
+
caseSensitive: itemAnswer.caseSensitive === true || fallback.caseSensitive === true,
|
|
334
|
+
imageUrl: asString(itemContent.imageUrl),
|
|
335
|
+
audioUrl: asString(itemContent.audioUrl),
|
|
336
|
+
showHints: itemContent.showHints === true,
|
|
337
|
+
hints: asArray(itemContent.hints).map((hint) => String(hint ?? '').trim()).filter(Boolean),
|
|
338
|
+
isExample,
|
|
339
|
+
points: isExample ? 0 : asNumber(item.points, 1),
|
|
340
|
+
questionNumber: asNumber(item.questionNumber, index + 1),
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
return {
|
|
344
|
+
content: '',
|
|
345
|
+
answer: {
|
|
346
|
+
instruction: asString(meta.instruction, 'Complete the sentences.'),
|
|
347
|
+
audioUrl: asString(meta.audioUrl),
|
|
348
|
+
imageUrl: asString(meta.imageUrl),
|
|
349
|
+
showHints: meta.showHints === true,
|
|
350
|
+
hints: asArray(meta.hints).map((hint) => String(hint ?? '').trim()).filter(Boolean),
|
|
351
|
+
items,
|
|
352
|
+
explanation: asString(apiQuestion.explanation),
|
|
353
|
+
points: items.reduce((total, item) => (item.isExample ? total : total + item.points), 0),
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
};
|
|
357
|
+
const reverseMatchingWithLinesGroup = (apiQuestion) => {
|
|
358
|
+
const content = asRecord(apiQuestion.content);
|
|
359
|
+
const answer = readAnswer(apiQuestion);
|
|
360
|
+
const fallbackAnswers = asArray(answer.answer);
|
|
361
|
+
const meta = asRecord(content.meta);
|
|
362
|
+
const rightItems = asArray(content.rightItems).map((raw, index) => {
|
|
363
|
+
const item = asRecord(raw);
|
|
364
|
+
return {
|
|
365
|
+
id: asString(item.id, `r${index + 1}`),
|
|
366
|
+
text: asString(item.text),
|
|
367
|
+
};
|
|
368
|
+
});
|
|
369
|
+
const items = asArray(content.items).map((rawItem, index) => {
|
|
370
|
+
const item = asRecord(rawItem);
|
|
371
|
+
const itemContent = asRecord(item.content);
|
|
372
|
+
const itemAnswer = asRecord(item.correctAnswer);
|
|
373
|
+
const fallback = fallbackAnswers[index];
|
|
374
|
+
const isExample = item.isExample === true;
|
|
375
|
+
return {
|
|
376
|
+
imageUrl: asString(itemContent.imageUrl),
|
|
377
|
+
correctAnswer: asString(itemAnswer.answer, typeof fallback === 'string' ? fallback : ''),
|
|
378
|
+
isExample,
|
|
379
|
+
points: isExample ? 0 : asNumber(item.points, 1),
|
|
380
|
+
questionNumber: asNumber(item.questionNumber, index + 1),
|
|
381
|
+
};
|
|
382
|
+
});
|
|
383
|
+
return {
|
|
384
|
+
content: '',
|
|
385
|
+
answer: {
|
|
386
|
+
title: asString(meta.title),
|
|
387
|
+
instruction: asString(meta.instruction, 'Look and match.'),
|
|
388
|
+
rightItems,
|
|
389
|
+
items,
|
|
390
|
+
explanation: asString(apiQuestion.explanation),
|
|
391
|
+
points: items.reduce((total, item) => (item.isExample ? total : total + item.points), 0),
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
};
|
|
311
395
|
const reverseCrossOutWordGroup = (apiQuestion) => {
|
|
312
396
|
const content = asRecord(apiQuestion.content);
|
|
313
397
|
const answer = readAnswer(apiQuestion);
|
|
@@ -460,6 +544,8 @@ const handlers = {
|
|
|
460
544
|
ANSWER_THE_QUESTION_GROUP: reverseAnswerTheQuestionGroup,
|
|
461
545
|
TRUE_FALSE_GROUP: reverseTrueFalseGroup,
|
|
462
546
|
TRUE_FALSE_CORRECT_GROUP: reverseTrueFalseCorrectGroup,
|
|
547
|
+
FILL_IN_BLANK_GROUP: reverseFillInBlankGroup,
|
|
548
|
+
MATCHING_WITH_LINES_GROUP: reverseMatchingWithLinesGroup,
|
|
463
549
|
CROSS_OUT_WORD_GROUP: reverseCrossOutWordGroup,
|
|
464
550
|
WORD_ORDER_AND_MATCH_GROUP: reverseWordOrderAndMatchGroup,
|
|
465
551
|
WORD_ORDER_AND_MATCH: reverseWordOrderAndMatchGroup,
|
|
@@ -14,6 +14,7 @@ import { transformChooseTheCorrectAnswer } from '../../../components/questions/t
|
|
|
14
14
|
import { transformChooseTheCorrectAnswerGroup } from '../../../components/questions/types/choose-the-correct-answer-group/transform';
|
|
15
15
|
import { transformCrossOutWordGroup } from '../../../components/questions/types/cross-out-word-group/transform';
|
|
16
16
|
import { transformTrueFalseCorrectGroup } from '../../../components/questions/types/true-false-correct-group/transform';
|
|
17
|
+
import { transformFillInBlankGroup } from '../../../components/questions/types/fill-in-blank-group/transform';
|
|
17
18
|
import { transformFillInBlank } from '../../../components/questions/types/fill-in-blank/transform';
|
|
18
19
|
import { transformWriteCorrectVerbForm } from '../../../components/questions/types/write-correct-verb-form/transform';
|
|
19
20
|
import { transformChooseCorrectAdjective } from '../../../components/questions/types/choose-correct-adjective/transform';
|
|
@@ -24,6 +25,7 @@ import { transformWordOrdering } from '../../../components/questions/types/word-
|
|
|
24
25
|
import { transformWordFillParagraph } from '../../../components/questions/types/word-fill-paragraph/transform';
|
|
25
26
|
import { transformMatchByWritingAnswer } from '../../../components/questions/types/match-by-writing-answer/transform';
|
|
26
27
|
import { transformMatchWordToPicture } from '../../../components/questions/types/match-word-to-picture/transform';
|
|
28
|
+
import { transformMatchingWithLinesGroup } from '../../../components/questions/types/matching-with-lines-group/transform';
|
|
27
29
|
import { transformWriteSentences } from '../../../components/questions/types/write-sentences/transform';
|
|
28
30
|
import { transformListenAndChooseFromAnswerGroup } from '../../../components/questions/types/listen-and-choose-from-answer-group/transform';
|
|
29
31
|
import { transformListenAndChooseObjectsInScene } from '../../../components/questions/types/listen-and-choose-objects-in-scene/transform';
|
|
@@ -65,6 +67,7 @@ const questionTransformHandlers = {
|
|
|
65
67
|
CHOOSE_THE_CORRECT_ANSWER_GROUP: transformChooseTheCorrectAnswerGroup,
|
|
66
68
|
CROSS_OUT_WORD_GROUP: transformCrossOutWordGroup,
|
|
67
69
|
TRUE_FALSE_CORRECT_GROUP: transformTrueFalseCorrectGroup,
|
|
70
|
+
FILL_IN_BLANK_GROUP: transformFillInBlankGroup,
|
|
68
71
|
FILL_IN_BLANK: transformFillInBlank,
|
|
69
72
|
WRITE_CORRECT_VERB_FORM: transformWriteCorrectVerbForm,
|
|
70
73
|
CHOOSE_CORRECT_ADJECTIVE: transformChooseCorrectAdjective,
|
|
@@ -75,6 +78,7 @@ const questionTransformHandlers = {
|
|
|
75
78
|
WORD_FILL_PARAGRAPH: transformWordFillParagraph,
|
|
76
79
|
MATCH_BY_WRITING_ANSWER: transformMatchByWritingAnswer,
|
|
77
80
|
MATCH_WORD_TO_PICTURE: transformMatchWordToPicture,
|
|
81
|
+
MATCHING_WITH_LINES_GROUP: transformMatchingWithLinesGroup,
|
|
78
82
|
WRITE_SENTENCES: transformWriteSentences,
|
|
79
83
|
LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP: transformListenAndChooseFromAnswerGroup,
|
|
80
84
|
LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE: transformListenAndChooseObjectsInScene,
|
|
@@ -29,7 +29,7 @@ export declare enum StudentSelectionType {
|
|
|
29
29
|
}
|
|
30
30
|
export type ResultStatus = 'PENDING' | 'PARTIAL_GRADED' | 'GRADED';
|
|
31
31
|
export type StudentStatus = 'NOT_STARTED' | 'IN_PROGRESS' | 'SUBMITTED';
|
|
32
|
-
export type QuestionType = 'FILL_IN_BLANK' | 'TRUE_FALSE' | 'MATCHING' | 'ORDERING' | 'LISTENING' | 'COLORING' | 'ESSAY' | 'LISTEN_AND_FILL_IN_THE_BLANK_WITH_IMAGE' | 'LISTEN_AND_TICK_ANSWER' | 'LISTEN_AND_FILL_NAME_NUMBER' | 'LISTENING_FILL_BLANK' | 'LISTENING_COLOR' | 'TICK_TRUE_OR_FALSE' | 'TICK_YES_OR_NO' | 'READING_TICK_CROSS' | 'ARRANGE_LETTERS_INTO_WORDS' | 'READ_PASSAGE_AND_COMPLETE_STORY' | 'CLOZE_TEST_WITH_TICK_BOX' | 'READ_AND_CHOOSE_APPROPRIATE_WORD' | 'WRITE_SHORT_PARAGRAPH' | 'LABEL_THE_PICTURE' | 'READING_LETTER_ARRANGE' | 'READING_PASSAGE_FILL' | 'FILL_BLANK' | 'FILL_MISSING_WORDS_IN_GRID' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'LABEL_THE_PICTURE' | 'READ_AND_COLOR_OBJECTS' | 'IMAGE_OBJECT_MATCHING' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'TRUE_FALSE_GROUP' | 'TRUE_FALSE_CORRECT_GROUP' | 'CROSS_OUT_WORD_GROUP' | 'SPONTANEOUS_QA_GROUP' | 'WORD_ORDER_AND_MATCH_GROUP' | 'WRITE_A_SHORT_LETTER' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_CORRECT_ADJECTIVE' | 'ANSWER_THE_QUESTION' | 'ANSWER_THE_QUESTION_GROUP' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'MATCH_WORD_TO_PICTURE' | 'WRITE_SENTENCES' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD' | 'WORD_FILL_STRUCTURED_FORM' | 'CROSSWORD_PUZZLE' | 'FIND_WORDS_IN_MATRIX';
|
|
32
|
+
export type QuestionType = 'FILL_IN_BLANK' | 'TRUE_FALSE' | 'MATCHING' | 'ORDERING' | 'LISTENING' | 'COLORING' | 'ESSAY' | 'LISTEN_AND_FILL_IN_THE_BLANK_WITH_IMAGE' | 'LISTEN_AND_TICK_ANSWER' | 'LISTEN_AND_FILL_NAME_NUMBER' | 'LISTENING_FILL_BLANK' | 'LISTENING_COLOR' | 'TICK_TRUE_OR_FALSE' | 'TICK_YES_OR_NO' | 'READING_TICK_CROSS' | 'ARRANGE_LETTERS_INTO_WORDS' | 'READ_PASSAGE_AND_COMPLETE_STORY' | 'CLOZE_TEST_WITH_TICK_BOX' | 'READ_AND_CHOOSE_APPROPRIATE_WORD' | 'WRITE_SHORT_PARAGRAPH' | 'LABEL_THE_PICTURE' | 'READING_LETTER_ARRANGE' | 'READING_PASSAGE_FILL' | 'FILL_BLANK' | 'FILL_MISSING_WORDS_IN_GRID' | 'LOOK_PICTURE_CHOOSE_CORRECT_ANSWER' | 'LOOK_PICTURE_FILL_BLANK_CHOOSE_ANSWER' | 'LOOK_PICTURE_FILL_WORD_HINT' | 'LABEL_THE_PICTURE' | 'READ_AND_COLOR_OBJECTS' | 'IMAGE_OBJECT_MATCHING' | 'READ_PASSAGE_AND_ANSWER_QUESTIONS' | 'CHOOSE_THE_CORRECT_ANSWER' | 'CHOOSE_THE_CORRECT_ANSWER_GROUP' | 'TRUE_FALSE_GROUP' | 'TRUE_FALSE_CORRECT_GROUP' | 'FILL_IN_BLANK_GROUP' | 'MATCHING_WITH_LINES_GROUP' | 'CROSS_OUT_WORD_GROUP' | 'SPONTANEOUS_QA_GROUP' | 'WORD_ORDER_AND_MATCH_GROUP' | 'WRITE_A_SHORT_LETTER' | 'WRITE_CORRECT_VERB_FORM' | 'CHOOSE_CORRECT_ADJECTIVE' | 'ANSWER_THE_QUESTION' | 'ANSWER_THE_QUESTION_GROUP' | 'WORD_ORDERING' | 'WORD_FILL_PARAGRAPH' | 'MATCH_BY_WRITING_ANSWER' | 'MATCH_WORD_TO_PICTURE' | 'WRITE_SENTENCES' | 'LISTEN_AND_CHOOSE_FROM_ANSWER_GROUP' | 'LISTEN_AND_CHOOSE_OBJECTS_IN_SCENE' | 'LISTEN_AND_DRAG_OBJECTS_INTO_SCENE' | 'LISTEN_AND_SPEAK_ANSWER' | 'LISTEN_AND_SPEAK_IMAGE_GROUP' | 'LISTEN_AND_SPEAK_QUESTION_LIST' | 'LISTEN_AND_SPEAK_COMPARE_IMAGES' | 'LISTEN_AND_SPEAK_WITH_STORY_IMAGES' | 'LISTEN_AND_SPEAK_ODD_ONE_OUT' | 'LISTEN_AND_SPEAK_INFO_EXCHANGE' | 'READ_DISPLAYED_CONTENT' | 'SPEAKING_DESCRIBE_IMAGE' | 'SPONTANEOUS_QA' | 'SPEAKING_CONVERSATION' | 'GN_SPEAKING_INTERVIEW' | 'SPEAKING_CUE_CARD' | 'WORD_FILL_STRUCTURED_FORM' | 'CROSSWORD_PUZZLE' | 'FIND_WORDS_IN_MATRIX';
|
|
33
33
|
export type Level = 'Pre-A1' | 'A1' | 'A2' | 'B1' | 'B2' | 'C1' | 'C2';
|
|
34
34
|
export type Difficulty = 'EASY' | 'MEDIUM' | 'HARD';
|
|
35
35
|
export type Skill = 'LISTENING' | 'READING' | 'WRITING' | 'SPEAKING';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export declare const FILL_IN_BLANK_ITEM_TYPE: "FILL_IN_BLANK";
|
|
2
|
+
export interface FillInBlankGroupItemAnswer {
|
|
3
|
+
answers: string[][];
|
|
4
|
+
caseSensitive?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface FillInBlankGroupItemContent {
|
|
7
|
+
question: string;
|
|
8
|
+
imageUrl?: string;
|
|
9
|
+
audioUrl?: string;
|
|
10
|
+
showHints?: boolean;
|
|
11
|
+
hints?: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface FillInBlankGroupItem {
|
|
14
|
+
questionType?: typeof FILL_IN_BLANK_ITEM_TYPE;
|
|
15
|
+
isExample?: boolean;
|
|
16
|
+
content: FillInBlankGroupItemContent;
|
|
17
|
+
correctAnswer?: FillInBlankGroupItemAnswer;
|
|
18
|
+
points?: number;
|
|
19
|
+
questionNumber?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface FillInBlankGroupContent {
|
|
22
|
+
meta?: {
|
|
23
|
+
instruction?: string;
|
|
24
|
+
audioUrl?: string;
|
|
25
|
+
imageUrl?: string;
|
|
26
|
+
showHints?: boolean;
|
|
27
|
+
hints?: string[];
|
|
28
|
+
};
|
|
29
|
+
items: FillInBlankGroupItem[];
|
|
30
|
+
}
|
|
31
|
+
export interface FillInBlankGroupCorrectAnswer {
|
|
32
|
+
answer: FillInBlankGroupItemAnswer[];
|
|
33
|
+
}
|
|
34
|
+
export interface FillInBlankGroupAPIPayload {
|
|
35
|
+
id?: string;
|
|
36
|
+
questionType: 'FILL_IN_BLANK_GROUP';
|
|
37
|
+
content: FillInBlankGroupContent;
|
|
38
|
+
correctAnswer: FillInBlankGroupCorrectAnswer;
|
|
39
|
+
points: number;
|
|
40
|
+
explanation?: string;
|
|
41
|
+
questionNumber: number;
|
|
42
|
+
partId?: string;
|
|
43
|
+
partNo?: number;
|
|
44
|
+
}
|
|
45
|
+
export type FillInBlankGroupLocalStorage = FillInBlankGroupAPIPayload;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const FILL_IN_BLANK_ITEM_TYPE = 'FILL_IN_BLANK';
|
|
@@ -33,4 +33,6 @@ export * from './word-order-and-match-group';
|
|
|
33
33
|
export * from './crossword-puzzle';
|
|
34
34
|
export * from './find-words-in-matrix';
|
|
35
35
|
export * from './match-word-to-picture';
|
|
36
|
+
export * from './matching-with-lines-group';
|
|
36
37
|
export * from './true-false-correct-group';
|
|
38
|
+
export * from './fill-in-blank-group';
|
|
@@ -52,5 +52,9 @@ export * from './crossword-puzzle';
|
|
|
52
52
|
export * from './find-words-in-matrix';
|
|
53
53
|
// MATCH_WORD_TO_PICTURE
|
|
54
54
|
export * from './match-word-to-picture';
|
|
55
|
+
// MATCHING_WITH_LINES_GROUP
|
|
56
|
+
export * from './matching-with-lines-group';
|
|
55
57
|
// TRUE_FALSE_CORRECT_GROUP
|
|
56
58
|
export * from './true-false-correct-group';
|
|
59
|
+
// FILL_IN_BLANK_GROUP
|
|
60
|
+
export * from './fill-in-blank-group';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface MatchingWithLinesRightItem {
|
|
2
|
+
id: string;
|
|
3
|
+
text: string;
|
|
4
|
+
}
|
|
5
|
+
export interface MatchingWithLinesGroupItemContent {
|
|
6
|
+
imageUrl: string;
|
|
7
|
+
}
|
|
8
|
+
export interface MatchingWithLinesGroupItem {
|
|
9
|
+
isExample?: boolean;
|
|
10
|
+
content: MatchingWithLinesGroupItemContent;
|
|
11
|
+
correctAnswer?: {
|
|
12
|
+
answer: string;
|
|
13
|
+
};
|
|
14
|
+
points?: number;
|
|
15
|
+
questionNumber?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface MatchingWithLinesGroupContent {
|
|
18
|
+
meta?: {
|
|
19
|
+
instruction?: string;
|
|
20
|
+
title?: string;
|
|
21
|
+
};
|
|
22
|
+
rightItems: MatchingWithLinesRightItem[];
|
|
23
|
+
items: MatchingWithLinesGroupItem[];
|
|
24
|
+
}
|
|
25
|
+
export interface MatchingWithLinesGroupCorrectAnswer {
|
|
26
|
+
answer: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface MatchingWithLinesGroupAPIPayload {
|
|
29
|
+
id?: string;
|
|
30
|
+
questionType: 'MATCHING_WITH_LINES_GROUP';
|
|
31
|
+
content: MatchingWithLinesGroupContent;
|
|
32
|
+
correctAnswer: MatchingWithLinesGroupCorrectAnswer;
|
|
33
|
+
points: number;
|
|
34
|
+
explanation?: string;
|
|
35
|
+
questionNumber: number;
|
|
36
|
+
partId?: string;
|
|
37
|
+
partNo?: number;
|
|
38
|
+
}
|
|
39
|
+
export type MatchingWithLinesGroupLocalStorage = MatchingWithLinesGroupAPIPayload;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|