diff --git a/src/addons/qbehaviour/deferredcbm/services/handlers/deferredcbm.ts b/src/addons/qbehaviour/deferredcbm/services/handlers/deferredcbm.ts index f7eabd3ea02..03337eb1447 100644 --- a/src/addons/qbehaviour/deferredcbm/services/handlers/deferredcbm.ts +++ b/src/addons/qbehaviour/deferredcbm/services/handlers/deferredcbm.ts @@ -21,6 +21,7 @@ import { CoreQuestionQuestionParsed, CoreQuestionsAnswers, CoreQuestionState } f import { CoreQuestionHelper } from '@features/question/services/question-helper'; import { AddonQbehaviourDeferredCBMComponent } from '../../component/deferredcbm'; import { CoreQuestionDelegate } from '@features/question/services/question-delegate'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support deferred CBM question behaviour. @@ -89,12 +90,12 @@ export class AddonQbehaviourDeferredCBMHandlerService implements CoreQuestionBeh answers: CoreQuestionsAnswers, component: string, componentId: string | number, - ): number { + ): QuestionCompleteGradableResponse { // First check if the question answer is complete. const complete = CoreQuestionDelegate.isCompleteResponse(question, answers, component, componentId); if (complete > 0) { // Answer is complete, check the user answered CBM too. - return answers['-certainty'] ? 1 : 0; + return answers['-certainty'] ? QuestionCompleteGradableResponse.YES : QuestionCompleteGradableResponse.NO; } return complete; diff --git a/src/addons/qbehaviour/deferredfeedback/services/handlers/deferredfeedback.ts b/src/addons/qbehaviour/deferredfeedback/services/handlers/deferredfeedback.ts index c0cc4ab2364..477f1804673 100644 --- a/src/addons/qbehaviour/deferredfeedback/services/handlers/deferredfeedback.ts +++ b/src/addons/qbehaviour/deferredfeedback/services/handlers/deferredfeedback.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; import { CoreQuestionBehaviourHandler, CoreQuestionQuestionWithAnswers } from '@features/question/services/behaviour-delegate'; import { CoreQuestionDBRecord } from '@features/question/services/database/question'; @@ -134,7 +135,7 @@ export class AddonQbehaviourDeferredFeedbackHandlerService implements CoreQuesti } // Answers have changed. Now check if the response is complete and calculate the new state. - let complete: number; + let complete: QuestionCompleteGradableResponse; let newState: string; if (isCompleteFn) { @@ -190,7 +191,7 @@ export type isCompleteResponseFunction = ( answers: CoreQuestionsAnswers, component: string, componentId: string | number, -) => number; +) => QuestionCompleteGradableResponse; /** * Check if two responses are the same. diff --git a/src/addons/qtype/calculatedmulti/services/handlers/calculatedmulti.ts b/src/addons/qtype/calculatedmulti/services/handlers/calculatedmulti.ts index 9ef004135dd..f436f232906 100644 --- a/src/addons/qtype/calculatedmulti/services/handlers/calculatedmulti.ts +++ b/src/addons/qtype/calculatedmulti/services/handlers/calculatedmulti.ts @@ -18,6 +18,7 @@ import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/ques import { CoreQuestionHandler } from '@features/question/services/question-delegate'; import { makeSingleton } from '@singletons'; import { AddonQtypeMultichoiceHandler } from '@addons/qtype/multichoice/services/handlers/multichoice'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support calculated multi question type. @@ -44,7 +45,7 @@ export class AddonQtypeCalculatedMultiHandlerService implements CoreQuestionHand isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // This question type depends on multichoice. return AddonQtypeMultichoiceHandler.isCompleteResponseSingle(answers); } @@ -62,7 +63,7 @@ export class AddonQtypeCalculatedMultiHandlerService implements CoreQuestionHand isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // This question type depends on multichoice. return AddonQtypeMultichoiceHandler.isGradableResponseSingle(answers); } diff --git a/src/addons/qtype/ddimageortext/services/handlers/ddimageortext.ts b/src/addons/qtype/ddimageortext/services/handlers/ddimageortext.ts index 835dfd37fbf..22f2be6416c 100644 --- a/src/addons/qtype/ddimageortext/services/handlers/ddimageortext.ts +++ b/src/addons/qtype/ddimageortext/services/handlers/ddimageortext.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Injectable, Type } from '@angular/core'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; import { CoreQuestion, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; @@ -53,17 +54,17 @@ export class AddonQtypeDdImageOrTextHandlerService implements CoreQuestionHandle isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // An answer is complete if all drop zones have an answer. // We should always receive all the drop zones with their value ('' if not answered). for (const name in answers) { const value = answers[name]; if (!value || value === '0') { - return 0; + return QuestionCompleteGradableResponse.NO; } } - return 1; + return QuestionCompleteGradableResponse.YES; } /** @@ -79,15 +80,15 @@ export class AddonQtypeDdImageOrTextHandlerService implements CoreQuestionHandle isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse{ for (const name in answers) { const value = answers[name]; if (value && value !== '0') { - return 1; + return QuestionCompleteGradableResponse.YES; } } - return 0; + return QuestionCompleteGradableResponse.NO; } /** @@ -108,7 +109,7 @@ export class AddonQtypeDdImageOrTextHandlerService implements CoreQuestionHandle question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isCompleteResponse(question, answers)) { + if (this.isCompleteResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/ddmarker/services/handlers/ddmarker.ts b/src/addons/qtype/ddmarker/services/handlers/ddmarker.ts index c8453e83623..38754da8a62 100644 --- a/src/addons/qtype/ddmarker/services/handlers/ddmarker.ts +++ b/src/addons/qtype/ddmarker/services/handlers/ddmarker.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Injectable, Type } from '@angular/core'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; import { CoreQuestion, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; @@ -55,15 +56,15 @@ export class AddonQtypeDdMarkerHandlerService implements CoreQuestionHandler { isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // If 1 dragitem is set we assume the answer is complete (like Moodle does). for (const name in answers) { if (name !== ':sequencecheck' && answers[name]) { - return 1; + return QuestionCompleteGradableResponse.YES; } } - return 0; + return QuestionCompleteGradableResponse.NO; } /** @@ -79,7 +80,7 @@ export class AddonQtypeDdMarkerHandlerService implements CoreQuestionHandler { isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { return this.isCompleteResponse(question, answers); } @@ -119,7 +120,7 @@ export class AddonQtypeDdMarkerHandlerService implements CoreQuestionHandler { question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isCompleteResponse(question, answers)) { + if (this.isCompleteResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/essay/services/handlers/essay.ts b/src/addons/qtype/essay/services/handlers/essay.ts index 45e3053e48d..64d62d75837 100644 --- a/src/addons/qtype/essay/services/handlers/essay.ts +++ b/src/addons/qtype/essay/services/handlers/essay.ts @@ -28,6 +28,7 @@ import { CoreObject } from '@singletons/object'; import { CoreWSFile } from '@services/ws'; import { makeSingleton, Translate } from '@singletons'; import { CoreFileHelper } from '@services/file-helper'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support essay question type. @@ -150,7 +151,8 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { return; } - if (this.isCompleteResponse(question, answers, component, componentId)) { + // Continue check in case the response completion cannot be determined. + if (this.isCompleteResponse(question, answers, component, componentId) === QuestionCompleteGradableResponse.YES) { return; } @@ -201,34 +203,38 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { answers: CoreQuestionsAnswers, component: string, componentId: string | number, - ): number { + ): QuestionCompleteGradableResponse { const hasTextAnswer = !!answers.answer; const uploadFilesSupported = question.responsefileareas !== undefined; const allowedOptions = this.getAllowedOptions(question); if (hasTextAnswer && this.checkInputWordCount(question, answers.answer, undefined)) { - return 0; + return QuestionCompleteGradableResponse.NO; } if (!allowedOptions.attachments) { - return hasTextAnswer ? 1 : 0; + return hasTextAnswer ? QuestionCompleteGradableResponse.YES : QuestionCompleteGradableResponse.NO; } if (!uploadFilesSupported || !question.parsedSettings) { // We can't know if the attachments are required or if the user added any in web. - return -1; + return QuestionCompleteGradableResponse.UNKNOWN; } const questionComponentId = CoreQuestion.getQuestionComponentId(question, componentId); const attachments = CoreFileSession.getFiles(component, questionComponentId); if (!allowedOptions.text) { - return attachments && attachments.length >= Number(question.parsedSettings.attachmentsrequired) ? 1 : 0; + return attachments && attachments.length >= Number(question.parsedSettings.attachmentsrequired) + ? QuestionCompleteGradableResponse.YES + : QuestionCompleteGradableResponse.NO; } return ((hasTextAnswer || question.parsedSettings.responserequired === '0') && - (attachments && attachments.length >= Number(question.parsedSettings.attachmentsrequired))) ? 1 : 0; + (attachments && attachments.length >= Number(question.parsedSettings.attachmentsrequired))) + ? QuestionCompleteGradableResponse.YES + : QuestionCompleteGradableResponse.NO; } /** @@ -246,16 +252,18 @@ export class AddonQtypeEssayHandlerService implements CoreQuestionHandler { answers: CoreQuestionsAnswers, component: string, componentId: string | number, - ): number { + ): QuestionCompleteGradableResponse { if (question.responsefileareas === undefined) { - return -1; + return QuestionCompleteGradableResponse.UNKNOWN; } const questionComponentId = CoreQuestion.getQuestionComponentId(question, componentId); const attachments = CoreFileSession.getFiles(component, questionComponentId); // Determine if the given response has online text or attachments. - return (answers.answer && answers.answer !== '') || (attachments && attachments.length > 0) ? 1 : 0; + return (answers.answer && answers.answer !== '') || (attachments && attachments.length > 0) + ? QuestionCompleteGradableResponse.YES + : QuestionCompleteGradableResponse.NO; } /** diff --git a/src/addons/qtype/gapselect/services/handlers/gapselect.ts b/src/addons/qtype/gapselect/services/handlers/gapselect.ts index 3c2e3e53070..bcb06a93f2c 100644 --- a/src/addons/qtype/gapselect/services/handlers/gapselect.ts +++ b/src/addons/qtype/gapselect/services/handlers/gapselect.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Injectable, Type } from '@angular/core'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; import { CoreQuestion, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; @@ -53,16 +54,16 @@ export class AddonQtypeGapSelectHandlerService implements CoreQuestionHandler { isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // We should always get a value for each select so we can assume we receive all the possible answers. for (const name in answers) { const value = answers[name]; if (!value || value === '0') { - return 0; + return QuestionCompleteGradableResponse.NO; } } - return 1; + return QuestionCompleteGradableResponse.YES; } /** @@ -78,16 +79,16 @@ export class AddonQtypeGapSelectHandlerService implements CoreQuestionHandler { isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // We should always get a value for each select so we can assume we receive all the possible answers. for (const name in answers) { const value = answers[name]; if (value && value !== '0') { - return 1; + return QuestionCompleteGradableResponse.YES; } } - return 0; + return QuestionCompleteGradableResponse.NO; } /** @@ -108,7 +109,7 @@ export class AddonQtypeGapSelectHandlerService implements CoreQuestionHandler { question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isCompleteResponse(question, answers)) { + if (this.isCompleteResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/match/services/handlers/match.ts b/src/addons/qtype/match/services/handlers/match.ts index 7feb1675a7f..88f64304507 100644 --- a/src/addons/qtype/match/services/handlers/match.ts +++ b/src/addons/qtype/match/services/handlers/match.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Injectable, Type } from '@angular/core'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; import { CoreQuestion, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; @@ -53,16 +54,16 @@ export class AddonQtypeMatchHandlerService implements CoreQuestionHandler { isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // We should always get a value for each select so we can assume we receive all the possible answers. for (const name in answers) { const value = answers[name]; if (!value || value === '0') { - return 0; + return QuestionCompleteGradableResponse.NO; } } - return 1; + return QuestionCompleteGradableResponse.YES; } /** @@ -78,16 +79,16 @@ export class AddonQtypeMatchHandlerService implements CoreQuestionHandler { isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // We should always get a value for each select so we can assume we receive all the possible answers. for (const name in answers) { const value = answers[name]; if (value && value !== '0') { - return 1; + return QuestionCompleteGradableResponse.YES; } } - return 0; + return QuestionCompleteGradableResponse.NO; } /** @@ -108,7 +109,7 @@ export class AddonQtypeMatchHandlerService implements CoreQuestionHandler { question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isCompleteResponse(question, answers)) { + if (this.isCompleteResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/multianswer/services/handlers/multianswer.ts b/src/addons/qtype/multianswer/services/handlers/multianswer.ts index 5755722ff7a..8babbaa67b2 100644 --- a/src/addons/qtype/multianswer/services/handlers/multianswer.ts +++ b/src/addons/qtype/multianswer/services/handlers/multianswer.ts @@ -13,6 +13,7 @@ // limitations under the License. import { Injectable, Type } from '@angular/core'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; import { CoreQuestion, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreQuestionHandler } from '@features/question/services/question-delegate'; @@ -54,7 +55,7 @@ export class AddonQtypeMultiAnswerHandlerService implements CoreQuestionHandler isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // Get all the inputs in the question to check if they've all been answered. const names = CoreQuestion.getBasicAnswers( CoreQuestionHelper.getAllInputNamesFromHtml(question.html || ''), @@ -62,11 +63,11 @@ export class AddonQtypeMultiAnswerHandlerService implements CoreQuestionHandler for (const name in names) { const value = answers[name]; if (!value) { - return 0; + return QuestionCompleteGradableResponse.NO; } } - return 1; + return QuestionCompleteGradableResponse.YES; } /** @@ -82,16 +83,16 @@ export class AddonQtypeMultiAnswerHandlerService implements CoreQuestionHandler isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { // We should always get a value for each select so we can assume we receive all the possible answers. for (const name in answers) { const value = answers[name]; if (value || value === false) { - return 1; + return QuestionCompleteGradableResponse.YES; } } - return 0; + return QuestionCompleteGradableResponse.NO; } /** @@ -130,7 +131,7 @@ export class AddonQtypeMultiAnswerHandlerService implements CoreQuestionHandler question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isCompleteResponse(question, answers)) { + if (this.isCompleteResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/multichoice/services/handlers/multichoice.ts b/src/addons/qtype/multichoice/services/handlers/multichoice.ts index 8f8cfda7e64..5c39ac184f4 100644 --- a/src/addons/qtype/multichoice/services/handlers/multichoice.ts +++ b/src/addons/qtype/multichoice/services/handlers/multichoice.ts @@ -20,6 +20,7 @@ import { CoreQuestionHandler } from '@features/question/services/question-delega import { CoreObject } from '@singletons/object'; import { makeSingleton, Translate } from '@singletons'; import { CoreUtils } from '@singletons/utils'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support multichoice question type. @@ -45,7 +46,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { let isSingle = true; let isMultiComplete = false; @@ -64,7 +65,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler return this.isCompleteResponseSingle(answers); } else { // Multi. - return isMultiComplete ? 1 : 0; + return isMultiComplete ? QuestionCompleteGradableResponse.YES : QuestionCompleteGradableResponse.NO; } } @@ -74,8 +75,10 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler * @param answers The question answers (without prefix). * @returns 1 if complete, 0 if not complete, -1 if cannot determine. */ - isCompleteResponseSingle(answers: CoreQuestionsAnswers): number { - return (answers.answer && answers.answer !== '') ? 1 : 0; + isCompleteResponseSingle(answers: CoreQuestionsAnswers): QuestionCompleteGradableResponse { + return (answers.answer && answers.answer !== '') + ? QuestionCompleteGradableResponse.YES + : QuestionCompleteGradableResponse.NO; } /** @@ -91,7 +94,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { return this.isCompleteResponse(question, answers); } @@ -102,7 +105,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler * @param answers Object with the question answers (without prefix). * @returns 1 if gradable, 0 if not gradable, -1 if cannot determine. */ - isGradableResponseSingle(answers: CoreQuestionsAnswers): number { + isGradableResponseSingle(answers: CoreQuestionsAnswers): QuestionCompleteGradableResponse { return this.isCompleteResponseSingle(answers); } @@ -168,7 +171,7 @@ export class AddonQtypeMultichoiceHandlerService implements CoreQuestionHandler question: AddonModQuizMultichoiceQuestion, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isGradableResponse(question, answers)) { + if (this.isGradableResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/numerical/services/handlers/numerical.ts b/src/addons/qtype/numerical/services/handlers/numerical.ts index d54c28a27ab..496d702f9e3 100644 --- a/src/addons/qtype/numerical/services/handlers/numerical.ts +++ b/src/addons/qtype/numerical/services/handlers/numerical.ts @@ -18,6 +18,7 @@ import { makeSingleton, Translate } from '@singletons'; import { convertTextToHTMLElement } from '@/core/utils/create-html-element'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { CoreObject } from '@singletons/object'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support numerical question type. @@ -68,43 +69,45 @@ export class AddonQtypeNumericalHandlerService implements CoreQuestionHandler { isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { if (!this.isGradableResponse(question, answers)) { - return 0; + return QuestionCompleteGradableResponse.NO; } const { answer, unit } = this.parseAnswer(question, answers.answer); if (answer === null) { - return 0; + return QuestionCompleteGradableResponse.NO; } if (!question.parsedSettings) { if (this.hasSeparateUnitField(question)) { - return this.isValidValue( answers.unit) ? 1 : 0; + return this.isValidValue( answers.unit) + ? QuestionCompleteGradableResponse.YES + : QuestionCompleteGradableResponse.NO; } // We cannot know if the answer should contain units or not. - return -1; + return QuestionCompleteGradableResponse.UNKNOWN; } if (question.parsedSettings.unitdisplay !== AddonQtypeNumericalHandlerService.UNITINPUT && unit) { // There should be no units or be outside of the input, not valid. - return 0; + return QuestionCompleteGradableResponse.NO; } if (this.hasSeparateUnitField(question) && !this.isValidValue( answers.unit)) { // Unit not supplied as a separate field and it's required. - return 0; + return QuestionCompleteGradableResponse.NO; } if (question.parsedSettings.unitdisplay === AddonQtypeNumericalHandlerService.UNITINPUT && question.parsedSettings.unitgradingtype === AddonQtypeNumericalHandlerService.UNITGRADED && !this.isValidValue(unit)) { // Unit not supplied inside the input and it's required. - return 0; + return QuestionCompleteGradableResponse.NO; } - return 1; + return QuestionCompleteGradableResponse.YES; } /** @@ -120,8 +123,10 @@ export class AddonQtypeNumericalHandlerService implements CoreQuestionHandler { isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { - return this.isValidValue( answers.answer) ? 1 : 0; + ): QuestionCompleteGradableResponse { + return this.isValidValue( answers.answer) + ? QuestionCompleteGradableResponse.YES + : QuestionCompleteGradableResponse.NO; } /** @@ -207,7 +212,7 @@ export class AddonQtypeNumericalHandlerService implements CoreQuestionHandler { question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (!this.isGradableResponse(question, answers)) { + if (this.isGradableResponse(question, answers) === QuestionCompleteGradableResponse.NO) { return Translate.instant('addon.qtype_numerical.pleaseenterananswer'); } diff --git a/src/addons/qtype/ordering/services/handlers/ordering.ts b/src/addons/qtype/ordering/services/handlers/ordering.ts index 2ff30b451a5..8d344b5ee93 100644 --- a/src/addons/qtype/ordering/services/handlers/ordering.ts +++ b/src/addons/qtype/ordering/services/handlers/ordering.ts @@ -17,6 +17,7 @@ import { CoreQuestionHandler } from '@features/question/services/question-delega import { CoreQuestion, CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/question/services/question'; import { makeSingleton } from '@singletons'; import { CoreSites } from '@services/sites'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support ordering question type. @@ -39,8 +40,8 @@ export class AddonQtypeOrderingHandlerService implements CoreQuestionHandler { /** * @inheritdoc */ - isCompleteResponse(): number { - return 1; + isCompleteResponse(): QuestionCompleteGradableResponse { + return QuestionCompleteGradableResponse.YES; } /** @@ -53,8 +54,8 @@ export class AddonQtypeOrderingHandlerService implements CoreQuestionHandler { /** * @inheritdoc */ - isGradableResponse(): number { - return 1; + isGradableResponse(): QuestionCompleteGradableResponse { + return QuestionCompleteGradableResponse.YES; } /** diff --git a/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts b/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts index 3055ff458ca..489af9a8b5a 100644 --- a/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts +++ b/src/addons/qtype/shortanswer/services/handlers/shortanswer.ts @@ -18,6 +18,7 @@ import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/ques import { CoreQuestionHandler } from '@features/question/services/question-delegate'; import { CoreObject } from '@singletons/object'; import { makeSingleton, Translate } from '@singletons'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support short answer question type. @@ -43,8 +44,8 @@ export class AddonQtypeShortAnswerHandlerService implements CoreQuestionHandler isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { - return answers.answer ? 1 : 0; + ): QuestionCompleteGradableResponse { + return answers.answer ? QuestionCompleteGradableResponse.YES : QuestionCompleteGradableResponse.NO; } /** @@ -60,7 +61,7 @@ export class AddonQtypeShortAnswerHandlerService implements CoreQuestionHandler isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { return this.isCompleteResponse(question, answers); } @@ -82,7 +83,7 @@ export class AddonQtypeShortAnswerHandlerService implements CoreQuestionHandler question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isGradableResponse(question, answers)) { + if (this.isGradableResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/addons/qtype/truefalse/services/handlers/truefalse.ts b/src/addons/qtype/truefalse/services/handlers/truefalse.ts index 24a05d9de16..ff686c8566d 100644 --- a/src/addons/qtype/truefalse/services/handlers/truefalse.ts +++ b/src/addons/qtype/truefalse/services/handlers/truefalse.ts @@ -19,6 +19,7 @@ import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '@features/ques import { CoreObject } from '@singletons/object'; import { AddonModQuizMultichoiceQuestion } from '@features/question/classes/base-question-component'; import { makeSingleton, Translate } from '@singletons'; +import { QuestionCompleteGradableResponse } from '@features/question/constants'; /** * Handler to support true/false question type. @@ -45,8 +46,8 @@ export class AddonQtypeTrueFalseHandlerService implements CoreQuestionHandler { isCompleteResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { - return answers.answer ? 1 : 0; + ): QuestionCompleteGradableResponse { + return answers.answer ? QuestionCompleteGradableResponse.YES : QuestionCompleteGradableResponse.NO; } /** @@ -62,7 +63,7 @@ export class AddonQtypeTrueFalseHandlerService implements CoreQuestionHandler { isGradableResponse( question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, - ): number { + ): QuestionCompleteGradableResponse { return this.isCompleteResponse(question, answers); } @@ -97,7 +98,7 @@ export class AddonQtypeTrueFalseHandlerService implements CoreQuestionHandler { question: CoreQuestionQuestionParsed, answers: CoreQuestionsAnswers, ): string | undefined { - if (this.isGradableResponse(question, answers)) { + if (this.isGradableResponse(question, answers) === QuestionCompleteGradableResponse.YES) { return; } diff --git a/src/core/features/question/classes/base-question-handler.ts b/src/core/features/question/classes/base-question-handler.ts index 3edcb57231d..9fdf587405f 100644 --- a/src/core/features/question/classes/base-question-handler.ts +++ b/src/core/features/question/classes/base-question-handler.ts @@ -16,6 +16,7 @@ import { Type } from '@angular/core'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from '../services/question'; import { CoreQuestionHandler } from '../services/question-delegate'; +import { QuestionCompleteGradableResponse } from '../constants'; /** * Base handler for question types. @@ -100,8 +101,8 @@ export class CoreQuestionBaseHandler implements CoreQuestionHandler { answers: CoreQuestionsAnswers, // eslint-disable-line @typescript-eslint/no-unused-vars component: string, // eslint-disable-line @typescript-eslint/no-unused-vars componentId: string | number, // eslint-disable-line @typescript-eslint/no-unused-vars - ): number { - return -1; + ): QuestionCompleteGradableResponse { + return QuestionCompleteGradableResponse.UNKNOWN; } /** @@ -119,8 +120,8 @@ export class CoreQuestionBaseHandler implements CoreQuestionHandler { answers: CoreQuestionsAnswers, // eslint-disable-line @typescript-eslint/no-unused-vars component: string, // eslint-disable-line @typescript-eslint/no-unused-vars componentId: string | number, // eslint-disable-line @typescript-eslint/no-unused-vars - ): number { - return -1; + ): QuestionCompleteGradableResponse { + return QuestionCompleteGradableResponse.UNKNOWN; } /** diff --git a/src/core/features/question/constants.ts b/src/core/features/question/constants.ts index 11743566159..ea16b58484f 100644 --- a/src/core/features/question/constants.ts +++ b/src/core/features/question/constants.ts @@ -37,3 +37,12 @@ export const enum QuestionDisplayOptionsValues { VISIBLE = 1, EDITABLE = 2, } + +/** + * Possible values for the question complete response or gradable response (compatible). + */ +export const enum QuestionCompleteGradableResponse { + UNKNOWN = -1, + NO = 0, + YES = 1, +} diff --git a/src/core/features/question/services/question-delegate.ts b/src/core/features/question/services/question-delegate.ts index 7d9b2bece74..e041acc43b4 100644 --- a/src/core/features/question/services/question-delegate.ts +++ b/src/core/features/question/services/question-delegate.ts @@ -19,6 +19,7 @@ import { CoreWSFile } from '@services/ws'; import { makeSingleton } from '@singletons'; import { CoreQuestionDefaultHandler } from './handlers/default-question'; import { CoreQuestionQuestionParsed, CoreQuestionsAnswers } from './question'; +import { QuestionCompleteGradableResponse } from '../constants'; /** * Interface that all question type handlers must implement. @@ -91,7 +92,7 @@ export interface CoreQuestionHandler extends CoreDelegateHandler { answers: CoreQuestionsAnswers, component: string, componentId: string | number, - ): number; + ): QuestionCompleteGradableResponse; /** * Check if a student has provided enough of an answer for the question to be graded automatically, @@ -108,7 +109,7 @@ export interface CoreQuestionHandler extends CoreDelegateHandler { answers: CoreQuestionsAnswers, component: string, componentId: string | number, - ): number; + ): QuestionCompleteGradableResponse; /** * Check if two responses are the same. @@ -296,7 +297,7 @@ export class CoreQuestionDelegateService extends CoreDelegate( @@ -305,7 +306,7 @@ export class CoreQuestionDelegateService extends CoreDelegate( @@ -332,7 +333,7 @@ export class CoreQuestionDelegateService extends CoreDelegate