Skip to content

Commit f144a29

Browse files
committed
MOBILE-2272 quiz: Fix error when calculating new state in offline
1 parent d2f4c85 commit f144a29

File tree

2 files changed

+114
-105
lines changed

2 files changed

+114
-105
lines changed

src/addon/qbehaviour/deferredfeedback/providers/handler.ts

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -83,71 +83,76 @@ export class AddonQbehaviourDeferredFeedbackHandler implements CoreQuestionBehav
8383
* @param isSameFn Function to override the default isSameResponse check.
8484
* @return Promise resolved with state.
8585
*/
86-
determineNewStateDeferred(component: string, attemptId: number, question: any, componentId: string | number, siteId?: string,
87-
isCompleteFn?: isCompleteResponseFunction, isSameFn?: isSameResponseFunction): Promise<CoreQuestionState> {
86+
async determineNewStateDeferred(component: string, attemptId: number, question: any, componentId: string | number,
87+
siteId?: string, isCompleteFn?: isCompleteResponseFunction, isSameFn?: isSameResponseFunction)
88+
: Promise<CoreQuestionState> {
8889

8990
// Check if we have local data for the question.
90-
return this.questionProvider.getQuestion(component, attemptId, question.slot, siteId).catch(() => {
91+
let dbQuestion;
92+
try {
93+
dbQuestion = await this.questionProvider.getQuestion(component, attemptId, question.slot, siteId);
94+
} catch (error) {
9195
// No entry found, use the original data.
92-
return question;
93-
}).then((dbQuestion) => {
94-
const state = this.questionProvider.getState(dbQuestion.state);
96+
dbQuestion = question;
97+
}
9598

96-
if (state.finished || !state.active) {
97-
// Question is finished, it cannot change.
98-
return state;
99-
}
99+
const state = this.questionProvider.getState(dbQuestion.state);
100100

101-
// We need to check if the answers have changed. Retrieve current stored answers.
102-
return this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId)
103-
.then((prevAnswers) => {
104-
105-
const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers);
106-
107-
prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true);
108-
const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers);
109-
110-
// If answers haven't changed the state is the same.
111-
if (isSameFn) {
112-
if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers,
113-
component, componentId)) {
114-
return state;
115-
}
116-
} else {
117-
if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) {
118-
return state;
119-
}
120-
}
101+
if (state.finished || !state.active) {
102+
// Question is finished, it cannot change.
103+
return state;
104+
}
121105

122-
// Answers have changed. Now check if the response is complete and calculate the new state.
123-
let complete: number,
124-
newState: string;
125-
if (isCompleteFn) {
126-
// Pass all the answers since some behaviours might need the extra data.
127-
complete = isCompleteFn(question, question.answers, component, componentId);
128-
} else {
129-
// Only pass the basic answers since questions should be independent of extra data.
130-
complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId);
131-
}
106+
const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers);
107+
108+
if (dbQuestion.state) {
109+
// Question already has a state stored. Check if answer has changed.
110+
let prevAnswers = await this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId);
132111

133-
if (complete < 0) {
134-
newState = 'cannotdeterminestatus';
135-
} else if (complete > 0) {
136-
newState = 'complete';
137-
} else {
138-
const gradable = this.questionDelegate.isGradableResponse(question, newBasicAnswers);
139-
if (gradable < 0) {
140-
newState = 'cannotdeterminestatus';
141-
} else if (gradable > 0) {
142-
newState = 'invalid';
143-
} else {
144-
newState = 'todo';
145-
}
112+
prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true);
113+
const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers);
114+
115+
// If answers haven't changed the state is the same.
116+
if (isSameFn) {
117+
if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers,
118+
component, componentId)) {
119+
return state;
120+
}
121+
} else {
122+
if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) {
123+
return state;
146124
}
125+
}
126+
}
127+
128+
// Answers have changed. Now check if the response is complete and calculate the new state.
129+
let complete: number;
130+
let newState: string;
131+
132+
if (isCompleteFn) {
133+
// Pass all the answers since some behaviours might need the extra data.
134+
complete = isCompleteFn(question, question.answers, component, componentId);
135+
} else {
136+
// Only pass the basic answers since questions should be independent of extra data.
137+
complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId);
138+
}
139+
140+
if (complete < 0) {
141+
newState = 'cannotdeterminestatus';
142+
} else if (complete > 0) {
143+
newState = 'complete';
144+
} else {
145+
const gradable = this.questionDelegate.isGradableResponse(question, newBasicAnswers);
146+
if (gradable < 0) {
147+
newState = 'cannotdeterminestatus';
148+
} else if (gradable > 0) {
149+
newState = 'invalid';
150+
} else {
151+
newState = 'todo';
152+
}
153+
}
147154

148-
return this.questionProvider.getState(newState);
149-
});
150-
});
155+
return this.questionProvider.getState(newState);
151156
}
152157

153158
/**

src/addon/qbehaviour/manualgraded/providers/handler.ts

Lines changed: 53 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -83,65 +83,69 @@ export class AddonQbehaviourManualGradedHandler implements CoreQuestionBehaviour
8383
* @param isSameFn Function to override the default isSameResponse check.
8484
* @return Promise resolved with state.
8585
*/
86-
determineNewStateManualGraded(component: string, attemptId: number, question: any, componentId: string | number,
86+
async determineNewStateManualGraded(component: string, attemptId: number, question: any, componentId: string | number,
8787
siteId?: string, isCompleteFn?: isCompleteResponseFunction, isSameFn?: isSameResponseFunction)
8888
: Promise<CoreQuestionState> {
8989

9090
// Check if we have local data for the question.
91-
return this.questionProvider.getQuestion(component, attemptId, question.slot, siteId).catch(() => {
91+
let dbQuestion;
92+
try {
93+
dbQuestion = await this.questionProvider.getQuestion(component, attemptId, question.slot, siteId);
94+
} catch (error) {
9295
// No entry found, use the original data.
93-
return question;
94-
}).then((dbQuestion) => {
95-
const state = this.questionProvider.getState(dbQuestion.state);
96+
dbQuestion = question;
97+
}
9698

97-
if (state.finished || !state.active) {
98-
// Question is finished, it cannot change.
99-
return state;
100-
}
99+
const state = this.questionProvider.getState(dbQuestion.state);
101100

102-
// We need to check if the answers have changed. Retrieve current stored answers.
103-
return this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId)
104-
.then((prevAnswers) => {
105-
106-
const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers);
107-
108-
prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true);
109-
const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers);
110-
111-
// If answers haven't changed the state is the same.
112-
if (isSameFn) {
113-
if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers,
114-
component, componentId)) {
115-
return state;
116-
}
117-
} else {
118-
if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) {
119-
return state;
120-
}
121-
}
101+
if (state.finished || !state.active) {
102+
// Question is finished, it cannot change.
103+
return state;
104+
}
122105

123-
// Answers have changed. Now check if the response is complete and calculate the new state.
124-
let complete: number,
125-
newState: string;
126-
if (isCompleteFn) {
127-
// Pass all the answers since some behaviours might need the extra data.
128-
complete = isCompleteFn(question, question.answers, component, componentId);
129-
} else {
130-
// Only pass the basic answers since questions should be independent of extra data.
131-
complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId);
132-
}
106+
const newBasicAnswers = this.questionProvider.getBasicAnswers(question.answers);
133107

134-
if (complete < 0) {
135-
newState = 'cannotdeterminestatus';
136-
} else if (complete > 0) {
137-
newState = 'complete';
138-
} else {
139-
newState = 'todo';
140-
}
108+
if (dbQuestion.state) {
109+
// Question already has a state stored. Check if answer has changed.
110+
let prevAnswers = await this.questionProvider.getQuestionAnswers(component, attemptId, question.slot, false, siteId);
141111

142-
return this.questionProvider.getState(newState);
143-
});
144-
});
112+
prevAnswers = this.questionProvider.convertAnswersArrayToObject(prevAnswers, true);
113+
const prevBasicAnswers = this.questionProvider.getBasicAnswers(prevAnswers);
114+
115+
// If answers haven't changed the state is the same.
116+
if (isSameFn) {
117+
if (isSameFn(question, prevAnswers, prevBasicAnswers, question.answers, newBasicAnswers,
118+
component, componentId)) {
119+
return state;
120+
}
121+
} else {
122+
if (this.questionDelegate.isSameResponse(question, prevBasicAnswers, newBasicAnswers, component, componentId)) {
123+
return state;
124+
}
125+
}
126+
}
127+
128+
// Check if the response is complete and calculate the new state.
129+
let complete: number;
130+
let newState: string;
131+
132+
if (isCompleteFn) {
133+
// Pass all the answers since some behaviours might need the extra data.
134+
complete = isCompleteFn(question, question.answers, component, componentId);
135+
} else {
136+
// Only pass the basic answers since questions should be independent of extra data.
137+
complete = this.questionDelegate.isCompleteResponse(question, newBasicAnswers, component, componentId);
138+
}
139+
140+
if (complete < 0) {
141+
newState = 'cannotdeterminestatus';
142+
} else if (complete > 0) {
143+
newState = 'complete';
144+
} else {
145+
newState = 'todo';
146+
}
147+
148+
return this.questionProvider.getState(newState);
145149
}
146150

147151
/**

0 commit comments

Comments
 (0)