From f144a29fee153af1362076e01e9e2c414d781f0c Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 30 Sep 2020 16:33:23 +0200 Subject: [PATCH] MOBILE-2272 quiz: Fix error when calculating new state in offline --- .../deferredfeedback/providers/handler.ts | 117 +++++++++--------- .../manualgraded/providers/handler.ts | 100 ++++++++------- 2 files changed, 113 insertions(+), 104 deletions(-) diff --git a/src/addon/qbehaviour/deferredfeedback/providers/handler.ts b/src/addon/qbehaviour/deferredfeedback/providers/handler.ts index e53242ffc..9ae43b3ec 100644 --- a/src/addon/qbehaviour/deferredfeedback/providers/handler.ts +++ b/src/addon/qbehaviour/deferredfeedback/providers/handler.ts @@ -83,71 +83,76 @@ export class AddonQbehaviourDeferredFeedbackHandler implements CoreQuestionBehav * @param isSameFn Function to override the default isSameResponse check. * @return Promise resolved with state. */ - determineNewStateDeferred(component: string, attemptId: number, question: any, componentId: string | number, siteId?: string, - isCompleteFn?: isCompleteResponseFunction, isSameFn?: isSameResponseFunction): Promise { + async determineNewStateDeferred(component: string, attemptId: number, question: any, componentId: string | number, + siteId?: string, isCompleteFn?: isCompleteResponseFunction, isSameFn?: isSameResponseFunction) + : Promise { // Check if we have local data for the question. - return this.questionProvider.getQuestion(component, attemptId, question.slot, siteId).catch(() => { + let dbQuestion; + try { + dbQuestion = await this.questionProvider.getQuestion(component, attemptId, question.slot, siteId); + } catch (error) { // No entry found, use the original data. - return question; - }).then((dbQuestion) => { - const state = this.questionProvider.getState(dbQuestion.state); + dbQuestion = question; + } - if (state.finished || !state.active) { - // Question is finished, it cannot change. - return state; + const state = this.questionProvider.getState(dbQuestion.state); + + if (state.finished || !state.active) { + // Question is finished, it cannot change. + return state; + } + + const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers); + + if (dbQuestion.state) { + // Question already has a state stored. Check if answer has changed. + let prevAnswers = await this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId); + + prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true); + const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers); + + // If answers haven't changed the state is the same. + if (isSameFn) { + if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers, + component, componentId)) { + return state; + } + } else { + if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) { + return state; + } } + } - // We need to check if the answers have changed. Retrieve current stored answers. - return this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId) - .then((prevAnswers) => { + // Answers have changed. Now check if the response is complete and calculate the new state. + let complete: number; + let newState: string; - const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers); + if (isCompleteFn) { + // Pass all the answers since some behaviours might need the extra data. + complete = isCompleteFn(question, question.answers, component, componentId); + } else { + // Only pass the basic answers since questions should be independent of extra data. + complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId); + } - prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true); - const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers); + if (complete < 0) { + newState = 'cannotdeterminestatus'; + } else if (complete > 0) { + newState = 'complete'; + } else { + const gradable = this.questionDelegate.isGradableResponse(question, newBasicAnswers); + if (gradable < 0) { + newState = 'cannotdeterminestatus'; + } else if (gradable > 0) { + newState = 'invalid'; + } else { + newState = 'todo'; + } + } - // If answers haven't changed the state is the same. - if (isSameFn) { - if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers, - component, componentId)) { - return state; - } - } else { - if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) { - return state; - } - } - - // Answers have changed. Now check if the response is complete and calculate the new state. - let complete: number, - newState: string; - if (isCompleteFn) { - // Pass all the answers since some behaviours might need the extra data. - complete = isCompleteFn(question, question.answers, component, componentId); - } else { - // Only pass the basic answers since questions should be independent of extra data. - complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId); - } - - if (complete < 0) { - newState = 'cannotdeterminestatus'; - } else if (complete > 0) { - newState = 'complete'; - } else { - const gradable = this.questionDelegate.isGradableResponse(question, newBasicAnswers); - if (gradable < 0) { - newState = 'cannotdeterminestatus'; - } else if (gradable > 0) { - newState = 'invalid'; - } else { - newState = 'todo'; - } - } - - return this.questionProvider.getState(newState); - }); - }); + return this.questionProvider.getState(newState); } /** diff --git a/src/addon/qbehaviour/manualgraded/providers/handler.ts b/src/addon/qbehaviour/manualgraded/providers/handler.ts index 2cfe4c20b..b12cb3e35 100644 --- a/src/addon/qbehaviour/manualgraded/providers/handler.ts +++ b/src/addon/qbehaviour/manualgraded/providers/handler.ts @@ -83,65 +83,69 @@ export class AddonQbehaviourManualGradedHandler implements CoreQuestionBehaviour * @param isSameFn Function to override the default isSameResponse check. * @return Promise resolved with state. */ - determineNewStateManualGraded(component: string, attemptId: number, question: any, componentId: string | number, + async determineNewStateManualGraded(component: string, attemptId: number, question: any, componentId: string | number, siteId?: string, isCompleteFn?: isCompleteResponseFunction, isSameFn?: isSameResponseFunction) : Promise { // Check if we have local data for the question. - return this.questionProvider.getQuestion(component, attemptId, question.slot, siteId).catch(() => { + let dbQuestion; + try { + dbQuestion = await this.questionProvider.getQuestion(component, attemptId, question.slot, siteId); + } catch (error) { // No entry found, use the original data. - return question; - }).then((dbQuestion) => { - const state = this.questionProvider.getState(dbQuestion.state); + dbQuestion = question; + } - if (state.finished || !state.active) { - // Question is finished, it cannot change. - return state; + const state = this.questionProvider.getState(dbQuestion.state); + + if (state.finished || !state.active) { + // Question is finished, it cannot change. + return state; + } + + const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers); + + if (dbQuestion.state) { + // Question already has a state stored. Check if answer has changed. + let prevAnswers = await this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId); + + prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true); + const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers); + + // If answers haven't changed the state is the same. + if (isSameFn) { + if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers, + component, componentId)) { + return state; + } + } else { + if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) { + return state; + } } + } - // We need to check if the answers have changed. Retrieve current stored answers. - return this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId) - .then((prevAnswers) => { + // Check if the response is complete and calculate the new state. + let complete: number; + let newState: string; - const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers); + if (isCompleteFn) { + // Pass all the answers since some behaviours might need the extra data. + complete = isCompleteFn(question, question.answers, component, componentId); + } else { + // Only pass the basic answers since questions should be independent of extra data. + complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId); + } - prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true); - const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers); + if (complete < 0) { + newState = 'cannotdeterminestatus'; + } else if (complete > 0) { + newState = 'complete'; + } else { + newState = 'todo'; + } - // If answers haven't changed the state is the same. - if (isSameFn) { - if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers, - component, componentId)) { - return state; - } - } else { - if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) { - return state; - } - } - - // Answers have changed. Now check if the response is complete and calculate the new state. - let complete: number, - newState: string; - if (isCompleteFn) { - // Pass all the answers since some behaviours might need the extra data. - complete = isCompleteFn(question, question.answers, component, componentId); - } else { - // Only pass the basic answers since questions should be independent of extra data. - complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId); - } - - if (complete < 0) { - newState = 'cannotdeterminestatus'; - } else if (complete > 0) { - newState = 'complete'; - } else { - newState = 'todo'; - } - - return this.questionProvider.getState(newState); - }); - }); + return this.questionProvider.getState(newState); } /**