Custom markign algorithm

31 views
Skip to first unread message

David Wishart

unread,
Jun 24, 2024, 8:30:20 AM6/24/24
to Numbas Users
6 years (I just checked!) after Christian advised me to use the new custom marking algorithms instead of JavaScript I've started doing it and have found some strange behaviour. I've made an example question below.

Basically the intention of the marking algorithm is to remove a mark if the student answer is correct to one degree of of accuracy less than being asked for. In the example question, 3.14 is obviously correct to 2 d.p. and would get full marks whereas anything that rounds to 3.1 (i.e. 1d.p.) would get a mark removed. This appears to work for any numbers between 3.05 and 3.15 as desired except if I enter the exact answer with a zero on the end e.g. 3.140, this triggers the precision warning (I'm fine with that) but also removes a mark. I have the partial credit for precision set to 100% as I don't want to penalise for this.

Ignore the references to scientific answers in the algorithm, it's there for future addition but we don't have questions that require it at the moment.

Ben Brawn

unread,
Jun 24, 2024, 11:22:00 AM6/24/24
to Numbas Users
Well, it's past 1 am here. 

I think I figured out what you want eventually... Here it is working how I suspect you want it to work

Here is the code 
-------------------------------------
correctPrecision (Has the student's answer been given to the desired precision?):    
 switch(
        //student_is_scientific, ?????
        settings["precisionType"]="dp",  if(countdp(studentNumber)>=countdp(precround((minvalue),settings["precision"]),true,false)),
        settings["precisionType"]="sigfig",  if(countsigfigs(studentNumber)>=countsigfigs(siground(minvalue, settings["precision"])),true,false),
        false
    )

numberInRange (Does the student's answer round to the expected answer):
switch(
        //student_is_scientific, ?????
        settings["precisionType"]="dp" and precround(studentNumber,settings["precision"])=precround(minvalue, settings["precision"]), correct(),
        settings["precisionType"]="sigfig" and siground(studentNumber,settings["precision"])=siground(minvalue, settings["precision"]), correct(),
        if(checkClose,
            correct();
            sub_credit(1/5,"Your answer contains a rounding error.")    
        ,
            incorrect();
            end()
        )
    )

checkClose (Award partial marks if close):
    switch(
        //student_is_scientific, siground(settings["maxvalue"],studentPrecision+scientific_precision_offset),
        settings["precisionType"]="dp",  if(precround(studentNumber, settings["precision"]-1)=precround(minvalue, settings["precision"]-1),true,false),
        settings["precisionType"]="sigfig",  if(siground(studentNumber, settings["precision"]-1)=siground(minvalue, settings["precision"]-1),true,false),
        false
    )


---------------------------------------------------
Message has been deleted
Message has been deleted

David Wishart

unread,
Jul 2, 2024, 11:00:21 AM7/2/24
to Numbas Users
Thank-you for taking the time to help me this in the middle of the night!

I've deleted my previous reply as I've realised that it made no sense due to pasting in a different bit of code to what I intended. The only pertinent point was that as it stood, my algorithm would  skew the allowed answer range if the actual answer was near a rounding boundary. For example if the answer to 2dp was 1.75 then my algorithm would check against any answers that matched that to 1dp so accepting anything between 1.75 and 1.85 but not 1.7.499999.

I've had a discussion with my colleague whose exam this is and we are going to change this. I've done that and it works as I'd like but it's really unwieldy as I am repeating the same calculations several times. The new question is here and I think the issue I'm having is not being able to assign variables using let. I'm either doing it wrong or just not getting the required jme syntax.

What I'd prefer is to be able to assign some calculations to variables (lines 24~26 of my algorithm) and use these in a subsequent switch statement (lines 31 and 34). Lines 29 and 32 work to serve the same purpose but are obviously awful from a programming point of view.

David Wishart

unread,
Jul 3, 2024, 10:50:25 AM7/3/24
to Numbas Users
Fixed it, I needed to write variables in the style of 

targetvalue (Midrange of expected values):
    (minvalue+maxvalue)/2

instead of 

let(targetvalue, (minvalue+maxvalue)/2);

Tidier and easier to read version here

Ben Brawn

unread,
Jul 4, 2024, 12:23:01 AM7/4/24
to Numbas Users
I'm glad you got it working the way you wanted.

Ben
Reply all
Reply to author
Forward
0 new messages