@oat-sa/tao-test-runner-qti
Version:
TAO Test Runner QTI implementation
120 lines (110 loc) • 5.01 kB
JavaScript
define(['lodash', 'taoTests/runner/plugin', 'core/logger'], function (_, pluginFactory, loggerFactory) { 'use strict';
_ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _;
pluginFactory = pluginFactory && Object.prototype.hasOwnProperty.call(pluginFactory, 'default') ? pluginFactory['default'] : pluginFactory;
loggerFactory = loggerFactory && Object.prototype.hasOwnProperty.call(loggerFactory, 'default') ? loggerFactory['default'] : loggerFactory;
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2020 (original work) Open Assessment Technologies SA ;
*/
const logger = loggerFactory('taoQtiTest/runner/plugins/controls/duration/duration');
/**
* Creates the timer plugin
*/
var duration = pluginFactory({
name: 'duration',
/**
* Install step, add behavior before the lifecycle.
*/
install() {
// define the "duration" store as "volatile" (removed on browser change).
this.getTestRunner().getTestStore().setVolatile(this.getName());
},
/**
* Initializes the plugin (called during runner's init)
*
* @returns {Promise}
*/
init() {
const testRunner = this.getTestRunner();
let currentUpdatePromise = Promise.resolve();
const getItemAttempt = () => {
const context = testRunner.getTestContext();
return `${context.itemIdentifier}#${context.attempt}`;
};
const getPositiveNumber = value => {
if (!_.isNumber(value) || value < 0) {
return 0;
}
return value;
};
//where the duration of attempts are stored
return testRunner.getPluginStore(this.getName()).then(durationStore => {
/**
* Gets the duration of a particular item from the store
*
* @param {String} attemptId - the attempt id to get the duration for
* @returns {Promise}
*/
const getItemDuration = attemptId => {
if (!/^(.*)+#+\d+$/.test(attemptId)) {
return Promise.reject(new Error('Is it really an attempt id, like "itemid#attempt"'));
}
return durationStore.getItem(attemptId);
};
/**
* Updates the duration of a particular item
*
* @param {Number} elapsed - time elapsed since previous tick
* @returns {Promise}
*/
const updateDuration = elapsed => {
const itemAttemptId = getItemAttempt();
currentUpdatePromise = currentUpdatePromise.then(() => getItemDuration(itemAttemptId)).then(duration => durationStore.setItem(itemAttemptId, getPositiveNumber(duration) + getPositiveNumber(elapsed) / 1000)).catch(err => {
logger.warn(`Error updating item duration! ${err && err.message}`);
});
return currentUpdatePromise;
};
/**
* Adds the current duration to the next action request.
* The duration will be sent to the server with the next request,
* usually submitItem() or callItemAction()
*
* @returns {Promise}
*/
const addDurationToCallActionParams = () => {
const itemAttemptId = getItemAttempt();
return currentUpdatePromise.then(() => getItemDuration(itemAttemptId)).then(duration => testRunner.getProxy().addCallActionParams({
itemDuration: getPositiveNumber(duration)
})).catch(err => {
logger.warn(`Error retrieving item duration! ${err && err.message}`);
});
};
//change plugin state
testRunner.on('tick', updateDuration).before('move skip exit timeout pause', addDurationToCallActionParams)
/**
* @event duration.get
* @param {String} attemptId - the attempt id to get the duration for
* @param {getDuration} getDuration - a receiver callback
*/.on('plugin-get.duration', (attemptId, getDuration) => {
if (_.isFunction(getDuration)) {
getDuration(getItemDuration(attemptId));
}
});
});
}
});
return duration;
});