feat: add multi choice submission logic

This commit is contained in:
2026-08-21 10:25:33 +03:30
parent ca88e6994e
commit 2e146e52b5
12 changed files with 262 additions and 22 deletions
@@ -147,6 +147,15 @@ export class AnswerAuthenticatedProvider {
}
submissionAnswer.choice = choice;
} else if (
currentQuestion.type === QuestionType.MULTI_CHOICE &&
answerSubmissionDto.choiceIds !== undefined
) {
const choices = currentQuestion.choices.filter((el) =>
answerSubmissionDto.choiceIds?.includes(el.id),
);
submissionAnswer.choices = choices;
} else if (
currentQuestion.type === QuestionType.NUMERIC &&
answerSubmissionDto.numericValue !== undefined
@@ -56,7 +56,7 @@ export class AnswerGuestProvider {
}
try {
return this.answerGuest(id, answerSubmissionDto);
return await this.answerGuest(id, answerSubmissionDto);
} finally {
await this.redisService.releaseLock(lockKey, lockToken);
}
@@ -142,6 +142,15 @@ export class AnswerGuestProvider {
}
newAnswer.choiceId = choice.id;
} else if (
currentQuestion.type === QuestionType.MULTI_CHOICE &&
answerSubmissionDto.choiceIds !== undefined
) {
const choiceIds = currentQuestion.choices
.filter((el) => answerSubmissionDto.choiceIds?.includes(el.id))
.map((el) => el.id);
newAnswer.choiceIds = [...new Set(choiceIds)].sort((a, b) => a - b);
} else if (
currentQuestion.type === QuestionType.NUMERIC &&
answerSubmissionDto.numericValue !== undefined
@@ -47,6 +47,7 @@ export class CalculateResultProvider {
rangeRules: true,
},
choice: true,
choices: true,
},
});
} catch (err) {
@@ -59,6 +60,8 @@ export class CalculateResultProvider {
question: answer.question,
choiceId: answer.choice?.id,
choice: answer.choice,
choiceIds: answer.choices?.map((choice) => choice.id),
choices: answer.choices,
numericValue: answer.numericValue,
})),
async (questionIds) =>
@@ -105,6 +108,7 @@ export class CalculateResultProvider {
submission.answers.map((answer) => ({
questionId: answer.questionId,
choiceId: answer.choiceId,
choiceIds: answer.choiceIds,
numericValue: answer.numericValue,
})),
async (questionIds) =>
@@ -141,6 +145,8 @@ export class CalculateResultProvider {
question?: Question;
choiceId?: number;
choice?: { id: number; score: number };
choiceIds?: Array<number>;
choices?: Array<{ id: number; score: number }>;
numericValue?: number;
}>,
loadQuestions: (questionIds: number[]) => Promise<Question[]>,
@@ -172,6 +178,22 @@ export class CalculateResultProvider {
if (choice) {
score += question.weight * choice.score;
}
} else if (
question.type === QuestionType.MULTI_CHOICE &&
answer.choiceIds !== undefined
) {
const selectedChoiceIds = new Set(answer.choiceIds);
const selectedChoices =
answer.choices ??
question.choices.filter((choice) => selectedChoiceIds.has(choice.id));
const multiChoiceScore = selectedChoices.reduce(
(sum, choice) => sum + choice.score,
0,
);
score += question.weight * multiChoiceScore;
} else if (
question.type === QuestionType.NUMERIC &&
answer.numericValue !== undefined
@@ -190,25 +212,31 @@ export class CalculateResultProvider {
let totalScores = 0;
questions.forEach((question) => {
const answerScores: number[] = [];
if (question.type === QuestionType.SINGLE_CHOICE) {
question.choices.forEach((choice) => {
answerScores.push(choice.score);
});
const maxScore =
question.choices.length > 0
? Math.max(...question.choices.map((choice) => choice.score))
: 0;
totalScores += question.weight * maxScore;
} else if (question.type === QuestionType.MULTI_CHOICE) {
const maxScore = question.choices.reduce(
(sum, choice) => sum + choice.score,
0,
);
totalScores += question.weight * maxScore;
} else if (
question.type === QuestionType.NUMERIC &&
question.rangeRules &&
question.rangeRules.length > 0
) {
question.rangeRules.forEach((rule) => {
answerScores.push(rule.score);
});
const maxScore = Math.max(
...question.rangeRules.map((rule) => rule.score),
);
totalScores += question.weight * maxScore;
}
const maxScore = answerScores.length > 0 ? Math.max(...answerScores) : 0;
totalScores += question.weight * maxScore;
});
const resultRanges = await loadResultRanges(score);