feat: multiple choice question must all be correct before next question (#432)

This commit is contained in:
Rotimi Best
2024-08-11 21:47:00 +01:00
committed by GitHub
parent 4c0288fd84
commit 7428b21a09
3 changed files with 46 additions and 21 deletions
@@ -25,6 +25,7 @@
nextStatusId: number; nextStatusId: number;
total: number; total: number;
}) => {}; }) => {};
export let isSaving = false;
const SELECTABLE_STATUS = [ const SELECTABLE_STATUS = [
{ {
@@ -128,7 +129,7 @@
'course.navItem.submissions.grading_modal.questions_tried' 'course.navItem.submissions.grading_modal.questions_tried'
)} ${answerPoints} ` )} ${answerPoints} `
}; };
data.questionAnswerByPoint[id] = `${points / answerPoints}`; data.questionAnswerByPoint[id] = `${Math.ceil(points / answerPoints)}`;
} else if (aiResponses.length) { } else if (aiResponses.length) {
const graded = aiResponses.find((res) => res.id === id); const graded = aiResponses.find((res) => res.id === id);
@@ -335,8 +336,9 @@
<PrimaryButton <PrimaryButton
onClick={() => { onClick={() => {
handleSave(data); handleSave(data);
onClose(); // onClose();
}} }}
isLoading={isSaving}
label={$t('course.navItem.submissions.grading_modal.submit_grades')} label={$t('course.navItem.submissions.grading_modal.submit_grades')}
variant={VARIANTS.CONTAINED} variant={VARIANTS.CONTAINED}
className="py-3 px-8 w-full" className="py-3 px-8 w-full"
@@ -5,6 +5,12 @@ export const isAnswerCorrect = (options, answer) => {
return options.some((option) => option.is_correct && option.value === answer); return options.some((option) => option.is_correct && option.value === answer);
}; };
/*
GRADING RULES
Textarea = no validation
Single = only one should be correct
Multiple = all should be correct
*/
export function wasCorrectAnswerSelected(currentQuestion, answers, isFinished) { export function wasCorrectAnswerSelected(currentQuestion, answers, isFinished) {
if (currentQuestion.question_type.id === QUESTION_TYPE.TEXTAREA) { if (currentQuestion.question_type.id === QUESTION_TYPE.TEXTAREA) {
return true; return true;
@@ -13,15 +19,20 @@ export function wasCorrectAnswerSelected(currentQuestion, answers, isFinished) {
const answer = answers[currentQuestion.name]; const answer = answers[currentQuestion.name];
const formattedAnswers = typeof answer === 'string' ? [answer] : answer; const formattedAnswers = typeof answer === 'string' ? [answer] : answer;
const isCorrect =
formattedAnswers &&
formattedAnswers.some((answer) => {
if (isAnswerCorrect(currentQuestion.options, answer)) {
return true;
}
return false; let isCorrect = false;
});
if (currentQuestion.question_type.id === QUESTION_TYPE.CHECKBOX) {
// Every correct answer should be in the selected answer
isCorrect = currentQuestion.options
.filter((o) => o.is_correct)
.every((option) => formattedAnswers?.includes(option.value));
} else if (currentQuestion.question_type.id === QUESTION_TYPE.RADIO) {
// At least one correct answer should be selected
isCorrect = formattedAnswers?.some((answer) =>
isAnswerCorrect(currentQuestion.options, answer)
);
}
if (isCorrect && !isFinished) { if (isCorrect && !isFinished) {
toggleConfetti(); toggleConfetti();
@@ -47,6 +47,7 @@
let openExercise = false; let openExercise = false;
let isGradeWithAI = false; let isGradeWithAI = false;
let fetching = false; let fetching = false;
let isSaving = false;
const submissionStatus: { [key: number]: string } = { const submissionStatus: { [key: number]: string } = {
1: $t('course.navItem.submissions.submission_status.submitted'), 1: $t('course.navItem.submissions.submission_status.submitted'),
@@ -243,30 +244,40 @@
questionAnswers: any; questionAnswers: any;
feedback: any; feedback: any;
}) { }) {
isSaving = true;
const { questionAnswerByPoint, questionAnswers, feedback } = submission; const { questionAnswerByPoint, questionAnswers, feedback } = submission;
let totalPoints = 0; let totalPoints = 0;
const updates = Object.keys(questionAnswerByPoint).map((questionId) => { for (const questionId in questionAnswerByPoint) {
const questionAnswer = questionAnswers.find( if (Object.prototype.hasOwnProperty.call(questionAnswerByPoint, questionId)) {
(answer: { question_id: string }) => answer.question_id == questionId const questionAnswer = questionAnswers.find(
); (answer: { question_id: string }) => answer.question_id == questionId
const point = questionAnswerByPoint[questionId]; );
const point = questionAnswerByPoint[questionId];
totalPoints += parseInt(point, 10); totalPoints += parseInt(point, 10);
return updateQuestionAnswer({ point }, { id: questionAnswer?.id }); const qaResponse = await updateQuestionAnswer({ point }, { id: questionAnswer?.id });
});
updateSubmission({ if (qaResponse.error) {
console.error('Error saving', qaResponse.error);
snackbar.error(`snackbar.something`);
return;
}
}
}
await updateSubmission({
id: submissionId, id: submissionId,
total: totalPoints, total: totalPoints,
feedback: feedback feedback: feedback
}).then((res) => console.log('Updated submission', res)); });
snackbar.success('snackbar.submissions.success.grading'); snackbar.success('snackbar.submissions.success.grading');
await Promise.all(updates); isSaving = false;
} }
async function firstRender(courseId: string) { async function firstRender(courseId: string) {
@@ -354,6 +365,7 @@
{updateStatus} {updateStatus}
deleteSubmission={handleDeleteSubmission} deleteSubmission={handleDeleteSubmission}
bind:isGradeWithAI bind:isGradeWithAI
{isSaving}
/> />
<CourseContainer bind:courseId={data.courseId}> <CourseContainer bind:courseId={data.courseId}>