--- loncom/homework/functionplotresponse.pm	2010/11/07 01:57:50	1.25
+++ loncom/homework/functionplotresponse.pm	2010/11/07 12:28:28	1.27
@@ -1,7 +1,7 @@
 # LearningOnline Network with CAPA
 # option list style responses
 #
-# $Id: functionplotresponse.pm,v 1.25 2010/11/07 01:57:50 www Exp $
+# $Id: functionplotresponse.pm,v 1.27 2010/11/07 12:28:28 www Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -553,86 +553,7 @@ sub d2dt2_cubic_hermite {
 #
 sub array_index {
    my ($xmin,$xmax,$x)=@_;
-   return int(($x-$xmin)/($xmax-$xmin)*200.+0.5);
-}
-
-#
-# Actual x-value of array index
-#
-
-sub index_x {
-   my ($xmin,$xmax,$i)=@_;
-   return $i*($xmax-$xmin)/200.+$xmin;
-}
-
-#
-# Assume function to be linear between array points
-# Return the two indices and the scale factor
-#
-
-sub indices_scale {
-   my ($xmin,$xmax,$x)=@_;
-   my $i=&array_index($xmin,$xmax,$x);
-   my $xr=&index_x($xmin,$xmax,$i);
-   if ($xr<$x) {
-# Desired x is right of array index
-      if ($i>=200) { return (200,200,0); }
-      return($i,$i+1,200.*($x-$xr)/($xmax-$xmin));
-   } elsif ($xr>$x) {
-# Desired x is left of array index
-      if ($i<=0) { return (0,0,0); }
-      return($i-1,$i,1.-200.*($xr-$x)/($xmax-$xmin));
-   } else {
-# Desired x is at array index (unlikely, but ...)
-      if ($i>=200) { return (200,200,0); }
-      if ($i<=0) { return (0,0,0); }
-      return ($i,$i,0);
-   }
-}
-
-#
-# Function value
-#
-
-sub func_val {
-   my ($xmin,$xmax,$x)=@_;
-   my ($il,$ih,$factor)=&indices_scale($xmin,$xmax,$x);
-   my $fl=$Apache::functionplotresponse::func[$il];
-   my $fh=$Apache::functionplotresponse::func[$ih];
-   unless (defined($fl) || defined($fh)) { return undef; }
-   unless (defined($fl)) { return $fh; }
-   unless (defined($fh)) { return $fl; }
-   return $fl+$factor*($fh-$fl);
-}
-
-#
-# First derivative
-#
-
-sub dfuncdx_val {
-   my ($xmin,$xmax,$x)=@_;
-   my ($il,$ih,$factor)=&indices_scale($xmin,$xmax,$x);
-   my $fl=$Apache::functionplotresponse::dfuncdx[$il];
-   my $fh=$Apache::functionplotresponse::dfuncdx[$ih];
-   unless (defined($fl) || defined($fh)) { return undef; }
-   unless (defined($fl)) { return $fh; }
-   unless (defined($fh)) { return $fl; }
-   return $fl+$factor*($fh-$fl);
-}
-
-#
-# Second derivative
-#
-
-sub d2funcdx2_val {
-   my ($xmin,$xmax,$x)=@_;
-   my ($il,$ih,$factor)=&indices_scale($xmin,$xmax,$x);
-   my $fl=$Apache::functionplotresponse::d2funcdx2[$il];
-   my $fh=$Apache::functionplotresponse::d2funcdx2[$ih];
-   unless (defined($fl) || defined($fh)) { return undef; }
-   unless (defined($fl)) { return $fh; }
-   unless (defined($fh)) { return $fl; }
-   return $fl+$factor*($fh-$fl);
+   return int(($x-$xmin)/($xmax-$xmin)*400.+0.5);
 }
 
 #
@@ -641,7 +562,7 @@ sub d2funcdx2_val {
 
 sub populate_arrays {
     my ($id,$xmin,$xmax)=@_;
-    for (my $i=0; $i<=200; $i++) {
+    for (my $i=0; $i<=400; $i++) {
        $Apache::functionplotresponse::func[$i]=undef;
        $Apache::functionplotresponse::dfuncdx[$i]=undef;
        $Apache::functionplotresponse::d2funcd2x[$i]=undef;
@@ -662,10 +583,10 @@ sub populate_arrays {
                         $env{'form.HWVAL_'.$id.'_'.$label.'P'.$ni.'_y'},
                         $env{'form.HWVAL_'.$id.'_'.$label.'S'.$ni.'_y'});
 # Run in small steps over spline parameter
-            for (my $t=0; $t<=1; $t+=0.00025) {
+            for (my $t=0; $t<=1; $t+=0.0001) {
                 my $xi=&array_index($xmin,$xmax,&cubic_hermite($t,@xparms));
                 if ($xi<$xiold) { return 'no_func'; }
-                if (($xi>$xiold) && ($xi>=0) && ($xi<=200)) {
+                if (($xi>$xiold) && ($xi>=0) && ($xi<=400)) {
                    if (defined($Apache::functionplotresponse::func[$xi])) { return 'no_func'; }
                    $xiold=$xi;
 # Function value
@@ -678,7 +599,7 @@ sub populate_arrays {
 # d^2y/dx^2
                    my $d2xdt2=&d2dt2_cubic_hermite($t,@xparms);
                    if ($d2xdt2) {
-                      $Apache::functionplotresponse::d2funcd2x[$xi]=&d2dt2_cubic_hermite($t,@yparms)/$d2xdt2;
+                      $Apache::functionplotresponse::d2funcdx2[$xi]=&d2dt2_cubic_hermite($t,@yparms)/$d2xdt2;
                    }
                 }
             }
@@ -786,8 +707,43 @@ sub start_functionplotresponse {
 }
 
 sub compare_rel {
-   my ($relationship,$value,$val,$tol)=@_;
-   if (abs($value-$val)<$tol) { return 1; }
+   my ($relationship,$value,$realval,$tol)=@_;
+   
+
+  &Apache::lonnet::logthis("Rel $relationship Val $value RV $realval T $tol");
+# is the real value defined?
+   unless (defined($realval)) {
+      if ($relationship eq 'eq') {
+         if ($value eq 'undef') {
+            return 1;
+         } else {
+            return 0;
+         }
+      } elsif ($relationship eq 'ne') {
+         if ($value eq 'undef') {
+            return 0;
+         } else {
+            return 1;
+         }
+      } else {
+         return 0;
+      }
+   }
+
+# it is defined.
+   if ($relationship eq 'gt') {
+      return ($realval>$value);
+   } elsif ($relationship eq 'ge') {
+      return ($realval>$value-$tol);
+   } elsif ($relationship eq 'lt') {
+      return ($realval<$value);
+   } elsif ($relationship eq 'le') {
+      return ($realval<$value+$tol);
+   } elsif ($relationship eq 'ne') {
+      return (abs($value-$realval)>$tol);
+   } else {
+      return (abs($value-$realval)<$tol);
+   }
    return 0;
 }
 
@@ -813,36 +769,39 @@ sub functionplotrulecheck {
    if ($xinitial eq '') {
       $xinitial=0;
    }
-   if ($xfinal ne '') {
-      if ($xinitial>$xfinal) {
-         $xfinal=$xinitial;
-      }
+   if ($xfinal eq '') {
+      $xfinal=$xinitial;
+   }
+   if ($xinitial>$xfinal) {
+       $xfinal=$xinitial;
    }
    &Apache::lonnet::logthis("Init $xinitial Final $xfinal");
-   if (($xfinal eq '') || ($xinitial==$xfinal)) {
-# This is only one point
-        &Apache::lonnet::logthis("One point $xinitial");
-        my $tol;
+   my $tol=$tolfunc;
+   if ($derivative==2) {
+      $tol=$told2fdx2;
+   } elsif ($derivative==1) {
+      $tol=$toldfdx;
+   }
+
+   my $li=&array_index($xmin,$xmax,$xinitial);
+   my $lh=&array_index($xmin,$xmax,$xfinal);
+   for (my $i=$li; $i<=$lh; $i++) {
         my $val;
         if ($derivative==2) {
-           $val=&d2funcdx2_val($xmin,$xmax,$xinitial);
-           $tol=$told2fdx2;
+            &Apache::lonnet::logthis("Second ".
+
+$Apache::functionplotresponse::d2funcdx2[$i-1].'__'.$Apache::functionplotresponse::d2funcdx2[$i].'__'.$Apache::functionplotresponse::d2funcdx2[$i+1]);
+           $val=$Apache::functionplotresponse::d2funcdx2[$i];
         } elsif ($derivative==1) {
-           $val=&dfuncdx_val($xmin,$xmax,$xinitial);
-           $tol=$toldfdx;
+           $val=$Apache::functionplotresponse::dfuncdx[$i];
         } else {
-           $val=&func_val($xmin,$xmax,$xinitial);
-           $tol=$tolfunc;
+           $val=$Apache::functionplotresponse::func[$i];
         }
-        &Apache::lonnet::logthis("Value $value ActVal $val Tol $tol");
-        return &compare_rel($relationship,$value,$val,$tol);
-   } else {
-# This is a range
+        unless (&compare_rel($relationship,$value,$val,$tol)) { return 0; };
    }
-   return 0;
+   return 1;
 }
 
-
 sub end_functionplotresponse {
   my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
   &Apache::response::end_response;
@@ -857,7 +816,7 @@ sub end_functionplotresponse {
          && &Apache::response::submitted()
          && $Apache::lonhomework::type eq 'exam') {
 
-        #&Apache::response::scored_response($partid,$id);
+        &Apache::response::scored_response($partid,$id);
 
     } elsif ($target eq 'grade'
          && &Apache::response::submitted()
@@ -876,7 +835,11 @@ sub end_functionplotresponse {
         $ymin=(defined($ymin)?$ymin:-10);
         my $ymax=&Apache::lonxml::get_param('ymax',$parstack,$safeeval);
         $ymax=(defined($ymax)?$ymax:10);
-        my $tolfunc=($ymax-$ymin)/100.;
+
+        my $percent=&Apache::lonxml::get_param('percenterror',$parstack,$safeeval);
+        $percent=(defined($percent)?$percent:5);
+
+        my $tolfunc=$percent*($ymax-$ymin)/100.;
         my $toldfdx=1;
         my $told2fdx2=1;
         if ($xmax>$xmin) {