WeBWorK Problems

a weak alternative to a polymorphic custom checker

a weak alternative to a polymorphic custom checker

by Dick Lane -
Number of replies: 2
After lots of naive tries at an answer checker to handle student responses of different types, I realized that this task might be better handled before sending a student response to a single ANS command.


Problem setup:  3 points given
Task: enter a normal to plane they determine or NONE if they are collinear
student response to process: vector or string

current solution: (with $normal equal to cross product of suitable vectors and $abNorm being its norm)
  if  ($abNorm == 0)  {
ANS( List('NONE') -> cmp() ;
$msg = 'comment about collinear points' ;
  }  else  {
ANS( $normal -> cmp( parallel => 1 ) ) ;
$msg = 'scalar multiples are also correct' ;
  }
Note: both of those ANS modes seem relatively quiet about chiding a student for entering the wrong type of info.
    Late insight: this provides a method for having a relevant $msg within my SOLUTION.


failed attempts at a custom checker (with $ab being cross product of PQ and PR vectors)
[the first presumes a "lazy evaluation" of compound clauses]
ANS( $ab -> cmp( checker => sub {
        my ( $correct , $student , $ansHash ) = @_ ;
        return ( ( (norm($correct) == 0) && ($student == "NONE") )
                ||      ( $correct -> isParallel( $student ) ) ) ;
        } ,
 showCoordinateHints => 0 )
) ;

ANS( $ab -> cmp( parallel => 1 , checker => sub {
        my ( $correct , $student , $ansHash ) = @_ ;
        return $student == "none" if (norm($correct) == 0) ;
        return  ($correct == $student) ;
        } ,
 showCoordinateHints => 0 )
) ;

In reply to Dick Lane

Re: a weak alternative to a polymorphic custom checker

by Gavin LaRose -
Hi Dick,

I may be misinterpreting your intent here. I would be inclined to have a single answer blank for the vector, or the string "none" if the three points are collinear. Something like

  Context("Vector");
  Context()->strings->add( none=>{} );

  for ( my $i=0; $i<3; $i++ ) {
    $x[$i] = random(1,10,1);
    $y[$i] = random(1,10,1);
    $z[$i] = random(1,10,1);
  }
  $pq = Vector( ( $x[1]-$x[0], $y[1]-$y[0], $z[1]-$z[0] ) );
  $pr = Vector( ( $x[2]-$x[0], $y[2]-$y[0], $z[2]-$z[0] ) );
  $ab = $pq x $pr;
  $abnorm = norm($ab);

  BEGIN_TEXT
  enter the vector, or none: \{ ans_rule(25) \}
  END_TEXT

  ANS( $ab->cmp( checker=>sub { 
    my ( $c, $s, $ans ) = @_;
    return ( $abnorm && $c == $s ) ||
        ( ! $abnorm && String("none") == $s );
  } ) );
(This is mostly just a skeleton of a problem, and isn't tested at all.)

Gavin

In reply to Gavin LaRose

Re: a weak alternative to a polymorphic custom checker

by Dick Lane -
Thanks, Gavin, for your improvement to my stab at a suitable custom checker.  I didn't respond right after I read and tried it because I wanted to explore the ways in which your code was better.  I suspected the use of String was crucial and confirmed that.  Then I thought to make it more self-contained by not having the norm be obtained via reference to a global, so inserted a norm computation, e.g.,

ANS( $ab->cmp( checker=>sub {
        my ( $c, $s, $ans ) = @_;
        my  $nc = norm($c) ;
        return  ( $nc && $c == $s ) ||
                ( ! $nc && String("none") == $s );
  } ) );

Perhaps here, or after a further bit of tinkering, things went awry.  Part of my testing involved inserting an assignment so that the points would be collinear --- that condition had been recognized before but not after some recent change.  Even if I reverted to your code (pasted-in), what worked before did not now.

Hence, I am reverting to the version I had when writing my note: the problem template identifies, via the  if ... else  block, which of two states exist (the points determine a plane or are collinear) and then produces a single answer box which is associated with an appropriate checker (and causes the CORRECT item to be suitable --- I was not paying attention to that detail when your version worked initially, but suspect it showed <0,0,0> for the collinear case).

I find this a bit strange.  Although I did not keep written notes during my test of your version and my initial changes to it, I know collinearity was identified before it wasn't.  [I will keep one of the current strange versions to examine further when I am less rushed.]