Custom quiz scoring in Adobe Captivate
Adobe Captivate 9 has a selection of built-in quiz processes that are designed to cover the majority of scenarios. Multiple choice, true/false, blank fill, matching and a few other types are supported.
Incorporating quizzes is always a bit of a struggle, not only in developing good quiz concepts, but in developing user feedback, structuring the user journey through the course, given the results, scoring strategies, and ensuring that any reporting functions to the LMS capture the right information and can be easily searched and interpreted.
Adobe can only anticipate a limited range of cases to be modeled in the Captivate user interface as, after a point the UI becomes unworkable. As designers delve into more unique user experiences, the only practical strategy is to dive “behind the scenes” and develop JavaScript-controlled user interactions. This is a very rich area for creativity since through JavaScript, pretty much any user interaction can be developed. Unfortunately, Adobe provides no documentation on the very extensive quiz control library that is loaded as part of the course player, making it a difficult process to figure out where to make changes. With work, it is possible to gain an understanding of this very rich set of tools, and with that comes the ability to circumvent the limitations of the Captivate UI in creating unique experiences.
Here, we will show how to override the internal scoring process. This has been tested on multiple choice quizzes so far, but the concepts may be applicable to the other quiz types. The function that we will show will enable you to assign any point value to the users answers. There need not be a single “right” answer. Scores can also be based on other real-time parameters, such as how many times the user has taken the quiz, and how long they have taken to submit. Scores are reported to the LMS through Captivate, no special communication with the LMS is needed.
The following information is targeted to folks with a relatively good background in JavaScript.
Where to put the JavaScript?
We use an external file to incorporate all JavaScript in our applications. It is far easier to manage and to make changes in near-real time. To do this, we use the “Execute Javascript at On Enter” function with the following small script to the first page of captivate presentation:
$(‘body’).append(‘<script src=”/<path to file>/myscript.js” async=”false”></script>’);
This path is from the root of the webserver and in our case, we don’t include the “http://url/…” to make this work wherever the course module is loaded
Taking over the scoring function
We will skip the majority of the gory details of how Captivate structures the quiz data and all the functions needed to manage the interaction. For the purpose of getting to the heart of the matter, you only need to know the following:
- Quiz pages have an “ID” that is needed to find the quiz data. The IDs all start with “Slidexxxxx” To get this ID, the easiest is to just find it using jQuery:
var slideID = $('[id^=Slide]').attr("id");
2. The quiz data is easily accessed using the following Captivate function:
var quizObject = cp.getQuestionObject(slideID);
The quizObject is very rich. It not only contains all of the quiz data, but also all of the functions necessary to manage this data. There is one critical function that, after everything, decides on what score to give a question. A question is scored regardless of whether the answer is “right or wrong” so this function is always called.
quizObject.getQuestionScoredPoints()
It is not necessary to know anything about the rest of the Captivate code, only that the value returned by this function will be captured as the score for a quiz question. By “overloading” this function, we can create an arbitrary function that determines score based on any information we wish. The following provides an example of how to overload this function, and information on the most likely variables one would use to create a custom scoring function:
// save a reference to the original function
saveGetScore = quizObject.__proto__.getQuestionScoredPoints
//overload the function
quizObject.__proto__.getQuestionScoredPoints = function () {
console.log('---- question Info -----');
console.log("question interaction id:" + this.questionData.iid);
console.log("answered correctly:" + this.getAnsweredCorrectly());
console.log("correct answer:" + this.getCorrectAnswerAsString());
console.log("chosen answer:" + this.getChosenAnswerAsString());
console.log("current attempt:" + this.currentAttempt);
console.log("number of attempts:" + this.numberOfAttempts);
console.log("end Time:" + this.endTime);
console.log("start Time:" + this.startTime);
// the question text
console.log("question text:" + this.questionData.qt);
//some internal ID information
console.log("question number:" + this.questionData.qnq);
console.log("slide number:" + this.m_slideIndex);
console.log("question object name:" + this.questionObjName);
console.log("answergroup:" + this.questionObjName);
console.log("-------------------");
// a returned score
return 100;
}
A typical output from this, after submitting a quiz question looks like:
---- question Info -----
question interaction id:10686
answered correctly:true
correct answer:B
chosen answer:B
current attempt:1
number of attempts:1
end Time:Sat Feb 25 2017 12:03:29 GMT-0500 (Eastern Standard Time)
start Time:Sat Feb 25 2017 12:03:20 GMT-0500 (Eastern Standard Time)
question text:Choose which is the right answer
question number:0
slide number:0
question object name:Slide10662q0
answergroup:Slide10662q0
-------------------
A complete example
The “interaction ID” shows up on the Captivate quiz tab when you are making the quiz page and can be set to a convenient value if you want. With the variables listed above, it is possible to develop a wide range of scoring systems. The following shows the code for a complete partial-credit scored question assuming there are five possible answers. ‘C’ is the best at 5 points, ‘A’ and ‘E’ are the worst at 1 point:
var slideID = $('[id^=Slide]').attr("id");
var quizObject = cp.getQuestionObject(slideID);
var saveGetScore = quizObject.__proto__.getQuestionScoredPoints;
quizObject.__proto__.getQuestionScoredPoints = function () {
var iid = this.questionData.iid;
if ( iid != "10686" ) {
// call the regular scoring function if not this question
return saveGetScore.call(this);
}
var chosen = this.getChosenAnswerAsString());
var score = 0
if (chosen == "A") { score = 1;}
if (chosen == "B") { score = 2;}
if (chosen == "C") { score = 5;}
if (chosen == "D") { score = 3;}
if (chosen == "E") { score = 1;}
return score;
}
From here, all kinds of interesting scoring techniques can be devised!
Examples include scoring based on:
- Time to complete
- Number of tries
- Answers to previous questions
Although the Captivate code base is not for the feint-hearted, with some work, we can use this base to create all kinds of interesting interactions!
Hello, firstable I want to congrats you for your great job! 🙂 I´m looking for use Multiple Choises slides with infinite attemps and penalty points setted at worng answers (partial score), so that, studients could always pass each question but, of course (at least as I hope) obteining variable score depending how many attemps they had made. The problem is Captivate only scores last attemp points (when they finally pass) and they alway get maximum score no matter how many attemps they tried… I wonder if the only way to fix it is using Javascript or also there is an easier native way to make it? Thank a lot!