Add support for additional answers for Numerical Input problems

TNL-5581
This commit is contained in:
Mushtaq Ali
2016-09-27 15:50:31 +05:00
committed by Mushtaq Ali
parent 19ce439360
commit 387f210363
7 changed files with 286 additions and 52 deletions

View File

@@ -187,21 +187,80 @@ describe 'MarkdownEditingDescriptor', ->
</problem>""")
it 'markup with multiple answers doesn\'t break numerical response', ->
it 'markup with additional answer does not break numerical response', ->
data = MarkdownEditingDescriptor.markdownToXml("""
Enter 1 with a tolerance:
= 1 +- .02
or= 2 +- 5%
or= 2
""")
expect(data).toXMLEqual("""<problem>
<numericalresponse answer="1">
<p>Enter 1 with a tolerance:</p>
<responseparam type="tolerance" default=".02"/>
<responseparam type="tolerance" default=".02"/>
<additional_answer answer="2"/>
<formulaequationinput/>
</numericalresponse>
</problem>"""
)
it 'markup for numerical with multiple additional answers renders correctly', ->
data = MarkdownEditingDescriptor.markdownToXml("""
Enter 1 with a tolerance:
= 1 +- .02
or= 2
or= 3
""")
expect(data).toXMLEqual("""<problem>
<numericalresponse answer="1">
<p>Enter 1 with a tolerance:</p>
<responseparam type="tolerance" default=".02"/>
<additional_answer answer="2"/>
<additional_answer answer="3"/>
<formulaequationinput/>
</numericalresponse>
</problem>""")
</problem>"""
)
it 'Do not render ranged/tolerance/alphabetical additional answers for numerical response', ->
data = MarkdownEditingDescriptor.markdownToXml("""
Enter 1 with a tolerance:
= 1 +- .02
or= 2
or= 3 +- 0.1
or= [4,6]
or= ABC
or= 7
""")
expect(data).toXMLEqual("""<problem>
<numericalresponse answer="1">
<p>Enter 1 with a tolerance:</p>
<responseparam type="tolerance" default=".02"/>
<additional_answer answer="2"/>
<additional_answer answer="7"/>
<formulaequationinput/>
</numericalresponse>
</problem>"""
)
it 'markup with feedback renders correctly in additional answer for numerical response', ->
data = MarkdownEditingDescriptor.markdownToXml("""
Enter 1 with a tolerance:
= 100 +- .02 {{ main feedback }}
or= 10 {{ additional feedback }}
""")
expect(data).toXMLEqual("""<problem>
<numericalresponse answer="100">
<p>Enter 1 with a tolerance:</p>
<responseparam type="tolerance" default=".02"/>
<additional_answer answer="10">
<correcthint>additional feedback</correcthint>
</additional_answer>
<formulaequationinput/>
<correcthint>main feedback</correcthint>
</numericalresponse>
</problem>"""
)
it 'converts multiple choice to xml', ->
data = MarkdownEditingDescriptor.markdownToXml("""A multiple choice problem presents radio buttons for student input. Students can only select a single option presented. Multiple Choice questions have been the subject of many areas of research due to the early invention and adoption of bubble sheets.

View File

@@ -567,50 +567,108 @@
// Line split here, trim off leading xxx= in each function
var answersList = p.split('\n'),
processNumericalResponse = function(val) {
var params, answer, string, textHint, hintLine, value;
// Numeric case is just a plain leading = with a single answer
value = val.replace(/^\=\s*/, '');
isRangeToleranceCase = function(answer) {
return _.contains(
['[', '('], answer[0]) && _.contains([']', ')'], answer[answer.length - 1]
);
},
textHint = extractHint(value);
hintLine = '';
if (textHint.hint) {
value = textHint.nothint;
hintLine = ' <correcthint' + textHint.labelassign + '>' + textHint.hint +
'</correcthint>\n';
getAnswerData = function(answerValue) {
var answerData = {},
answerParams = /(.*?)\+\-\s*(.*?$)/.exec(answerValue);
if (answerParams) {
answerData.answer = answerParams[1].replace(/\s+/g, ''); // inputs like 5*2 +- 10
answerData.default = answerParams[2];
} else {
answerData.answer = answerValue.replace(/\s+/g, ''); // inputs like 5*2
}
return answerData;
},
if (_.contains(['[', '('], value[0]) && _.contains([']', ')'], value[value.length - 1])) {
// [5, 7) or (5, 7), or (1.2345 * (2+3), 7*4 ] - range tolerance case
// = (5*2)*3 should not be used as range tolerance
string = '<numericalresponse answer="' + value + '">\n';
string += ' <formulaequationinput />\n';
string += hintLine;
string += '</numericalresponse>\n\n';
return string;
}
processNumericalResponse = function(answerValues) {
var firstAnswer, answerData, numericalResponseString, additionalAnswerString,
textHint, hintLine, additionalTextHint, additionalHintLine, orMatch, hasTolerance;
if (isNaN(parseFloat(value))) {
// First string case is s?= [e.g. = 100]
firstAnswer = answerValues[0].replace(/^\=\s*/, '');
// If answer is not numerical
if (isNaN(parseFloat(firstAnswer)) && !isRangeToleranceCase(firstAnswer)) {
return false;
}
// Tries to extract parameters from string like 'expr +- tolerance'
params = /(.*?)\+\-\s*(.*?$)/.exec(value);
if (params) {
answer = params[1].replace(/\s+/g, ''); // support inputs like 5*2 +- 10
string = '<numericalresponse answer="' + answer + '">\n';
string += ' <responseparam type="tolerance" default="' + params[2] + '" />\n';
} else {
answer = value.replace(/\s+/g, ''); // support inputs like 5*2
string = '<numericalresponse answer="' + answer + '">\n';
textHint = extractHint(firstAnswer);
hintLine = '';
if (textHint.hint) {
firstAnswer = textHint.nothint;
// safe-lint: disable=javascript-concat-html
hintLine = ' <correcthint' + textHint.labelassign + '>' +
// safe-lint: disable=javascript-concat-html
textHint.hint + '</correcthint>\n';
}
string += ' <formulaequationinput />\n';
string += hintLine;
string += '</numericalresponse>\n\n';
// Range case
if (isRangeToleranceCase(firstAnswer)) {
// [5, 7) or (5, 7), or (1.2345 * (2+3), 7*4 ] - range tolerance case
// = (5*2)*3 should not be used as range tolerance
// safe-lint: disable=javascript-concat-html
numericalResponseString = '<numericalresponse answer="' + firstAnswer + '">\n';
} else {
answerData = getAnswerData(firstAnswer);
// safe-lint: disable=javascript-concat-html
numericalResponseString = '<numericalresponse answer="' + answerData.answer + '">\n';
if (answerData.default) {
// safe-lint: disable=javascript-concat-html
numericalResponseString += ' <responseparam type="tolerance" default="' +
// safe-lint: disable=javascript-concat-html
answerData.default + '" />\n';
}
}
return string;
// Additional answer case or= [e.g. or= 10]
// Since answerValues[0] is firstAnswer, so we will not include this in additional answers.
additionalAnswerString = '';
for (i = 1; i < answerValues.length; i++) {
additionalHintLine = '';
additionalTextHint = extractHint(answerValues[i]);
orMatch = /^or\=\s*(.*)/.exec(additionalTextHint.nothint);
if (orMatch) {
hasTolerance = /(.*?)\+\-\s*(.*?$)/.exec(orMatch[1]);
// Do not add additional_answer if additional answer is not numerical (eg. or= ABC)
// or contains range tolerance case (eg. or= (5,7)
// or has tolerance (eg. or= 10 +- 0.02)
if (isNaN(parseFloat(orMatch[1])) ||
isRangeToleranceCase(orMatch[1]) ||
hasTolerance) {
continue;
}
if (additionalTextHint.hint) {
// safe-lint: disable=javascript-concat-html
additionalHintLine = '<correcthint' +
// safe-lint: disable=javascript-concat-html
additionalTextHint.labelassign + '>' +
// safe-lint: disable=javascript-concat-html
additionalTextHint.hint + '</correcthint>';
}
// safe-lint: disable=javascript-concat-html
additionalAnswerString += ' <additional_answer answer="' + orMatch[1] + '">';
additionalAnswerString += additionalHintLine;
additionalAnswerString += '</additional_answer>\n';
}
}
// Add additional answers string to numerical problem string.
if (additionalAnswerString) {
numericalResponseString += additionalAnswerString;
}
numericalResponseString += ' <formulaequationinput />\n';
numericalResponseString += hintLine;
numericalResponseString += '</numericalresponse>\n\n';
return numericalResponseString;
},
processStringResponse = function(values) {
@@ -657,7 +715,7 @@
return string;
};
return processNumericalResponse(answersList[0]) || processStringResponse(answersList);
return processNumericalResponse(answersList) || processStringResponse(answersList);
});