Skip to content

Commit

Permalink
MOBILE-4690 quiz: Add QuestionCompleteGradableResponse enum
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyserver committed Jan 22, 2025
1 parent f151316 commit 38d4890
Show file tree
Hide file tree
Showing 17 changed files with 128 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -190,7 +191,7 @@ export type isCompleteResponseFunction = (
answers: CoreQuestionsAnswers,
component: string,
componentId: string | number,
) => number;
) => QuestionCompleteGradableResponse;

/**
* Check if two responses are the same.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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;
}

/**
Expand All @@ -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;
}

Expand Down
11 changes: 6 additions & 5 deletions src/addons/qtype/ddmarker/services/handlers/ddmarker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -79,7 +80,7 @@ export class AddonQtypeDdMarkerHandlerService implements CoreQuestionHandler {
isGradableResponse(
question: CoreQuestionQuestionParsed,
answers: CoreQuestionsAnswers,
): number {
): QuestionCompleteGradableResponse {
return this.isCompleteResponse(question, answers);
}

Expand Down Expand Up @@ -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;
}

Expand Down
28 changes: 18 additions & 10 deletions src/addons/qtype/essay/services/handlers/essay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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, <string> 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;
}

/**
Expand All @@ -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;
}

/**
Expand Down
15 changes: 8 additions & 7 deletions src/addons/qtype/gapselect/services/handlers/gapselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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;
}

/**
Expand All @@ -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;
}

Expand Down
15 changes: 8 additions & 7 deletions src/addons/qtype/match/services/handlers/match.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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;
}

/**
Expand All @@ -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;
}

Expand Down
Loading

0 comments on commit 38d4890

Please sign in to comment.