Diff for /loncom/homework/functionplotresponse.pm between versions 1.69 and 1.77

version 1.69, 2011/10/27 00:36:37 version 1.77, 2011/11/19 23:35:25
Line 1 Line 1
 # LearningOnline Network with CAPA  # LearningOnline Network with CAPA
 # option list style responses  # Functionplot responses
 #  #
 # $Id$  # $Id$
 #  #
Line 35  use Apache::run; Line 35  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 379  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  # Answer spline display
 #   # 
 # points: x,y,slope_x,slope_y  # points: x,y,slope_x,slope_y
Line 431  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 542  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 604  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='V'.$Apache::functionplotresponse::counter;
      } else {
         $label='V'.$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('lengthpercenterror',$parstack,$safeeval),
              &Apache::lonxml::get_param('anglepercenterror',$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('Percent error length:','lengthpercenterror',
                                        $token,'8').
                &Apache::edit::text_arg('Percent error angle:','anglepercenterror',
                                        $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',
                                                              'lengthpercenterror','anglepercenterror');
       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='V'.$Apache::functionplotresponse::counter;
      } else {
         $label='V'.$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('anglepercenterror',$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('Percent error angle:','anglepercenterror',
                                        $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','anglepercenterror');
       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 844  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 1017  sub fpr_d2fdx2 { Line 1370  sub fpr_d2fdx2 {
                                                                 $Apache::functionplotresponse::fpr_xmax,                                                                  $Apache::functionplotresponse::fpr_xmax,
                                                                 $arg)];                                                                  $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)=@_;
   }
   
   sub vectorlength {
      my ($x,$y)=@_;
      return sqrt($x*$x+$y*$y);
   }
   
   
   #
   # Evaluate a functionplotvectorrule
   #
   
   sub functionplotvectorrulecheck {
      my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
      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,$lengthpercenterror,$anglepercenterror)=split(/\:/,$rule);
   }
   
   sub sumcheck {
      my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
      my ($label,$type,$id,$object,$length,$angle,$lengthpercenterror,$lengthabserror,$anglepercenterror)=split(/\:/,$rule);
   }
   
   #
   # Evaluate a functionplotrule
   #
     
 sub functionplotrulecheck {  sub functionplotrulecheck {
    my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;     my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_;
Line 1241  sub end_functionplotruleset { Line 1650  sub end_functionplotruleset {
                  $ad='INCORRECT';                   $ad='INCORRECT';
                  last;                   last;
               }                }
              }
   # And now go through the vector rules
              foreach my $rule (@Apache::functionplotresponse::functionplotvectorrules) {
                 unless (&functionplotvectorrulecheck($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)) {
                    $ad='INCORRECT';
                    last;
                 }
            }             }
 # If it's not wrong, it's correct   # If it's not wrong, it's correct 
            unless ($ad) { $ad='EXACT_ANS' };             unless ($ad) { $ad='EXACT_ANS' };

Removed from v.1.69  
changed lines
  Added in v.1.77


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