[system] / trunk / pg / macros / PGmorematrixmacros.pl Repository:
ViewVC logotype

View of /trunk/pg/macros/PGmorematrixmacros.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1123 - (download) (as text) (annotate)
Wed Jun 11 15:28:47 2003 UTC (16 years, 6 months ago) by lr003k
File size: 19644 byte(s)
Ok, there is the ans_array_filter added which allows for the answer to be coming from the ans_array.

    1 #!/usr/local/bin/webwork-perl
    2 
    3 BEGIN{
    4   be_strict();
    5 }
    6 
    7 sub _PGmorematrixmacros_init{}
    8 
    9 sub random_inv_matrix { ## Builds and returns a random invertible \$row by \$col matrix.
   10 
   11     warn "Usage: \$new_matrix = random_inv_matrix(\$rows,\$cols)"
   12       if (@_ != 2);
   13     my $A = new Matrix($_[0],$_[1]);
   14     my $A_lr = new Matrix($_[0],$_[1]);
   15     my $det = 0;
   16     my $safety=0;
   17     while ($det == 0 and $safety < 6) {
   18         foreach my $i (1..$_[0]) {
   19             foreach my $j (1..$_[1]) {
   20                 $A->assign($i,$j,random(-9,9,1) );
   21                 }
   22             }
   23             $A_lr = $A->decompose_LR();
   24             $det = $A_lr->det_LR();
   25         }
   26     return $A;
   27 }
   28 
   29 sub swap_rows{
   30 
   31     warn "Usage: \$new_matrix = swap_rows(\$matrix,\$row1,\$row2);"
   32       if (@_ != 3);
   33     my $matrix = $_[0];
   34     my ($i,$j) = ($_[1],$_[2]);
   35     warn "Error:  Rows to be swapped must exist!"
   36       if ($i>@$matrix or $j >@$matrix);
   37     warn "Warning:  Swapping the same row is pointless"
   38       if ($i==$j);
   39     my $cols = @{$matrix->[0]};
   40     my $B = new Matrix(@$matrix,$cols);
   41     foreach my $k (1..$cols){
   42         $B->assign($i,$k,element $matrix($j,$k));
   43         $B->assign($j,$k,element $matrix($i,$k));
   44     }
   45     return $B;
   46 }
   47 
   48 sub row_mult{
   49 
   50     warn "Usage: \$new_matrix = row_mult(\$matrix,\$scalar,\$row);"
   51       if (@_ != 3);
   52     my $matrix = $_[0];
   53     my ($scalar,$row) = ($_[1],$_[2]);
   54     warn "Undefined row multiplication"
   55       if ($row > @$matrix);
   56     my $B = new Matrix(@$matrix,@{$matrix->[0]});
   57     foreach my $j (1..@{$matrix->[0]}) {
   58         $B->assign($row,$j,$scalar*element $matrix($row,$j));
   59     }
   60     return $B;
   61 }
   62 
   63 sub linear_combo{
   64 
   65     warn "Usage: \$new_matrix = linear_combo(\$matrix,\$scalar,\$row1,\$row2);"
   66       if (@_ != 4);
   67     my $matrix = $_[0];
   68     my ($scalar,$row1,$row2) = ($_[1],$_[2],$_[3]);
   69     warn "Undefined row in multiplication"
   70       if ($row1>@$matrix or $row2>@$matrix);
   71     warn "Warning:  Using the same row"
   72       if ($row1==$row2);
   73     my $B = new Matrix(@$matrix,@{$matrix->[0]});
   74     foreach my $j (1..@$matrix) {
   75         my ($t1,$t2) = (element $matrix($row1,$j),element $matrix($row2,$j));
   76         $B->assign($row2,$j,$scalar*$t1+$t2);
   77     }
   78     return $B;
   79 }
   80 
   81 =head3 basis_cmp()
   82 
   83 Compares a list of vectors by finding the change of coordinate matrix
   84 from the Prof's vectors to the students, and then taking the determinant of
   85 that to determine the existence of the change of coordinate matrix going the
   86 other way.
   87 
   88 ANS( basis_cmp( vectors_as_array_ref_in_array_ref, options_hash ) );
   89 
   90   1. a reference to an array of correct vectors
   91   2. a hash with the following keys (all optional):
   92     mode      --  'basis' (default) (only a basis allowed)
   93               'orthogonal' (only an orthogonal basis is allowed)
   94               'unit' (only unit vectors in the basis allowed)
   95               'orthonormal' (only orthogonal unit vectors in basis allowed)
   96     zeroLevelTol  --  absolute tolerance to allow when answer is close
   97                  to zero
   98 
   99     debug     --  if set to 1, provides verbose listing of
  100                 hash entries throughout fliters.
  101 
  102     help    --  'none' (default) (is quiet on all errors)
  103           'dim' (Tells student if wrong number of vectors are entered)
  104           'length' (Tells student if there is a vector of the wrong length)
  105           'orthogonal' (Tells student if their vectors are not orthogonal)
  106               (This is only in orthogonal mode)
  107           'unit' (Tells student if there is a vector not of unit length)
  108               (This is only in unit mode)
  109           'orthonormal' (Gives errors from orthogonal and orthonormal)
  110               (This is only in orthonormal mode)
  111           'verbose' (Gives all the above answer messages)
  112 
  113   Returns an answer evaluator.
  114 
  115 EXAMPLES:
  116 
  117   basis_cmp([[1,0,0],[0,1,0],[0,0,1]])
  118                   --  correct answer is any basis for R^3.
  119   basis_cmp([1,0,2,0],[0,1,0,0], 'mode'=>orthonormal )
  120                   --  correct answer is any orthonormal basis
  121                     for this space such as:
  122                     [1/sqrt(3),0,2/sqrt(3),0],[0,1,0,0]
  123 
  124 =cut
  125 
  126 
  127 sub basis_cmp {
  128   my $correctAnswer = shift;
  129   my %opt = @_;
  130 
  131   set_default_options(  \%opt,
  132         'zeroLevelTol'        =>  $main::functZeroLevelTolDefault,
  133               'debug'         =>  0,
  134         'mode'          =>  'basis',
  135         'help'          =>  'none',
  136       );
  137 
  138   # produce answer evaluator
  139   BASIS_CMP(
  140         'correct_ans'     =>  $correctAnswer,
  141         'zeroLevelTol'      =>  $opt{'zeroLevelTol'},
  142         'debug'       =>  $opt{'debug'},
  143         'mode'        =>  $opt{'mode'},
  144         'help'        =>  $opt{'help'},
  145   );
  146 }
  147 
  148 =head BASIS_CMP
  149 
  150 Made to keep the same format as num_cmp and fun_cmp.
  151 
  152 =cut
  153 
  154 sub BASIS_CMP {
  155   my %mat_params = @_;
  156   my $zeroLevelTol        = $mat_params{'zeroLevelTol'};
  157 
  158   # Check that everything is defined:
  159   $mat_params{debug} = 0 unless defined($mat_params{debug});
  160   $zeroLevelTol = $main::functZeroLevelTolDefault     unless defined $zeroLevelTol;
  161   $mat_params{'zeroLevelTol'}       =   $zeroLevelTol;
  162 
  163 ## This is where the correct answer should be checked someday.
  164   my $matrix          = Matrix->new_from_col_vecs($mat_params{'correct_ans'});
  165 
  166 #construct the answer evaluator
  167   my $answer_evaluator = new AnswerEvaluator;
  168 
  169       $answer_evaluator->{debug} = $mat_params{debug};
  170 
  171       $answer_evaluator->ans_hash(  correct_ans     =>  pretty_print($mat_params{correct_ans}),
  172           rm_correct_ans    =>  $matrix,
  173           zeroLevelTol    =>  $mat_params{zeroLevelTol},
  174           debug     =>  $mat_params{debug},
  175           mode      =>  $mat_params{mode},
  176           help      =>  $mat_params{help},
  177       );
  178 
  179   $answer_evaluator->install_pre_filter(sub {my $rh_ans = shift;
  180     $rh_ans->{student_ans} =~ s/\s+//g;   # remove all whitespace
  181     $rh_ans;
  182   });
  183 
  184   $answer_evaluator->install_pre_filter(\&math_constants);
  185   $answer_evaluator->install_pre_filter(sub{my $rh_ans = shift; my @options = @_;
  186     if( $rh_ans->{ans_label} =~ /ArRaY/ ){
  187       $rh_ans = ans_array_filter($rh_ans,@options);
  188       my @student_array = @{$rh_ans->{ra_student_ans}};
  189       my @array = ();
  190       for( my $i = 0; $i < scalar(@student_array) ; $i ++ )
  191       {
  192         push( @array, Matrix->new_from_array_ref($student_array[$i]));
  193       }
  194       $rh_ans->{ra_student_ans} = \@array;
  195       $rh_ans;
  196     }else{
  197       vec_list_string($rh_ans,@options);
  198     }
  199 
  200   });#ra_student_ans is now the students answer as an array of vectors
  201   # anonymous subroutine to check dimension and length of the student vectors
  202   # if either is wrong, the answer is wrong.
  203   $answer_evaluator->install_pre_filter(sub{
  204     my $rh_ans = shift;
  205     my $length = $rh_ans->{rm_correct_ans}->[1];
  206     my $dim = $rh_ans->{rm_correct_ans}->[2];
  207     if( $dim != scalar(@{$rh_ans->{ra_student_ans}}))
  208     {
  209 
  210       $rh_ans->{score} = 0;
  211       if( $rh_ans->{help} =~ /dim|verbose/ )
  212       {
  213         $rh_ans->throw_error('EVAL','You have entered the wrong number of vectors.');
  214       }else{
  215         $rh_ans->throw_error('EVAL');
  216       }
  217     }
  218     for( my $i = 0; $i < scalar( @{$rh_ans->{ra_student_ans} }) ; $i++ )
  219     {
  220       if( $length != $rh_ans->{ra_student_ans}->[$i]->[1])
  221       {
  222         $rh_ans->{score} = 0;
  223         if( $rh_ans->{help} =~ /length|verbose/ )
  224         {
  225           $rh_ans->throw_error('EVAL','You have entered vector(s) of the wrong length.');
  226         }else{
  227           $rh_ans->throw_error('EVAL');
  228         }
  229       }
  230     }
  231     $rh_ans;
  232   });
  233   # Install prefilter for various modes
  234   if( $mat_params{mode} ne 'basis' )
  235   {
  236     if( $mat_params{mode} =~ /orthogonal|orthonormal/ )
  237     {
  238       $answer_evaluator->install_pre_filter(sub{
  239         my $rh_ans = shift;
  240         my @vecs = @{$rh_ans->{ra_student_ans}};
  241         my ($i,$j) = (0,0);
  242         my $num = scalar(@vecs);
  243         my $length = $vecs[0]->[1];
  244 
  245         for( ; $i < $num ; $i ++ )
  246         {
  247           for( $j = $i+1; $j < $num ; $j++ )
  248           {
  249             my $sum = 0;
  250             my $k = 0;
  251 
  252             for( ; $k < $length; $k++ ) {
  253               $sum += $vecs[$i]->[0][$k][0]*$vecs[$j]->[0][$k][0];
  254             }
  255 
  256             if( $sum > $mat_params{zeroLevelTol} )
  257             {
  258               $rh_ans->{score} = 0;
  259               if( $rh_ans->{help} =~ /orthogonal|orthonormal|verbose/ )
  260               {
  261                 $rh_ans->throw_error('EVAL','You have entered vectors which are not orthogonal. ');
  262               }else{
  263                 $rh_ans->throw_error('EVAL');
  264               }
  265             }
  266           }
  267         }
  268 
  269 
  270         $rh_ans;
  271       });
  272     }
  273 
  274     if( $mat_params{mode} =~ /unit|orthonormal/ )
  275     {
  276       $answer_evaluator->install_pre_filter(sub{
  277         my $rh_ans = shift;
  278         my @vecs = @{$rh_ans->{ra_student_ans}};
  279         my $i = 0;
  280         my $num = scalar(@vecs);
  281         my $length = $vecs[0]->[1];
  282 
  283         for( ; $i < $num ; $i ++ )
  284         {
  285           my $sum = 0;
  286           my $k = 0;
  287 
  288           for( ; $k < $length; $k++ ) {
  289             $sum += $vecs[$i]->[0][$k][0]*$vecs[$i]->[0][$k][0];
  290           }
  291           if( abs(sqrt($sum) - 1) > $mat_params{zeroLevelTol} )
  292           {
  293             $rh_ans->{score} = 0;
  294 
  295             if( $rh_ans->{help} =~ /unit|orthonormal|verbose/ )
  296             {
  297               $rh_ans->throw_error('EVAL','You have entered vector(s) which are not of unit length.');
  298             }else{
  299               $rh_ans->throw_error('EVAL');
  300             }
  301           }
  302         }
  303 
  304 
  305         $rh_ans;
  306       });
  307 
  308     }
  309   }
  310       $answer_evaluator->install_evaluator(\&compare_basis, %mat_params);
  311   $answer_evaluator->install_post_filter(
  312     sub {my $rh_ans = shift;
  313         if ($rh_ans->catch_error('SYNTAX') ) {
  314           $rh_ans->{ans_message} = $rh_ans->{error_message};
  315           $rh_ans->clear_error('SYNTAX');
  316         }
  317         if ($rh_ans->catch_error('EVAL') ) {
  318           $rh_ans->{ans_message} = $rh_ans->{error_message};
  319           $rh_ans->clear_error('EVAL');
  320         }
  321         $rh_ans;
  322     }
  323   );
  324   $answer_evaluator;
  325 }
  326 
  327 =head4 compare_basis
  328 
  329   compare_basis( $ans_hash, %options);
  330 
  331                 {ra_student_ans},     # a reference to the array of students answer vectors
  332                                {rm_correct_ans},      # a reference to the correct answer matrix
  333                                %options
  334                               )
  335 
  336 =cut
  337 
  338 sub compare_basis {
  339   my ($rh_ans, %options) = @_;
  340   my @ch_coord;
  341   my @vecs = @{$rh_ans->{ra_student_ans}};
  342 
  343   # A lot of the follosing code was taken from Matrix::proj_coeff
  344   # calling this method recursively would be a waste of time since
  345   # the prof's matrix never changes and solve_LR is an expensive
  346   # operation. This way it is only done once.
  347   my $matrix = $rh_ans->{rm_correct_ans};
  348   my ($dim,$x_vector, $base_matrix);
  349   my $errors = undef;
  350   my $lin_space_tr= ~ $matrix;
  351   $matrix = $lin_space_tr * $matrix;
  352   my $matrix_lr = $matrix->decompose_LR();
  353 
  354   #finds the coefficient vectors for each of the students vectors
  355   for( my $i = 0; $i < scalar(@{$rh_ans->{ra_student_ans}}) ; $i++ )
  356   {
  357 
  358     $vecs[$i] = $lin_space_tr*$vecs[$i];
  359     ($dim,$x_vector, $base_matrix) = $matrix_lr->solve_LR($vecs[$i]);
  360     push( @ch_coord, $x_vector );
  361     $errors = "A unique adapted answer could not be determined.  Possibly the parameters have coefficient zero.<br>  dim = $dim base_matrix is $base_matrix\n" if $dim;  # only print if the dim is not zero.
  362   }
  363 
  364   if( defined($errors))
  365   {
  366     $rh_ans->throw_error('EVAL', $errors) ;
  367   }else{
  368     my $ch_coord_mat = Matrix->new_from_col_vecs(\@ch_coord);#creates change of coordinate matrix
  369                   #existence of this matrix implies that
  370                   #the all of the students answers are a
  371                   #linear combo of the prof's
  372     $ch_coord_mat = $ch_coord_mat->decompose_LR();
  373 
  374     if( $ch_coord_mat->det_LR() > $options{zeroLevelTol} )# if the det of the change of coordinate matrix is
  375                   # non-zero, this implies the existence of an inverse
  376                   # which implies all of the prof's vectors are a linear
  377                   # combo of the students vectors, showing containment
  378                   # both ways.
  379     {
  380       # I think sometimes if the students space has the same dimension as the profs space it
  381       # will get projected into the profs space even if it isn't a basis for that space.
  382       # this just checks that the prof's matrix times the change of coordinate matrix is actually
  383       #the students matrix
  384       if(  abs(Matrix->new_from_col_vecs(\@{$rh_ans->{ra_student_ans}}) - ($rh_ans->{rm_correct_ans})*(Matrix->new_from_col_vecs(\@ch_coord))) < $options{zeroLevelTol} )
  385       {
  386         $rh_ans->{score} = 1;
  387       }else{
  388         $rh_ans->{score} = 0;
  389       }
  390     }
  391     else{
  392       $rh_ans->{score}=0;
  393     }
  394   }
  395   $rh_ans;
  396 
  397 }
  398 
  399 
  400 =head 2 vec_list_string
  401 
  402 This is a check_syntax type method (in fact I borrowed some of that method's code) for vector input.
  403 The student needs to enter vectors like:        [1,0,0],[1,2,3],[0,9/sqrt(10),1/sqrt(10)]
  404 Each entry can contain functions and operations and the usual math constants (pi and e).
  405 The vectors, however can not be added or multiplied or scalar multiplied by the student.
  406 Most errors are handled well. Any error in an entry is caught by the PG_answer_eval like it is in num_cmp or fun_cmp.
  407 Right now the method basically ignores every thing outside the vectors. Also, an unmatched open parenthesis is caught,
  408 but a unmatched close parenthesis ends the vector, and since everything outside is ignored, no error is sent (other than the
  409 later when the length of the vectors is checked.
  410 In the end, the method returns an array of Matrix objects.
  411 
  412 
  413 =cut
  414 
  415 sub vec_list_string{
  416   my $rh_ans = shift;
  417   my %options = @_;
  418   my $i;
  419   my $entry = "";
  420   my $char;
  421   my @paren_stack;
  422   my $length = length($rh_ans->{student_ans});
  423   my @temp;
  424   my $j = 0;
  425   my @answers;
  426   my $paren;
  427   my $display_ans;
  428 
  429   for( $i = 0; $i < $length ; $i++ )
  430   {
  431     $char = substr($rh_ans->{student_ans},$i,1);
  432 
  433     if( $char =~ /\(|\[|\{/ ){
  434         push( @paren_stack, $char )
  435     }
  436 
  437     if( !( $char =~ /\(|\[|\{/ && scalar(@paren_stack) == 1 ) )
  438     {
  439       if( $char !~ /,|\)|\]|\}/ ){
  440         $entry .= $char;
  441       }else{
  442         if( $char =~ /,/ || ( $char =~ /\)|\]|\}/ && scalar(@paren_stack) == 1 ) )
  443         {
  444           if( length($entry) == 0 ){
  445             if( $char !~ /,/ ){
  446               $rh_ans->throw_error('EVAL','There is a syntax error in your answer');
  447             }else{
  448                 $rh_ans->{preview_text_string}   .= ",";
  449                 $rh_ans->{preview_latex_string}  .= ",";
  450                 $display_ans .= ",";
  451             }
  452           }else{
  453 
  454             # This parser code was origianally taken from PGanswermacros::check_syntax
  455             # but parts of it needed to be slighty modified for this context
  456             my $parser = new AlgParserWithImplicitExpand;
  457             my $ret = $parser -> parse($entry);     #for use with loops
  458 
  459             if ( ref($ret) )  {   ## parsed successfully
  460               $parser -> tostring();
  461               $parser -> normalize();
  462               $entry = $parser -> tostring();
  463               $rh_ans->{preview_text_string} .= $entry.",";
  464               $rh_ans->{preview_latex_string} .=  $parser -> tolatex().",";
  465 
  466             } else {          ## error in parsing
  467 
  468               $rh_ans->{'student_ans'}      = 'syntax error:'.$display_ans. $parser->{htmlerror},
  469               $rh_ans->{'ans_message'}      = $display_ans.$parser -> {error_msg},
  470               $rh_ans->{'preview_text_string'}  = '',
  471               $rh_ans->{'preview_latex_string'} = '',
  472               $rh_ans->throw_error('SYNTAX',  'syntax error in answer:'.$display_ans.$parser->{htmlerror} . "$main::BR" .$parser -> {error_msg}.".$main::BR");
  473             }
  474 
  475             my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($entry);
  476 
  477             if ($PG_eval_errors) {
  478               $rh_ans->throw_error('EVAL','There is a syntax error in your answer.') ;
  479               $rh_ans->{ans_message} = clean_up_error_msg($PG_eval_errors);
  480               last;
  481             } else {
  482               $entry = prfmt($inVal,$options{format});
  483               $display_ans .= $entry.",";
  484               push(@temp , $entry);
  485             }
  486 
  487             if( $char =~ /\)|\]|\}/ && scalar(@paren_stack) == 1)
  488             {
  489               pop @paren_stack;
  490               chop($rh_ans->{preview_text_string});
  491               chop($rh_ans->{preview_latex_string});
  492               chop($display_ans);
  493               $rh_ans->{preview_text_string} .= "]";
  494               $rh_ans->{preview_latex_string} .= "]";
  495               $display_ans .= "]";
  496               if( scalar(@temp) > 0 )
  497               {
  498                 push( @answers,Matrix->new_from_col_vecs([\@temp]));
  499                 while(scalar(@temp) > 0 ){
  500                   pop @temp;
  501                 }
  502               }else{
  503                 $rh_ans->throw_error('EVAL','There is a syntax error in your answer.');
  504               }
  505             }
  506           }
  507           $entry = "";
  508         }else{
  509           $paren = pop @paren_stack;
  510           if( scalar(@paren_stack) > 0 ){
  511             #this uses ASCII to check if the parens match up
  512             # in ASCII ord ( = 40 , ord ) = 41 , ord [ = 91 ,
  513             # ord ] = 93 , ord { = 123 , ord } = 125
  514             if( (ord($char) - ord($paren) <= 2) ){
  515               $entry = $entry . $char;
  516             }else{
  517               $rh_ans->throw_error('EVAL','There is a syntax error in your answer');
  518             }
  519           }
  520         }
  521       }
  522     }else{
  523       $rh_ans->{preview_text_string}   .= "[";
  524       $rh_ans->{preview_latex_string}  .= "[";
  525       $display_ans .= "[";
  526     }
  527   }
  528   $rh_ans->{ra_student_ans} = \@answers;
  529   $rh_ans->{student_ans} = $display_ans unless $rh_ans->{error_flag};
  530   $rh_ans;
  531 }
  532 
  533 sub ans_array_filter{
  534   my $rh_ans = shift;
  535   my %options = @_;
  536   $rh_ans->{ans_label} =~ /ArRaY(\d+)\[\d+,\d+,\d+\]/;
  537   my $ans_num = $1;
  538   my @keys = grep /ArRaY$ans_num/, keys(%{$main::inputs_ref});
  539   my $key;
  540   my @array = ();
  541   my ($i,$j,$k) = (0,0,0);
  542 
  543   #the keys aren't in order, so their info has to be put into the array before doing anything with it
  544   foreach $key (@keys){
  545     $key =~ /ArRaY\d+\[(\d+),(\d+),(\d+)\]/;
  546     ($i,$j,$k) = ($1,$2,$3);
  547     $array[$i][$j][$k] = ${$main::inputs_ref}{'ArRaY'.$ans_num.'['.$i.','.$j.','.$k.']'};
  548   }
  549 
  550   my $display_ans = "";
  551 
  552   for( $i=0; $i < scalar(@array) ; $i ++ )
  553   {
  554     $display_ans .= " [";
  555           $rh_ans->{preview_text_string} .= ' [';
  556           $rh_ans->{preview_latex_string} .= ' [';
  557     for( $j = 0; $j < scalar( @{$array[$i]} ) ; $j++ )
  558     {
  559       $display_ans .= " [";
  560                   $rh_ans->{preview_text_string} .= ' [';
  561                   $rh_ans->{preview_latex_string} .= ' [';
  562       for( $k = 0; $k < scalar( @{$array[$i][$j]} ) ; $k ++ ){
  563         my $entry = $array[$i][$j][$k];
  564 
  565         # This parser code was origianally taken from PGanswermacros::check_syntax
  566         # but parts of it needed to be slighty modified for this context
  567         my $parser = new AlgParserWithImplicitExpand;
  568         my $ret = $parser -> parse($entry);     #for use with loops
  569 
  570         if ( ref($ret) )  {   ## parsed successfully
  571           $parser -> tostring();
  572           $parser -> normalize();
  573           $entry = $parser -> tostring();
  574           $rh_ans->{preview_text_string} .= $entry.",";
  575           $rh_ans->{preview_latex_string} .=  $parser -> tolatex().",";
  576         } else {          ## error in parsing
  577           $rh_ans->{'student_ans'}      = 'syntax error:'.$display_ans. $parser->{htmlerror},
  578           $rh_ans->{'ans_message'}      = $display_ans.$parser -> {error_msg},
  579           $rh_ans->{'preview_text_string'}  = '',
  580           $rh_ans->{'preview_latex_string'} = '',
  581           $rh_ans->throw_error('SYNTAX',  'syntax error in answer:'.$display_ans.$parser->{htmlerror} . "$main::BR" .$parser -> {error_msg}.".$main::BR");
  582         }
  583 
  584         my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($entry);
  585         if ($PG_eval_errors) {
  586           $rh_ans->throw_error('EVAL','There is a syntax error in your answer.') ;
  587           $rh_ans->{ans_message} = clean_up_error_msg($PG_eval_errors);
  588           last;
  589         } else {
  590           $entry = prfmt($inVal,$options{format});
  591           $display_ans .= $entry.",";
  592           $array[$i][$j][$k] = $entry;
  593         }
  594       }
  595       chop($rh_ans->{preview_text_string});
  596       chop($rh_ans->{preview_latex_string});
  597       chop($display_ans);
  598                   $rh_ans->{preview_text_string} .= '] ,';
  599                   $rh_ans->{preview_latex_string} .= '] ,';
  600       $display_ans .= '] ,';
  601 
  602     }
  603     chop($rh_ans->{preview_text_string});
  604     chop($rh_ans->{preview_latex_string});
  605     chop($display_ans);
  606                 $rh_ans->{preview_text_string} .= '] ,';
  607                 $rh_ans->{preview_latex_string} .= '] ,';
  608     $display_ans .= '] ,';
  609   }
  610   chop($rh_ans->{preview_text_string});
  611   chop($rh_ans->{preview_latex_string});
  612   chop($display_ans);
  613 
  614   $rh_ans->{original_student_ans} = $display_ans;
  615   $rh_ans->{ra_student_ans} = \@array;
  616   $rh_ans->{student_ans} = $display_ans;
  617 
  618   $rh_ans;
  619 
  620 }
  621 
  622 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9