Diff for /loncom/homework/functionplotresponse.pm between versions 1.53 and 1.79

version 1.53, 2011/01/28 16:06:49 version 1.79, 2011/11/20 02:53:27
Line 1 Line 1
 # LearningOnline Network with CAPA  # LearningOnline Network with CAPA
 # option list style responses  # Functionplot responses
 #  #
 # $Id$  # $Id$
 #  #
Line 31  use strict; Line 31  use strict;
 use Apache::response();  use Apache::response();
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnet;  use Apache::lonnet;
   use Apache::run;
     
 BEGIN {  BEGIN {
   &Apache::lonxml::register('Apache::functionplotresponse',('functionplotresponse','backgroundplot','spline',    &Apache::lonxml::register('Apache::functionplotresponse',('functionplotresponse','backgroundplot','spline',
                                                               'plotobject','plotvector','functionplotvectorrule','functionplotvectorsumrule',
                                                             'functionplotrule','functionplotruleset',                                                              'functionplotrule','functionplotruleset',
                                                             'functionplotelements'));                                                              'functionplotelements'));
 }  }
Line 61  sub geogebra_endcode { Line 63  sub geogebra_endcode {
 #  #
 sub geogebra_spline_program {  sub geogebra_spline_program {
     return (<<ENDSPLINEPROGRAM);      return (<<ENDSPLINEPROGRAM);
 <param name="ggbBase64" value="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" />  <param name="ggbBase64" value="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"/>
 ENDSPLINEPROGRAM  ENDSPLINEPROGRAM
 }  }
   
Line 74  sub geogebra_default_parameters { Line 76  sub geogebra_default_parameters {
         <param name="image" value="/adm/lonIcons/lonanim.gif"  />          <param name="image" value="/adm/lonIcons/lonanim.gif"  />
         <param name="boxborder" value="false"  />          <param name="boxborder" value="false"  />
         <param name="centerimage" value="true"  />          <param name="centerimage" value="true"  />
  <param name="cache_archive" value="geogebra.jar, geogebra_main.jar, geogebra_gui.jar, geogebra_cas.jar, geogebra_algos.jar, geogebra_export.jar, geogebra_javascript.jar, jlatexmath.jar, jlm_greek.jar, jlm_cyrillic.jar, geogebra_properties.jar" />   <param name="cache_archive" value="geogebra.jar, geogebra_main.jar, geogebra_gui.jar, geogebra_cas.jar, geogebra_export.jar, geogebra_algos.jar, geogebra_javascript.jar, geogebra_properties.jar, jlatexmath.jar, jlm_cyrillic.jar, jlm_greek.jar" />
  <param name="cache_version" value="3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0, 3.9.115.0" />   <param name="cache_version" value="4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0,4.0.1.0" />
         <param name="framePossible" value="false" />          <param name="framePossible" value="false" />
   
         <param name="showResetIcon" value="false" />          <param name="showResetIcon" value="false" />
Line 163  sub update_register { Line 165  sub update_register {
 sub set_point_coordinate {  sub set_point_coordinate {
    my ($id,$variable,$x,$y,$fixed)=@_;     my ($id,$variable,$x,$y,$fixed)=@_;
    my $mult=($fixed?'a*':'');     my $mult=($fixed?'a*':'');
   # Get rid of wild exponents, make sure it's a number
      $x=1.*$x;
      $y=1.*$y;
   # GeoGebra does not understand "E"
      $x=~s/[e|E]/\*10\^/;
      $x=~s/\+//;
      $y=~s/[e|E]/\*10\^/;
      $y=~s/\+//;
    return (<<ENDSETVARIABLE);     return (<<ENDSETVARIABLE);
 document.ggbApplet_$id.evalCommand("a=1");  document.ggbApplet_$id.evalCommand("a=1");
 document.ggbApplet_$id.evalCommand("$variable=$mult($x,$y)");  document.ggbApplet_$id.evalCommand("$variable=$mult($x,$y)");
Line 333  ENDYOFFAXISLABEL Line 343  ENDYOFFAXISLABEL
     return $return;      return $return;
 }  }
   
   #
   # Subroutine to produce background and answer plots
   #
   
 sub plot_script {  sub plot_script {
    my ($id,$function,$fixed,$label,$color,$xmin,$xmax,$thickness)=@_;     my ($id,$function,$fixed,$label,$color,$xmin,$xmax,$thickness)=@_;
    $label=~s/\W//g;     $label=~s/\W//g;
Line 366  sub plot_script { Line 380  sub plot_script {
 }  }
   
 #  #
   # Subroutine to produce objects
   #
   
   sub plotobject_script {
      my ($id,$label,$x,$y)=@_;
      unless ($label) {
         $Apache::functionplotresponse::counter++;
         $label='O'.$Apache::functionplotresponse::counter;
      }
      &generate_input_field($id,$label,$x,$y);
      return "document.ggbApplet_$id.evalCommand('a=1');\n".
             "document.ggbApplet_$id.setVisible('a', false);\n".
             "document.ggbApplet_$id.setLabelVisible('a', false);\n".
             "document.ggbApplet_$id.evalCommand('$label=a*($x,$y)');\n".
             "document.ggbApplet_$id.setVisible('$label', true);\n".
             "document.ggbApplet_$id.setLabelVisible('$label', true);\n";
   }
   
   #
   # Subroutine to produce vectors
   #
   
   sub plotvector_script {
      my ($id,$label,$xs,$ys,$xe,$ye,$xmin,$xmax)=@_;
      unless ($label) {
         $Apache::functionplotresponse::counter++;
         $label='V'.$Apache::functionplotresponse::counter;
      }
      my $startlabel=$label.'Start';
      my $endlabel=$label.'End';
      my $pointlabel=$label.'Point';
      my $pointx=2.*($xmax-$xmin)+$xmax;
      my $anglelabel=$label.'Angle';
      return 
          &new_point_coordinate($id,$startlabel,$xs,$ys,0).
          &new_point_coordinate($id,$endlabel,$xe,$ye,0).
          (<<ENDVECTOR);
   document.ggbApplet_$id.evalCommand("$label=Vector[$startlabel,$endlabel]");
   document.ggbApplet_$id.setLabelVisible("$label",true);
   document.ggbApplet_$id.setLineThickness("$label",8);
   document.ggbApplet_$id.evalCommand("$pointlabel=($pointx,y($startlabel))");
   document.ggbApplet_$id.evalCommand("$anglelabel=Angle[$pointlabel,$startlabel,$endlabel]");
   document.ggbApplet_$id.setLabelVisible("$anglelabel",true);
   document.ggbApplet_$id.setLabelStyle("$anglelabel",VALUE=2);
   ENDVECTOR
   }
   
   #
   # Answer spline display
   # 
   # points: x,y,slope_x,slope_y
   
   sub answer_spline_script {
      my ($id,@points)=@_;
      my $order=int(($#points+1)/4);
      if ($order<2) { $order=2; }
      if ($order>8) { $order=8; }
      $Apache::functionplotresponse::counter++;
      my $label='CSpline'.$Apache::functionplotresponse::counter;
      my $output='document.ggbApplet_'.$id.'.evalCommand("'.$label.'=Spline'.$order.'[';
      for (my $i=0;$i<=$#points;$i+=4) {
         $output.="($points[$i],$points[$i+1]),($points[$i+2],$points[$i+3]),";
      }
      $output=~s/\,$//;
      $output.=']");'."\n";
      for (my $i=2; $i<2*$order; $i+=2) {
          $output.='document.ggbApplet_'.$id.'.setColor("'.$label.'_'.($i>=10?'{':'').$i.($i>=10?'}':'').'",0,170,0);'."\n";
      }
      for (my $i=1; $i<2*$order; $i+=2) {
          $output.='document.ggbApplet_'.$id.'.setVisible("'.$label.'_'.($i>=10?'{':'').$i.($i>=10?'}':'').'",false);'."\n";
      }
   
      return $output;
   }
   
   #
 # Subroutine that generates code for spline $label based on stored information  # Subroutine that generates code for spline $label based on stored information
 #  #
   
Line 390  sub generate_spline { Line 480  sub generate_spline {
    $result.='document.ggbApplet_'.$id.'.evalCommand("Spline'.$order.'['.join(',',@coords).']");'."\n";     $result.='document.ggbApplet_'.$id.'.evalCommand("Spline'.$order.'['.join(',',@coords).']");'."\n";
    return $result;     return $result;
 }  }
   
   #
   # Object
   #
   
   sub start_plotobject {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      my $internalid = $Apache::inputtags::part.'_'.$Apache::inputtags::response[-1];
      my $x=&Apache::lonxml::get_param('x',$parstack,$safeeval);
      my $y=&Apache::lonxml::get_param('y',$parstack,$safeeval);
      my $label=&Apache::lonxml::get_param('label',$parstack,$safeeval);
      $label=~s/\W//gs;
      $label=ucfirst($label);
      unless ($label) { $label="NewObject"; }
      if ($target eq 'web') {
         my ($xmin,$xmax,$ymin,$ymax)=&boundaries($parstack,$safeeval,-3);
         unless (defined($x)) { $x=$xmin; }
         unless (defined($y)) { $y=$ymin; }
         $result.=&plotobject_script($internalid,$label,$x,$y);
      } elsif ($target eq 'edit') {
           $result=&Apache::edit::tag_start($target,$token,'Plot Object').
                &Apache::edit::text_arg('Label on Plot:','label',
                                        $token,'16').
                &Apache::edit::text_arg('x:','x',
                                        $token,'8').
                &Apache::edit::text_arg('y:','y',
                                        $token,'8').
                &Apache::edit::end_row();
     } elsif ($target eq 'modified') {
       $env{'form.'.&Apache::edit::html_element_name('label')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('label')});
       my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'label','x','y');
       if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
     }
     return $result;
   }
   
   sub end_plotobject {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      if ($target eq 'edit') {
          $result=&Apache::edit::end_table();
      }
      return $result;
   }
   
   #
   # Vector
   #
   
   sub start_plotvector {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      my $internalid = $Apache::inputtags::part.'_'.$Apache::inputtags::response[-1];
      my $tailx=&Apache::lonxml::get_param('tailx',$parstack,$safeeval);
      my $taily=&Apache::lonxml::get_param('taily',$parstack,$safeeval);
      my $tipx=&Apache::lonxml::get_param('tipx',$parstack,$safeeval);
      my $tipy=&Apache::lonxml::get_param('tipy',$parstack,$safeeval);
   
      my $label=&Apache::lonxml::get_param('label',$parstack,$safeeval);
      $label=~s/\W//gs;
      $label=ucfirst($label);
      unless ($label) { $label="NewVector"; }
      if ($target eq 'web') {
         my ($xmin,$xmax,$ymin,$ymax)=&boundaries($parstack,$safeeval,-3);
         unless (defined($tailx)) { $tailx=$xmin; }
         unless (defined($taily)) { $taily=$ymin; }
         unless (defined($tipx)) { $tipx=$xmin; }
         unless (defined($tipy)) { $tipy=$ymin; }
         $result.=&plotvector_script($internalid,$label,$tailx,$taily,$tipx,$tipy,$xmin,$xmax);
      } elsif ($target eq 'edit') {
           $result=&Apache::edit::tag_start($target,$token,'Plot Vector').
                &Apache::edit::text_arg('Label on Plot:','label',
                                        $token,'16').
                &Apache::edit::text_arg('Tail x:','tailx',
                                        $token,'8').
                &Apache::edit::text_arg('Tail y:','taily',
                                        $token,'8').
                &Apache::edit::text_arg('Tip x:','tipx',
                                        $token,'8').
                &Apache::edit::text_arg('Tip y:','tipy',
                                        $token,'8').
   
                &Apache::edit::end_row();
     } elsif ($target eq 'modified') {
       $env{'form.'.&Apache::edit::html_element_name('label')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('label')});
       my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'label','tailx','taily','tipx','tipy');
       if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
     }
     return $result;
   }
   
   sub end_plotvector {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      if ($target eq 'edit') {
          $result=&Apache::edit::end_table();
      }
      return $result;
   }
   
   
   
 #  #
 # <backgroundplot function="..." fixed="yes/no" />  # <backgroundplot function="..." fixed="yes/no" />
 #  #
Line 501  sub start_functionplotrule { Line 694  sub start_functionplotrule {
            &Apache::lonxml::get_param('percenterror',$parstack,$safeeval)             &Apache::lonxml::get_param('percenterror',$parstack,$safeeval)
           )));            )));
    } elsif ($target eq 'edit') {     } elsif ($target eq 'edit') {
         $result=&Apache::edit::tag_start($target,$token,'Function Plot Evaluation Rule').          $result=&Apache::edit::tag_start($target,$token,'Function Plot Graph Rule').
              &Apache::edit::text_arg('Index/Name:','index',               &Apache::edit::text_arg('Index/Name:','index',
                                      $token,'10').'&nbsp;'.                                       $token,'10').'&nbsp;'.
              &Apache::edit::select_arg(&mt('Function:'),'derivativeorder',               &Apache::edit::select_arg(&mt('Function:'),'derivativeorder',
Line 531  sub start_functionplotrule { Line 724  sub start_functionplotrule {
                                    ['lt','less than'],                                     ['lt','less than'],
                                    ['le','less than or equal']],$token).                                     ['le','less than or equal']],$token).
              $result.= &Apache::edit::select_or_text_arg('Value:','value',               $result.= &Apache::edit::select_or_text_arg('Value:','value',
                                                [['undef','not defined']],$token,'8').                                                 [['undef','not defined']],$token,'30').
              &Apache::edit::text_arg('Percent error:','percenterror',               &Apache::edit::text_arg('Percent error:','percenterror',
                                      $token,'8').                                       $token,'8').
              &Apache::edit::end_row();               &Apache::edit::end_row();
   } elsif ($target eq 'modified') {    } elsif ($target eq 'modified') {
     if (($env{'form.'.&Apache::edit::html_element_name('xinitial')} ne '') & ($env{'form.'.&Apache::edit::html_element_name('xinitiallabel')} eq 'start')) {      if (($env{'form.'.&Apache::edit::html_element_name('xinitial')} ne '') && ($env{'form.'.&Apache::edit::html_element_name('xinitiallabel')} eq 'start')) {
        $env{'form.'.&Apache::edit::html_element_name('xinitiallabel')}='';         $env{'form.'.&Apache::edit::html_element_name('xinitiallabel')}='';
     }      }
     if (($env{'form.'.&Apache::edit::html_element_name('xfinal')} ne '') & ($env{'form.'.&Apache::edit::html_element_name('xfinallabel')} eq 'end')) {      if (($env{'form.'.&Apache::edit::html_element_name('xfinal')} ne '') && ($env{'form.'.&Apache::edit::html_element_name('xfinallabel')} eq 'end')) {
        $env{'form.'.&Apache::edit::html_element_name('xfinallabel')}='';         $env{'form.'.&Apache::edit::html_element_name('xfinallabel')}='';
     }      }
     my $constructtag=&Apache::edit::get_new_args($token,$parstack,      my $constructtag=&Apache::edit::get_new_args($token,$parstack,
Line 563  sub end_functionplotrule { Line 756  sub end_functionplotrule {
   
   
 #  #
   # <functionplotvectorrule ... />
   #
   sub start_functionplotvectorrule {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      my $label=&Apache::lonxml::get_param('index',$parstack,$safeeval);
      $Apache::functionplotresponse::counter++;
      if ($label=~/\W/) {
         &Apache::lonxml::warning(&mt('Rule indices should only contain alphanumeric characters.'));
      }
      $label=~s/\W//gs;
      unless ($label) {
         $label='R'.$Apache::functionplotresponse::counter;
      } else {
         $label='R'.$label;
      }
      if ($Apache::functionplotresponse::splineorder{$label}) {
          &Apache::lonxml::error(&mt('Rule indices must be unique.'));
      }
   
      if ($target eq 'grade') {
   # Simply remember - in order - for later
   
         my $id=$Apache::inputtags::response[-1];
         my $partid=$Apache::inputtags::part;
         my $internalid = $partid.'_'.$id;
   
         my $vector=&Apache::lonxml::get_param('vector',$parstack,$safeeval);
         $vector=~s/\W//gs;
         $vector=ucfirst($vector);
   
         my $attachpoint=&Apache::lonxml::get_param('attachpoint',$parstack,$safeeval);
         $attachpoint=~s/\W//gs;
         $attachpoint=ucfirst($attachpoint);
   
         my $notattachpoint=&Apache::lonxml::get_param('notattachpoint',$parstack,$safeeval);
         $notattachpoint=~s/\W//gs;
         $notattachpoint=ucfirst($notattachpoint);
   
         my $tailpoint=&Apache::lonxml::get_param('tailpoint',$parstack,$safeeval);
         $tailpoint=~s/\W//gs;
         $tailpoint=ucfirst($tailpoint);
         my $tippoint=&Apache::lonxml::get_param('tippoint',$parstack,$safeeval);
         $tippoint=~s/\W//gs;
         $tippoint=ucfirst($tippoint);
   
         my $nottailpoint=&Apache::lonxml::get_param('nottailpoint',$parstack,$safeeval);
         $nottailpoint=~s/\W//gs;
         $nottailpoint=ucfirst($nottailpoint);
         my $nottippoint=&Apache::lonxml::get_param('nottippoint',$parstack,$safeeval);
         $nottippoint=~s/\W//gs;
         $nottippoint=ucfirst($nottippoint);
   
         push(@Apache::functionplotresponse::functionplotvectorrules,join(':',(
              $label,
              'vector',
              $internalid,
              $vector,
              $attachpoint,
              $notattachpoint,
              $tailpoint,
              $tippoint,
              $nottailpoint,
              $nottippoint,
              &Apache::lonxml::get_param('length',$parstack,$safeeval),
              &Apache::lonxml::get_param('angle',$parstack,$safeeval),
              &Apache::lonxml::get_param('lengtherror',$parstack,$safeeval),
              &Apache::lonxml::get_param('angleerror',$parstack,$safeeval),
             )));
      } elsif ($target eq 'edit') {
           $result=&Apache::edit::tag_start($target,$token,'Function Plot Vector Rule').
                &Apache::edit::text_arg('Index/Name:','index',
                                        $token,'10').'&nbsp;'.
                &Apache::edit::text_arg('Vector:','vector',
                                         $token,'16').'<br />'.
                &Apache::edit::text_arg('Attached to object:','attachpoint',
                                         $token,'16').
                &Apache::edit::text_arg('Not attached to object:','notattachpoint',
                                         $token,'16').'<br />'.
                &Apache::edit::text_arg('Tail attached to object:','tailpoint',
                                         $token,'16').
                &Apache::edit::text_arg('Tip attached to object:','tippoint',
                                         $token,'16').
                &Apache::edit::text_arg('Tail not attached to object:','nottailpoint',
                                         $token,'16').
                &Apache::edit::text_arg('Tip not attached to object:','nottippoint',
                                         $token,'16').'<br />'.
                &Apache::edit::text_arg('Length:','length',
                                        $token,'16').
                &Apache::edit::text_arg('Angle:','angle',
                                        $token,'16').
                &Apache::edit::text_arg('Absolute error length:','lengtherror',
                                        $token,'8').
                &Apache::edit::text_arg('Absolute error angle:','angleerror',
                                        $token,'8').
                &Apache::edit::end_row();
     } elsif ($target eq 'modified') {
       $env{'form.'.&Apache::edit::html_element_name('vector')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('vector')});
       $env{'form.'.&Apache::edit::html_element_name('attachpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('attachpoint')});
       $env{'form.'.&Apache::edit::html_element_name('notattachpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('notattachpoint')});
       $env{'form.'.&Apache::edit::html_element_name('tailpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('tailpoint')});
       $env{'form.'.&Apache::edit::html_element_name('tippoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('tippoint')});
       $env{'form.'.&Apache::edit::html_element_name('nottailpoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('nottailpoint')});
       $env{'form.'.&Apache::edit::html_element_name('nottippoint')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('nottippoint')});
       my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                                                    $safeeval,'index','vector','attachpoint','notattachpoint',
                                                              'tailpoint','tippoint','nottailpoint','nottipoint',
                                                              'length','angle',
                                                              'lengtherror','angleerror');
       if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
      }
      return $result;
   }
   
   sub end_functionplotvectorrule {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      if ($target eq 'edit') {
          $result=&Apache::edit::end_table();
      }
      return $result;
   }
   
   #
   # <functionplotvectorsumrule ... />
   #
   sub start_functionplotvectorsumrule {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      my $label=&Apache::lonxml::get_param('index',$parstack,$safeeval);
      $Apache::functionplotresponse::counter++;
      if ($label=~/\W/) {
         &Apache::lonxml::warning(&mt('Rule indices should only contain alphanumeric characters.'));
      }
      $label=~s/\W//gs;
      unless ($label) {
         $label='R'.$Apache::functionplotresponse::counter;
      } else {
         $label='R'.$label;
      }
      if ($Apache::functionplotresponse::splineorder{$label}) {
          &Apache::lonxml::error(&mt('Rule indices must be unique.'));
      }
      if ($target eq 'grade') {
   # Simply remember - in order - for later
         my $id=$Apache::inputtags::response[-1];
         my $partid=$Apache::inputtags::part;
         my $internalid = $partid.'_'.$id;
         my $object=&Apache::lonxml::get_param('object',$parstack,$safeeval);
         $object=~s/\W//gs;
         $object=ucfirst($object);
         push(@Apache::functionplotresponse::functionplotvectorrules,join(':',(
              $label,
              'sum',
              $internalid,
              $object,
              &Apache::lonxml::get_param('length',$parstack,$safeeval),
              &Apache::lonxml::get_param('angle',$parstack,$safeeval),
              &Apache::lonxml::get_param('lengthpercenterror',$parstack,$safeeval),
              &Apache::lonxml::get_param('lengthabserror',$parstack,$safeeval),
              &Apache::lonxml::get_param('angleerror',$parstack,$safeeval),
             )));
      } elsif ($target eq 'edit') {
           $result=&Apache::edit::tag_start($target,$token,'Function Plot Vector Sum Rule').
                &Apache::edit::text_arg('Index/Name:','index',
                                        $token,'10').'&nbsp;'.
                &Apache::edit::text_arg('Vectors attached to object:','object',
                                         $token,'16').'<br />'.
                &Apache::edit::text_arg('Sum vector length:','length',
                                        $token,'16').
                &Apache::edit::text_arg('Sum vector angle:','angle',
                                        $token,'16').
                &Apache::edit::text_arg('Percent error length:','lengthpercenterror',
                                        $token,'8').
                &Apache::edit::text_arg('Absolute error length:','lengthabserror',
                                        $token,'8').
                &Apache::edit::text_arg('Error angle:','angleerror',
                                        $token,'8').
                &Apache::edit::end_row();
     } elsif ($target eq 'modified') {
       $env{'form.'.&Apache::edit::html_element_name('object')}=ucfirst($env{'form.'.&Apache::edit::html_element_name('object')});
       my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                                                    $safeeval,'index','object',
                                                              'length','angle',
                                                              'lengthpercenterror','lengthabserror','angleerror');
       if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); }
      }
      return $result;
   }
   
   sub end_functionplotvectorsumrule {
      my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
      my $result='';
      if ($target eq 'edit') {
          $result=&Apache::edit::end_table();
      }
      return $result;
   }
   
   #
 # <spline index="..." order="1,2,3,4" initx="..." inity="..." scalex="..." scaley="..." />  # <spline index="..." order="1,2,3,4" initx="..." inity="..." scalex="..." scaley="..." />
 #  #
 # Unfortunately, GeoGebra seems to want all splines after everything else, so we need to store them  # Unfortunately, GeoGebra seems to want all splines after everything else, so we need to store them
Line 719  sub array_index { Line 1112  sub array_index {
 #  #
   
 sub populate_arrays {  sub populate_arrays {
     my ($id,$xmin,$xmax)=@_;      my ($id,$xmin,$xmax,$ymin,$ymax)=@_;
     for (my $i=0; $i<=400; $i++) {      for (my $i=0; $i<=400; $i++) {
        $Apache::functionplotresponse::actualxval[$i]=undef;         $Apache::functionplotresponse::actualxval[$i]=undef;
        $Apache::functionplotresponse::func[$i]=undef;         $Apache::functionplotresponse::func[$i]=undef;
Line 747  sub populate_arrays { Line 1140  sub populate_arrays {
                 my $xi=&array_index($xmin,$xmax,$xreal);                  my $xi=&array_index($xmin,$xmax,$xreal);
                 if ($xi<$xiold) { return 'no_func'; }                  if ($xi<$xiold) { return 'no_func'; }
                 if (($xi>$xiold) && ($xi>=0) && ($xi<=400)) {                  if (($xi>$xiold) && ($xi>=0) && ($xi<=400)) {
                    if (defined($Apache::functionplotresponse::func[$xi])) { return 'no_func'; }  
                    $xiold=$xi;                     $xiold=$xi;
                    $Apache::functionplotresponse::actualxval[$xi]=$xreal;                     $Apache::functionplotresponse::actualxval[$xi]=$xreal;
 # Function value  # Function value
                    my $funcval=&cubic_hermite($t,@yparms);                     my $funcval=&cubic_hermite($t,@yparms);
   
   # Do we already have a value for this point, and is it different from the new one?
                      if ((defined($Apache::functionplotresponse::func[$xi])) &&
                          (abs($Apache::functionplotresponse::func[$xi]-$funcval)>($ymax-$ymin)/100.)) { 
                          return 'no_func'; 
                      }
   # Okay, remember the new point
                    $Apache::functionplotresponse::func[$xi]=$funcval;                     $Apache::functionplotresponse::func[$xi]=$funcval;
   
                    if (defined($funcval)) {                     if (defined($funcval)) {
                       if ($xi<$Apache::functionplotresponse::functionplotrulelabels{'start'}) {                        if ($xi<$Apache::functionplotresponse::functionplotrulelabels{'start'}) {
                          $Apache::functionplotresponse::functionplotrulelabels{'start'}=$xi;                           $Apache::functionplotresponse::functionplotrulelabels{'start'}=$xi;
Line 796  sub start_functionplotresponse { Line 1196  sub start_functionplotresponse {
   $Apache::functionplotresponse::counter=0;    $Apache::functionplotresponse::counter=0;
 # Remember rules  # Remember rules
   undef @Apache::functionplotresponse::functionplotrules;    undef @Apache::functionplotresponse::functionplotrules;
     undef @Apache::functionplotresponse::functionplotvectorrules;
 # Remember failed rules  # Remember failed rules
   if ($target eq 'grade') {    if ($target eq 'grade') {
      undef @Apache::functionplotresponse::failedrules;       undef @Apache::functionplotresponse::failedrules;
Line 847  sub start_functionplotresponse { Line 1248  sub start_functionplotresponse {
                                   ['yes','no'],$token).'<br />'.                                    ['yes','no'],$token).'<br />'.
              &Apache::edit::select_arg('Grid visible:','gridvisible',               &Apache::edit::select_arg('Grid visible:','gridvisible',
                                   ['yes','no'],$token).'<br />'.                                    ['yes','no'],$token).'<br />'.
              &Apache::edit::text_arg('Background plot(s) for answer (function:xmin:xmax,function:xmin:xmax,...):',               &Apache::edit::text_arg('Background plot(s) for answer (function(x):xmin:xmax,function(x):xmin:xmax,x1:y1:sx1:sy1:x2:y2:sx2:sy2,...):',
                                          'answerdisplay',$token,'50');                                           'answerdisplay',$token,'50').
   
              &Apache::edit::end_row().&Apache::edit::start_spanning_row();               &Apache::edit::end_row().&Apache::edit::start_spanning_row();
   } elsif ($target eq 'modified') {    } elsif ($target eq 'modified') {
     my $constructtag=&Apache::edit::get_new_args($token,$parstack,      my $constructtag=&Apache::edit::get_new_args($token,$parstack,
Line 934  sub compare_rel { Line 1334  sub compare_rel {
   
 sub addlog {  sub addlog {
    my ($text)=@_;     my ($text)=@_;
      $text=~s/\'/\\\'/g;
    $Apache::functionplotresponse::ruleslog.=$text.'<br />';     $Apache::functionplotresponse::ruleslog.=$text.'<br />';
 }  }
   
Line 941  sub actualval { Line 1342  sub actualval {
    my ($i,$xmin,$xmax)=@_;     my ($i,$xmin,$xmax)=@_;
    return $xmin+$i/400.*($xmax-$xmin);     return $xmin+$i/400.*($xmax-$xmin);
 }  }
   
   sub fpr_val {
      my ($arg)=@_;
      return &actualval($Apache::functionplotresponse::functionplotrulelabels{$arg},
                        $Apache::functionplotresponse::fpr_xmin,
                        $Apache::functionplotresponse::fpr_xmax);
   }
   
   sub fpr_f {
      my ($arg)=@_;
      return $Apache::functionplotresponse::func[&array_index($Apache::functionplotresponse::fpr_xmin,
                                                              $Apache::functionplotresponse::fpr_xmax,
                                                              $arg)];
   }
   
   sub fpr_dfdx {
      my ($arg)=@_;
      return $Apache::functionplotresponse::dfuncdx[&array_index($Apache::functionplotresponse::fpr_xmin,
                                                                 $Apache::functionplotresponse::fpr_xmax,
                                                                 $arg)];
   }
   
   sub fpr_d2fdx2 {
      my ($arg)=@_;
      return $Apache::functionplotresponse::d2funcdx2[&array_index($Apache::functionplotresponse::fpr_xmin,
                                                                   $Apache::functionplotresponse::fpr_xmax,
                                                                   $arg)];
   }
   
   
   sub vectorcoords {
      my ($id,$label)=@_;
      return ($env{'form.HWVAL_'.$id.'_'.$label.'Start_x'},
              $env{'form.HWVAL_'.$id.'_'.$label.'End_x'},
              $env{'form.HWVAL_'.$id.'_'.$label.'Start_y'},
              $env{'form.HWVAL_'.$id.'_'.$label.'End_y'});
   }
   
   sub objectcoords {
      my ($id,$label)=@_;
      return ($env{'form.HWVAL_'.$id.'_'.$label.'_x'},
              $env{'form.HWVAL_'.$id.'_'.$label.'_y'});
   }
    
   sub vectorangle {
      my ($x,$y)=@_;
      my $angle=57.2957795*atan2($y,$x);
      if ($angle<0) { $angle=360+$angle; }
      return $angle;
   }
   
   sub vectorlength {
      my ($x,$y)=@_;
      return sqrt($x*$x+$y*$y);
   }
   
   sub relvector {
      my ($xs,$xe,$ys,$ye)=@_;
      return ($xe-$xs,$ye-$ys);
   }
   
   sub plotvectorlength {
      return &vectorlength(&relvector(&vectorcoords(@_)));
   }
   
   sub plotvectorangle {
      return &vectorangle(&relvector(&vectorcoords(@_)));
   }
   
   
   #
   # Evaluate a functionplotvectorrule
   #
   
   sub functionplotvectorrulecheck {
      my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
      &addlog("=================");
      my ($label,$type)=split(/\:/,$rule);
      if ($type eq 'vector') {
         return &vectorcheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval);
      } elsif ($type eq 'sum') {
         return &sumcheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval);
      }
   }
   
   sub vectorcheck {
      my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
      my ($label,$type,$id,$vector,
          $attachpoint,$notattachpoint,
          $tailpoint,$tippoint,$nottailpoint,$nottippoint,
          $length,$angle,$lengtherror,$angleerror)=split(/\:/,$rule);
      &addlog("Vector Rule $label for vector ".$vector);
      if ($length ne '') {
         &addlog("Checking for length $length with error $lengtherror");
         $length=&Apache::run::run($length,$safeeval);
         &addlog("Length evaluated to $length");
         my $thislength=&plotvectorlength($id,$vector);
         &addlog("Found length $thislength");
         if (abs($thislength-$length)>$lengtherror) {
            &setfailed($label);
            return 0;
         }
      }
      &addlog("Rule $label passed.");
      return 1;
   }
   
   sub sumcheck {
      my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
      my ($label,$type,$id,$object,$length,$angle,$lengthpercenterror,$lengthabserror,$angleerror)=split(/\:/,$rule);
      &addlog("Vector Sum Rule $label for vectors attached to ".$object);
   
      &addlog("Rule $label passed.");
      return 1;
   }
   
   #
   # Evaluate a functionplotrule
   #
     
 sub functionplotrulecheck {  sub functionplotrulecheck {
    my ($rule,$xmin,$xmax,$ymin,$ymax)=@_;     my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
   
    my ($label,$derivative,$xinitial,$xinitiallabel,$xfinal,$xfinallabel,$minimumlength,$maximumlength,$relationship,$value,$percent)     my ($label,$derivative,$xinitial,$xinitiallabel,$xfinal,$xfinallabel,$minimumlength,$maximumlength,$relationship,$value,$percent)
       =split(/\:/,$rule);        =split(/\:/,$rule);
    $percent=($percent>0?$percent:5);     $percent=($percent>0?$percent:5);
    &addlog("=================");     &addlog("=================");
    &addlog("Rule $label for ".($derivative<0?'integral':('function itself','first derivative','second derivative')[$derivative])." $relationship $value");     &addlog("Rule $label for ".($derivative<0?'integral':('function itself','first derivative','second derivative')[$derivative])." $relationship $value");
   #
   # Evaluate the value
   #
      if ($value=~/\D/) {
         $Apache::functionplotresponse::fpr_xmin=$xmin;
         $Apache::functionplotresponse::fpr_xmax=$xmax;
         $value=&Apache::run::run($value,$safeeval);
         &addlog("Value evaluated to $value");
      }
   
   #
   # Minimum and maximum lengths of the interval
   #
    if ((defined($minimumlength)) || (defined($maximumlength))) {     if ((defined($minimumlength)) || (defined($maximumlength))) {
       &addlog("Minimumlength $minimumlength Maximumlength $maximumlength");        &addlog("Minimumlength $minimumlength Maximumlength $maximumlength");
    }     }
Line 1024  sub functionplotrulecheck { Line 1557  sub functionplotrulecheck {
      unless (&compare_rel($relationship,$value,$integral,$tol)) {       unless (&compare_rel($relationship,$value,$integral,$tol)) {
         &addlog("Actual integral ".(defined($integral)?$integral:'undef').", expected $value, tolerance $tol");          &addlog("Actual integral ".(defined($integral)?$integral:'undef').", expected $value, tolerance $tol");
         &addlog("Rule $label failed.");          &addlog("Rule $label failed.");
         my $hintlabel=$label;          &setfailed($label);
         $hintlabel=~s/^R//;  
         push(@Apache::functionplotresponse::failedrules,$hintlabel);  
         &addlog("Set hint condition $hintlabel");  
         return 0;          return 0;
      }        } 
    } else {     } else {
Line 1093  sub checklength { Line 1623  sub checklength {
 }  }
   
 sub setfailed {  sub setfailed {
    my ($label)=@_;     my ($hintlabel)=@_;
    my $hintlabel=$label;  
    $hintlabel=~s/^R//;     $hintlabel=~s/^R//;
    push(@Apache::functionplotresponse::failedrules,$hintlabel);     push(@Apache::functionplotresponse::failedrules,$hintlabel);
    &addlog("Set hint condition $hintlabel");     &addlog("Set hint condition $hintlabel");
Line 1138  sub end_functionplotruleset { Line 1667  sub end_functionplotruleset {
         $Apache::functionplotresponse::ruleslog='';          $Apache::functionplotresponse::ruleslog='';
         $Apache::functionplotresponse::functionplotrulelabels{'start'}=400;          $Apache::functionplotresponse::functionplotrulelabels{'start'}=400;
         $Apache::functionplotresponse::functionplotrulelabels{'end'}=0;          $Apache::functionplotresponse::functionplotrulelabels{'end'}=0;
         if (&populate_arrays($internalid,$xmin,$xmax) eq 'no_func') {          if (&populate_arrays($internalid,$xmin,$xmax,$ymin,$ymax) eq 'no_func') {
            $ad='NOT_FUNCTION';             $ad='NOT_FUNCTION';
         } else {          } else {
            &addlog("Start of function ".&actualval($Apache::functionplotresponse::functionplotrulelabels{'start'},$xmin,$xmax)." (index ".             &addlog("Start of function ".&actualval($Apache::functionplotresponse::functionplotrulelabels{'start'},$xmin,$xmax)." (index ".
Line 1148  sub end_functionplotruleset { Line 1677  sub end_functionplotruleset {
   
 # We have a function that we can actually grade, go through the spline rules.  # We have a function that we can actually grade, go through the spline rules.
            foreach my $rule (@Apache::functionplotresponse::functionplotrules) {             foreach my $rule (@Apache::functionplotresponse::functionplotrules) {
               unless (&functionplotrulecheck($rule,$xmin,$xmax,$ymin,$ymax)) {                unless (&functionplotrulecheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)) {
                    $ad='INCORRECT';
                    last;
                 }
              }
   # And now go through the vector rules
              foreach my $rule (@Apache::functionplotresponse::functionplotvectorrules) {
                 unless (&functionplotvectorrulecheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)) {
                  $ad='INCORRECT';                   $ad='INCORRECT';
                  last;                   last;
               }                }
Line 1219  sub end_functionplotelements { Line 1755  sub end_functionplotelements {
         my $answerdisplay=&Apache::lonxml::get_param('answerdisplay',$parstack,$safeeval,-2);          my $answerdisplay=&Apache::lonxml::get_param('answerdisplay',$parstack,$safeeval,-2);
         if ($answerdisplay=~/\S/s) {          if ($answerdisplay=~/\S/s) {
            foreach my $plot (split(/\s*\,\s*/,$answerdisplay)) {             foreach my $plot (split(/\s*\,\s*/,$answerdisplay)) {
               my ($func,$xl,$xh)=split(/\s*\:\s*/,$plot);                my @components=split(/\s*\:\s*/,$plot);
               if ((!defined($xl)) || ($xl eq '')) { $xl=$xmin; }                if ($#components<3) {
               if ((!defined($xh)) || ($xh eq '')) { $xh=$xmax; }  # Just a simple plot
               $result.=&plot_script($internalid,$func,1,'','00aa00',$xl,$xh,6);                   my ($func,$xl,$xh)=@components;
                    if ((!defined($xl)) || ($xl eq '')) { $xl=$xmin; }
                    if ((!defined($xh)) || ($xh eq '')) { $xh=$xmax; }
                    $result.=&plot_script($internalid,$func,1,'','00aa00',$xl,$xh,6);
                 } else {
   # This is a spline
                    $result.=&answer_spline_script($internalid,@components);
                 }
            }             }
         }          }
      }       }

Removed from v.1.53  
changed lines
  Added in v.1.79


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>