Add functionality to create question pools

[HFP-57]
pull/4/head^2
Timothy Lim 2016-10-20 13:36:40 +02:00
parent 024d46da38
commit 3285a8fa4a
2 changed files with 91 additions and 34 deletions

View File

@ -126,6 +126,9 @@ H5P.QuestionSet = function (options, contentId, contentData) {
var endTemplate = new EJS({text: resulttemplate}); var endTemplate = new EJS({text: resulttemplate});
var params = $.extend(true, {}, defaults, options); var params = $.extend(true, {}, defaults, options);
var poolSize; // Number of questions to be pooled into a subset
var poolQuestions; // Questions in a pool
var poolOrder; // Order of questions in a pool
var currentQuestion = 0; var currentQuestion = 0;
var questionInstances = []; var questionInstances = [];
var questionOrder; //Stores order of questions to allow resuming of question set var questionOrder; //Stores order of questions to allow resuming of question set
@ -144,7 +147,85 @@ H5P.QuestionSet = function (options, contentId, contentData) {
questionOrder = contentData.previousState.order; questionOrder = contentData.previousState.order;
} }
// Create a pool of questions if necessary
/**
* Randomizes questions in an array and updates an array containing their order
* @param {array} questions
* @param {array} questionOrder
* @return {Object.<array, array>} questionOrdering
*/
var randomizeQuestionOrdering = function (questions, questionOrder) {
// Save the original order of the questions in a nested array [[question0,0],[question1,1]...
var questionOrdering = questions.map(function(object, index) { return [object, index] });
questionOrdering = H5P.shuffleArray(questionOrdering);
// Retrieve questions and indexes
questions = questionOrdering.map(d => d[0]);
// Use the previous question order if it exists
var newOrder;
if (questionOrder) {
newOrder = questionOrdering.map(d => questionOrder[d[1]]);
}
else{
newOrder = questionOrdering.map(d => d[1]);
}
return {
questions:questions,
questionOrder:newOrder
};
}
// Create a pool (a subset) of questions if necessary
if (params.poolSize) {
// If a previous pool exists, recreate it
if(contentData.previousState && contentData.previousState.poolOrder) {
poolOrder = contentData.previousState.poolOrder;
// Recreate the pool from the saved data
var pool = [];
for (var i = 0; i < poolOrder.length; i++) {
pool[i] = params.questions[poolOrder[i]];
}
// Replace original questions with just the ones in the pool
params.questions = pool;
}
// Otherwise create a new pool
else {
// Sanitize input
if (params.poolSize > params.questions.length) {
poolSize = params.questions.length;
}
else {
poolSize = params.poolSize;
}
// Randomize and get the results
var poolResult = randomizeQuestionOrdering(params.questions, poolOrder);
poolQuestions = poolResult.questions;
poolOrder = poolResult.questionOrder;
// Discard extra questions
poolQuestions = poolQuestions.slice(0,poolSize);
poolOrder = poolOrder.slice(0,poolSize);
// Replace original questions with just the ones in the pool
params.questions = poolQuestions;
}
}
// Create the html template for the question container
var $template = $(template.render(params)); var $template = $(template.render(params));
// Set overrides for questions // Set overrides for questions
var override; var override;
if (params.override.showSolutionButton || params.override.retryButton) { if (params.override.showSolutionButton || params.override.retryButton) {
@ -171,7 +252,7 @@ H5P.QuestionSet = function (options, contentId, contentData) {
question = params.questions[questionOrder[i]]; question = params.questions[questionOrder[i]];
} }
else { else {
// Use generic order when initialzing for the first time // Use a generic order when initialzing for the first time
question = params.questions[i]; question = params.questions[i];
} }
@ -197,38 +278,6 @@ H5P.QuestionSet = function (options, contentId, contentData) {
questionInstances.push(questionInstance); questionInstances.push(questionInstance);
} }
/**
* Randomizes questions in an array and updates an array containing their order
* @param {array} questions
* @param {array} questionOrder
* @return {Object.<array, array>} questionOrdering
*/
var randomizeQuestionOrdering = function (questions, questionOrder) {
// Save the original order of the questions in a nested array [[question0,0],[question1,1]...
var questionOrdering = questions.map(function(object, index) { return [object, index] });
questionOrdering = H5P.shuffleArray(questionOrdering);
// Retrieve questions and indexes
questions = questionOrdering.map(d => d[0]);
// Use the previous question order if it exists
var newOrder;
if (questionOrder) {
newOrder = questionOrdering.map(d => questionOrder[d[1]]);
}
else{
newOrder = questionOrdering.map(d => d[1]);
}
return {
questions:questions,
questionOrder:newOrder
};
}
// Randomize questions only on instantiation // Randomize questions only on instantiation
if (params.randomQuestions && contentData.previousState === undefined) { if (params.randomQuestions && contentData.previousState === undefined) {
var result = randomizeQuestionOrdering(questionInstances,questionOrder); var result = randomizeQuestionOrdering(questionInstances,questionOrder);
@ -1015,7 +1064,8 @@ H5P.QuestionSet = function (options, contentId, contentData) {
answers: questionInstances.map(function (qi) { answers: questionInstances.map(function (qi) {
return qi.getCurrentState(); return qi.getCurrentState();
}), }),
order: questionOrder order: questionOrder,
poolOrder: poolOrder
}; };
}; };
}; };

View File

@ -209,6 +209,13 @@
"description": "Enable to randomize the order of questions on display.", "description": "Enable to randomize the order of questions on display.",
"default": false "default": false
}, },
{
"name": "poolSize",
"type": "number",
"label": "Number of questions to be shown:",
"description": "Create a randomized batch of questions from the total.",
"optional": true
},
{ {
"name": "endGame", "name": "endGame",
"type": "group", "type": "group",