Skip to content

Commit

Permalink
add tests for issue #1132
Browse files Browse the repository at this point in the history
  • Loading branch information
christianp committed Dec 13, 2024
1 parent c67131b commit 24cc553
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 16 deletions.
4 changes: 3 additions & 1 deletion runtime/scripts/parts/jme.js
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@ JMEPart.prototype = /** @lends Numbas.JMEPart.prototype */
if(!tree && this.marks>0) {
this.error('part.jme.answer missing');
}
scope = scope.unset(this.question.local_definitions);
if(this.question) {
scope = scope.unset(this.question.local_definitions);
}
var expr = jme.display.treeToJME(tree,{plaindecimal: true},scope);
settings.correctVariables = jme.findvars(jme.compile(expr),[],scope);
settings.correctAnswer = jme.display.simplifyExpression(
Expand Down
9 changes: 6 additions & 3 deletions tests/jme-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -10716,10 +10716,13 @@ Scope.prototype = /** @lends Numbas.jme.Scope.prototype */ {
*
* @param {string} name
*/
deleteVariable: function(name) {
deleteVariable: function(name, options) {
options = options || {};
name = jme.normaliseName(name, this);
this.deleted.variables[name] = true;
this.deleted.constants[name] = true;
if(options.delete_constant !== false) {
this.deleted.constants[name] = true;
}
},
/** Mark the given function name as deleted from the scope.
*
Expand Down Expand Up @@ -11059,7 +11062,7 @@ Scope.prototype = /** @lends Numbas.jme.Scope.prototype */ {
var s = new Scope([this]);
if(defs.variables) {
defs.variables.forEach(function(v) {
s.deleteVariable(v);
s.deleteVariable(v, {delete_constant: false});
});
}
if(defs.functions) {
Expand Down
9 changes: 9 additions & 0 deletions tests/jme/jme-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,15 @@ Numbas.queueScript('jme_tests',['qunit','jme','jme-rules','jme-display','jme-cal
assert.equal(Numbas.jme.display.exprToLaTeX('exp(2)','',s),'E^{ 2 }','exp when the constant e is rendered as E');
});

QUnit.test('unset', function(assert) {
const scope = new jme.Scope([Numbas.jme.builtinScope]);
scope.setVariable('e', scope.evaluate('3'));
const unset_scope = scope.unset({variables: ['e']});
assert.notOk(unset_scope.getVariable('e'), 'e is not a defined variable after being unset');
assert.ok(unset_scope.getConstant('e'), 'e is still a constant after being unset');
assert.ok(assert, unset_scope.evaluate('ln(e)=1').value, 'ln(e) = 1');
});


QUnit.module('Pattern-matching');
QUnit.test('matchExpression', function(assert) {
Expand Down
27 changes: 15 additions & 12 deletions tests/numbas-runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -10307,10 +10307,13 @@ Scope.prototype = /** @lends Numbas.jme.Scope.prototype */ {
*
* @param {string} name
*/
deleteVariable: function(name) {
deleteVariable: function(name, options) {
options = options || {};
name = jme.normaliseName(name, this);
this.deleted.variables[name] = true;
this.deleted.constants[name] = true;
if(options.delete_constant !== false) {
this.deleted.constants[name] = true;
}
},
/** Mark the given function name as deleted from the scope.
*
Expand Down Expand Up @@ -10650,7 +10653,7 @@ Scope.prototype = /** @lends Numbas.jme.Scope.prototype */ {
var s = new Scope([this]);
if(defs.variables) {
defs.variables.forEach(function(v) {
s.deleteVariable(v);
s.deleteVariable(v, {delete_constant: false});
});
}
if(defs.functions) {
Expand Down Expand Up @@ -25040,8 +25043,9 @@ Exam.prototype = /** @lends Numbas.Exam.prototype */ {
this.timeRemaining = this.settings.duration;
this.updateScore(); //initialise score
//set countdown going
if(this.mode!='review')
if(this.mode!='review') {
this.startTiming();
}

switch(this.settings.navigateMode) {
case 'sequence':
Expand Down Expand Up @@ -25098,8 +25102,7 @@ Exam.prototype = /** @lends Numbas.Exam.prototype */ {
* @fires Numbas.Exam#event:hideTiming
* @fires Numbas.Exam#event:showTiming
*/
startTiming: function()
{
startTiming: function() {
this.inProgress = true;
this.stopwatch = {
start: new Date(),
Expand All @@ -25124,12 +25127,10 @@ Exam.prototype = /** @lends Numbas.Exam.prototype */ {
* @fires Numbas.Exam#event:countDown
* @fires Numbas.Exam#event:alert
*/
countDown: function()
{
countDown: function() {
var t = new Date();
this.timeSpent = this.stopwatch.oldTimeSpent + (t - this.stopwatch.start)/1000;
if(this.settings.navigateMode=='sequence' && this.settings.duration > 0)
{
if(this.settings.duration > 0) {
this.timeRemaining = Math.ceil((this.stopwatch.end - t)/1000);
this.display && this.display.showTiming();
this.events.trigger('showTiming');
Expand Down Expand Up @@ -25161,8 +25162,7 @@ Exam.prototype = /** @lends Numbas.Exam.prototype */ {
*
* @fires Numbas.Exam#event:endTiming
*/
endTiming: function()
{
endTiming: function() {
this.inProgress = false;
clearInterval( this.stopwatch.id );
this.events.trigger('endTiming');
Expand Down Expand Up @@ -32395,6 +32395,9 @@ JMEPart.prototype = /** @lends Numbas.JMEPart.prototype */
if(!tree && this.marks>0) {
this.error('part.jme.answer missing');
}
if(this.question) {
scope = scope.unset(this.question.local_definitions);
}
var expr = jme.display.treeToJME(tree,{plaindecimal: true},scope);
settings.correctVariables = jme.findvars(jme.compile(expr),[],scope);
settings.correctAnswer = jme.display.simplifyExpression(
Expand Down
26 changes: 26 additions & 0 deletions tests/parts/part-tests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,32 @@ Numbas.queueScript('part_tests',['qunit','json','jme','localisation','parts/numb
}
);

question_test(
'e defined as a variable is not used in mathematical expression part answers',
{
variables: {
'e': {
name: 'e',
definition: '3'
}
},
parts: [
{
type: 'jme',
answer: 'e^2+a',
answerSimplification: 'basic',
}
]
},
async function(assert, q) {
const p = q.getPart('p0');
var res = await mark_part(p,['e^2+a']);
console.log(p.getCorrectAnswer(p.getScope()));
console.log(res);
assert.equal(res.credit,1,'"e^2+a" correct');
}
);

question_test(
"A big question",
{"name":"Working on standalone part instances","tags":[],"metadata":{"description":"<p>Check that the&nbsp;MarkingScript reimplementations of the marking algorithms work properly.</p>","licence":"None specified"},"statement":"<p>Parts&nbsp;<strong>a</strong> to&nbsp;<strong>f</strong> use the standard marking algorithms.</p>","advice":"","rulesets":{},"extensions":[],"variables":{"m":{"name":"m","group":"Ungrouped variables","definition":"id(2)","description":"","templateType":"anything"}},"variablesTest":{"condition":"","maxRuns":100},"ungrouped_variables":["m"],"variable_groups":[],"functions":{},"preamble":{"js":"","css":""},"parts":[{"type":"numberentry","marks":1,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[],"variableReplacementStrategy":"originalfirst","customMarkingAlgorithm":"","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>Write a number between 1 and 2</p>","minValue":"1","maxValue":"2","correctAnswerFraction":false,"allowFractions":false,"mustBeReduced":false,"mustBeReducedPC":0,"precisionType":"dp","precision":"2","precisionPartialCredit":0,"precisionMessage":"You have not given your answer to the correct precision.","strictPrecision":false,"showPrecisionHint":true,"notationStyles":["plain","en","si-en"],"correctAnswerStyle":"plain"},{"type":"matrix","marks":1,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[],"variableReplacementStrategy":"originalfirst","customMarkingAlgorithm":"","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>Write a $2 \\times 2$ identity matrix.</p>","correctAnswer":"id(2)","correctAnswerFractions":false,"numRows":"2","numColumns":"2","allowResize":true,"tolerance":0,"markPerCell":true,"allowFractions":false,"precisionType":"dp","precision":0,"precisionPartialCredit":"40","precisionMessage":"You have not given your answer to the correct precision.","strictPrecision":true},{"type":"jme","marks":1,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[],"variableReplacementStrategy":"originalfirst","customMarkingAlgorithm":"","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>Write $x$</p>","answer":"x","showPreview":true,"checkingType":"absdiff","checkingAccuracy":0.001,"failureRate":1,"vsetRangePoints":5,"vsetRange":[0,1],"checkVariableNames":true,"expectedVariableNames":["x"],"notallowed":{"strings":["("],"showStrings":false,"partialCredit":0,"message":"<p>No brackets!</p>"}},{"type":"patternmatch","marks":1,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[],"variableReplacementStrategy":"originalfirst","customMarkingAlgorithm":"","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>Write \"a+\"</p>","answer":"a+","displayAnswer":"","caseSensitive":true,"partialCredit":"30","matchMode":"exact"},{"type":"1_n_2","marks":0,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[],"variableReplacementStrategy":"originalfirst","customMarkingAlgorithm":"","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>Choose choice 1</p>","minMarks":0,"maxMarks":0,"shuffleChoices":false,"displayType":"radiogroup","displayColumns":0,"choices":["Choice 1","Choice 2","Choice 3"],"matrix":["1",0,"-1"],"distractors":["Choice 1 is good","Choice 2 is not great","Choice 3 is bad"]},{"type":"numberentry","marks":1,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[{"variable":"m","part":"p1","must_go_first":false}],"variableReplacementStrategy":"alwaysreplace","customMarkingAlgorithm":"","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>What's&nbsp;the determinant of the matrix in part b?</p>","minValue":"det(m)","maxValue":"det(m)","correctAnswerFraction":false,"allowFractions":false,"mustBeReduced":false,"mustBeReducedPC":0,"notationStyles":["plain","en","si-en"],"correctAnswerStyle":"plain"},{"type":"numberentry","marks":1,"showCorrectAnswer":true,"showFeedbackIcon":true,"scripts":{},"variableReplacements":[],"variableReplacementStrategy":"originalfirst","customMarkingAlgorithm":"q:\n apply_marking_script(\"numberentry\",studentAnswer,settings+[\"minvalue\":4,\"maxvalue\":5],1)\n\nr:\n apply_marking_script(\"numberentry\",studentAnswer,settings+[\"minvalue\":3,\"maxvalue\":4],1)\n\nmark:\n feedback(\"number between 4 and 5\");\n concat_feedback(q[\"mark\"][\"feedback\"],marks/2);\n feedback(\"number between 3 and 4\");\n concat_feedback(r[\"mark\"][\"feedback\"],marks/2)","extendBaseMarkingAlgorithm":true,"unitTests":[],"prompt":"<p>Write a number between 4 and 5, and between 3 and 4.</p>","minValue":"1","maxValue":"2","correctAnswerFraction":false,"allowFractions":false,"mustBeReduced":false,"mustBeReducedPC":0,"notationStyles":["plain","en","si-en"],"correctAnswerStyle":"plain"}]},
Expand Down

0 comments on commit 24cc553

Please sign in to comment.