UNPKG

@oat-sa/tao-test-runner-qti

Version:
161 lines (150 loc) 6.63 kB
define(['lodash', 'taoQtiTest/runner/helpers/map', 'taoQtiTest/runner/config/states'], function (_, mapHelper, states) { 'use strict'; _ = _ && Object.prototype.hasOwnProperty.call(_, 'default') ? _['default'] : _; mapHelper = mapHelper && Object.prototype.hasOwnProperty.call(mapHelper, 'default') ? mapHelper['default'] : mapHelper; states = states && Object.prototype.hasOwnProperty.call(states, 'default') ? states['default'] : states; /* * 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) 2017 (original work) Open Assessment Technologies SA * */ /** * Get the updater * @param {Map} testDataHolder - the data holder * @returns {dataUpdater} * @throws {TypeError} if the data holder is not or incorrectly set */ function dataUpdaterFactory(testDataHolder) { if (!testDataHolder || !_.isFunction(testDataHolder.get) || !_.isFunction(testDataHolder.set)) { throw new TypeError('A data holder is mandatory for the udpater'); } /** * Exposes the methods to update test data * @typedef {Object} dataUpdater */ return { /** * Update test data from a dataSet (usually their raw data given by the proxy). * If the dataSet is a collection, we use only the last matching object. * @param {Object|Object[]} dataSet - object[s] that contains or not testData, testContext & testMap */ update: function update(dataSet) { var self = this; /** * Check if a collection's item contains test contextual data * @param {Object} contextualData * @returns {Boolean} */ var isContextual = function isContextual(contextualData) { return contextualData && (_.isPlainObject(contextualData.testContext) || _.isPlainObject(contextualData.testData) || _.isPlainObject(contextualData.testMap)); }; /** * Update the test data from contextual data * @param {Object} contextualData */ var updateData = function updateData(contextualData) { var builtTestMap; var updatedTestMap; if (contextualData) { if (_.isPlainObject(contextualData.testData)) { testDataHolder.set('testData', contextualData.testData); } if (_.isPlainObject(contextualData.testContext)) { testDataHolder.set('testContext', contextualData.testContext); } if (_.isPlainObject(contextualData.testMap)) { //the received map is not complete and should be "built" builtTestMap = self.buildTestMap(contextualData.testMap); if (builtTestMap) { testDataHolder.set('testMap', builtTestMap); } } //always update the map stats updatedTestMap = self.updateStats(); if (updatedTestMap) { testDataHolder.set('testMap', updatedTestMap); } } }; if (isContextual(dataSet)) { updateData(dataSet); } else { updateData(_.findLast(dataSet, isContextual)); } }, /** * - reindex and build the jump table * - patch the current testMap if a partial map is set * * @param {Object} testMap - the testMap to build * @returns {Object} the built testMap */ buildTestMap: function buildTestMap(testMap) { var newMap = null; if (testMap) { if (testMap.scope && testMap.scope !== 'test') { newMap = mapHelper.patch(testDataHolder.get('testMap'), testMap); } else { newMap = mapHelper.reindex(testMap); } } return newMap; }, /** * Update current map stats based on the context * * @returns {Object} the updated testMap */ updateStats: function updateStats() { const testMap = testDataHolder.get('testMap'); const testContext = testDataHolder.get('testContext'); let updatedTestMap = null; if (testMap && testContext && _.isNumber(testContext.itemPosition)) { const item = mapHelper.getItemAt(testMap, testContext.itemPosition); if (item && testContext.state === states.testSession.interacting) { const testPart = mapHelper.getPart(testMap, testContext.testPartId); //flag as viewed, always item.viewed = true; if (testPart && testPart.isLinear) { item.answered = true; } updatedTestMap = mapHelper.updateItemStats(testMap, testContext.itemPosition); } } return updatedTestMap; }, /** * Let's you update the plugins configuration from when filling testData * @param {plugin[]} plugins - the test runner plugins * @param {Objectt} [pluginsConfig] - the configuration to set on the plugins */ updatePluginsConfig(plugins, pluginsConfig) { //to keep backward compatibility with the deprecated testData if (!pluginsConfig) { const testData = testDataHolder.get('testData'); pluginsConfig = testData && testData.config && testData.config.plugins; } if (plugins && pluginsConfig) { _.forEach(pluginsConfig, (config, pluginName) => { if (_.isPlainObject(plugins[pluginName]) && _.isFunction(plugins[pluginName].setConfig) && _.isPlainObject(config)) { plugins[pluginName].setConfig(config); } }); } } }; } return dataUpdaterFactory; });