feat: change answer submission architecture
This commit is contained in:
@@ -1,9 +1,4 @@
|
||||
import {
|
||||
BadRequestException,
|
||||
ForbiddenException,
|
||||
HttpStatus,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { BadRequestException, HttpStatus, Injectable } from '@nestjs/common';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Submission } from '../entities/submission.entity';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
@@ -21,6 +16,8 @@ import { NumericMetadata } from '@/modules/questions/interfaces/numeric-metadata
|
||||
import { SubmissionAnswer } from '../entities/submission-answer.entity';
|
||||
import { ChoicesService } from '@/modules/questions/providers/choices.service';
|
||||
import { CalculateResultProvider } from './calculate-result.provider';
|
||||
import { QuestionsService } from '@/modules/questions/providers/questions.service';
|
||||
import { SubmissionResult } from '../entities/submission-result.entity';
|
||||
|
||||
@Injectable()
|
||||
export class AnswerSubmissionProvider {
|
||||
@@ -42,6 +39,17 @@ export class AnswerSubmissionProvider {
|
||||
@InjectRepository(SubmissionAnswer)
|
||||
private readonly submissionAnswerRepository: Repository<SubmissionAnswer>,
|
||||
|
||||
/**
|
||||
* Inject SubmissionResult Repository
|
||||
*/
|
||||
@InjectRepository(SubmissionResult)
|
||||
private readonly submissionResultRepository: Repository<SubmissionResult>,
|
||||
|
||||
/**
|
||||
* Inject Questions Service
|
||||
*/
|
||||
private readonly questionsService: QuestionsService,
|
||||
|
||||
/**
|
||||
* Inject Choices Service
|
||||
*/
|
||||
@@ -84,35 +92,9 @@ export class AnswerSubmissionProvider {
|
||||
|
||||
try {
|
||||
submission = await this.submissionRepository.findOne({
|
||||
where: { id: submissionId },
|
||||
where: { id: submissionId, user: { id: user.id } },
|
||||
relations: {
|
||||
user: true,
|
||||
test: {
|
||||
questions: {
|
||||
choices: true,
|
||||
rangeRules: true,
|
||||
},
|
||||
},
|
||||
answers: {
|
||||
question: true,
|
||||
},
|
||||
result: {
|
||||
resultRange: true,
|
||||
},
|
||||
},
|
||||
order: {
|
||||
answers: {
|
||||
question: {
|
||||
order: 'ASC',
|
||||
},
|
||||
},
|
||||
test: {
|
||||
questions: {
|
||||
choices: {
|
||||
order: 'ASC',
|
||||
},
|
||||
},
|
||||
},
|
||||
test: true,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -127,44 +109,69 @@ export class AnswerSubmissionProvider {
|
||||
);
|
||||
}
|
||||
|
||||
if (submission.user.id !== user.id) {
|
||||
throw new ForbiddenException('auth.errors.accessDenied');
|
||||
}
|
||||
// if (submission.user.id !== user.id) {
|
||||
// throw new ForbiddenException('auth.errors.accessDenied');
|
||||
// }
|
||||
|
||||
const allQuestions = [...submission.test.questions].sort(
|
||||
(a, b) => a.order - b.order,
|
||||
);
|
||||
const answeredQuestions = submission.answers.map((el) => el.question);
|
||||
// const allQuestions = [...submission.test.questions].sort(
|
||||
// (a, b) => a.order - b.order,
|
||||
// );
|
||||
// const answeredQuestions = submission.answers.map((el) => el.question);
|
||||
|
||||
const questionStats = this.getQuestionStats(
|
||||
allQuestions,
|
||||
answeredQuestions,
|
||||
);
|
||||
// const questionStats = this.getQuestionStats(
|
||||
// allQuestions,
|
||||
// answeredQuestions,
|
||||
// );
|
||||
|
||||
const currentQuestion: Question | null =
|
||||
await this.questionsService.findOneForAdmin({
|
||||
where: {
|
||||
test: { id: submission.test.id },
|
||||
order: submission.currentQuestionOrder,
|
||||
},
|
||||
relations: {
|
||||
choices: true,
|
||||
rangeRules: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!currentQuestion) {
|
||||
let result: SubmissionResult | null;
|
||||
|
||||
try {
|
||||
result = await this.submissionResultRepository.findOne({
|
||||
where: { submission: { id: submission.id } },
|
||||
relations: {
|
||||
resultRange: true,
|
||||
},
|
||||
});
|
||||
} catch (err) {
|
||||
throw new AppTimeoutException(err);
|
||||
}
|
||||
|
||||
if (!questionStats.current) {
|
||||
return new AppResponse({
|
||||
isCompleted: true,
|
||||
currentQuestion: null,
|
||||
result: submission.result
|
||||
result: result
|
||||
? {
|
||||
score: submission.result.score,
|
||||
probability: submission.result.probability,
|
||||
title: submission.result.resultRange?.title,
|
||||
description: submission.result.resultRange?.description,
|
||||
score: result.score,
|
||||
probability: result.probability,
|
||||
title: result.resultRange?.title,
|
||||
description: result.resultRange?.description,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
}
|
||||
|
||||
this.checkAnswerCorrectness(questionStats.current, answerSubmissionDto);
|
||||
this.checkAnswerCorrectness(currentQuestion, answerSubmissionDto);
|
||||
|
||||
const submissionAnswer = this.submissionAnswerRepository.create({
|
||||
submission,
|
||||
question: questionStats.current,
|
||||
question: currentQuestion,
|
||||
});
|
||||
|
||||
if (
|
||||
questionStats.current.type === QuestionType.MULTI_CHOICE &&
|
||||
currentQuestion.type === QuestionType.MULTI_CHOICE &&
|
||||
answerSubmissionDto.choiceId
|
||||
) {
|
||||
const choice = await this.choicesService.findOneForAdmin(
|
||||
@@ -181,7 +188,7 @@ export class AnswerSubmissionProvider {
|
||||
|
||||
submissionAnswer.choice = choice;
|
||||
} else if (
|
||||
questionStats.current.type === QuestionType.NUMERIC &&
|
||||
currentQuestion.type === QuestionType.NUMERIC &&
|
||||
answerSubmissionDto.numericValue
|
||||
) {
|
||||
submissionAnswer.numericValue = answerSubmissionDto.numericValue;
|
||||
@@ -193,7 +200,19 @@ export class AnswerSubmissionProvider {
|
||||
throw new AppTimeoutException(err);
|
||||
}
|
||||
|
||||
if (!questionStats.next) {
|
||||
const nextQuestion: Question | null =
|
||||
await this.questionsService.findOneForAdmin({
|
||||
where: {
|
||||
test: { id: submission.test.id },
|
||||
order: submission.currentQuestionOrder + 1,
|
||||
},
|
||||
relations: {
|
||||
choices: true,
|
||||
rangeRules: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!nextQuestion) {
|
||||
const result = await this.calculateResultProvider.calculate(submission);
|
||||
return new AppResponse({
|
||||
isCompleted: true,
|
||||
@@ -202,14 +221,9 @@ export class AnswerSubmissionProvider {
|
||||
});
|
||||
}
|
||||
|
||||
const nextQuestion = questionStats.next;
|
||||
|
||||
return new AppResponse({
|
||||
isCompleted: false,
|
||||
isFinal:
|
||||
nextQuestion.id === allQuestions[allQuestions.length - 1].id
|
||||
? true
|
||||
: undefined,
|
||||
// isFinal: ,
|
||||
currentQuestion: {
|
||||
type: nextQuestion.type,
|
||||
content: nextQuestion.content,
|
||||
|
||||
Reference in New Issue
Block a user