version 1.73, 2011/11/18 18:54:21
|
version 1.80, 2011/11/21 02:34:58
|
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', |
'plotobject','plotvector','functionplotvectorrule','functionplotvectorsumrule', |
'functionplotrule','functionplotruleset', |
'functionplotrule','functionplotruleset', |
'functionplotelements')); |
'functionplotelements')); |
} |
} |
Line 389 sub plotobject_script {
|
Line 389 sub plotobject_script {
|
$Apache::functionplotresponse::counter++; |
$Apache::functionplotresponse::counter++; |
$label='O'.$Apache::functionplotresponse::counter; |
$label='O'.$Apache::functionplotresponse::counter; |
} |
} |
|
&generate_input_field($id,$label,$x,$y); |
return "document.ggbApplet_$id.evalCommand('a=1');\n". |
return "document.ggbApplet_$id.evalCommand('a=1');\n". |
"document.ggbApplet_$id.setVisible('a', false);\n". |
"document.ggbApplet_$id.setVisible('a', false);\n". |
"document.ggbApplet_$id.setLabelVisible('a', false);\n". |
"document.ggbApplet_$id.setLabelVisible('a', false);\n". |
Line 412 sub plotvector_script {
|
Line 413 sub plotvector_script {
|
my $pointlabel=$label.'Point'; |
my $pointlabel=$label.'Point'; |
my $pointx=2.*($xmax-$xmin)+$xmax; |
my $pointx=2.*($xmax-$xmin)+$xmax; |
my $anglelabel=$label.'Angle'; |
my $anglelabel=$label.'Angle'; |
return(<<ENDVECTOR); |
return |
document.ggbApplet_$id.evalCommand("$startlabel=($xs,$ys)"); |
&new_point_coordinate($id,$startlabel,$xs,$ys,0). |
document.ggbApplet_$id.setVisible("$startlabel",false); |
&new_point_coordinate($id,$endlabel,$xe,$ye,0). |
document.ggbApplet_$id.setLabelVisible("$startlabel",false); |
(<<ENDVECTOR); |
document.ggbApplet_$id.evalCommand("$endlabel=($xe,$ye)"); |
|
document.ggbApplet_$id.setLabelVisible("$endlabel",false); |
|
document.ggbApplet_$id.evalCommand("$label=Vector[$startlabel,$endlabel]"); |
document.ggbApplet_$id.evalCommand("$label=Vector[$startlabel,$endlabel]"); |
document.ggbApplet_$id.setLabelVisible("$label",true); |
document.ggbApplet_$id.setLabelVisible("$label",true); |
document.ggbApplet_$id.setLineThickness("$label",8); |
document.ggbApplet_$id.setLineThickness("$label",8); |
Line 425 document.ggbApplet_$id.evalCommand("$poi
|
Line 424 document.ggbApplet_$id.evalCommand("$poi
|
document.ggbApplet_$id.evalCommand("$anglelabel=Angle[$pointlabel,$startlabel,$endlabel]"); |
document.ggbApplet_$id.evalCommand("$anglelabel=Angle[$pointlabel,$startlabel,$endlabel]"); |
document.ggbApplet_$id.setLabelVisible("$anglelabel",true); |
document.ggbApplet_$id.setLabelVisible("$anglelabel",true); |
document.ggbApplet_$id.setLabelStyle("$anglelabel",VALUE=2); |
document.ggbApplet_$id.setLabelStyle("$anglelabel",VALUE=2); |
document.ggbApplet_$id.registerObjectUpdateListener('$startlabel','updatePointCoordinates_$id'); |
|
document.ggbApplet_$id.registerObjectUpdateListener('$endlabel','updatePointCoordinates_$id'); |
|
document.ggbApplet_$id.registerObjectUpdateListener('$anglelabel','updatePointCoordinates_$id'); |
|
ENDVECTOR |
ENDVECTOR |
} |
} |
|
|
Line 514 sub start_plotobject {
|
Line 510 sub start_plotobject {
|
$token,'8'). |
$token,'8'). |
&Apache::edit::end_row(); |
&Apache::edit::end_row(); |
} elsif ($target eq 'modified') { |
} 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'); |
my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'label','x','y'); |
if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); } |
if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); } |
} |
} |
Line 568 sub start_plotvector {
|
Line 565 sub start_plotvector {
|
|
|
&Apache::edit::end_row(); |
&Apache::edit::end_row(); |
} elsif ($target eq 'modified') { |
} 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'); |
my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'label','tailx','taily','tipx','tipy'); |
if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); } |
if ($constructtag) { $result=&Apache::edit::rebuild_tag($token); } |
} |
} |
Line 696 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').' '. |
$token,'10').' '. |
&Apache::edit::select_arg(&mt('Function:'),'derivativeorder', |
&Apache::edit::select_arg(&mt('Function:'),'derivativeorder', |
Line 758 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').' '. |
|
&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('lengtherror',$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').' '. |
|
&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('Error length:','lengtherror', |
|
$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', |
|
,'lengtherror','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 998 sub start_functionplotresponse {
|
Line 1193 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 1171 sub fpr_d2fdx2 {
|
Line 1367 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)=@_; |
|
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; |
|
} |
|
} |
|
if ($angle ne '') { |
|
&addlog("Checking for angle $angle with error $angleerror"); |
|
$angle=&Apache::run::run($angle,$safeeval); |
|
&addlog("Angle evaluated to $angle"); |
|
my $thisangle=&plotvectorangle($id,$vector); |
|
&addlog("Found angle $thisangle"); |
|
my $anglediff=abs($thisangle-$angle); |
|
&addlog("Angle difference: $anglediff"); |
|
if ($anglediff>360.-$anglediff) { |
|
$anglediff=360.-$anglediff; |
|
} |
|
&addlog("Smallest angle difference: $anglediff"); |
|
if ($anglediff>$angleerror) { |
|
&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,$lengtherror,$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,$safeeval)=@_; |
my ($rule,$xmin,$xmax,$ymin,$ymax,$safeeval)=@_; |
Line 1267 sub functionplotrulecheck {
|
Line 1571 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 1336 sub checklength {
|
Line 1637 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 1395 sub end_functionplotruleset {
|
Line 1695 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' }; |