OK, I found the issue. When the student checks or submits the answer, the error message about the the student's answer being a formula is generated while the individual entries are being collected and processed into the matrix object, and because an error was produced, the student's matrix is not produced, and no further checking is done. But in preview mode, that message is not produced (the type checking is not performed), and so the student answer is created (as a Formula object returning a matrix value), and the rest of the answer checking is performed. One of the actions taken for matrix answer checking is a test to see if the student matrix is the same size as the correct answer matrix. That is done by calling the matrix's dimensions
method. But when the student answer contains the x, that answer is a Formula, not a Matrix object, and so doesn't have a dimensions()
method to call. That causes the answer checker to die (apparently silently), without returning the requires AnswerHash object, which is the source of the error you are seeing.
The checking of the dimensions is in Matrix object's cmp_preprocess()
method. There is a check there that the student's answer is a Matrix, but the check is actually that its return type is a Matrix, whereas it probably should be that the object's class is a Matrix (since that is what guarantees the presence of the dimensions()
method). So one possible fix is to change
return if $student->type ne 'Matrix';
to
return if $student->classMatch('Matrix');
at line 1033 of pg/lib/Value/AnswerChecker.pm
.
Another would be to add a dimensions()
method to the Formula object that returns the dimension of the matrix result (if it is a matrix), and a reasonable value for other things (like the size of a vector, or the length of a list, or 1 for a number). But that would suggest that it would be reasonable to have a dimensions()
method for all MathObjects. That would be a reasonable addition, but the cmp_preprocess()
fix is easier to do as a work-around, so I present that below.
One way to do it would be to add
package my::Matrix;
our @ISA = ('Value::Matrix');
sub cmp_preprocess {
my $self = shift; my $ans = shift;
my $student = $ans->{student_value};
return if !$student->classMatch('Matrix');
return $self->SUPER::cmp_preprocess($ans);
}
package main;
Context("Matrix");
Context->{value}{Matrix} = 'my::Matrix';
to your problem file. This defines a subclass of Value::Matrix
that has the patched cmp_preprocess()
function.
Of course, you don't want to have to do this for every file containing matrices, and since it is a general problem, you may want to work around it for all problems involving matrices. You can do that by using the File Manger to create a file in your course's templates/macros
folder named parserCustomization.pl
that contains
package my::Matrix;
our @ISA = ('Value::Matrix');
sub cmp_preprocess {
my $self = shift; my $ans = shift;
my $student = $ans->{student_value};
return if !$student->classMatch('Matrix');
return $self->SUPER::cmp_preprocess($ans);
}
package main;
$context{Matrix} = Context("Matrix");
Context->{value}{Matrix} = 'my::Matrix';
Context("Numeric");
This file will be loaded by every problem that loads the MathObjects.pl
file. It makes a local copy of the Matrix context that will be used whenever Context("Matrix")
is called and patches it to include the patched matrix subclass. That should take care of it for now until it is fixed in WeBWorK.