188 lines
5.7 KiB
TypeScript
188 lines
5.7 KiB
TypeScript
import { FillBlanksExercise, LevelPart, ListeningPart, MatchSentencesExercise, MultipleChoiceExercise, ReadingPart, TrueFalseExercise, WriteBlanksExercise } from "@/interfaces/exam";
|
|
import { ModuleState } from "../types";
|
|
import ReorderResult from "./types";
|
|
|
|
const reorderFillBlanks = (exercise: FillBlanksExercise, startId: number): ReorderResult<FillBlanksExercise> => {
|
|
const newSolutions = exercise.solutions
|
|
.sort((a, b) => parseInt(a.id) - parseInt(b.id))
|
|
.map((solution, index) => ({
|
|
...solution,
|
|
id: (startId + index).toString()
|
|
}));
|
|
|
|
const idMapping = exercise.solutions
|
|
.sort((a, b) => parseInt(a.id) - parseInt(b.id))
|
|
.reduce((acc, solution, index) => {
|
|
acc[solution.id] = (startId + index).toString();
|
|
return acc;
|
|
}, {} as Record<string, string>);
|
|
|
|
let newText = exercise.text;
|
|
Object.entries(idMapping).forEach(([oldId, newId]) => {
|
|
const regex = new RegExp(`\\{\\{${oldId}\\}\\}`, 'g');
|
|
newText = newText.replace(regex, `{{${newId}}}`);
|
|
});
|
|
|
|
|
|
const newWords = exercise.words.map(word => {
|
|
if (typeof word === 'string') {
|
|
return word;
|
|
} else if ('letter' in word && 'word' in word) {
|
|
return word;
|
|
} else if ('options' in word) {
|
|
return word;
|
|
}
|
|
return word;
|
|
});
|
|
|
|
const newUserSolutions = exercise.userSolutions?.map(solution => ({
|
|
...solution,
|
|
id: idMapping[solution.id] || solution.id
|
|
}));
|
|
|
|
return {
|
|
exercise: {
|
|
...exercise,
|
|
solutions: newSolutions,
|
|
text: newText,
|
|
words: newWords,
|
|
userSolutions: newUserSolutions
|
|
},
|
|
lastId: startId + newSolutions.length - 1
|
|
};
|
|
|
|
};
|
|
|
|
const reorderWriteBlanks = (exercise: WriteBlanksExercise, startId: number): ReorderResult<WriteBlanksExercise> => {
|
|
const newSolutions = exercise.solutions
|
|
.sort((a, b) => parseInt(a.id) - parseInt(b.id))
|
|
.map((solution, index) => ({
|
|
...solution,
|
|
id: (startId + index).toString()
|
|
}));
|
|
|
|
return {
|
|
exercise: {
|
|
...exercise,
|
|
solutions: newSolutions,
|
|
text: newSolutions.reduce((text, solution, index) => {
|
|
return text.replace(
|
|
new RegExp(`\\{\\{${solution.id}\\}\\}`),
|
|
`{{${startId + index}}}`
|
|
);
|
|
}, exercise.text)
|
|
},
|
|
lastId: startId + newSolutions.length
|
|
};
|
|
};
|
|
|
|
const reorderTrueFalse = (exercise: TrueFalseExercise, startId: number): ReorderResult<TrueFalseExercise> => {
|
|
const newQuestions = exercise.questions
|
|
.sort((a, b) => parseInt(a.id) - parseInt(b.id))
|
|
.map((question, index) => ({
|
|
...question,
|
|
id: (startId + index).toString()
|
|
}));
|
|
|
|
return {
|
|
exercise: {
|
|
...exercise,
|
|
questions: newQuestions
|
|
},
|
|
lastId: startId + newQuestions.length
|
|
};
|
|
};
|
|
|
|
const reorderMatchSentences = (exercise: MatchSentencesExercise, startId: number): ReorderResult<MatchSentencesExercise> => {
|
|
const newSentences = exercise.sentences
|
|
.sort((a, b) => parseInt(a.id) - parseInt(b.id))
|
|
.map((sentence, index) => ({
|
|
...sentence,
|
|
id: (startId + index).toString()
|
|
}));
|
|
|
|
return {
|
|
exercise: {
|
|
...exercise,
|
|
sentences: newSentences
|
|
},
|
|
lastId: startId + newSentences.length
|
|
};
|
|
};
|
|
|
|
|
|
const reorderMultipleChoice = (exercise: MultipleChoiceExercise, startId: number): ReorderResult<MultipleChoiceExercise> => {
|
|
const newQuestions = exercise.questions
|
|
.sort((a, b) => parseInt(a.id) - parseInt(b.id))
|
|
.map((question, index) => ({
|
|
...question,
|
|
id: (startId + index).toString()
|
|
}));
|
|
|
|
return {
|
|
exercise: {
|
|
...exercise,
|
|
questions: newQuestions
|
|
},
|
|
lastId: startId + newQuestions.length
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
const reorderExercises = (moduleState: ModuleState) => {
|
|
let currentId = 1;
|
|
|
|
const reorderedSections = moduleState.sections.map(section => {
|
|
const currentSection = section.state as ReadingPart | ListeningPart |LevelPart;
|
|
const reorderedExercises = currentSection.exercises.map(exercise => {
|
|
let result;
|
|
switch (exercise.type) {
|
|
case 'fillBlanks':
|
|
result = reorderFillBlanks(exercise, currentId);
|
|
currentId = result.lastId;
|
|
return result.exercise;
|
|
case 'writeBlanks':
|
|
result = reorderWriteBlanks(exercise, currentId);
|
|
currentId = result.lastId;
|
|
return result.exercise;
|
|
case 'trueFalse':
|
|
result = reorderTrueFalse(exercise, currentId);
|
|
currentId = result.lastId;
|
|
return result.exercise;
|
|
case 'matchSentences':
|
|
result = reorderMatchSentences(exercise, currentId);
|
|
currentId = result.lastId;
|
|
return result.exercise;
|
|
case 'multipleChoice':
|
|
result = reorderMultipleChoice(exercise, currentId);
|
|
currentId = result.lastId
|
|
return result.exercise;
|
|
default:
|
|
return exercise;
|
|
}
|
|
});
|
|
return {
|
|
...section,
|
|
state: {
|
|
...currentSection,
|
|
exercises: reorderedExercises
|
|
}
|
|
};
|
|
});
|
|
|
|
return {
|
|
...moduleState,
|
|
sections: reorderedSections
|
|
};
|
|
};
|
|
|
|
export {
|
|
reorderFillBlanks,
|
|
reorderWriteBlanks,
|
|
reorderTrueFalse,
|
|
reorderMatchSentences,
|
|
reorderExercises,
|
|
reorderMultipleChoice,
|
|
}; |