Commented all related to shuffle
This commit is contained in:
@@ -20,7 +20,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
onNext,
|
onNext,
|
||||||
onBack,
|
onBack,
|
||||||
}) => {
|
}) => {
|
||||||
const { shuffleMaps } = useExamStore((state) => state);
|
//const { shuffleMaps } = useExamStore((state) => state);
|
||||||
const [answers, setAnswers] = useState<{ id: string; solution: string }[]>(userSolutions);
|
const [answers, setAnswers] = useState<{ id: string; solution: string }[]>(userSolutions);
|
||||||
const hasExamEnded = useExamStore((state) => state.hasExamEnded);
|
const hasExamEnded = useExamStore((state) => state.hasExamEnded);
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
return solution.toLowerCase() === option.toLowerCase();
|
return solution.toLowerCase() === option.toLowerCase();
|
||||||
} else if ('letter' in option) {
|
} else if ('letter' in option) {
|
||||||
return solution.toLowerCase() === option.word.toLowerCase();
|
return solution.toLowerCase() === option.word.toLowerCase();
|
||||||
} else if ('options' in option) {
|
} /*else if ('options' in option) {
|
||||||
if (shuffleMaps.length !== 0) {
|
if (shuffleMaps.length !== 0) {
|
||||||
const shuffleMap = shuffleMaps.find((map) => map.id == x.id)
|
const shuffleMap = shuffleMaps.find((map) => map.id == x.id)
|
||||||
if (!shuffleMap) {
|
if (!shuffleMap) {
|
||||||
@@ -73,7 +73,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return solution.toLowerCase() === (option.options[x.solution as keyof typeof option.options] || '').toLowerCase();
|
return solution.toLowerCase() === (option.options[x.solution as keyof typeof option.options] || '').toLowerCase();
|
||||||
}
|
}*/
|
||||||
return false;
|
return false;
|
||||||
}).length;
|
}).length;
|
||||||
|
|
||||||
@@ -129,7 +129,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
setAnswers((prev) => [...prev.filter((x) => x.id !== id), { id: id, solution: value }]);
|
setAnswers((prev) => [...prev.filter((x) => x.id !== id), { id: id, solution: value }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const getShuffles = () => {
|
/*const getShuffles = () => {
|
||||||
let shuffle = {};
|
let shuffle = {};
|
||||||
if (shuffleMaps.length !== 0) {
|
if (shuffleMaps.length !== 0) {
|
||||||
shuffle = {
|
shuffle = {
|
||||||
@@ -139,7 +139,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shuffle;
|
return shuffle;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -166,7 +166,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
<div className="bg-mti-gray-smoke rounded-xl px-5 py-6 flex flex-col gap-4">
|
<div className="bg-mti-gray-smoke rounded-xl px-5 py-6 flex flex-col gap-4">
|
||||||
<span className="font-medium text-mti-purple-dark">Options</span>
|
<span className="font-medium text-mti-purple-dark">Options</span>
|
||||||
<div className="flex gap-4 flex-wrap">
|
<div className="flex gap-4 flex-wrap">
|
||||||
{currentMCSelection.selection?.options && Object.entries(currentMCSelection.selection.options).map(([key, value]) => {
|
{currentMCSelection.selection?.options && Object.entries(currentMCSelection.selection.options).sort((a, b) => a[0].localeCompare(b[0])).map(([key, value]) => {
|
||||||
return <button
|
return <button
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"border border-mti-purple-light rounded-full px-3 py-0.5 transition ease-in-out duration-300",
|
"border border-mti-purple-light rounded-full px-3 py-0.5 transition ease-in-out duration-300",
|
||||||
@@ -212,14 +212,14 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
color="purple"
|
color="purple"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
onClick={() => onBack({ exercise: id, solutions: answers, score: calculateScore(), type, ...getShuffles() })}
|
onClick={() => onBack({ exercise: id, solutions: answers, score: calculateScore(), type, })}//...getShuffles() })}
|
||||||
className="max-w-[200px] w-full">
|
className="max-w-[200px] w-full">
|
||||||
Back
|
Back
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
color="purple"
|
color="purple"
|
||||||
onClick={() => onNext({ exercise: id, solutions: answers, score: calculateScore(), type, ...getShuffles() })}
|
onClick={() => onNext({ exercise: id, solutions: answers, score: calculateScore(), type, })}//...getShuffles() })}
|
||||||
className="max-w-[200px] self-end w-full">
|
className="max-w-[200px] self-end w-full">
|
||||||
Next
|
Next
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function Question({
|
|||||||
export default function MultipleChoice({ id, prompt, type, questions, userSolutions, onNext, onBack }: MultipleChoiceExercise & CommonProps) {
|
export default function MultipleChoice({ id, prompt, type, questions, userSolutions, onNext, onBack }: MultipleChoiceExercise & CommonProps) {
|
||||||
const [answers, setAnswers] = useState<{ question: string; option: string }[]>(userSolutions);
|
const [answers, setAnswers] = useState<{ question: string; option: string }[]>(userSolutions);
|
||||||
|
|
||||||
const { shuffleMaps } = useExamStore((state) => state);
|
//const { shuffleMaps } = useExamStore((state) => state);
|
||||||
const { questionIndex, setQuestionIndex } = useExamStore((state) => state);
|
const { questionIndex, setQuestionIndex } = useExamStore((state) => state);
|
||||||
const { userSolutions: storeUserSolutions, setUserSolutions } = useExamStore((state) => state);
|
const { userSolutions: storeUserSolutions, setUserSolutions } = useExamStore((state) => state);
|
||||||
const hasExamEnded = useExamStore((state) => state.hasExamEnded);
|
const hasExamEnded = useExamStore((state) => state.hasExamEnded);
|
||||||
@@ -109,12 +109,12 @@ export default function MultipleChoice({ id, prompt, type, questions, userSoluti
|
|||||||
});
|
});
|
||||||
|
|
||||||
let isSolutionCorrect;
|
let isSolutionCorrect;
|
||||||
if (shuffleMaps.length == 0) {
|
//if (shuffleMaps.length == 0) {
|
||||||
isSolutionCorrect = matchingQuestion?.solution === x.option;
|
isSolutionCorrect = matchingQuestion?.solution === x.option;
|
||||||
} else {
|
//} else {
|
||||||
const shuffleMap = shuffleMaps.find((map) => map.id == x.question)
|
// const shuffleMap = shuffleMaps.find((map) => map.id == x.question)
|
||||||
isSolutionCorrect = shuffleMap?.map[x.option] == matchingQuestion?.solution;
|
// isSolutionCorrect = shuffleMap?.map[x.option] == matchingQuestion?.solution;
|
||||||
}
|
//}
|
||||||
return isSolutionCorrect || false;
|
return isSolutionCorrect || false;
|
||||||
}).length;
|
}).length;
|
||||||
const missing = total - correct;
|
const missing = total - correct;
|
||||||
@@ -122,7 +122,7 @@ export default function MultipleChoice({ id, prompt, type, questions, userSoluti
|
|||||||
return { total, correct, missing };
|
return { total, correct, missing };
|
||||||
};
|
};
|
||||||
|
|
||||||
const getShuffles = () => {
|
/*const getShuffles = () => {
|
||||||
let shuffle = {};
|
let shuffle = {};
|
||||||
if (shuffleMaps.length !== 0) {
|
if (shuffleMaps.length !== 0) {
|
||||||
shuffle = {
|
shuffle = {
|
||||||
@@ -132,11 +132,11 @@ export default function MultipleChoice({ id, prompt, type, questions, userSoluti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shuffle;
|
return shuffle;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
if (questionIndex === questions.length - 1) {
|
if (questionIndex === questions.length - 1) {
|
||||||
onNext({ exercise: id, solutions: answers, score: calculateScore(), type, ...getShuffles() });
|
onNext({ exercise: id, solutions: answers, score: calculateScore(), type, });//...getShuffles() });
|
||||||
} else {
|
} else {
|
||||||
setQuestionIndex(questionIndex + 1);
|
setQuestionIndex(questionIndex + 1);
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ export default function MultipleChoice({ id, prompt, type, questions, userSoluti
|
|||||||
|
|
||||||
const back = () => {
|
const back = () => {
|
||||||
if (questionIndex === 0) {
|
if (questionIndex === 0) {
|
||||||
onBack({ exercise: id, solutions: answers, score: calculateScore(), type, ...getShuffles() });
|
onBack({ exercise: id, solutions: answers, score: calculateScore(), type, });// ...getShuffles() });
|
||||||
} else {
|
} else {
|
||||||
setQuestionIndex(questionIndex - 1);
|
setQuestionIndex(questionIndex - 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,26 +17,36 @@ function Question({
|
|||||||
}: MultipleChoiceQuestion & { userSolution: string | undefined; onSelectOption?: (option: string) => void; showSolution?: boolean }) {
|
}: MultipleChoiceQuestion & { userSolution: string | undefined; onSelectOption?: (option: string) => void; showSolution?: boolean }) {
|
||||||
const { userSolutions } = useExamStore((state) => state);
|
const { userSolutions } = useExamStore((state) => state);
|
||||||
|
|
||||||
|
/*
|
||||||
|
const getShuffledOptions = (options: {id: string, text: string}[], questionShuffleMap: ShuffleMap) => {
|
||||||
|
const shuffledOptions = ['A', 'B', 'C', 'D'].map(newId => {
|
||||||
|
const originalId = questionShuffleMap.map[newId];
|
||||||
|
const originalOption = options.find(option => option.id === originalId);
|
||||||
|
return {
|
||||||
|
id: newId,
|
||||||
|
text: originalOption!.text
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return shuffledOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const getShuffledSolution = (originalSolution: string, questionShuffleMap: ShuffleMap) => {
|
||||||
|
for (const [newPosition, originalPosition] of Object.entries(questionShuffleMap.map)) {
|
||||||
|
if (originalPosition === originalSolution) {
|
||||||
|
return newPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return originalSolution;
|
||||||
|
}
|
||||||
|
|
||||||
const questionShuffleMap = userSolutions.reduce((foundMap, userSolution) => {
|
const questionShuffleMap = userSolutions.reduce((foundMap, userSolution) => {
|
||||||
if (foundMap) return foundMap;
|
if (foundMap) return foundMap;
|
||||||
return userSolution.shuffleMaps?.find(map => map.id === id) || null;
|
return userSolution.shuffleMaps?.find(map => map.id === id) || null;
|
||||||
}, null as ShuffleMap | null);
|
}, null as ShuffleMap | null);
|
||||||
|
*/
|
||||||
const shuffledOptions = new Array(options.length);
|
|
||||||
options.forEach(option => {
|
const questionOptions = options; // questionShuffleMap ? getShuffledOptions(options as {id: string, text: string}[], questionShuffleMap) : options;
|
||||||
const newId = questionShuffleMap?.map[option.id];
|
const newSolution = solution; //questionShuffleMap ? getShuffledSolution(solution, questionShuffleMap) : solution;
|
||||||
const newIndex = options.findIndex(opt => opt.id === newId);
|
|
||||||
shuffledOptions[newIndex] = option;
|
|
||||||
});
|
|
||||||
|
|
||||||
const lettersMap = ['A', 'B', 'C', 'D'];
|
|
||||||
const optionsWithLetters = shuffledOptions.map((option, index) => ({
|
|
||||||
...option,
|
|
||||||
id: lettersMap[index]
|
|
||||||
}));
|
|
||||||
|
|
||||||
const questionOptions = questionShuffleMap ? optionsWithLetters : options;
|
|
||||||
const newQuestionSolution = questionShuffleMap ? questionShuffleMap.map[solution] : solution;
|
|
||||||
|
|
||||||
const renderPrompt = (prompt: string) => {
|
const renderPrompt = (prompt: string) => {
|
||||||
return reactStringReplace(prompt, /((<u>)[\w\s']+(<\/u>))/g, (match) => {
|
return reactStringReplace(prompt, /((<u>)[\w\s']+(<\/u>))/g, (match) => {
|
||||||
@@ -46,11 +56,11 @@ function Question({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const optionColor = (option: string) => {
|
const optionColor = (option: string) => {
|
||||||
if (option === newQuestionSolution && !userSolution) {
|
if (option === newSolution && !userSolution) {
|
||||||
return "!border-mti-gray-davy !text-mti-gray-davy";
|
return "!border-mti-gray-davy !text-mti-gray-davy";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option === newQuestionSolution) {
|
if (option === newSolution) {
|
||||||
return "!border-mti-purple-light !text-mti-purple-light";
|
return "!border-mti-purple-light !text-mti-purple-light";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +87,8 @@ function Question({
|
|||||||
"flex flex-col items-center border border-mti-gray-platinum p-4 px-8 rounded-xl gap-4 cursor-pointer bg-white relative",
|
"flex flex-col items-center border border-mti-gray-platinum p-4 px-8 rounded-xl gap-4 cursor-pointer bg-white relative",
|
||||||
optionColor(option!.id),
|
optionColor(option!.id),
|
||||||
)}>
|
)}>
|
||||||
<span className={clsx("text-sm", newQuestionSolution !== option?.id && userSolution !== option?.id && "opacity-50")}>{option?.id}</span>
|
<span className={clsx("text-sm", newSolution !== option?.id && userSolution !== option?.id && "opacity-50")}>{option?.id}</span>
|
||||||
<img src={option?.src!} alt={`Option ${option?.id}`} />
|
{"src" in option && <img src={option?.src!} alt={`Option ${option?.id}`} />}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
{variant === "text" &&
|
{variant === "text" &&
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
const { partIndex, setPartIndex } = useExamStore((state) => state);
|
const { partIndex, setPartIndex } = useExamStore((state) => state);
|
||||||
const { exerciseIndex, setExerciseIndex } = useExamStore((state) => state);
|
const { exerciseIndex, setExerciseIndex } = useExamStore((state) => state);
|
||||||
const [storeQuestionIndex, setStoreQuestionIndex] = useExamStore((state) => [state.questionIndex, state.setQuestionIndex]);
|
const [storeQuestionIndex, setStoreQuestionIndex] = useExamStore((state) => [state.questionIndex, state.setQuestionIndex]);
|
||||||
const [shuffleMaps, setShuffleMaps] = useExamStore((state) => [state.shuffleMaps, state.setShuffleMaps])
|
//const [shuffleMaps, setShuffleMaps] = useExamStore((state) => [state.shuffleMaps, state.setShuffleMaps])
|
||||||
const [currentExercise, setCurrentExercise] = useState<Exercise>();
|
const [currentExercise, setCurrentExercise] = useState<Exercise>();
|
||||||
|
|
||||||
const scrollToTop = () => Array.from(document.getElementsByTagName("body")).forEach((body) => body.scrollTo(0, 0));
|
const scrollToTop = () => Array.from(document.getElementsByTagName("body")).forEach((body) => body.scrollTo(0, 0));
|
||||||
@@ -180,11 +180,11 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
const [contextWord, setContextWord] = useState<string | undefined>(undefined);
|
const [contextWord, setContextWord] = useState<string | undefined>(undefined);
|
||||||
const [contextWordLine, setContextWordLine] = useState<number | undefined>(undefined);
|
const [contextWordLine, setContextWordLine] = useState<number | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
/*useEffect(() => {
|
||||||
if (showSolutions && userSolutions[exerciseIndex].shuffleMaps) {
|
if (showSolutions && userSolutions[exerciseIndex].shuffleMaps) {
|
||||||
setShuffleMaps(userSolutions[exerciseIndex].shuffleMaps as ShuffleMap[])
|
setShuffleMaps(userSolutions[exerciseIndex].shuffleMaps as ShuffleMap[])
|
||||||
}
|
}
|
||||||
}, [showSolutions])
|
}, [showSolutions])*/
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (hasExamEnded && exerciseIndex === -1) {
|
if (hasExamEnded && exerciseIndex === -1) {
|
||||||
@@ -214,8 +214,9 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
userSolutions: userSolutions.find((x) => x.exercise === exercise.id)?.solutions || [],
|
userSolutions: userSolutions.find((x) => x.exercise === exercise.id)?.solutions || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (exam.shuffle && exercise.type === "multipleChoice") {
|
/*if (exam.shuffle && exercise.type === "multipleChoice") {
|
||||||
if (shuffleMaps.length == 0 && !showSolutions) {
|
if (shuffleMaps.length == 0 && !showSolutions) {
|
||||||
|
console.log("Shuffling answers");
|
||||||
const newShuffleMaps: ShuffleMap[] = [];
|
const newShuffleMaps: ShuffleMap[] = [];
|
||||||
|
|
||||||
exercise.questions = exercise.questions.map(question => {
|
exercise.questions = exercise.questions.map(question => {
|
||||||
@@ -242,6 +243,7 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
|
|
||||||
setShuffleMaps(newShuffleMaps);
|
setShuffleMaps(newShuffleMaps);
|
||||||
} else {
|
} else {
|
||||||
|
console.log("Retrieving shuffles");
|
||||||
exercise.questions = exercise.questions.map(question => {
|
exercise.questions = exercise.questions.map(question => {
|
||||||
const questionShuffleMap = shuffleMaps.find(map => map.id === question.id);
|
const questionShuffleMap = shuffleMaps.find(map => map.id === question.id);
|
||||||
if (questionShuffleMap) {
|
if (questionShuffleMap) {
|
||||||
@@ -261,20 +263,21 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
exercise.words = exercise.words.map(word => {
|
exercise.words = exercise.words.map(word => {
|
||||||
if ('options' in word) {
|
if ('options' in word) {
|
||||||
const options = { ...word.options };
|
const options = { ...word.options };
|
||||||
const shuffledKeys = Object.keys(options).sort(() => Math.random() - 0.5);
|
const originalKeys = Object.keys(options);
|
||||||
|
const shuffledKeys = [...originalKeys].sort(() => Math.random() - 0.5);
|
||||||
|
|
||||||
const newOptions = shuffledKeys.reduce((acc, key, index) => {
|
const newOptions = shuffledKeys.reduce((acc, key, index) => {
|
||||||
acc[key as keyof typeof options] = options[shuffledKeys[index] as keyof typeof options];
|
acc[key as keyof typeof options] = options[originalKeys[index] as keyof typeof options];
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as { [key in keyof typeof options]: string });
|
}, {} as { [key in keyof typeof options]: string });
|
||||||
|
|
||||||
const optionMapping = shuffledKeys.reduce((acc, key, index) => {
|
const optionMapping = originalKeys.reduce((acc, key, index) => {
|
||||||
acc[key as keyof typeof options] = Object.keys(options)[index] as keyof typeof options;
|
acc[key as keyof typeof options] = shuffledKeys[index];
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as { [key in keyof typeof options]: string });
|
}, {} as { [key in keyof typeof options]: string });
|
||||||
|
|
||||||
newShuffleMaps.push({ id: word.id, map: optionMapping });
|
newShuffleMaps.push({ id: word.id, map: optionMapping });
|
||||||
|
|
||||||
return { ...word, options: newOptions };
|
return { ...word, options: newOptions };
|
||||||
}
|
}
|
||||||
return word;
|
return word;
|
||||||
@@ -283,20 +286,17 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
setShuffleMaps(newShuffleMaps);
|
setShuffleMaps(newShuffleMaps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return exercise;
|
return exercise;
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const newExercise = getExercise();
|
//console.log("Getting another exercise");
|
||||||
setCurrentExercise(newExercise);
|
//setShuffleMaps([]);
|
||||||
|
setCurrentExercise(getExercise());
|
||||||
}, [partIndex, exerciseIndex]);
|
}, [partIndex, exerciseIndex]);
|
||||||
|
|
||||||
|
|
||||||
//useShuffledMultipleChoiceOptions(currentExercise, exam.shuffle, storeQuestionIndex, shuffleMaps, setShuffleMaps, setCurrentExercise);
|
|
||||||
//useShuffledFillBlanksOptions(currentExercise, exam.shuffle, storeQuestionIndex, shuffleMaps, setShuffleMaps, setCurrentExercise);
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const regex = /.*?['"](.*?)['"] in line (\d+)\?$/;
|
const regex = /.*?['"](.*?)['"] in line (\d+)\?$/;
|
||||||
if (currentExercise && currentExercise.type === "multipleChoice") {
|
if (currentExercise && currentExercise.type === "multipleChoice") {
|
||||||
@@ -321,7 +321,7 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
setContextWord(undefined);
|
setContextWord(undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [storeQuestionIndex, contextWordLine, exerciseIndex, partIndex, shuffleMaps]);
|
}, [storeQuestionIndex, contextWordLine, exerciseIndex, partIndex]); //, shuffleMaps]);
|
||||||
|
|
||||||
const nextExercise = (solution?: UserSolution) => {
|
const nextExercise = (solution?: UserSolution) => {
|
||||||
scrollToTop();
|
scrollToTop();
|
||||||
@@ -362,9 +362,9 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
|
|||||||
|
|
||||||
if (solution) {
|
if (solution) {
|
||||||
let stat = { ...solution, module: "level" as Module, exam: exam.id }
|
let stat = { ...solution, module: "level" as Module, exam: exam.id }
|
||||||
if (exam.shuffle) {
|
/*if (exam.shuffle) {
|
||||||
stat.shuffleMaps = shuffleMaps
|
stat.shuffleMaps = shuffleMaps
|
||||||
}
|
}*/
|
||||||
onFinish([...userSolutions.filter((x) => x.exercise !== solution.exercise), { ...stat }]);
|
onFinish([...userSolutions.filter((x) => x.exercise !== solution.exercise), { ...stat }]);
|
||||||
} else {
|
} else {
|
||||||
onFinish(userSolutions);
|
onFinish(userSolutions);
|
||||||
|
|||||||
Reference in New Issue
Block a user