diff --git a/src/qtiItem/helper/maxScore.js b/src/qtiItem/helper/maxScore.js
index c7ae047b..1e272f6f 100644
--- a/src/qtiItem/helper/maxScore.js
+++ b/src/qtiItem/helper/maxScore.js
@@ -37,6 +37,7 @@ var pairExists = function pairExists(collection, pair) {
}
return collection[pair[0] + ' ' + pair[1]] || collection[pair[1] + ' ' + pair[0]];
};
+const externalScoredValues = ['human', 'externalMachine'];
export default {
/**
@@ -48,9 +49,15 @@ export default {
scoreOutcome = item.getOutcomeDeclaration('SCORE');
//try setting the computed normal maximum only if the processing type is known, i.e. 'templateDriven'
- if (scoreOutcome && item.responseProcessing && item.responseProcessing.processingType === 'templateDriven') {
+ if (
+ scoreOutcome &&
+ item.responseProcessing &&
+ item.responseProcessing.processingType === 'templateDriven' &&
+ !externalScoredValues.includes(scoreOutcome.attr('externalScored'))
+ ) {
+ const interactions = item.getInteractions();
normalMaximum = _.reduce(
- item.getInteractions(),
+ interactions,
function (acc, interaction) {
var interactionMaxScore = interaction.getNormalMaximum();
if (_.isNumber(interactionMaxScore)) {
@@ -83,28 +90,32 @@ export default {
//try setting the computed normal maximum only if the processing type is known, i.e. 'templateDriven'
if (scoreOutcome && item.responseProcessing && item.responseProcessing.processingType === 'templateDriven') {
- maxScore = _.reduce(
- item.getInteractions(),
- function (acc, interaction) {
- var interactionMaxScore = interaction.getNormalMaximum();
- if (_.isNumber(interactionMaxScore)) {
- return gamp.add(acc, interactionMaxScore);
- } else {
- hasInvalidInteraction = true;
- return acc;
- }
- },
- 0
- );
-
- customOutcomes = _(item.getOutcomes()).filter(function (outcome) {
- return outcome.id() !== 'SCORE' && outcome.id() !== 'MAXSCORE';
- });
+ const interactions = item.getInteractions();
+ if (externalScoredValues.includes(scoreOutcome.attr('externalScored'))) {
+ maxScore = scoreOutcome.attr('normalMaximum') || 0;
+ } else {
+ maxScore = _.reduce(
+ interactions,
+ function (acc, interaction) {
+ var interactionMaxScore = interaction.getNormalMaximum();
+ if (_.isNumber(interactionMaxScore)) {
+ return gamp.add(acc, interactionMaxScore);
+ } else {
+ hasInvalidInteraction = true;
+ return acc;
+ }
+ },
+ 0
+ );
+ customOutcomes = _(item.getOutcomes()).filter(function (outcome) {
+ return outcome.id() !== 'SCORE' && outcome.id() !== 'MAXSCORE';
+ });
- if (customOutcomes.size()) {
- maxScore = customOutcomes.reduce(function (acc, outcome) {
- return gamp.add(acc, parseFloat(outcome.attr('normalMaximum') || 0));
- }, maxScore);
+ if (customOutcomes.size()) {
+ maxScore = customOutcomes.reduce(function (acc, outcome) {
+ return gamp.add(acc, parseFloat(outcome.attr('normalMaximum') || 0));
+ }, maxScore);
+ }
}
maxScoreOutcome = item.getOutcomeDeclaration('MAXSCORE');
@@ -133,6 +144,18 @@ export default {
item.removeOutcome('MAXSCORE');
}
}
+
+ const isAllResponseProcessingRulesNone = !interactions.some(interaction => {
+ const responseDeclaration = interaction.getResponseDeclaration();
+ const template = responseHelper.getTemplateNameFromUri(responseDeclaration.template);
+ return template !== 'NONE';
+ });
+ // remove MAXSCORE and SCORE outcome variables when all interactions are configured with none response processing rule,
+ // and the externalScored property of the SCORE variable is set to None
+ if (!scoreOutcome.attr('externalScored') && isAllResponseProcessingRulesNone) {
+ item.removeOutcome('MAXSCORE');
+ item.removeOutcome('SCORE');
+ }
}
},
@@ -261,6 +284,9 @@ export default {
} else if (template === 'MAP_RESPONSE_POINT') {
//map point response processing does not work on choice based interaction
max = 0;
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -302,6 +328,9 @@ export default {
} else if (template === 'MAP_RESPONSE' || template === 'MAP_RESPONSE_POINT') {
//map response processing does not work on order based interaction
max = 0;
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -485,6 +514,9 @@ export default {
}
} else if (template === 'MAP_RESPONSE_POINT') {
max = 0;
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -676,6 +708,9 @@ export default {
}
} else if (template === 'MAP_RESPONSE_POINT') {
max = false;
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -724,6 +759,9 @@ export default {
if (responseDeclaration.mappingAttributes.upperBound) {
max = Math.min(max, parseFloat(responseDeclaration.mappingAttributes.upperBound || 0));
}
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -769,6 +807,9 @@ export default {
}
} else if (template === 'MAP_RESPONSE_POINT') {
max = 0;
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -833,6 +874,9 @@ export default {
}
} else if (template === 'MAP_RESPONSE_POINT') {
max = 0;
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
}
return max;
},
@@ -867,6 +911,9 @@ export default {
if (responseDeclaration.mappingAttributes.upperBound) {
max = Math.min(max, parseFloat(responseDeclaration.mappingAttributes.upperBound || 0));
}
+ } else if (template === 'NONE') {
+ //get the normalMaximum from SCORE outcome because we don't have any choices selected
+ max = interaction.getRootElement().getOutcomeDeclaration('SCORE').getAttributes().normalMaximum;
} else {
max = 0;
}
diff --git a/test/qtiItem/maxScore/data/external-scored-none.json b/test/qtiItem/maxScore/data/external-scored-none.json
new file mode 100644
index 00000000..be84a69f
--- /dev/null
+++ b/test/qtiItem/maxScore/data/external-scored-none.json
@@ -0,0 +1,297 @@
+{
+ "identifier": "i654b6b0b5e16d82f276338e15208b3",
+ "serial": "item_654ce58fdf4f1377015349",
+ "qtiClass": "assessmentItem",
+ "attributes": {
+ "identifier": "i654b6b0b5e16d82f276338e15208b3",
+ "title": "Item 2",
+ "label": "Item 2",
+ "xml:lang": "en-US",
+ "adaptive": false,
+ "timeDependent": false,
+ "toolName": "TAO",
+ "toolVersion": "2023.12",
+ "class": ""
+ },
+ "body": {
+ "serial": "container_containeritembody_654ce58fdf4e6721636620",
+ "body": "\n
\n
\n {{interaction_choiceinteraction_654b76d90b56d470570604}}\n <\/div>\n <\/div>\n ",
+ "elements": {
+ "interaction_choiceinteraction_654b76d90b56d470570604": {
+ "serial": "interaction_choiceinteraction_654b76d90b56d470570604",
+ "qtiClass": "choiceInteraction",
+ "attributes": {
+ "responseIdentifier": "RESPONSE",
+ "shuffle": false,
+ "maxChoices": 0,
+ "minChoices": 0,
+ "orientation": "vertical"
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ },
+ "choices": {
+ "choice_simplechoice_654b76d90b898949225000": {
+ "identifier": "choice_1",
+ "serial": "choice_simplechoice_654b76d90b898949225000",
+ "qtiClass": "simpleChoice",
+ "attributes": {
+ "identifier": "choice_1",
+ "fixed": false,
+ "showHide": "show"
+ },
+ "body": {
+ "serial": "container_containerstatic_654b76d90b943674815336",
+ "body": "choice #1",
+ "elements": {},
+ "attributes": [],
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ },
+ "choice_simplechoice_654b76d90ba6f483696171": {
+ "identifier": "choice_2",
+ "serial": "choice_simplechoice_654b76d90ba6f483696171",
+ "qtiClass": "simpleChoice",
+ "attributes": {
+ "identifier": "choice_2",
+ "fixed": false,
+ "showHide": "show"
+ },
+ "body": {
+ "serial": "container_containerstatic_654b76d90babe501012222",
+ "body": "choice #2",
+ "elements": {},
+ "attributes": [],
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ },
+ "choice_simplechoice_654b76d90bbb1853138831": {
+ "identifier": "choice_3",
+ "serial": "choice_simplechoice_654b76d90bbb1853138831",
+ "qtiClass": "simpleChoice",
+ "attributes": {
+ "identifier": "choice_3",
+ "fixed": false,
+ "showHide": "show"
+ },
+ "body": {
+ "serial": "container_containerstatic_654b76d90bbe6755624053",
+ "body": "choice #3",
+ "elements": {},
+ "attributes": [],
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ }
+ },
+ "prompt": {
+ "serial": "container_containerstatic_654b76d90b7f8096069101",
+ "body": "",
+ "elements": {},
+ "attributes": [],
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ }
+ }
+ },
+ "attributes": [],
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ }
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ },
+ "namespaces": {
+ "": "http:\/\/www.imsglobal.org\/xsd\/imsqti_v2p2",
+ "m": "http:\/\/www.w3.org\/1998\/Math\/MathML",
+ "xsi": "http:\/\/www.w3.org\/2001\/XMLSchema-instance"
+ },
+ "schemaLocations": {
+ "http:\/\/www.imsglobal.org\/xsd\/imsqti_v2p2": "http:\/\/www.imsglobal.org\/xsd\/qti\/qtiv2p2\/imsqti_v2p2.xsd"
+ },
+ "stylesheets": {},
+ "outcomes": {
+ "outcomedeclaration_654b76d90b1d1446776777": {
+ "identifier": "SCORE",
+ "serial": "outcomedeclaration_654b76d90b1d1446776777",
+ "qtiClass": "outcomeDeclaration",
+ "attributes": {
+ "identifier": "SCORE",
+ "cardinality": "single",
+ "baseType": "float",
+ "longInterpretation": "",
+ "externalScored": "human",
+ "normalMaximum": 5,
+ "normalMinimum": 0
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ },
+ "defaultValue": null
+ },
+ "outcomedeclaration_654b76d90b39c289062914": {
+ "identifier": "MAXSCORE",
+ "serial": "outcomedeclaration_654b76d90b39c289062914",
+ "qtiClass": "outcomeDeclaration",
+ "attributes": {
+ "identifier": "MAXSCORE",
+ "cardinality": "single",
+ "baseType": "float"
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ },
+ "defaultValue": "5"
+ }
+ },
+ "responses": {
+ "responsedeclaration_654b76d90b09c782359669": {
+ "identifier": "RESPONSE",
+ "serial": "responsedeclaration_654b76d90b09c782359669",
+ "qtiClass": "responseDeclaration",
+ "attributes": {
+ "identifier": "RESPONSE",
+ "cardinality": "multiple",
+ "baseType": "identifier"
+ },
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ },
+ "defaultValue": [],
+ "mapping": [],
+ "areaMapping": [],
+ "howMatch": "no_response_processing",
+ "correctResponses": [],
+ "mappingAttributes": {
+ "defaultValue": 0
+ },
+ "feedbackRules": {}
+ }
+ },
+ "feedbacks": {},
+ "responseProcessing": {
+ "serial": "response_templatesdriven_654b76d90bec8048342511",
+ "qtiClass": "responseProcessing",
+ "attributes": {},
+ "debug": {
+ "relatedItem": "item_654b76d90ad81699556382"
+ },
+ "processingType": "templateDriven",
+ "responseRules": []
+ },
+ "apipAccessibility": ""
+}
diff --git a/test/qtiItem/maxScore/test.js b/test/qtiItem/maxScore/test.js
index b94f04ea..e92b6c4e 100644
--- a/test/qtiItem/maxScore/test.js
+++ b/test/qtiItem/maxScore/test.js
@@ -62,7 +62,10 @@ define([
'json!taoQtiItem/test/qtiItem/maxScore/data/gapmatch-matchmax.json',
'json!taoQtiItem/test/qtiItem/maxScore/data/gapmatch-map-matchmax.json',
'json!taoQtiItem/test/qtiItem/maxScore/data/graphic-gap-infinite.json',
- 'json!taoQtiItem/test/qtiItem/maxScore/data/graphic-associate-matchmax.json'
+ 'json!taoQtiItem/test/qtiItem/maxScore/data/graphic-associate-matchmax.json',
+ 'json!taoQtiItem/test/qtiItem/maxScore/data/response-none.json',
+ 'json!taoQtiItem/test/qtiItem/maxScore/data/external-scored.json',
+ 'json!taoQtiItem/test/qtiItem/maxScore/data/external-scored-none.json'
], function(
_,
Element,
@@ -110,7 +113,10 @@ define([
dataGapMatchMatchmax,
dataGapMatchMapMatchmax,
dataGapMatchInfinite,
- dataGraphicAssocMatchmax
+ dataGraphicAssocMatchmax,
+ dataResponseNone,
+ dataResponseExternalScored,
+ dataResponseExternalScoredNone,
) {
'use strict';
@@ -402,7 +408,10 @@ define([
data: dataGraphicAssocMatchmax,
expectedMaximum: 5,
maxScore: 5
- }
+ },
+ { title: 'response - none', data: dataResponseNone, expectedMaximum: 5, maxScore: 5 },
+ { title: 'external scored', data: dataResponseExternalScored, expectedMaximum: 6, maxScore: 6 },
+ { title: 'removed MAXSCORE and SCORE', data: dataResponseExternalScoredNone, expectedMaximum: undefined, maxScore: undefined },
];
QUnit.cases.init(cases).test('setNormalMaximum', function(settings, assert) {
@@ -422,14 +431,21 @@ define([
assert.ok(Element.isA(item, 'assessmentItem'), 'item loaded');
outcomeScore = item.getOutcomeDeclaration('SCORE');
- assert.ok(_.isUndefined(outcomeScore.attr('normalMaximum')), 'normalMaximum initially undefined');
+
+ if (outcomeScore && outcomeScore.getAttributes()['externalScored']) {
+ assert.ok(outcomeScore.attr('normalMaximum'), 'normalMaximum defined');
+ } else {
+ assert.ok(_.isUndefined(outcomeScore && outcomeScore.attr('normalMaximum')), 'normalMaximum initially undefined');
+ }
maxScore.setNormalMaximum(item);
- assert.equal(
- outcomeScore.attr('normalMaximum'),
- settings.expectedMaximum,
- 'calculated normalMaximum is correct'
- );
+ if (!_.isUndefined(settings.expectedMaximum)) {
+ assert.equal(
+ outcomeScore.attr('normalMaximum'),
+ settings.expectedMaximum,
+ 'calculated normalMaximum is correct'
+ );
+ }
maxScore.setMaxScore(item);
if (!_.isUndefined(settings.maxScore)) {
@@ -438,7 +454,11 @@ define([
assert.ok(Element.isA(outcomeMaxScore, 'outcomeDeclaration'), 'MAXSCORE outcome exists');
assert.equal(outcomeMaxScore.getDefaultValue(), settings.maxScore);
} else {
- assert.expect(4);
+ if (!_.isUndefined(settings.expectedMaximum)) {
+ assert.expect(4);
+ } else {
+ assert.expect(3);
+ }
assert.ok(_.isUndefined(item.getOutcomeDeclaration('MAXSCORE')), 'MAXSCORE undefined');
}
});