You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(58) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
(53) |
Feb
(56) |
Mar
|
Apr
|
May
(30) |
Jun
(78) |
Jul
(121) |
Aug
(155) |
Sep
(77) |
Oct
(61) |
Nov
(45) |
Dec
(94) |
2006 |
Jan
(116) |
Feb
(33) |
Mar
(11) |
Apr
(23) |
May
(60) |
Jun
(89) |
Jul
(130) |
Aug
(109) |
Sep
(124) |
Oct
(63) |
Nov
(82) |
Dec
(45) |
2007 |
Jan
(31) |
Feb
(35) |
Mar
(123) |
Apr
(36) |
May
(18) |
Jun
(134) |
Jul
(133) |
Aug
(241) |
Sep
(126) |
Oct
(31) |
Nov
(15) |
Dec
(5) |
2008 |
Jan
(11) |
Feb
(6) |
Mar
(16) |
Apr
(29) |
May
(43) |
Jun
(149) |
Jul
(27) |
Aug
(29) |
Sep
(37) |
Oct
(20) |
Nov
(4) |
Dec
(6) |
2009 |
Jan
(34) |
Feb
(30) |
Mar
(16) |
Apr
(6) |
May
(1) |
Jun
(32) |
Jul
(22) |
Aug
(7) |
Sep
(18) |
Oct
(50) |
Nov
(22) |
Dec
(8) |
2010 |
Jan
(17) |
Feb
(15) |
Mar
(10) |
Apr
(9) |
May
(67) |
Jun
(30) |
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
(1) |
Dec
|
From: Mike G. v. a. <we...@ma...> - 2007-12-03 22:41:45
|
Log Message: ----------- Corrected spelling in pod documents. Modified Files: -------------- pg/macros: AppletObjects.pl Revision Data ------------- Index: AppletObjects.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/AppletObjects.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacros/AppletObjects.pl -Lmacros/AppletObjects.pl -u -r1.1 -r1.2 --- macros/AppletObjects.pl +++ macros/AppletObjects.pl @@ -68,7 +68,7 @@ Inserts applet at this point in the HTML code. (In TeX mode a message "Applet" is written.) This method also adds the applets header material into the header portion of the HTML page. It effectively inserts -the outputs of both C<$applet-E<gt>inserHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> ) in the appropriate places. +the outputs of both C<$applet-E<gt>insertHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> ) in the appropriate places. =cut @@ -121,7 +121,7 @@ ################################### # Add java script functions to header section of HTML to - # communicate with the applet. + # communicate with the "ExternalInterface" applet. ################################### $applet->header(<<'END_HEADER'); |
From: dpvc v. a. <we...@ma...> - 2007-12-02 14:29:28
|
Log Message: ----------- Fixed a problem where intervals minus sets containing more than one point were not being handled properly. Modified Files: -------------- pg/lib/Value: Set.pm Revision Data ------------- Index: Set.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Set.pm,v retrieving revision 1.20 retrieving revision 1.21 diff -Llib/Value/Set.pm -Llib/Value/Set.pm -u -r1.20 -r1.21 --- lib/Value/Set.pm +++ lib/Value/Set.pm @@ -138,7 +138,7 @@ } elsif ($x < $b) { my $context = $self->context; push(@union,$context->Package("Interval")->make($context,$I->{open},$a,$x,')')); - $I->{open} = '('; $I->{data}[0] = $x; + $I->{open} = '('; $I->{data}[0] = $a = $x; } else { $I->{close} = ')' if ($x == $b); last; |
From: Gavin L. v. a. <we...@ma...> - 2007-11-26 18:08:00
|
Log Message: ----------- Add mg as a mass unit. Hopefully the fact that this wasn't here before is an oddity rather than indicating that I'm screwing something up. Modified Files: -------------- pg/lib: Units.pm Revision Data ------------- Index: Units.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Units.pm,v retrieving revision 1.6 retrieving revision 1.7 diff -Llib/Units.pm -Llib/Units.pm -u -r1.6 -r1.7 --- lib/Units.pm +++ lib/Units.pm @@ -214,12 +214,17 @@ 's' => -1 }, # MASS +# mg -- miligrams # g -- grams # kg -- kilograms # + 'mg' => { + 'factor' => 0.000001, + 'kg' => 1 + }, 'g' => { 'factor' => 0.001, - 'kg' => 1 + 'kg' => 1 }, # ENGLISH MASS # slug -- slug |
From: Gavin L. v. a. <we...@ma...> - 2007-11-20 15:14:05
|
Log Message: ----------- Make VectorField plotting honor setting of x_steps and y_steps. Modified Files: -------------- pg/lib: VectorField.pm Revision Data ------------- Index: VectorField.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/VectorField.pm,v retrieving revision 1.3 retrieving revision 1.4 diff -Llib/VectorField.pm -Llib/VectorField.pm -u -r1.3 -r1.4 --- lib/VectorField.pm +++ lib/VectorField.pm @@ -255,10 +255,10 @@ my $brush = new GD::Image($self->arrow_weight,$self->arrow_weight); my $brush_color = $brush->colorAllocate($g->im->rgb($arrow_color)); # transfer color $g->im->setBrush($brush); - my $x_steps = 10; + my $x_steps = $self->x_steps; my $xmin = $self->xmin; my $x_stepsize = ( $self->xmax - $self->xmin )/$x_steps; - my $y_steps = 10; + my $y_steps = $self->y_steps; my $ymin = $self->ymin; my $y_stepsize = ( $self->ymax - $self->ymin )/$y_steps; my $dt = $self->dt; |
From: dpvc v. a. <we...@ma...> - 2007-11-15 12:40:49
|
Log Message: ----------- When two sets are added, combine them rather than form a union. (This allows Inequailities context to report errors better when student answers are of the form x=a or x=b.) Modified Files: -------------- pg/lib/Value: Set.pm Revision Data ------------- Index: Set.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/Set.pm,v retrieving revision 1.19 retrieving revision 1.20 diff -Llib/Value/Set.pm -Llib/Value/Set.pm -u -r1.19 -r1.20 --- lib/Value/Set.pm +++ lib/Value/Set.pm @@ -84,10 +84,11 @@ # # -# Addition forms additional sets +# Addition forms unions (or combines sets) # sub add { my ($self,$l,$r) = Value::checkOpOrderWithPromote(@_); + return $self->make($l->value,$r->value) if $l->type eq 'Set' && $r->type eq 'Set'; Value::Union::form($self->context,$l,$r); } sub dot {my $self = shift; $self->add(@_)} |
From: dpvc v. a. <we...@ma...> - 2007-11-15 12:39:45
|
Log Message: ----------- Do the reduction check on sets when they are compared (to see if there are repeated values, for example). Modified Files: -------------- pg/lib/Value: AnswerChecker.pm Revision Data ------------- Index: AnswerChecker.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Value/AnswerChecker.pm,v retrieving revision 1.114 retrieving revision 1.115 diff -Llib/Value/AnswerChecker.pm -Llib/Value/AnswerChecker.pm -u -r1.114 -r1.115 --- lib/Value/AnswerChecker.pm +++ lib/Value/AnswerChecker.pm @@ -1128,8 +1128,10 @@ # sub cmp_equal { my ($self,$ans) = @_; - return Value::List::cmp_equal(@_) if $ans->{student_value}->type eq 'Set'; - $self->SUPER::cmp_equal($ans); + return $self->SUPER::cmp_equal($ans) unless $ans->{student_value}->type eq 'Set'; + my $error = $self->cmp_checkUnionReduce($ans->{student_value},$ans); + if ($error) {$self->cmp_Error($ans,$error); return} + return Value::List::cmp_equal(@_); } # |
From: dpvc v. a. <we...@ma...> - 2007-11-15 12:38:11
|
Log Message: ----------- Produce error messages when the student enters something like x=1 or x=1. Modified Files: -------------- pg/macros: contextInequalities.pl Revision Data ------------- Index: contextInequalities.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextInequalities.pl,v retrieving revision 1.16 retrieving revision 1.17 diff -Lmacros/contextInequalities.pl -Lmacros/contextInequalities.pl -u -r1.16 -r1.17 --- macros/contextInequalities.pl +++ macros/contextInequalities.pl @@ -30,15 +30,15 @@ =head1 USAGE loadMacros("contextInequalities.pl"); - + Context("Inequalities"); $S1 = Compute("1 < x <= 4"); $S2 = Inequality("(1,4]"); # force interval to be inequality - + Context("Inequalities-Only"); $S1 = Compute("1 < x <= 4"); $S2 = Inequality("(1,4]"); # generates an error - + $S3 = Compute("x < -2 or x > 2"); # forms a Union $S4 = Compute("x = 1"); # forms a Set @@ -516,10 +516,9 @@ "overlaps" => "Your$nth answer contains overlapping inequalities", "overlaps in sets" => "Your$nth answer contains equalities that are already included elsewhere", "uncombined intervals" => "Your$nth answer can be simplified by combining some inequalities", - # shouldn't get the following ones from inequalities - "uncombined sets" => "", - "repeated elements in set" => "", - "repeated elements" => "", + "uncombined sets" => "", # shouldn't get this from inequalities + "repeated elements in set" => "Your$nth answer contains repeated values", + "repeated elements" => "Your$nth answer contains repeated values", }->{$error}; } else { return unless Value::can($student,"isReduced"); |
From: Mike G. v. a. <we...@ma...> - 2007-11-10 21:57:13
|
Log Message: ----------- Corrected typo in string answer evaluators (affecting blank answers mainly) Removed FIXME note from PGnumericevaluators.pl Modified Files: -------------- pg/macros: PGnumericevaluators.pl PGstringevaluators.pl Revision Data ------------- Index: PGnumericevaluators.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGnumericevaluators.pl,v retrieving revision 1.2 retrieving revision 1.3 diff -Lmacros/PGnumericevaluators.pl -Lmacros/PGnumericevaluators.pl -u -r1.2 -r1.3 --- macros/PGnumericevaluators.pl +++ macros/PGnumericevaluators.pl @@ -555,7 +555,7 @@ sub std_num_cmp_list { my ( $relPercentTol, $format, @answerList) = @_; - #FIXME? errors if not defined? + my %options = ( 'relTol' => $relPercentTol, 'format' => $format, ); Index: PGstringevaluators.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGstringevaluators.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacros/PGstringevaluators.pl -Lmacros/PGstringevaluators.pl -u -r1.1 -r1.2 --- macros/PGstringevaluators.pl +++ macros/PGstringevaluators.pl @@ -552,7 +552,7 @@ ); # Remove blank prefilter if the correct answer is blank - $answer_evaluator->install_pre_filter('erase') if $answer_evaluator->{correct_ans} eq ''; + $answer_evaluator->install_pre_filter('erase') if $answer_evaluator->ans_hash->{correct_ans} eq ''; my %known_filters = ( 'remove_whitespace' => \&remove_whitespace, |
From: Mike G. v. a. <we...@ma...> - 2007-11-10 21:04:13
|
Log Message: ----------- Made changes in the way the default values for answer evaluators are set. (They were frequently undefined.) We now get them from the envir variable which seems to work. For example: $functAbsTolDefault = PG_restricted_eval(q/$envir{functAbsTolDefault}/); Modified Files: -------------- pg/macros: PGanswermacros.pl PGfunctionevaluators.pl PGnumericevaluators.pl Revision Data ------------- Index: PGnumericevaluators.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGnumericevaluators.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacros/PGnumericevaluators.pl -Lmacros/PGnumericevaluators.pl -u -r1.1 -r1.2 --- macros/PGnumericevaluators.pl +++ macros/PGnumericevaluators.pl @@ -78,12 +78,12 @@ my $user_context; sub _PGnumericevaluators_init { $CA = PG_restricted_eval(q/$CA/); - $numAbsTolDefault = PG_restricted_eval(q/$numAbsTolDefault/); - $numFormatDefault = PG_restricted_eval(q/$numFormatDefault/); - $numRelPercentTolDefault = PG_restricted_eval(q/$numRelPercentTolDefault/); - $numZeroLevelDefault = PG_restricted_eval(q/$numZeroLevelDefault/); - $numZeroLevelTolDefault = PG_restricted_eval(q/$numZeroLevelTolDefault/); - $useOldAnswerMacros = PG_restricted_eval(q/$useOldAnswerMacros/); + $numAbsTolDefault = PG_restricted_eval(q/$envir{numAbsTolDefault}/); + $numFormatDefault = PG_restricted_eval(q/$envir{numFormatDefault}/); + $numRelPercentTolDefault = PG_restricted_eval(q/$envir{numRelPercentTolDefault}/); + $numZeroLevelDefault = PG_restricted_eval(q/$envir{numZeroLevelDefault}/); + $numZeroLevelTolDefault = PG_restricted_eval(q/$envir{numZeroLevelTolDefault}/); + $useOldAnswerMacros = PG_restricted_eval(q/$envir{useOldAnswerMacros}/); unless ($useOldAnswerMacros) { $user_context = PG_restricted_eval(q/\%context/); $Context = sub { Parser::Context->current($user_context, @_) }; @@ -378,7 +378,8 @@ if( defined( $out_options{'units'} ) ) { $ans = "$ans $out_options{'units'}"; - push( @output_list, NUM_CMP( 'correctAnswer' => $ans, + push( @output_list, NUM_CMP( + 'correctAnswer' => $ans, 'tolerance' => $out_options{'tolerance'}, 'tolType' => $out_options{'tolType'}, 'format' => $out_options{'format'}, @@ -392,26 +393,28 @@ } elsif( defined( $out_options{'strings'} ) ) { - push( @output_list, NUM_CMP( 'correctAnswer' => $ans, - 'tolerance' => $out_options{tolerance}, - 'tolType' => $out_options{tolType}, - 'format' => $out_options{'format'}, - 'mode' => $out_options{'mode'}, - 'zeroLevel' => $out_options{'zeroLevel'}, + push( @output_list, NUM_CMP( + 'correctAnswer' => $ans, + 'tolerance' => $out_options{tolerance}, + 'tolType' => $out_options{tolType}, + 'format' => $out_options{'format'}, + 'mode' => $out_options{'mode'}, + 'zeroLevel' => $out_options{'zeroLevel'}, 'zeroLevelTol' => $out_options{'zeroLevelTol'}, - 'debug' => $out_options{'debug'}, - 'strings' => $out_options{'strings'}, + 'debug' => $out_options{'debug'}, + 'strings' => $out_options{'strings'}, ) ); } else { push(@output_list, - NUM_CMP( 'correctAnswer' => $ans, + NUM_CMP( + 'correctAnswer' => $ans, 'tolerance' => $out_options{tolerance}, 'tolType' => $out_options{tolType}, 'format' => $out_options{'format'}, 'mode' => $out_options{'mode'}, 'zeroLevel' => $out_options{'zeroLevel'}, - 'zeroLevelTol' => $out_options{'zeroLevelTol'}, + 'zeroLevelTol' => $out_options{'zeroLevelTol'}, 'debug' => $out_options{'debug'}, ), ); @@ -552,9 +555,9 @@ sub std_num_cmp_list { my ( $relPercentTol, $format, @answerList) = @_; - + #FIXME? errors if not defined? my %options = ( 'relTol' => $relPercentTol, - 'format' => $format, + 'format' => $format, ); set_default_options( \%options, @@ -945,7 +948,7 @@ # my @keys = qw(correctAnswer tolerance tolType format mode zeroLevel zeroLevelTol debug); foreach my $key (@keys) { - warn "$key must be defined in options when calling NUM_CMP" + warn( "$key must be defined in options when calling NUM_CMP" ) unless defined($num_params{$key}); } Index: PGanswermacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGanswermacros.pl,v retrieving revision 1.64 retrieving revision 1.65 diff -Lmacros/PGanswermacros.pl -Lmacros/PGanswermacros.pl -u -r1.64 -r1.65 --- macros/PGanswermacros.pl +++ macros/PGanswermacros.pl @@ -143,10 +143,10 @@ my $useBaseTenLog; sub _PGanswermacros_init { $BR = PG_restricted_eval(q/$BR/); - $functLLimitDefault = PG_restricted_eval(q/$functLLimitDefault/); - $functULimitDefault = PG_restricted_eval(q/$functULimitDefault/); - $functVarDefault = PG_restricted_eval(q/$functVarDefault/); - $useBaseTenLog = PG_restricted_eval(q/$useBaseTenLog/); + $functLLimitDefault = PG_restricted_eval(q/$envir{functLLimitDefault}/); + $functULimitDefault = PG_restricted_eval(q/$envir{functULimitDefault}/); + $functVarDefault = PG_restricted_eval(q/$envir{functVarDefault}/); + $useBaseTenLog = PG_restricted_eval(q/$envir{useBaseTenLog}/); } Index: PGfunctionevaluators.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGfunctionevaluators.pl,v retrieving revision 1.1 retrieving revision 1.2 diff -Lmacros/PGfunctionevaluators.pl -Lmacros/PGfunctionevaluators.pl -u -r1.1 -r1.2 --- macros/PGfunctionevaluators.pl +++ macros/PGfunctionevaluators.pl @@ -71,17 +71,17 @@ my $useOldAnswerMacros; my $user_context; sub _PGfunctionevaluators_init { - $functAbsTolDefault = PG_restricted_eval(q/$functAbsTolDefault/); - $functLLimitDefault = PG_restricted_eval(q/$functLLimitDefault/); - $functMaxConstantOfIntegration = PG_restricted_eval(q/$functMaxConstantOfIntegration/); - $functNumOfPoints = PG_restricted_eval(q/$functNumOfPoints/); - $functRelPercentTolDefault = PG_restricted_eval(q/$functRelPercentTolDefault/); - $functULimitDefault = PG_restricted_eval(q/$functULimitDefault/); - $functVarDefault = PG_restricted_eval(q/$functVarDefault/); - $functZeroLevelDefault = PG_restricted_eval(q/$functZeroLevelDefault/); - $functZeroLevelTolDefault = PG_restricted_eval(q/$functZeroLevelTolDefault/); - $inputs_ref = PG_restricted_eval(q/$inputs_ref/); - $useOldAnswerMacros = PG_restricted_eval(q/$useOldAnswerMacros/); + $functAbsTolDefault = PG_restricted_eval(q/$envir{functAbsTolDefault}/); + $functLLimitDefault = PG_restricted_eval(q/$envir{functLLimitDefault}/); + $functMaxConstantOfIntegration = PG_restricted_eval(q/$envir{functMaxConstantOfIntegration}/); + $functNumOfPoints = PG_restricted_eval(q/$envir{functNumOfPoints}/); + $functRelPercentTolDefault = PG_restricted_eval(q/$envir{functRelPercentTolDefault}/); + $functULimitDefault = PG_restricted_eval(q/$envir{functULimitDefault}/); + $functVarDefault = PG_restricted_eval(q/$envir{functVarDefault}/); + $functZeroLevelDefault = PG_restricted_eval(q/$envir{functZeroLevelDefault}/); + $functZeroLevelTolDefault = PG_restricted_eval(q/$envir{functZeroLevelTolDefault}/); + $inputs_ref = PG_restricted_eval(q/$envir{inputs_ref}/); + $useOldAnswerMacros = PG_restricted_eval(q/$envir{useOldAnswerMacros}/); unless ($useOldAnswerMacros) { $user_context = PG_restricted_eval(q/\%context/); $Context = sub { Parser::Context->current($user_context, @_) }; |
From: Sam H. v. a. <we...@ma...> - 2007-11-08 00:09:02
|
Log Message: ----------- Split answer evaluators into several new files, based on the type of answer being evaluated. The answer evaluators are fully documented, but the rest of the functions in PGanswermacros.pl still need docs. This still needs to be tested a bunch before it's ready for prime time. Modified Files: -------------- pg/macros: PGanswermacros.pl Added Files: ----------- pg/macros: PGfunctionevaluators.pl PGmiscevaluators.pl PGnumericevaluators.pl PGstringevaluators.pl PGtextevaluators.pl Revision Data ------------- --- /dev/null +++ macros/PGnumericevaluators.pl @@ -0,0 +1,1223 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: pg/macros/PGnumericevaluators.pl,v 1.1 2007/11/08 00:00:15 sh002i Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +=head1 NAME + +PGnumericevaluators.pl - Macros that generate numeric answer evaluators. + +=head1 SYNOPSIS + + ANS(num_cmp($answer_or_answer_array_ref, %options_hash)); + + ANS(std_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(std_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(std_num_cmp_list($relTol, $format, @answerList)); + ANS(std_num_cmp_abs_list($absTol, $format, @answerList)); + + ANS(arith_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(arith_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(arith_num_cmp_list($relTol, $format, @answerList)); + ANS(arith_num_cmp_abs_list($absTol, $format, @answerList)); + + ANS(strict_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(strict_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(strict_num_cmp_list($relTol, $format, @answerList)); + ANS(strict_num_cmp_abs_list($absTol, $format, @answerList)); + + ANS(frac_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(frac_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(frac_num_cmp_list($relTol, $format, @answerList)); + ANS(frac_num_cmp_abs_list($absTol, $format, @answerList)); + +=head1 DESCRIPTION + +Numeric answer evaluators take in a numerical answer, compare it to the correct +answer, and return a score. In addition, they can choose to accept or reject an +answer based on its format, closeness to the correct answer, and other criteria. + +The general numeric answer evaluator is num_cmp(). It takes a hash of named +options as parameters. There are also sixteen specific "mode"_num_cmp() answer +evaluators for use in common situations which feature a simplified syntax. + +=head2 MathObjects and answer evaluators + +The MathObjects system provides $obj->cmp() methods that produce answer +evaluators for a wide variety of answer types. num_cmp() has been rewritten to +use the appropriate MathObject to produce the answer evaluator. It is +recommended that you use the MathObjects cmp() methods directly if possible. + +=cut + +BEGIN { be_strict() } + +# Until we get the PG cacheing business sorted out, we need to use +# PG_restricted_eval to get the correct values for some(?) PG environment +# variables. We do this once here and place the values in lexicals for later +# access. +my $CA; +my $Context; +my $numAbsTolDefault; +my $numFormatDefault; +my $numRelPercentTolDefault; +my $numZeroLevelDefault; +my $numZeroLevelTolDefault; +my $useOldAnswerMacros; +my $user_context; +sub _PGnumericevaluators_init { + $CA = PG_restricted_eval(q/$CA/); + $numAbsTolDefault = PG_restricted_eval(q/$numAbsTolDefault/); + $numFormatDefault = PG_restricted_eval(q/$numFormatDefault/); + $numRelPercentTolDefault = PG_restricted_eval(q/$numRelPercentTolDefault/); + $numZeroLevelDefault = PG_restricted_eval(q/$numZeroLevelDefault/); + $numZeroLevelTolDefault = PG_restricted_eval(q/$numZeroLevelTolDefault/); + $useOldAnswerMacros = PG_restricted_eval(q/$useOldAnswerMacros/); + unless ($useOldAnswerMacros) { + $user_context = PG_restricted_eval(q/\%context/); + $Context = sub { Parser::Context->current($user_context, @_) }; + } +} + +=head1 num_cmp + + ANS(num_cmp($answer_or_answer_array_ref, %options)); + +num_cmp() returns one or more answer evaluators (subroutine references) that +compare the student's answer to a numeric value. Evaluation options are +specified as items in the %options hash. This can make for more readable code +than using the "mode"_num_cmp() style, but some people find one or the other +easier to remember. + +=head2 Options + +$answer_or_answer_array_ref can either be a scalar containing a numeric value or +a reference to an array of numeric scalars. If multiple answers are provided, +num_cmp() will return a list of answer evaluators, one for each answer +specified. %options is a hash containing options that affect the way the +comparison is performed. All hash items are optional. Allowed options are: + +=over + +=item mode + +This determines the allowable methods for entering an answer. Answers which do +not meet this requirement will be graded as incorrect, regardless of their +numerical value. The recognized modes are: + +=over + +=item std (default) + +The default mode allows any expression which evaluates to a number, including +those using elementary functions like sin() and exp(), as well as the operations +of arithmetic (+, -, *, /, and ^). + +=item strict + +Only decimal numbers are allowed. + +=item frac + +Only whole numbers and fractions are allowed. + +=item arith + +Arithmetic expressions are allowed, but no functions. + +=back + +Note that all modes allow the use of "pi" and "e" as constants, and also the use +of "E" to represent scientific notation. + +=item format + +The format to use when displaying the correct and submitted answers. This has no +effect on how answers are evaluated; it is only for cosmetic purposes. The +formatting syntax is the same as Perl uses for the sprintf() function. Format +strings are of the form '%m.nx' or '%m.nx#', where m and n are described below, +and x is a formatter. + +Esentially, m is the minimum length of the field (make this negative to +left-justify). Note that the decimal point counts as a character when +determining the field width. If m begins with a zero, the number will be padded +with zeros instead of spaces to fit the field. + +The precision specifier (n) works differently depending on which formatter you +are using. For d, i, o, u, x and X formatters (non-floating point formatters), n +is the minimum number of digits to display. For e and f, it is the number of +digits that appear after the decimal point (extra digits will be rounded; +insufficient digits will be padded with spaces--see '#' below). For g, it is the +number of significant digits to display. + +The full list of formatters can be found in the manpage for printf(3), or by +typing "perldoc -f sprintf" at a terminal prompt. The following is a brief +summary of the most frequent formatters: + + %d decimal number + %ld long decimal number + %u unsigned decimal number + %lu long unsigned decimal number + %x hexadecimal number + %o octal number + %e floating point number in scientific notation + %f floating point number + %g either %e or %f, whichever takes less space + +Technically, %g will use %e if the exponent is less than -4 or greater than or +equal to the precision. Trailing zeros are removed in this mode. + +If the format string ends in '#', trailing zeros will be removed in the decimal +part. Note that this is not a standard syntax; it is handled internally by +WeBWorK and not by Perl (although this should not be a concern to end users). +The default format is '%0.5f#', which displays as a floating point number with 5 +digits of precision and no trailing zeros. Other useful format strings might be +'%0.2f' for displaying dollar amounts, or '%010d' to display an integer with +leading zeros. Setting format to an empty string ( '' ) means no formatting will +be used; this will show 'arbitrary' precision floating points. + +=item tol + +An absolute tolerance value. The student answer must be a fixed distance from +the correct answer to qualify. For example, an absolute tolerance of 5 means +that any number which is +-5 of the correct answer qualifies as correct. abstol +is accepted as a synonym for tol. + +=item relTol + +A relative tolerance. Relative tolerances are given in percentages. A relative +tolerance of 1 indicates that the student answer must be within 1% of the +correct answer to qualify as correct. In other words, a student answer is +correct when + + abs(studentAnswer - correctAnswer) <= abs(.01*relTol*correctAnswer) + +tol and relTol are mutually exclusive. reltol is also accpeted as a synonym for +relTol. + +=item zeroLevel, zeroLevelTol + +zeroLevel and zeroLevelTol specify a alternative absolute tolerance to use when +the correct answer is very close to zero. + +If the correct answer has an absolute value less than or equal to zeroLevel, +then the student answer must be, in absolute terms, within zeroLevelTol of +correctAnswer, i.e., + + abs(studentAnswer - correctAnswer) <= zeroLevelTol + +In other words, if the correct answer is very near zero, an absolute tolerance +will be used. One must do this to handle floating point answers very near zero, +because of the inaccuracy of floating point arithmetic. However, the default +values are almost always adequate. + +=item units + +A string representing the units of the correct answer. If specified, the student +answer must include these units. The strings and units options are mutually +exclusive. + +=item strings + +A reference to an array of strings which are valid (but incorrect) answers. This +prevents non-numeric entries like "NaN" or "None" from causing a syntax error. +The strings and units options are mutually exclusive. + +=item debug + +If set to 1, extra debugging information will be output. + +=back + +=head2 Examples + + # correct answer is 5, using defaults for all options + num_cmp(5); + + # correct answers are 5, 6, and 7, using defaults for all options + num_cmp([5,6,7]); + + # correct answer is 5, mode is strict + num_cmp(5, mode=>'strict'); + + # correct answers are 5 and 6, both with 5% relative tolerance + num_cmp([5,6], relTol=>5); + + # correct answer is 6, "Inf", "Minf", and "NaN" recognized as valid, but + # incorrect answers. + num_cmp(6, strings=>["Inf", "Minf", "NaN"]); + + # correct answer is "-INF", "INF" and numerical expressions recognized as + # valid, but incorrect answers. + num_cmp("-INF", strings => ["INF", "-INF"]); + +=cut + +sub num_cmp { + my $correctAnswer = shift @_; + $CA = $correctAnswer; + my @opt = @_; + my %out_options; + +######################################################################### +# Retain this first check for backword compatibility. Allows input of the form +# num_cmp($ans, 1, '%0.5f') but warns against it +######################################################################### + my %known_options = ( + 'mode' => 'std', + 'format' => $numFormatDefault, + 'tol' => $numAbsTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'units' => undef, + 'strings' => undef, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'tolType' => 'relative', + 'tolerance' => 1, + 'reltol' => undef, #alternate spelling + 'unit' => undef, #alternate spelling + 'debug' => 0 + ); + + my @output_list; + my( $relPercentTol, $format, $zeroLevel, $zeroLevelTol) = @opt; + + unless( ref($correctAnswer) eq 'ARRAY' || scalar( @opt ) == 0 || + ( defined($opt[0]) and exists $known_options{$opt[0]} ) ) { + # unless the first parameter is a list of arrays + # or the second parameter is a known option or + # no options were used, + # use the old num_cmp which does not use options, but has inputs + # $relPercentTol,$format,$zeroLevel,$zeroLevelTol + warn "This method of using num_cmp() is deprecated. Please rewrite this" . + " problem using the options style of parameter passing (or" . + " check that your first option is spelled correctly)."; + + %out_options = ( 'relTol' => $relPercentTol, + 'format' => $format, + 'zeroLevel' => $zeroLevel, + 'zeroLevelTol' => $zeroLevelTol, + 'mode' => 'std' + ); + } + +######################################################################### +# Now handle the options assuming they are entered in the form +# num_cmp($ans, relTol=>1, format=>'%0.5f') +######################################################################### + %out_options = @opt; + assign_option_aliases( \%out_options, + 'reltol' => 'relTol', + 'unit' => 'units', + 'abstol' => 'tol', + ); + + set_default_options( \%out_options, + 'tolType' => (defined($out_options{'tol'}) ) ? 'absolute' : 'relative', # the existence of "tol" means that we use absolute tolerance mode + 'tolerance' => (defined($out_options{'tolType'}) && $out_options{'tolType'} eq 'absolute' ) ? $numAbsTolDefault : $numRelPercentTolDefault, # relative tolerance is the default + 'mode' => 'std', + 'format' => $numFormatDefault, + 'tol' => undef, + 'relTol' => undef, + 'units' => undef, + 'strings' => undef, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'debug' => 0, + ); + + # can't use both units and strings + if( defined( $out_options{'units'} ) && defined( $out_options{'strings'} ) ) { + warn "Can't use both 'units' and 'strings' in the same problem " . + "(check your parameters to num_cmp() )"; + } + + # absolute tolType and relTol are incompatible. So are relative tolType and tol + if( defined( $out_options{'relTol'} ) && $out_options{'tolType'} eq 'absolute' ) { + warn "The 'tolType' 'absolute' is not compatible with 'relTol' " . + "(check your parameters to num_cmp() )"; + } + if( defined( $out_options{'tol'} ) && $out_options{'tolType'} eq 'relative' ) { + warn "The 'tolType' 'relative' is not compatible with 'tol' " . + "(check your parameters to num_cmp() )"; + } + + + # Handle legacy options + if ($out_options{tolType} eq 'absolute') { + $out_options{'tolerance'}=$out_options{'tol'} if defined($out_options{'tol'}); + delete($out_options{'relTol'}) if exists( $out_options{'relTol'} ); + } else { + $out_options{'tolerance'}=$out_options{'relTol'} if defined($out_options{'relTol'}); + # delete($out_options{'tol'}) if exists( $out_options{'tol'} ); + } + # end legacy options + + # thread over lists + my @ans_list = (); + + if ( ref($correctAnswer) eq 'ARRAY' ) { + @ans_list = @{$correctAnswer}; + } + else { push( @ans_list, $correctAnswer ); + } + + # produce answer evaluators + foreach my $ans (@ans_list) { + if( defined( $out_options{'units'} ) ) { + $ans = "$ans $out_options{'units'}"; + + push( @output_list, NUM_CMP( 'correctAnswer' => $ans, + 'tolerance' => $out_options{'tolerance'}, + 'tolType' => $out_options{'tolType'}, + 'format' => $out_options{'format'}, + 'mode' => $out_options{'mode'}, + 'zeroLevel' => $out_options{'zeroLevel'}, + 'zeroLevelTol' => $out_options{'zeroLevelTol'}, + 'debug' => $out_options{'debug'}, + 'units' => $out_options{'units'}, + ) + ); + } elsif( defined( $out_options{'strings'} ) ) { + + + push( @output_list, NUM_CMP( 'correctAnswer' => $ans, + 'tolerance' => $out_options{tolerance}, + 'tolType' => $out_options{tolType}, + 'format' => $out_options{'format'}, + 'mode' => $out_options{'mode'}, + 'zeroLevel' => $out_options{'zeroLevel'}, + 'zeroLevelTol' => $out_options{'zeroLevelTol'}, + 'debug' => $out_options{'debug'}, + 'strings' => $out_options{'strings'}, + ) + ); + } else { + push(@output_list, + NUM_CMP( 'correctAnswer' => $ans, + 'tolerance' => $out_options{tolerance}, + 'tolType' => $out_options{tolType}, + 'format' => $out_options{'format'}, + 'mode' => $out_options{'mode'}, + 'zeroLevel' => $out_options{'zeroLevel'}, + 'zeroLevelTol' => $out_options{'zeroLevelTol'}, + 'debug' => $out_options{'debug'}, + ), + ); + } + } + + return (wantarray) ? @output_list : $output_list[0]; +} + +#legacy code for compatability purposes +sub num_rel_cmp { # compare numbers + std_num_cmp( @_ ); +} + +=head1 "mode"_num_cmp() functions + +There are 16 functions that provide simplified interfaces to num_cmp(). They are +organized into four groups, based on the number of answers accpeted (single or +list) and whether relative or absolute tolerances are used. Each group contains +four functions, one for each evaluation mode. See the mode option to num_cmp() +above for details about each mode. + + GROUP:| "normal" | "list" | "abs" | "abs_list" | + | single answer | list of answers | single answer | list of answers | + MODE: | relative tol. | relative tolerance | absolute tolerance | absolute tolerance | + -------+----------------+---------------------+--------------------+-------------------------+ + std | std_num_cmp | std_num_cmp_list | std_num_cmp_abs | std_num_cmp_abs_list | + frac | frac_num_cmp | frac_num_cmp_list | frac_num_cmp_abs | frac_num_cmp_abs_list | + strict | strict_num_cmp | strict_num_cmp_list | strict_num_cmp_abs | strict_num_cmp_abs_list | + arith | arith_num_cmp | arith_num_cmp_list | arith_num_cmp_abs | arith_num_cmp_abs_list | + +The functions in each group take the same arguments. + +=head2 The normal group + + ANS(std_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(arith_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(strict_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + ANS(frac_num_cmp($correctAnswer, $relTol, $format, $zeroLevel, $zeroLevelTol)); + +This group of functions produces answer evaluators for a single correct answer +using relative tolerances. The first argument, $correctAnswer, is required. The +rest are optional. The arguments are equivalent to the identically-named options +to num_cmp(), above. + +=head2 The list group + + ANS(std_num_cmp_list($relTol, $format, @answerList)); + ANS(arith_num_cmp_list($relTol, $format, @answerList)); + ANS(strict_num_cmp_list($relTol, $format, @answerList)); + ANS(frac_num_cmp_list($relTol, $format, @answerList)); + +This group of functions produces answer evaluators for a list of correct answers +using relative tolerances. $relTol and $format are equivelent to the +identically-named options to num_cmp() above. @answerList must contain one or +more correct answers. A list of answer evaluators is returned, one for each +answer provided in @answerList. All answer returned evaluators will use the +relative tolerance and format specified. + +=head2 The abs group + + ANS(std_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(arith_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(strict_num_cmp_abs($correctAnswer, $absTol, $format)); + ANS(frac_num_cmp_abs($correctAnswer, $absTol, $format)); + +This group of functions produces answer evaluators for a single correct answer +using absolute tolerances. The first argument, $correctAnswer, is required. The +rest are optional. The arguments are equivalent to the identically-named options +to num_cmp(), above. + +=head2 The abs_list group + + ANS(std_num_cmp_abs_list($absTol, $format, @answerList)); + ANS(arith_num_cmp_abs_list($absTol, $format, @answerList)); + ANS(strict_num_cmp_abs_list($absTol, $format, @answerList)); + ANS(frac_num_cmp_abs_list($absTol, $format, @answerList)); + +This group of functions produces answer evaluators for a list of correct answers +using absolute tolerances. $absTol and $format are equivelent to the +identically-named options to num_cmp() above. @answerList must contain one or +more correct answers. A list of answer evaluators is returned, one for each +answer provided in @answerList. All answer returned evaluators will use the +absolute tolerance and format specified. + +=head2 Examples + + # The student answer must be a number in decimal or scientific notation + # which is within .1 percent of 3.14159. This assumes + # $numRelPercentTolDefault has been set to .1. + ANS(strict_num_cmp(3.14159)); + + # The student answer must be a number within .01 percent of $answer (e.g. # + 3.14159 if $answer is 3.14159 or $answer is "pi" or $answer is 4*atan(1)). + ANS(strict_num_cmp($answer, .01)); + + # The student answer can be a number or fraction, e.g. 2/3. + ANS(frac_num_cmp($answer)); # or + ANS(frac_num_cmp($answer, .01)); + + # The student answer can be an arithmetic expression, e.g. (2+3)/7-2^.5 . + ANS(arith_num_cmp($answer)); # or + ANS(arith_num_cmp($answer, .01)); + + # The student answer can contain elementary functions, e.g. sin(.3+pi/2) + ANS(std_num_cmp($answer)); # or + ANS(std_num_cmp( $answer, .01)); + +=cut + +sub std_num_cmp { # compare numbers allowing use of elementary functions + my ( $correctAnswer, $relPercentTol, $format, $zeroLevel, $zeroLevelTol ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + 'zeroLevel' => $zeroLevel, + 'zeroLevelTol' => $zeroLevelTol + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $numRelPercentTolDefault, + 'mode' => 'std', + 'format' => $numFormatDefault, + 'relTol' => $numRelPercentTolDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'debug' => 0, + ); + + num_cmp([$correctAnswer], %options); +} + +## Similar to std_num_cmp but accepts a list of numbers in the form +## std_num_cmp_list(relpercentTol,format,ans1,ans2,ans3,...) +## format is of the form "%10.3g" or "", i.e., a format suitable for sprintf(). Use "" for default +## You must enter a format and tolerance + +sub std_num_cmp_list { + my ( $relPercentTol, $format, @answerList) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $numRelPercentTolDefault, + 'mode' => 'std', + 'format' => $numFormatDefault, + 'relTol' => $numRelPercentTolDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); + +} + +sub std_num_cmp_abs { # compare numbers allowing use of elementary functions with absolute tolerance + my ( $correctAnswer, $absTol, $format) = @_; + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'std', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp([$correctAnswer], %options); +} + +## See std_num_cmp_list for usage + +sub std_num_cmp_abs_list { + my ( $absTol, $format, @answerList ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format, + ); + + set_default_options( \%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'std', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + +sub frac_num_cmp { # only allow fractions and numbers as submitted answer + + my ( $correctAnswer, $relPercentTol, $format, $zeroLevel, $zeroLevelTol ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + 'zeroLevel' => $zeroLevel, + 'zeroLevelTol' => $zeroLevelTol + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $relPercentTol, + 'mode' => 'frac', + 'format' => $numFormatDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'debug' => 0, + ); + + num_cmp([$correctAnswer], %options); +} + +## See std_num_cmp_list for usage +sub frac_num_cmp_list { + my ( $relPercentTol, $format, @answerList ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $relPercentTol, + 'mode' => 'frac', + 'format' => $numFormatDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + +sub frac_num_cmp_abs { # only allow fraction expressions as submitted answer with absolute tolerance + my ( $correctAnswer, $absTol, $format ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'frac', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp([$correctAnswer], %options); +} + +## See std_num_cmp_list for usage + +sub frac_num_cmp_abs_list { + my ( $absTol, $format, @answerList ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'frac', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + + +sub arith_num_cmp { # only allow arithmetic expressions as submitted answer + + my ( $correctAnswer, $relPercentTol, $format, $zeroLevel, $zeroLevelTol ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + 'zeroLevel' => $zeroLevel, + 'zeroLevelTol' => $zeroLevelTol + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $relPercentTol, + 'mode' => 'arith', + 'format' => $numFormatDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'debug' => 0, + ); + + num_cmp([$correctAnswer], %options); +} + +## See std_num_cmp_list for usage +sub arith_num_cmp_list { + my ( $relPercentTol, $format, @answerList ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $relPercentTol, + 'mode' => 'arith', + 'format' => $numFormatDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + +sub arith_num_cmp_abs { # only allow arithmetic expressions as submitted answer with absolute tolerance + my ( $correctAnswer, $absTol, $format ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'arith', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp([$correctAnswer], %options); +} + +## See std_num_cmp_list for usage +sub arith_num_cmp_abs_list { + my ( $absTol, $format, @answerList ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'arith', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + +sub strict_num_cmp { # only allow numbers as submitted answer + my ( $correctAnswer, $relPercentTol, $format, $zeroLevel, $zeroLevelTol ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + 'zeroLevel' => $zeroLevel, + 'zeroLevelTol' => $zeroLevelTol + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $relPercentTol, + 'mode' => 'strict', + 'format' => $numFormatDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'debug' => 0, + ); + num_cmp([$correctAnswer], %options); + +} + +## See std_num_cmp_list for usage +sub strict_num_cmp_list { # compare numbers + my ( $relPercentTol, $format, @answerList ) = @_; + + my %options = ( 'relTol' => $relPercentTol, + 'format' => $format, + ); + + set_default_options( \%options, + 'tolType' => 'relative', + 'tolerance' => $relPercentTol, + 'mode' => 'strict', + 'format' => $numFormatDefault, + 'zeroLevel' => $numZeroLevelDefault, + 'zeroLevelTol' => $numZeroLevelTolDefault, + 'relTol' => $numRelPercentTolDefault, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + + +sub strict_num_cmp_abs { # only allow numbers as submitted answer with absolute tolerance + my ( $correctAnswer, $absTol, $format ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'strict', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + num_cmp([$correctAnswer], %options); + +} + +## See std_num_cmp_list for usage +sub strict_num_cmp_abs_list { # compare numbers + my ( $absTol, $format, @answerList ) = @_; + + my %options = ( 'tolerance' => $absTol, + 'format' => $format + ); + + set_default_options (\%options, + 'tolType' => 'absolute', + 'tolerance' => $absTol, + 'mode' => 'strict', + 'format' => $numFormatDefault, + 'zeroLevel' => 0, + 'zeroLevelTol' => 0, + 'debug' => 0, + ); + + num_cmp(\@answerList, %options); +} + +=head1 Miscellaneous functions + +=head2 [DEPRECATED] numerical_compare_with_units + + ANS(numerical_compare_with_units($correct_ans_with_units, %options)) + +This function is deprecated. Use num_cmp with the units option instead: + + ANS(num_cmp($correct_ans, units=>$units)); + +=cut + +## sub numerical_compare_with_units +## Compares a number with units +## Deprecated; use num_cmp() +## +## IN: a string which includes the numerical answer and the units +## a hash with the following keys (all optional): +## mode -- 'std', 'frac', 'arith', or 'strict' +## format -- the format to use when displaying the answer +## tol -- an absolute tolerance, or +## relTol -- a relative tolerance +## zeroLevel -- if the correct answer is this close to zero, then zeroLevelTol applies +## zeroLevelTol -- absolute tolerance to allow when correct answer is close to zero + +# This mode is depricated. send input through num_cmp -- it can handle units. + +sub numerical_compare_with_units { + my $correct_answer = shift; # the answer is a string which includes both the numerical answer and the units. + my %options = @_; # all of the other inputs are (key value) pairs + + # Prepare the correct answer + $correct_answer = str_filters( $correct_answer, 'trim_whitespace' ); + + # it surprises me that the match below works since the first .* is greedy. + my ($correct_num_answer, $correct_units) = $correct_answer =~ /^(.*)\s+([^\s]*)$/; + $options{units} = $correct_units; + + num_cmp($correct_num_answer, %options); +} + +=head2 [DEPRECATED] std_num_str_cmp() + + ANS(std_num_str_cmp($correctAnswer, $ra_legalStrings, $relTol, $format, $zeroLevel, $zeroLevelTol)) + +This function is deprecated. Use num_cmp() with the strings option instead: + + ANS(num_cmp($correctAnswer, strings=>$ra_legalStrings, ...)); + +=cut + +sub std_num_str_cmp { + my ( $correctAnswer, $ra_legalStrings, $relpercentTol, $format, $zeroLevel, $zeroLevelTol ) = @_; + # warn ('This method is depreciated. Use num_cmp instead.'); + return num_cmp ($correctAnswer, strings=>$ra_legalStrings, relTol=>$relpercentTol, format=>$format, + zeroLevel=>$zeroLevel, zeroLevelTol=>$zeroLevelTol); +} + +sub NUM_CMP { # low level numeric compare (now uses Parser) + return ORIGINAL_NUM_CMP(@_) + if $useOldAnswerMacros; + + my %num_params = @_; + + # + # check for required parameters + # + my @keys = qw(correctAnswer tolerance tolType format mode zeroLevel zeroLevelTol debug); + foreach my $key (@keys) { + warn "$key must be defined in options when calling NUM_CMP" + unless defined($num_params{$key}); + } + + my $correctAnswer = $num_params{correctAnswer}; + my $mode = $num_params{mode}; + my %options = (debug => $num_params{debug}); + + # + # Hack to fix up exponential notation in correct answer + # (e.g., perl will pass .0000001 as 1e-07). + # + $correctAnswer = uc($correctAnswer) + if $correctAnswer =~ m/e/ && Value::isNumber($correctAnswer); + + # + # Get an apppropriate context based on the mode + # + my $context; + for ($mode) { + /^strict$/i and do { + $context = Parser::Context->getCopy($user_context,"LimitedNumeric"); + last; + }; + /^arith$/i and do { + $context = Parser::Context->getCopy($user_context,"LegacyNumeric"); + $context->functions->disable('All'); + last; + }; + /^frac$/i and do { + $context = Parser::Context->getCopy($user_context,"LimitedNumeric-Fraction"); + last; + }; + + # default + $context = Parser::Context->getCopy($user_context,"LegacyNumeric"); + } + $context->{format}{number} = $num_params{'format'}; + $context->strings->clear; + # FIXME: should clear variables as well? Copy them from the current context? + + # + # Add the strings to the context + # + if ($num_params{strings}) { + foreach my $string (@{$num_params{strings}}) { + my %tex = ($string =~ m/^(-?)inf(inity)?$/i)? (TeX => "$1\\infty"): (); + %tex = (TeX => "-\\infty") if uc($string) eq "MINF"; + $context->strings->add(uc($string) => {%tex}) + unless $context->strings->get(uc($string)); + } + } + + # + # Set the tolerances + # + if ($num_params{tolType} eq 'absolute') { + $context->flags->set( + tolerance => $num_params{tolerance}, + tolType => 'absolute', + ); + } else { + $context->flags->set( + tolerance => .01*$num_params{tolerance}, + tolType => 'relative', + ); + } + $context->flags->set( + zeroLevel => $num_params{zeroLevel}, + zeroLevelTol => $num_params{zeroLevelTol}, + ); + + # + # Get the proper Parser object for the professor's answer + # using the initialized context + # + my $oldContext = &$Context(); &$Context($context); my $r; + if ($num_params{units}) { + $r = new Parser::Legacy::NumberWithUnits($correctAnswer); + $options{rh_correct_units} = $num_params{units}; + } else { + $r = Value::Formula->new($correctAnswer); + die "The professor's answer can't be a formula" unless $r->isConstant; + $r = $r->eval; $r = new Value::Real($r) unless Value::class($r) eq 'String'; + $r->{correct_ans} = $correctAnswer; + if ($mode eq 'phase_pi') { + my $pi = 4*atan2(1,1); + while ($r > $pi/2) {$r -= $pi} + while ($r < -$pi/2) {$r += $pi} + } + } + # + # Get the answer checker from the parser object + # + my $cmp = $r->cmp(%options); + $cmp->install_pre_filter(sub { + my $rh_ans = shift; + $rh_ans->{original_student_ans} = $rh_ans->{student_ans}; + $rh_ans->{original_correct_ans} = $rh_ans->{correct_ans}; + return $rh_ans; + }); + $cmp->install_post_filter(sub { + my $rh_ans = shift; + $rh_ans->{student_ans} = $rh_ans->{student_value}->string + if ref($rh_ans->{student_value}); + return $rh_ans; + }); + &$Context($oldContext); + + return $cmp; +} + +# +# The original version, for backward compatibility +# (can be removed when the Parser-based version is more fully tested.) +# +sub ORIGINAL_NUM_CMP { # low level numeric compare + my %num_params = @_; + + my @keys = qw ( correctAnswer tolerance tolType format mode zeroLevel zeroLevelTol debug ); + foreach my $key (@keys) { + warn "$key must be defined in options when calling NUM_CMP" unless defined ($num_params{$key}); + } + + my $correctAnswer = $num_params{'correctAnswer'}; + my $format = $num_params{'format'}; + my $mode = $num_params{'mode'}; + + if( $num_params{tolType} eq 'relative' ) { + $num_params{'tolerance'} = .01*$num_params{'tolerance'}; + } + + my $formattedCorrectAnswer; + my $correct_units; + my $correct_num_answer; + my %correct_units; + my $corrAnswerIsString = 0; + + + if (defined($num_params{units}) && $num_params{units}) { + $correctAnswer = str_filters( $correctAnswer, 'trim_whitespace' ); + # units are in form stuff space units where units contains no spaces. + + ($correct_num_answer, $correct_units) = $correctAnswer =~ /^(.*)\s+([^\s]*)$/; + %correct_units = Units::evaluate_units($correct_units); + if ( defined( $correct_units{'ERROR'} ) ) { + warn ("ERROR: The answer \"$correctAnswer\" in the problem definition cannot be parsed:\n" . + "$correct_units{'ERROR'}\n"); + } + # $formattedCorrectAnswer = spf($correct_num_answer,$num_params{'format'}) . " $correct_units"; + $formattedCorrectAnswer = prfmt($correct_num_answer,$num_params{'format'}) . " $correct_units"; + + } elsif (defined($num_params{strings}) && $num_params{strings}) { + my $legalString = ''; + my @legalStrings = @{$num_params{strings}}; + $correct_num_answer = $correctAnswer; + $formattedCorrectAnswer = $correctAnswer; + foreach $legalString (@legalStrings) { + if ( uc($correctAnswer) eq uc($legalString) ) { + $corrAnswerIsString = 1; + + last; + } + } ## at this point $corrAnswerIsString = 0 iff correct answer is numeric + } else { + $correct_num_answer = $correctAnswer; + $formattedCorrectAnswer = prfmt( $correctAnswer, $num_params{'format'} ); + } + + $correct_num_answer = math_constants($correct_num_answer); + + my $PGanswerMessage = ''; + + my ($inVal,$correctVal,$PG_eval_errors,$PG_full_error_report); + + if (defined($correct_num_answer) && $correct_num_answer =~ /\S/ && $corrAnswerIsString == 0 ) { + ($correctVal, $PG_eval_errors,$PG_full_error_report) = PG_answer_eval($correct_num_answer); + } else { # case of a string answer + $PG_eval_errors = ' '; + $correctVal = $correctAnswer; + } + + if ( ($PG_eval_errors && $corrAnswerIsString == 0) or ((not is_a_number($correctVal)) && $corrAnswerIsString == 0)) { + ##error message from eval or above + warn "Error in 'correct' answer: $PG_eval_errors<br> + The answer $correctAnswer evaluates to $correctVal, + which cannot be interpreted as a number. "; + + } + ######################################################################### + + #construct the answer evaluator + my $answer_evaluator = new AnswerEvaluator; + $answer_evaluator->{debug} = $num_params{debug}; + $answer_evaluator->ans_hash( + correct_ans => $correctVal, + type => "${mode}_number", + tolerance => $num_params{tolerance}, + tolType => $num_params{tolType}, + units => $correct_units, + original_correct_ans => $formattedCorrectAnswer, + rh_correct_units => \%correct_units, + answerIsString => $corrAnswerIsString, + ); + my ($in, $formattedSubmittedAnswer); + $answer_evaluator->install_pre_filter(sub {my $rh_ans = shift; + $rh_ans->{original_student_ans} = $rh_ans->{student_ans}; $rh_ans;} + ); + + + + if (defined($num_params{units}) && $num_params{units}) { + $answer_evaluator->install_pre_filter(\&check_units); + } + if (defined($num_params{strings}) && $num_params{strings}) { + $answer_evaluator->install_pre_filter(\&check_strings, %num_params); + } + + ## FIXME? - this pre filter was moved before check_units to allow + ## for latex preview of answers with no units. + ## seems to work but may have unintended side effects elsewhere. + + ## Actually it caused trouble with the check strings package so it has been moved back + # We'll try some other method -- perhaps add code to fix_answer for display + $answer_evaluator->install_pre_filter(\&check_syntax); + + $answer_evaluator->install_pre_filter(\&math_constants); + + if ($mode eq 'std') { + # do nothing + } elsif ($mode eq 'strict') { + $answer_evaluator->install_pre_filter(\&is_a_number); + } elsif ($mode eq 'arith') { + $answer_evaluator->install_pre_filter(\&is_an_arithmetic_expression); + } elsif ($mode eq 'frac') { + $answer_evaluator->install_pre_filter(\&is_a_fraction); + + } elsif ($mode eq 'phase_pi') { + $answer_evaluator->install_pre_filter(\&phase_pi); + + } else { + $PGanswerMessage = 'Tell your professor that there is an error in his or her answer mechanism. No mode was specified.'; + $formattedSubmittedAnswer = $in; + } + + if ($corrAnswerIsString == 0 ){ # avoiding running compare_numbers when correct answer is a string. + $answer_evaluator->install_evaluator(\&compare_numbers, %num_params); + } + + +############################################################################### +# We'll leave these next lines out for now, so that the evaluated versions of the student's and professor's +# can be displayed in the answer message. This may still cause a few anomolies when strings are used +# +############################################################################### + + $answer_evaluator->install_post_filter(\&fix_answers_for_display); + + $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; + return $rh_ans unless $rh_ans->catch_error('EVAL'); + $rh_ans->{student_ans} = $rh_ans->{original_student_ans}. ' '. $rh_ans->{error_message}; + $rh_ans->clear_error('EVAL'); } ); + $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('SYNTAX'); } ); + $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('UNITS'); } ); + $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('NUMBER'); } ); + $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('STRING'); } ); + $answer_evaluator; +} + +=head1 SEE ALSO + +L<PGanswermacros.pl>, L<MathObjects>. + +=cut + +1; --- /dev/null +++ macros/PGmiscevaluators.pl @@ -0,0 +1,134 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: pg/macros/PGmiscevaluators.pl,v 1.1 2007/11/08 00:00:15 sh002i Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +=head1 NAME + +PGmiscevaluators.pl - Some miscellaneous answer macros. + +=head1 SYNOPSIS + +=head1 DESCRIPTION + +Currently contains answer evaluators for radio buttons and checkboxes. + +=head2 MathObjects and answer evaluators + +The MathObjects system provides a parserRadioButtons.pl file that manages +display and checking of radio-button based answers. It is recommended that you +use this method directly if possible. + +=cut + +BEGIN { be_strict() } +sub _PGmiscevaluators_init {} + +=head1 checkbox_cmp + + ANS(checkbox_cmp($correctAnswer)) + +$correctAnswer is a string containing the names of the correct boxes, e.g. +"ACD". Note that this means that individual checkbox names can only be one +character. Internally, this is largely the same as unordered_cs_str_cmp(). + +=cut + +# added 6/14/2000 by David Etlinger +# because of the conversion of the answer +# string to an array, I thought it better not +# to force STR_CMP() to work with this + +#added 2/26/2003 by Mike Gage +# handled the case where multiple answers are passed as an array reference +# rather than as a \0 delimited string. +sub checkbox_cmp { + my $correctAnswer = shift @_; + my %options = @_; + assign_option_aliases( \%options, + ); + set_default_options( \%options, + 'debug' => 0, + 'type' => 'checkbox_cmp', + ); + my $answer_evaluator = new AnswerEvaluator( + correct_ans => $correctAnswer, + type => $options{type}, + ); + # pass along debug requests + $answer_evaluator->{debug} = $options{debug}; + + # join student answer array into a single string if necessary + $answer_evaluator->install_pre_filter(sub { + my $rh_ans = shift; + $rh_ans->{_filter_name} = 'convert student_ans to string'; + $rh_ans->{student_ans} = join("", @{$rh_ans->{student_ans}}) + if ref($rh_ans->{student_ans}) =~/ARRAY/i; + $rh_ans; + }); + # ignore order of check boxes + $answer_evaluator->install_pre_filter(\&ignore_order); + # compare as strings + $answer_evaluator->install_evaluator(sub { + my $rh_ans = shift; + $rh_ans->{_filter_name} = 'compare strings generated by checked boxes'; + $rh_ans->{score} = ($rh_ans->{student_ans} eq $rh_ans->{correct_ans}) ? 1 : 0; + $rh_ans; + }); + # fix up preview displays + $answer_evaluator->install_post_filter( sub { + my $rh_ans = shift; + $rh_ans->{_filter_name} = 'adjust preview strings'; + $rh_ans->{type} = $options{type}; + $rh_ans->{preview_text_string} = '\\text{'.$rh_ans->{student_ans}.'}', + $rh_ans->{preview_latex_string} = '\\text{'.$rh_ans->{student_ans}.'}', + $rh_ans; + + + }); + + return $answer_evaluator; +} + +=head1 radio_cmp + + ANS(radio_cmp($correctAnswer)) + +$correctAnswer is a string containing the name of the correct radio button, +e.g. "Choice1". This is case sensitive and whitespace sensitive, so the correct +answer must match the name of the radio button exactly. + +=cut + +#added 6/28/2000 by David Etlinger +#exactly the same as strict_str_cmp, +#but more intuitive to the user + +# check that answer is really a string and not an array +# also use ordinary string compare +sub radio_cmp { + #strict_str_cmp( @_ ); + my $response = shift; # there should be only one item. + warn "Multiple choices -- this should not happen with radio buttons. Have + you used checkboxes perhaps?" if ref($response); #triggered if an ARRAY is passed + str_cmp($response); +} + +=head1 SEE ALSO + +L<PGanswermacros.pl>, L<MathObjects>. + +=cut + +1; Index: PGanswermacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGanswermacros.pl,v retrieving revision 1.63 retrieving revision 1.64 diff -Lmacros/PGanswermacros.pl -Lmacros/PGanswermacros.pl -u -r1.63 -r1.64 --- macros/PGanswermacros.pl +++ macros/PGanswermacros.pl @@ -1,3363 +1,177 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader$ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ -# This file is PGanswermacros.pl -# This includes the subroutines for the ANS macros, that -# is, macros allowing a more flexible answer checking -#################################################################### -# Copyright @ 1995-2000 University of Rochester -# All Rights Reserved -#################################################################### -#$Id$ +# FIXME TODO: +# Document and maybe split out: filters, graders, utilities =head1 NAME - PGanswermacros.pl -- located in the courseScripts directory +PGanswermacros.pl - Macros for building answer evaluators. =head1 SYNPOSIS - Number Answer Evaluators: - num_cmp() -- uses an input hash to determine parameters +Number Answer Evaluators: - std_num_cmp(), std_num_cmp_list(), std_num_cmp_abs, std_num_cmp_abs_list() - frac_num_cmp(), frac_num_cmp_list(), frac_num_cmp_abs, frac_num_cmp_abs_list() - arith_num_cmp(), arith_num_cmp_list(), arith_num_cmp_abs, arith_num_cmp_abs_list() - strict_num_cmp(), strict_num_cmp_list(), strict_num_cmp_abs, strict_num_cmp_abs_list() - numerical_compare_with_units() -- requires units as part of the answer - std_num_str_cmp() -- also accepts a set of strings as possible answers - - Function Answer Evaluators: - fun_cmp() -- uses an input hash to determine parameters - - function_cmp(), function_cmp_abs() - function_cmp_up_to_constant(), function_cmp_up_to_constant_abs() - multivar_function_cmp() - - String Answer Evaluators: - str_cmp() -- uses an input hash to determine parameters - - std_str_cmp(), std_str_cmp_list(), std_cs_str_cmp(), std_cs_str_cmp_list() - strict_str_cmp(), strict_str_cmp_list() - ordered_str_cmp(), ordered_str_cmp_list(), ordered_cs_str_cmp(), ordered_cs_str_cmp_list() - unordered_str_cmp(), unordered_str_cmp_list(), unordered_cs_str_cmp(), unordered_cs_str_cmp_list() - - Miscellaneous Answer Evaluators: - checkbox_cmp() - radio_cmp() - -=cut - -=head1 DESCRIPTION - -This file adds subroutines which create "answer evaluators" for checking -answers. Each answer evaluator accepts a single input from a student answer, -checks it and creates an output hash %ans_hash with seven or eight entries -(the preview_latex_string is optional). The output hash is now being created -with the AnswerHash package "class", which is located at the end of this file. -This class is currently just a wrapper for the hash, but this might change in -the future as new capabilities are added. - - score => $correctQ, - correct_ans => $originalCorrEqn, - student_ans => $modified_student_ans - original_student_ans => $original_student_answer, - ans_message => $PGanswerMessage, - type => 'typeString', - preview_text_string => $preview_text_string, - preview_latex_string => $preview_latex_string - - - $ans_hash{score} -- a number between 0 and 1 indicating - whether the answer is correct. Fractions - allow the implementation of partial - credit for incorrect answers. - $ans_hash{correct_ans} -- The correct answer, as supplied by the - instructor and then formatted. This can - be viewed by the student after the answer date. - $ans_hash{student_ans} -- This is the student answer, after reformatting; - for example the answer might be forced - to capital letters for comparison with - the instructors answer. For a numerical - answer, it gives the evaluated answer. - This is displayed in the section reporting - the results of checking the student answers. - $ans_hash{original_student_ans} -- This is the original student answer. This is displayed - on the preview page and may be used for sticky answers. - $ans_hash{ans_message} -- Any error message, or hint provided by the answer evaluator. - This is also displayed in the section reporting - the results of checking the student answers. - $ans_hash{type} -- A string indicating the type of answer evaluator. This - helps in preprocessing the student answer for errors. - Some examples: - 'number_with_units' - 'function' - 'frac_number' - 'arith_number' - $ans_hash{preview_text_string} -- This typically shows how the student answer was parsed. It is - displayed on the preview page. For a student answer of 2sin(3x) - this would be 2*sin(3*x). For string answers it is typically the - same as $ans_hash{student_ans}. - $ans_hash{preview_latex_string} -- THIS IS OPTIONAL. This is latex version of the student answer - which is used to show a typeset view on the answer on the preview - page. For a student answer of 2/3, this would be \frac{2}{3}. - -Technical note: the routines in this file are not actually answer evaluators. Instead, they create -answer evaluators. An answer evaluator is an anonymous subroutine, referenced by a named scalar. The -routines in this file build the subroutine and return a reference to it. Later, when the student -actually enters an answer, the problem processor feeds that answer to the referenced subroutine, which -evaluates it and returns a score (usually 0 or 1). For most users, this distinction is unimportant, but -if you plan on writing your own answer evaluators, you should understand this point. - -=cut - -BEGIN { - be_strict(); # an alias for use strict. This means that all global variable must contain main:: as a prefix. -} - - -my ($BR , # convenient localizations. - $PAR , - $numRelPercentTolDefault , - $numZeroLevelDefault , - $numZeroLevelTolDefault , - $numAbsTolDefault , - $numFormatDefault , - $functRelPercentTolDefault , - $functZeroLevelDefault , - $functZeroLevelTolDefault , - $functAbsTolDefault , - $functNumOfPoints , - $functVarDefault , - $functLLimitDefault , - $functULimitDefault , - $functMaxConstantOfIntegration , - $CA , - $rh_envir , - $useBaseTenLog , - $inputs_ref , - $QUESTIONNAIRE_ANSWERS , - $user_context, - $Context, -); - - - - -sub _PGanswermacros_init { - - $BR = main::PG_restricted_eval(q!$main::BR!); - $PAR = main::PG_restricted_eval(q!$main::PAR!); - - # import defaults - # these are now imported from the %envir variable - $numRelPercentTolDefault = main::PG_restricted_eval(q!$main::numRelPercentTolDefault!); - $numZeroLevelDefault = main::PG_restricted_eval(q!$main::numZeroLevelDefault!); - $numZeroLevelTolDefault = main::PG_restricted_eval(q!$main::numZeroLevelTolDefault!); - $numAbsTolDefault = main::PG_restricted_eval(q!$main::numAbsTolDefault!); - $numFormatDefault = main::PG_restricted_eval(q!$main::numFormatDefault!); - $functRelPercentTolDefault = main::PG_restricted_eval(q!$main::functRelPercentTolDefault!); - $functZeroLevelDefault = main::PG_restricted_eval(q!$main::functZeroLevelDefault!); - $functZeroLevelTolDefault = main::PG_restricted_eval(q!$main::functZeroLevelTolDefault!); - $functAbsTolDefault = main::PG_restricted_eval(q!$main::functAbsTolDefault!); - $functNumOfPoints = main::PG_restricted_eval(q!$main::functNumOfPoints!); - $functVarDefault = main::PG_restricted_eval(q!$main::functVarDefault!); - $functLLimitDefault = main::PG_restricted_eval(q!$main::functLLimitDefault!); - $functULimitDefault = main::PG_restricted_eval(q!$main::functULimitDefault!); - $functMaxConstantOfIntegration = main::PG_restricted_eval(q!$main::functMaxConstantOfIntegration!); - $rh_envir = main::PG_restricted_eval(q!\%main::envir!); - $useBaseTenLog = main::PG_restricted_eval(q!$main::useBaseTenLog!); - $inputs_ref = main::PG_restricted_eval(q!$main::inputs_ref!); - $QUESTIONNAIRE_ANSWERS = ''; - - if (!main::PG_restricted_eval(q!$main::useOldAnswerMacros!)) { - $user_context = main::PG_restricted_eval(q!\%context!); - $Context = sub {Parser::Context->current($user_context,@_)}; - } -} - - - -########################################################################## - -#Note use $rh_envir to read environment variables - -####################################... [truncated message content] |
From: Mike G. v. a. <we...@ma...> - 2007-11-06 16:55:58
|
Log Message: ----------- Added some further documentation pointing out the workaround to make flash objects embedded within forms (as all objects in a PG problem are) work with IE. -- Mike Modified Files: -------------- pg/lib: Applet.pm Revision Data ------------- Index: Applet.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Applet.pm,v retrieving revision 1.2 retrieving revision 1.3 diff -Llib/Applet.pm -Llib/Applet.pm -u -r1.2 -r1.3 --- lib/Applet.pm +++ lib/Applet.pm @@ -137,6 +137,22 @@ # <param name="quality" value="high" /><param name="bgcolor" value="#ffffcc" /> # </object> +=pod + +The secret to making this applet work with IE in addition to normal browsers +is the addition of the C(<form></form>) construct just before the object. + +For some reason IE has trouble locating a flash object which is contained +within a form. Adding this second blank form with the larger problemMainForm +seems to solve the problem. + +This follows method2 of the advice given in url(http://kb.adobe.com/selfservice/viewContent.do?externalId=kb400730&sliceId=2) +Method1 and methods involving SWFObject(Geoff Stearns) and SWFFormFix (Steve Kamerman) have yet to be fully investigated: +http://devel.teratechnologies.net/swfformfix/swfobject_swfformfix_source.js +http://www.teratechnologies.net/stevekamerman/index.php?m=01&y=07&entry=entry070101-033933 + +=cut + use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT'; <form></form> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" |
From: Mike G. v. a. <we...@ma...> - 2007-11-06 16:54:14
|
Log Message: ----------- Provides front end for Applet.pm. To use applets add loadMacros("AppletObjects.pl") to the top of your PG problem file. $applet = FlashApplet(); gets you started. There is reasonable POD documentation in this file including a working problem for the ExternalInterface.swf flash object. -- Mike Added Files: ----------- pg/macros: AppletObjects.pl Revision Data ------------- --- /dev/null +++ macros/AppletObjects.pl @@ -0,0 +1,209 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: pg/macros/AppletObjects.pl,v 1.1 2007/11/06 16:45:28 gage Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +=head1 NAME + +AppletOjects.pl - Macro-based front end for the Applet.pm module. + + +=head1 DESCRIPTION + +This subroutines in this +file provide mechanisms to insert Flash applets (and later Java applets) +into a WeBWorK problem. + + +=head1 SEE ALSO + +L<Applets.pm>. + +=cut + +sub _PGapplets_init {}; # don't reload this file + +=head3 + FlashApplet + + Useage: $applet = FlashApplet(); + +=cut + +sub FlashApplet { + return new FlashApplet(); + +} + +package FlashApplet; + +=head2 Methods + +=cut + +## this method is defined in this file +## because the main subroutines HEADER_TEXT and MODES are +## not available to the module FlashApplet when that file +## is compiled (at the time the apache child process is first initialized) + +=head3 insert + + Useage: TEXT( $applet->insert() ); + \{ $applet->insert \} (used within BEGIN_TEXT/END_TEXT blocks) + +=cut + +=pod + +Inserts applet at this point in the HTML code. (In TeX mode a message "Applet" is written.) This method +also adds the applets header material into the header portion of the HTML page. It effectively inserts +the outputs of both C<$applet-E<gt>inserHeader> and C<$applet-E<gt>insertObject> (defined in L<Applet.pm> ) in the appropriate places. + +=cut + +sub insert { ## inserts both header text and object text + my $self = shift; + main::HEADER_TEXT($self->insertHeader()); + return main::MODES(TeX=>' {\bf flash applet } ', HTML=>$self->insertObject); +} + + +=head3 Example problem + + +=cut + + + +=pod + + + DOCUMENT(); + + # Load whatever macros you need for the problem + loadMacros("PG.pl", + "PGbasicmacros.pl", + "PGchoicemacros.pl", + "PGanswermacros.pl", + "AppletObjects.pl", + "MathObjects.pl", + "source.pl" + ); + + ## Do NOT show partial correct answers + $showPartialCorrectAnswers = 0; + + + + ################################### + # Create link to applet + ################################### + + $applet = FlashApplet(); + my $appletName = "ExternalInterface"; + $applet->codebase(findAppletCodebase("$appletName.swf")); + $applet->appletName($appletName); + $applet->appletId($appletName); + + # findAppletCodebase looks for the applet in a list + # of locations specified in global.conf + + ################################### + # Add java script functions to header section of HTML to + # communicate with the applet. + ################################### + + $applet->header(<<'END_HEADER'); + <script type="text/javascript" src="https://devel.webwork.rochester.edu:8002/webwork2_files/js/BrowserSniffer.js"> + </script> + + + <script language="JavaScript"> + function getBrowser() { + //alert("look for sniffer"); + var sniffer = new BrowserSniffer(); + //alert("found sniffer" +sniffer); + return sniffer; + } + + function updateStatus(sMessage) { + //alert("update form with " + sMessage); + //window.document.problemMainForm.playbackStatus.value = sMessage; + //document.problemMainForm.playbackStatus.value = sMessage; + document.getElementById("playbackStatus").value = sMessage; + } + + function newColor() { + //var app = getFlashMovie("ExternalInterface").getElementById("movie1"); + // alert(app); + // The difficult issue in adapting Barbara's original file was locating + // the object. It took several tries to find a method that worked + // and it is quite likely that it will not work in all browsers. + + //alert("update color"); + //alert(getFlashMovie("ExternalInterface")); + getFlashMovie("ExternalInterface").updateColor(Math.round(Math.random() * 0xFFFFFF)); + } + + function submitAction() { newColor() + } + + </script> + END_HEADER + + ################################### + # Configure applet + ################################### + + # not used here. Allows for uploading an xml string for the applet + + + + + ################################### + # write the text for the problem + ################################### + + TEXT(beginproblem()); + + + TEXT( MODES(TeX=>'object code', HTML=><<END_SCRIPT ) ); + <script> + //alert("foobar"); + initialize(); + // this should really be done in the <body> tag -- can we make that happen? + </script> + END_SCRIPT + + + BEGIN_TEXT + \{ $applet->insert \} + $PAR + + The Flash object operates above this line. The box and button below this line are part of + the WeBWorK problem. They communicate with the Flash object. + $HR + Status <input type="text" id="playbackStatus" value="started" /><br /> + Color <input type="button" value="new color" name="newColorButton" onClick="newColor()" /> + $PAR $HR + This flash applet was created by Barbara Kaskosz. + + END_TEXT + + ENDDOCUMENT(); + + + + +=cut \ No newline at end of file |
From: dpvc v. a. <we...@ma...> - 2007-11-06 16:47:19
|
Log Message: ----------- When (-x)*y or x*(-y) reductions are performed, don't print extra parentheses in string and TeX version. I.e., display as -xy not -(xy). This makes reduction with polynomials work better. Modified Files: -------------- pg/lib/Parser/BOP: multiply.pm Revision Data ------------- Index: multiply.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Parser/BOP/multiply.pm,v retrieving revision 1.15 retrieving revision 1.16 diff -Llib/Parser/BOP/multiply.pm -Llib/Parser/BOP/multiply.pm -u -r1.15 -r1.16 --- lib/Parser/BOP/multiply.pm +++ lib/Parser/BOP/multiply.pm @@ -67,6 +67,13 @@ return $self; } +sub makeNeg { + my $self = shift; + $self = $self->SUPER::makeNeg(@_); + $self->{op}{noParens} = 1; + return $self; +} + $Parser::reduce->{'1*x'} = 1; $Parser::reduce->{'x*1'} = 1; $Parser::reduce->{'0*x'} = 1; @@ -76,6 +83,26 @@ $Parser::reduce->{'x*n'} = 1; $Parser::reduce->{'fn*x'} = 1; +sub string { + my ($self,$precedence,$showparens,$position,$outerRight) = @_; + my $string; my $bop = $self->{def}; + $position = '' unless defined($position); + $showparens = '' unless defined($showparens); + my $extraParens = $self->context->flag('showExtraParens'); + my $addparens = + defined($precedence) && !$self->{noParens} && + ($showparens eq 'all' || (($showparens eq 'extra' || $bop->{fullparens}) && $extraParens > 1) || + $precedence > $bop->{precedence} || ($precedence == $bop->{precedence} && + ($bop->{associativity} eq 'right' || ($showparens eq 'same' && $extraParens)))); + $outerRight = !$addparens && ($outerRight || $position eq 'right'); + + $string = $self->{lop}->string($bop->{precedence},$bop->{leftparens},'left',$outerRight). + $bop->{string}. + $self->{rop}->string($bop->{precedence},$bop->{rightparens},'right'); + + $string = $self->addParens($string) if $addparens; + return $string; +} sub TeX { my ($self,$precedence,$showparens,$position,$outerRight) = @_; @@ -87,7 +114,7 @@ $cdot = '\cdot ' unless $cdot; my $addparens = - defined($precedence) && + defined($precedence) && !$self->{noParens} && ($showparens eq 'all' || $precedence > $bop->{precedence} || ($precedence == $bop->{precedence} && ($bop->{associativity} eq 'right' || $showparens eq 'same'))); |
From: dpvc v. a. <we...@ma...> - 2007-11-06 16:28:28
|
Log Message: ----------- Don't reduce -ax+b to b-ax in polynomial contexts. Modified Files: -------------- pg/macros: contextLimitedPolynomial.pl Revision Data ------------- Index: contextLimitedPolynomial.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextLimitedPolynomial.pl,v retrieving revision 1.20 retrieving revision 1.21 diff -Lmacros/contextLimitedPolynomial.pl -Lmacros/contextLimitedPolynomial.pl -u -r1.20 -r1.21 --- macros/contextLimitedPolynomial.pl +++ macros/contextLimitedPolynomial.pl @@ -417,9 +417,9 @@ ); } # - # Don't convert -ax-b to -(ax+b), etc. + # Don't convert -ax-b to -(ax+b), or -ax+b to b-ax, etc. # - $context->reduction->set("(-x)-y"=>0); + $context->reduction->set("(-x)-y"=>0,"(-x)+y"=>0); # # A context where coefficients can't include operations |
From: dpvc v. a. <we...@ma...> - 2007-11-06 15:57:49
|
Log Message: ----------- Fixed a problem introduced in the previous version where an error is reported about undefined values used in addition. Modified Files: -------------- pg/macros: contextLimitedPolynomial.pl Revision Data ------------- Index: contextLimitedPolynomial.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextLimitedPolynomial.pl,v retrieving revision 1.19 retrieving revision 1.20 diff -Lmacros/contextLimitedPolynomial.pl -Lmacros/contextLimitedPolynomial.pl -u -r1.19 -r1.20 --- macros/contextLimitedPolynomial.pl +++ macros/contextLimitedPolynomial.pl @@ -150,7 +150,8 @@ $self->{exponents} = [(0) x scalar(keys %{$vIndex})]; $self->{exponents}[$self->{index}] = 1; } elsif ($self->class eq 'Number') { - $self->{exponents} = []; + my $vIndex = LimitedPolynomial::getVarIndex($self); + $self->{exponents} = [(0) x scalar(keys %{$vIndex})]; } if ($self->{exponents}) { my $power = join(',',@{$self->{exponents}}); |
From: Mike G. v. a. <we...@ma...> - 2007-11-05 16:54:12
|
Log Message: ----------- This version of Applet.pm now works with IE. More documentation and features are forth coming but it is ready for some experimental use by those developing Applets. Modified Files: -------------- pg/lib: Applet.pm Revision Data ------------- Index: Applet.pm =================================================================== RCS file: /webwork/cvs/system/pg/lib/Applet.pm,v retrieving revision 1.1 retrieving revision 1.2 diff -Llib/Applet.pm -Llib/Applet.pm -u -r1.1 -r1.2 --- lib/Applet.pm +++ lib/Applet.pm @@ -96,10 +96,10 @@ use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT'; <script language="javascript">AC_FL_RunContent = 0;</script> - <script src="http://hosted2.webwork.rochester.edu/webwork2_files/applets/AC_RunActiveContent.js" language="javascript"></script> - - <script type="text/javascript" src="http://hosted2.webwork.rochester.edu/webwork2_files/js/BrowserSniffer.js"> + <script src="http://hosted2.webwork.rochester.edu/webwork2_files/applets/AC_RunActiveContent.js" language="javascript"> </script> + + <script language="JavaScript"> var flash; @@ -108,9 +108,7 @@ return (isIE) ? window[movieName] : window.document[movieName]; //return window.document[movieName]; } - function getBrowser() { - return new BrowserSniffer(); - } + function initialize() { getFlashMovie("$appletId").$initializeAction("$base64_xmlString"); @@ -119,7 +117,7 @@ document.problemMainForm.$returnFieldName.value = getFlashMovie("$appletId").$submitAction(); } - </script>, + </script> END_HEADER_SCRIPT @@ -140,6 +138,7 @@ # </object> use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT'; + <form></form> <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" id="ExternalInterface" width="500" height="375" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> |
From: dpvc v. a. <we...@ma...> - 2007-11-05 15:09:54
|
Log Message: ----------- Bring jsMath to version 3.4f: * Fixed a problem with the \bbox extension where the sizes of boxed items in super- and subscripts was incorrectly set, and where super- and subscripts for large operators that are boxed might be placed incorrectly. * Version 3.4e arranged for tex2math to recognize \begin{xxx}...\end{xxx} outside of math mode. It incorrectly placed the environment into in-line math mode rather than display mode. This had been corrected. * One more attempt to work around alignment problems with MSIE with a DOCTYPE that triggers "standards" mode. I think I finally found the real problem, and was able to remove several hacks that were not completely effective. Modified Files: -------------- webwork-modperl/htdocs/jsMath: jsMath.js webwork-modperl/htdocs/jsMath/easy: load.js webwork-modperl/htdocs/jsMath/extensions: bbox.js webwork-modperl/htdocs/jsMath/plugins: tex2math.js webwork-modperl/htdocs/jsMath/uncompressed: jsMath.js Revision Data ------------- Index: jsMath.js =================================================================== RCS file: /webwork/cvs/system/webwork-modperl/htdocs/jsMath/jsMath.js,v retrieving revision 1.39 retrieving revision 1.40 diff -Lhtdocs/jsMath/jsMath.js -Lhtdocs/jsMath/jsMath.js -u -r1.39 -r1.40 --- htdocs/jsMath/jsMath.js +++ htdocs/jsMath/jsMath.js @@ -40,11 +40,11 @@ //start = new Date().getTime(); jsMath.Script.Uncompress([ - ['if(!','window','.jsMath','||!',1,'.','jsMath.','loaded','){var ','jsMath_old','=',1,2,';',0,'document.','getElementById','||!',15,'childNodes||!',15,'createElement','){','alert("','The',' mathematics ','on this page requires W3C DOM support in its JavaScript. "+"Unfortunately, your ','browser',' doesn\'t seem to have this.")}','else{',1,2,'={version:"3.4e",document:document,',1,':',1,',','platform',':(','navigator.',37,'.match(/','Mac/)?"mac":',39,37,41,'Win/)?"pc":"unix"),','sizes',':[50,60,70,85,100,120,144,173,207,249],','styles',':{".math','":"font-family:serif; font-style:normal; font-weight:normal','",".typeset',51,'; ','line-height:normal','","div.','typeset','":"text-align',':center; margin:1em 0px;","span.',57,58,':left',52,' span',58,62,'; border:','0px; margin:0px; ','padding:0px','",".typeset .','normal',51,70,'size0','":"font-size:','50','%",".typeset .','size1',75,'60',77,'size2',75,'70',77,'size3',75,'85',77,'size4',75,'100',77,'size5',75,'120',77,'size6'! ,75,'144',77,'size7',75,'173',77,'size8',75,'207',77,'size9',75,'249',77,'cmr10','":"font-family:jsMath-',114,', serif',70,'cmbx10',115,119,', ','jsMath-cmr10',70,'cmti10',115,125,', ',123,70,'cmmi10',115,131,70,'cmsy10',115,135,70,'cmex10',115,139,70,'textit','":"font-family',':serif; ','font-style:italic',70,'textbf',144,':serif; font-weight:bold',70,'link":"','text-decoration:none',70,'error',75,'10pt; ',146,'; "+"','background-color',':#FFFFCC; padding:1px',159,'border:','1px solid',' #CC0000',70,'blank":"','display:inline-block','; ','overflow:hidden',67,'0px none; width:0px','; height:','0px;",".','typeset .','spacer','":"',168,'","#jsMath_hiddenSpan":"','visibility',':','hidden','; ','position:absolute','; top:0px',';left:0px',159,55,'; text-indent:0px","#','jsMath_message','":"','position:fixed','; bottom:1px; ','left:2px; ',160,':#E6E6E6','; "+"border:solid 1px #959595; margin:0px; padding:','1px 8px','; "+"z-index:102; color',': black','; font-size:','small; ','wi! dth:auto',';","#','jsMath_panel','":"',192,'; bottom:1.5em; ri! ght:1.5e m','; padding:.8em 1.6em',159,160,':#DDDDDD',67,'outset 2px',159,'z-index:103; ',203,'; color:black',201,'10pt; font-style:normal","#',205,' .disabled":"color:#888888","#',205,' .infoLink',75,'85%","#',205,' *":"','font-size:inherit; font-style:inherit; font-family:inherit','; ',55,'","#',205,' div":"',160,':inherit; color:inherit;","#',205,' span":"',160,236,205,' td','":"border:0px; padding:0px; margin:0px; background-color:inherit; color:inherit;","#',205,' tr',243,205,' table',243,'jsMath_button','":"',192,193,'right:2px; ',160,':white',197,'0px 3px 1px 3px',199,':black; ',153,201,'x-small',159,203,'; cursor:hand;","#',250,228,69,67,68,55,159,229,'","#jsMath_global":"',146,';","#jsMath_float','":"',184,185,'; left:0px; max-width:80%; "+"z-index:101; ',203,'; height:auto',277,' .drag":"',160,':#DDDDDD',67,'outset 1px',173,'12px',201,'1px',277,' .close":"',160,196,67,'inset 1px; width:8px',173,'8px; margin:1px 2px',277,' .source":"',160,':#E2E2E2',67,289,159,203,283,'; pad! ding:8px 15px',159,'font-family:courier, fixed',201,'90%","#jsMath_noFont .message',58,': center',209,67,'3px solid #DD0000',159,160,':#FFF8F8; color: #AA0000',201,202,203,204,'jsMath_noFont .link','":"',69,' 5px 2px 5px',67,'2px outset; ',160,':#E8E8E8',159,'color:black',201,'80%; ',203,266,'jsMath_PrintWarning',' .message',58,':center',209,67,'3px solid #DD0000',159,160,': #FFF8F8; color: #AA0000',201,'x-',202,203,';","@media print":"#',250,' {display:none','}\\n"+"#jsMath_Warning',358,'}","@media screen":"#',342,358,'}"},Element',':function(','A){return ',6,15,16,'("jsMath_"+A)},','BBoxFor',365,'A','){this.','hidden.innerHTML','="<nobr><','span class=\\"',57,'\\"><',377,'scale\\">"+A+"</span></span></nobr>";var B={w:this.',182,'.offsetWidth',',h:this.',182,'.offsetHeight','};this.',375,'="";return B},EmBoxFor',365,'B){var A=',6,'Global.cache.R;if(!A[this.em]){A[this.em]={}}if(!A[this.em][B]){var C=this.BBoxFor(B);','A[this.em][B]={w:C.w/this.em,h:C.h/this.em}}return A[th! is.em][B]},','EmBoxForItalics',365,391,6,393,'if(B.match(/<i>|! class=\\ "(icm|italic|igreek|iaccent)/i)){C.w=C.Mw','=this.BBoxFor','(B+',6,'Browser.','italicString',').w-',6,404,'italicCorrection','}',394,'Init',':function(){','if(',6,'Setup.inited','!=1){',0,6,416,'){',6,'Setup.','Body()}if(',6,416,'!=1){if(',6,416,'==-100','){return }',23,'It looks like jsMath failed to set up properly (error code "+',6,416,'+"). "+"I will try to keep going, but it could get ugly.");',6,416,'=1}}this.em',401,'("<span style=\\""+',6,404,'block+";','width:13em;height:1em','\\"></span','>").w/13;','if(this.','em==0',374,'em',401,'("<img src=\\""+',6,'blank+"\\" style=\\"',445,'\\"/>").w/13}','var A=',6,'Global.cache','.B;',0,'A[this.em]){A[this.em]={};','A[this.em].','bb',401,'("x");','var C=',464,'bb.h;',464,'d',401,'("x"+',6,'HTML.Rule(1,','C/',6,'em)).h-C;if(',6,404,405,'){',464,'ic=',6,371,'(',6,404,405,').w}}',6,404,409,'=',464,'ic;var F=',464,'bb;var D=F.h;var E=',464,'d;this.h=(D-E)/this.em;this.d=E/this.em;this.hd=this.h+this.d;this.xWidth=F.w;this.',423! ,'TeXfonts','();var B=this.EmBoxFor("<',377,114,'\\">M</span>").w/2;this.TeX.M_height=B*(26/14);this.TeX.h=this.h;this.TeX.d=this.d;this.TeX.hd=this.hd;this.Img.Scale();',0,'this.initialized',374,423,'Sizes','();this.','Img.UpdateFonts()}this.p_height=(','this.TeX.cmex10[0].','h+',516,'d)/0.85;',510,'=1},ReInit',413,'var A',401,'("x").w;if(A!=this.xWidth',374,'Init()}},Loaded',413,'if(',9,8,'B=["Process","ProcessBeforeShowing","ConvertTeX","ConvertTeX2","ConvertLaTeX","ConvertCustom","CustomSearch","Synchronize","Macro","document"];','for(var A=0;A<','B','.length;A++){','if(',9,'[B[A]]){','delete ',9,'[B[A]]}}}if(',9,'){this.Insert(','jsMath,',9,')}',9,'=null;',6,7,'=1},Add',365,'C,A){for(var B in A){','C[B]=A[B]}},Insert',365,553,'if(C[B]&&typeof (A[B])=="object"&&(','typeof (C[B])=="','object"||',558,'function")){this.Insert(C[B],A[B])}',29,'C[B]=A[B]}}},Package',365,'B,A',543,'B.prototype,A)}};',6,'Global={isLocal:1,cache:{','T:{},D:{},R:{},B',':{}},ClearCache',413,6,460! ,'={',570,':{}}},GoGlobal',365,391,'String(',6,1,'.','location! );var C' ,'=(',6,'isCHMmode','?"#":"?");if(B){A=A.replace(/\\?.*/,"")+"?"+B}',6,'Controls.','Reload(',6,'root+"jsMath-','global.html"+C+escape(A))},Init',413,'if(',6,'Controls.cookie.','global=="always"&&!',6,'noGoGlobal','){','if(navigator.','accentColorName',431,0,6,1,'){',6,1,'=',1,'}',6,590,7,'=1;',6,590,'defaults.hiddenGlobal',548,'this.GoGlobal(',6,590,'SetCookie(2))}},Register',413,458,6,1,'.parent;',0,6,'isCHMode){',6,587,'=(',6,1,'.','location.','protocol=="mk:")}try{',0,6,587,374,'Domain()}if(A',2,'&&A.',6,'isGlobal){A.',6,'Register(',6,1,')}}catch(B){',6,601,'=1}},Domain',413,603,'appName=="Microsoft Internet Explorer"&&',6,37,'=="mac"&&',39,'userProfile','!=null',431,'if(',1,'==parent',431,'var B=',6,15,'domain;try{while(true){try{if(parent.',15,'title',668,'){return }}','catch(A){}',0,15,'domain.match(/\\..*\\./)){break}',6,15,'domain=',6,15,'domain.replace(/^[^.]*\\./,"")}}',682,6,15,688,'B}};',6,'Script={request:null,Init',413,'if(!(',6,598,'asynch&&',6,598,'progress',! ')){if(',1,'.XMLHttpRequest','&&!(',6,15,'URL&&',6,15,'URL.match(/^file:\\/\\/.*\\\\/))){try{','this.request','=new XMLHttpRequest}catch(C){}}',0,717,'&&',1,'.','ActiveXObject',8,'A=["MSXML2.XMLHTTP.5','.0","MSXML2.XMLHTTP','.4',727,'.3',727,'","Microsoft.XMLHTTP"];','for(var B=0;B<','A.length&&!',717,';B++){try{',717,'=new ',724,'(A[B])}catch(C){}}}}',0,717,'||',6,423,'domainChanged',374,'Load=this.delayedLoad;this.needsBody=1}},Load',365,'B,A){','if(A){',6,'Message.Set("Loading "+','B);',6,'Script.','Delay(1);',6,'Script.Push(','this,"xmlRequest",B',');',6,759,6,'Message',',"Clear")}',29,6,759,760,')}},xmlRequest',365,'url){','this.blocking','=1;try{',717,'.open("GET",url,false);',717,'.send(null)}catch(err){',774,'=0;if(',6,'Translate.','restart&&',6,'Translate.asynchronous){return""}throw"jsMath can\'t load the file \'"+url+"\'\\n"+"',765,': "+err.message}if(',717,'.status','&&',717,790,'>=400){',774,781,6,783,'restart&&',6,786,'Error status: "+',717,790,'}',0,'url','.m! atch(/\\.js$/)){','return(',717,'.responseText',')}var tmpQueu! e','=thi s.queue;this.queue','=[];',6,1,'.eval(',717,811,');',774,'=0;','this.queue=this.queue.concat(','tmpQueue);this.Process();return""},cancelTimeout:30*1000,iframe:null,blocking:0,cancelTimer:null,needsBody:0,queue:[],Synchronize',365,'A,B){','if(typeof (','A)!="string"){',6,759,'null,A,B)}',29,6,759,6,1,',"eval",A)}},Push',365,'A,C,B){','this.queue','[',840,'.length]=[A,C,B];if(!(',774,'||(this.needsBody&&!',6,15,'body))){this.Process()}},Process',413,'while(',840,'.length&&!',774,8,'C=',840,'[0];',840,'=',840,'.slice(1);',458,'this.SaveQueue();var B=C[0];var E=C[1];var D=C[2];if(B){B[E](D)}',29,'if(E){E(D)}}this.','RestoreQueue','(A)}},SaveQueue',413,'var A',813,'=[];return A},',866,365,'A){',823,'A)},delayedLoad',365,'A',374,'Push(this,"startLoad",A)},startLoad',365,'A){','this.iframe','=',6,15,21,'("iframe");','this.iframe.style.',180,'="',182,'";',889,'position="absolute";',889,'width="0px";',889,'height="0px','";if(',6,15,'body.firstChild','){',6,15,'body.insertBefore(',88! 3,',',6,15,903,')}',29,6,15,'body','.appendChild(',883,')}',774,'=1;this.','url=A;',0,'A',808,883,'.src=A}',29,883,'.src=',6,593,'loader.html"}if(A.substr(0,',6,'root.length',')==',6,'root){A=A.substr(',6,936,')}',6,753,'A);','this.cancelTimer','=setTimeout("',6,756,'cancelLoad','()",this.cancelTimeout)},endLoad',365,'A){if(',946,'){clearTimeout(',946,');',946,'=null}',6,765,'.Clear();if(A!="cancel"){',774,'=0;this.Process','()}},Start',413,'this.tmpQueue',813,'=[]},End',413,823,967,');',539,967,'},',950,413,946,548,6,765,'.Set("Can\'t load file");this.endLoad("cancel")},Delay',365,'A){',774,'=1;setTimeout("',6,756,'endDelay','()",A)},',990,413,774,964,'()},','imageCount',':0,WaitForImage',365,'B){',774,922,997,'++;',448,'img==null',374,'img=[]}',458,'new Image',514,'img[this.img.length]=A;A.onload=function(){if(--',6,756,997,'==0){',6,756,990,'()}};A.onerror=A.onload;A.onabort=A.onload;A.src=B},Uncompress',365,'data){for(var k=0;k<data.length;k++){var d=data[k];var n=d.len! gth;for(var i=0;i<n;i++){',827,'d[i])=="number"){d[i]=d[d[i]]}! }data[k] =d.join("")}',1,817,'data.join(""))}};',6,765,'={blank:null,message:null,text:null,clear:null,Init',413,0,6,15,'body||!',6,598,706,431,'if(',6,423,'stylesReady){','this.message','=',6,'Setup.DIV("message",{visibility:"hidden','"})}',29,1044,'=',6,1047,'",position:"absolute",','bottom:"1px",left:"2px",','backgroundColor',':"#E6E6E6",border:"solid 1px #959595",margin:"0px",padding:"1px 8px",zIndex:102,color:"black",fontSize:"small",width:"auto"})}','this.text','=',6,15,'createTextNode','("");',1044,918,1058,');',1044,'.onmousedown=',6,783,'Cancel},Set',365,750,'if(this.clear){clearTimeout(this.clear',');this.clear=null}if(',6,598,706,'){',0,1058,374,'Init();',0,1058,681,'if(',6,404,'textNodeBug','){',1044,'.innerHTML','=B}',29,1058,'.nodeValue','=B}','this.message.style.',180,'="visible";',751,1100,'cursor="pointer";',0,1100,'cursor){',1100,'cursor="hand"}',1044,'.title=" Cancel Processing of Math "}',29,1100,'cursor="";',1044,'.title=""}}',29,'if(B.substr(0,8)!="Loading "){',! 6,1,790,'=B}}},Clear',413,1075,')}this.clear=setTimeout("',6,765,'.doClear()",1000)},doClear',413,448,'clear',374,'clear',548,6,1,790,'="";if(',1058,'){',1058,1098,'=""}if(',1044,'){',1100,180,'="',182,'"}}},Blank',413,'if(','this.blank','||!',6,15,'body',431,1154,'=',6,423,'DIV("blank",{position:(',6,404,'msiePositionFixedBug','?"absolute":"fixed"),top:"0px",left:"0px",bottom:"0px",right:"0px",zIndex:101,',1056,':"white"});if(',6,404,'msieBlankBug){',1154,1094,'=" ";',1154,'.style.width="110%";',1154,'.style.height="110%"}},UnBlank',413,'if(',1154,'){',6,15,'body.removeChild(',1154,')}',1154,'=null}};',6,'Setup={',7,':[],DIV',365,'D,B',8,'C=',6,15,21,'("div");C.id="jsMath_"+D;','for(var A in ','B){C.style[A]=B[A]}',0,6,15,'body.hasChildNodes){',6,15,'body',918,'C)}',29,6,15,907,'C,',6,15,903,')}return C},Script',365,750,448,7,'[B]){return }',29,'this.',7,'[B]=1}',0,'B.match("^([a-zA-Z]+:/?)?/")){B=',6,'root+B}',6,756,'Load(B,A)},Hidden',413,6,182,'=this.DIV("Hidden",{! ',180,':"',182,1054,'top:0,left:0,border:0,padding:0,margin:0}! );',6,'h iddenTop=',6,182,';return },Source',413,'if(',6,'Autoload','&&',6,1257,'.root){',6,'root=',6,1257,'.','root}',29,6,'root="";',458,6,15,'getElementsByTagName("','script");',751,733,'A.','length;B++){','var D=A[B].src;if(D&&D.match("(^|/|\\\\\\\\)',6,'js$")){',6,1263,'D.','replace(/',6,'js$/,"");break}}}}if(',6,'root.charAt(','0)=="\\\\"){',6,1263,6,'root.replace','(/\\\\/g,"/")}if(',6,1290,'0)=="/"){if(',6,1290,'1)!="/"){if(',6,15,641,'port){',6,'root=":"+',6,15,641,'port+',6,1267,6,'root="//"+',6,15,641,'host+',6,1267,6,1263,6,15,641,'protocol+',6,1267,29,0,6,'root.match','(/^[a-z]+:/i)){var D=','new String(',6,15,584,'=new RegExp("/[^/]*/\\\\.\\\\./");',6,1263,'D.replace(new RegExp("[^/]*$"),"")+',6,'root;while(',6,1334,'(C)){',6,1263,6,1295,'(C,"/")}}}',6,'Img.',1263,6,'root+"fonts/";',6,'blank=',6,'root+"blank.gif";this.Domain()},Domain',413,'try{',6,15,'domain}catch(D',431,'var C="";',458,6,15,'domain;if(',6,1334,'("://([^/]*)/")){C=RegExp.$1}C=C.replace(/:\\d+$/,"");if(! C==""||C==A',431,603,'appName=="Microsoft Internet Explorer"&&',6,37,'=="mac"&&',39,'onLine&&',39,667,'&&',6,15,'all',431,'C=C.split(/\\./);A=A.split(/\\./);if(C.length<2||A.length<2||','C[C.length-','1',']!=A[A.length-','1]||',1393,'2',1395,'2]){this.','DomainWarning','();return }var E=',1393,'2]+"."+',1393,'1];for(var B=3;B<=C.length&&B<=A.',1279,'if(',1393,'B',1395,'B]){break}E=',1393,'B]+"."+E}',6,15,688,'E;this.',746,'=1},',1401,413,23,'In order for jsMath to be able to load the additional "+"components that it may need, the ',6,'js file must be "+"',7,' from a server in the same domain as the page that "+"contains it. Because that is not the case for this page, "+"the',25,'displayed here may not appear correctly.")},','EncodeFont',365,'C',8,'B=',6,'TeX[C];if(B','[0].c',668,431,533,'128;A++){var D=B[A];B[A]=D[3];if(B[A]==null){B[A]={}}B[A].w=D[0];B[A].h=D[1];if(D[2]!=null){B[A].d=D[2]}B[A].c=',6,'TeX.encoding[A]}},Fonts',413,733,6,'TeX.fam.length;','B++){',458,6,'TeX.! fam[','B];if(A',374,1431,'(A)}}},TeXfont',365,'C',8,'B=',6,143! 7,'==nul l',431,458,6,'EmBoxFor("<span class=\\""+C+"\\">"+B[65].c','+"</span>");B.hd=A.h;B.dh=0.05;B.d=',6,1467,'+',6,476,'B.hd)+"</span>").h-B.hd;B.h=B.hd-B.d;','if(C=="',131,'"){B.skewchar=','127}',29,1475,135,1477,'48}}},',504,413,533,6,1448,'A++){if(',6,1452,'A]){this.TeXfont(',6,1452,'A])}}},Sizes',413,6,'TeXparams','=[];var B;var A;for(A=0;A<',6,47,535,6,1498,'[A]={}}for(B in ',6,'TeX){',827,6,'TeX[B])!="object"){for(A=0;A<',6,47,535,6,1498,'[A][B]=',6,47,'[A]*',6,'TeX[B]/100}}}},Styles',365,'A){',0,'A){A=',6,49,';A[".',175,'scale"]="font-size:"+',6,598,'scale+"%";this.stylesReady=1}',6,759,'this,"','AddStyleSheet','",A);if(',6,404,'styleChangeDelay','){',6,759,6,'Script,"Delay",1)}},',1537,365,'D',8,'B=',6,15,1274,'head")[0];var A="";for(var E in D){A+=E+" {"+D[E]+"}\\n"}if(',6,15,'createStyleSheet){B.insertAdjacentHTML("beforeEnd","<','span style=\\"','display:none\\">x</span>"+"<style type=\\"text/css\\">"+A+"</style>")}',29,468,6,15,21,'("style");C.type="text/css";C',918,6! ,15,1062,'(A));B',918,'C)}},Body',413,448,'inited',431,'this.inited=-','1;',6,423,'Hidden();',1578,'2;',6,404,1084,1578,'3;if(',6,598,'blank){',6,765,'.Blank()}',1578,'4;',6,423,'Styles();',1578,'5;',6,590,1084,1578,'6;',6,759,6,'Setup,"User","pre-font");',1578,'7;',6,759,6,'Font,"Check");if(',6,'Font.register.length){',6,759,6,'Font,"LoadRegistered")}this.inited=1},User',365,953,6,'Setup.UserEvent[A',']){(',6,1627,'])()}},UserEvent:{"pre-font":null,"onload":null}};',6,'Update={',504,365,'D){',1204,'D){for(var B in D[A]){for(var C in D[A][B]){',6,'TeX[A][B][C]=D[A][B][C]}}}},TeXfontCodes',365,'C){',1204,'C){',733,'C[A].',1279,6,'TeX[A][B].c=C[A][B]}}}};',6,'Browser={allowAbsolute:1,allowAbsoluteDelim:0,separateSkips:0,valignBug:0,operaHiddenFix:"",','msieCenterBugFix',':"",','msieInlineBlockFix',':"",','msieSpaceFix',':"",imgScale:1,renameOK:1,',1541,':0,delay:1,version:0,','TestSpanHeight',413,6,375,'="<span','><','span style=\\""+this.block+";','height:2em;width:','1px',4! 46,'></span>";var B=',6,'hidden.firstChild;',458,'B.firstChild! ;','this .spanHeightVaries','=(B',386,'>=A',386,'&&B',386,'>0);','this.spanHeightTooBig','=(B',386,'>A',386,');',6,375,'=""},','TestInlineBlock',413,'this.block','="display:-moz-inline-box";','this.hasInlineBlock','=',6,'BBoxFor("<span style=\\""+this.block+";','width:10px;height:5px\\"></span>").w>0;if','(',1696,'){',6,'styles[".typeset .','blank"]=',6,1705,'blank','"].replace(/',168,'/,',1694,');',6,1705,176,'"]=',6,1705,176,1710,168,'/,"")}',29,1694,'="',168,'";',1696,'=',6,1699,1700,'(!',1696,681,1694,'+=";',170,'";',458,6,371,'("x").h;this.mozInlineBlockBug=',6,1699,'height:"+A+"px;width:1px',446,'>x"+"<',1666,1748,';vertical-align:-"+A+"px',446,'>").h>2*A;this.widthAddsBorder=',6,1699,170,';height:1px;width:10px',';border-left:','10px solid',446,'>").w>10;','this.msieBorderBug','=',6,1699,1748,446,'>x").h!=',6,1699,1748,1760,164,446,'>x").h;this.blankWidthBug=',1764,'||',6,1699,1667,'0px',446,'>").h==0},','TestRenameOK',413,6,375,1664,'></span>";',458,6,1672,'A.setAttribute("na! me","','jsMath_test','");this.renameOK=(',6,15,'getElementsByName("',1796,'").length>0);',6,375,1691,'TestStyleChange',413,6,375,1664,' ID=\\"',1796,'\\">x</span>";var B=',6,1672,458,'B',383,';',6,423,1537,'({"#',1796,75,'200%"});this.',1541,'=(B',383,'==A);',6,375,1691,'VersionAtLeast',365,391,1336,'this.version',').split(".");','B=',1336,'B',1839,'if(B[1]==null){B[1]="0"}return A[0]>B[0]||(A[0]==B[0]&&A[1]>=B[1])},Init',413,6,27,'="unknown";this.',1692,514,1660,514,1786,514,1806,514,'MSIE',514,'Mozilla',514,'Opera',514,'OmniWeb',514,'Safari',514,'Konqueror','();if(','this.allowAbsoluteDelim','){',6,'Box.DelimExtend=',6,'Box.DelimExtendAbsolute;',6,'Box.Layout=',6,'Box.LayoutAbsolute}',29,6,'Box.DelimExtend=',6,'Box.DelimExtendRelative;',6,'Box.Layout=',6,'Box.LayoutRelative}if(','this.separateSkips','){',6,'HTML.Place=',6,'HTML.','PlaceSeparateSkips',';',6,'Typeset.prototype.','Place=',6,1897,1894,'}},MSIE',413,'if(',1675,'&&!',1683,'){',6,27,'="MSIE',900,6,37,'=="pc"){th! is.','IE7=(',1,709,668,');this.quirks=(',6,15,'compatMode=="Ba! ckCompat ");this.msieStandard6=!this.quirks&&!','this.IE7',';',1869,'=1;',1888,'=1',';this.buttonCheck=1;this.','msieBlankBug=1;this.','msieAccentBug',922,'msieRelativeClipBug','=1;this.msieDivWidthBug=1;this.',1167,922,'msieIntegralBug',922,'waitForImages',922,'msieAlphaBug=!',1924,';this.','alphaPrintBug','=!',1924,';this.',1652,'="position:relative; ";this.',1654,'=" ',168,';";this.msieTeXfontBaselineBug=!',6,404,'quirks;',0,1924,374,1656,'="<',1559,168,446,'>"}',6,'Macro("joinrel","\\\\mathrel{\\\\kern-5mu}"),',6,'Parser.prototype.mathchardef.','mapstocharOrig','=',6,1970,'mapstochar;',539,6,1970,1975,6,'Macro("mapstochar","\\\\rlap{\\\\',1971,'\\\\,}\\\\kern1mu"),',6,1705,'arial"]="font-family: \'Arial unicode MS\'";',0,1924,'||this.quirks){',6,'styles["#',190,'"]=',6,1991,190,1710,192,'/,"',184,'").',1286,203,'/,"");',6,1991,205,'"]=',6,1991,205,1710,192,'/,"',184,'").',1286,203,'/,"");',6,1991,250,'"]="width:','1px; "+',6,1991,250,1710,192,'/,"',184,'").',1286,203,'/,"");',6,1! ,'.attachEvent("','onscroll",',6,590,'MoveButton',');',448,'IE7){',6,1,2038,'onresize",',6,590,2042,')}this.msieMoveButtonHack=',1924,'}',6,1991,328,'"]+=" ','display: inline-block',';";',6,1705,176,'"]=',6,1705,176,1710,168,'/,"");',6,49,'[".tex2math_div"]=',6,49,'["div.',57,'"]+"; width: 100%; ',2060,900,'screen.deviceXDPI','&&','screen.logicalXDPI','&&',2082,'!=',2084,374,'imgScale*=',2084,'/',2082,';',6,598,'alpha=0}this.',405,'="<i>x</i>";',6,'EmBoxFor=',6,395,'}',29,'if(',6,37,'=="mac"){this.msieAbsoluteBug',922,'msieButtonBug',1935,1931,'quirks=1;',6,423,'Script("jsMath-msie-mac.js");',6,'Parser.prototype.macros.angle=["Replace","ord","<font face=\\"Symbol\\">‹</font>","normal"];',6,1991,205,2023,'42em; "+',6,1991,205,1710,203,'/,"");',6,598,'printwarn=0}}',6,'Macro("not","\\\\mathrel{\\\\rlap{\\\\kern3mu','/}}")}},',1859,413,'if(',6,182,'.ATTRIBUTE_NODE){',6,27,'="',1859,900,6,37,1915,1945,'=1}',1869,'=1;',6,1991,250,'"]=',6,1991,250,1710,'cursor:hand','/,"curs! or:pointer");',6,1991,328,'"]=',6,1991,328,1710,2163,'/,"curso! r:pointe r");',6,2135,'/}}");',603,'vendor=="Firefox"){',1838,'=',39,'vendorSub}',29,603,'userAgent.match','(" Firefox/([0-9.]+)( |$)")){',1838,'=RegExp.$1}}}},',1863,413,603,'accentColorName){',6,27,'="',1863,'";','this.allowAbsolute','=',1696,';',1869,'=',2199,';this.valignBug=!',2199,1930,1091,'=1;',6,'noChangeGlobal=1;',0,1696,'){',6,'Setup.Script("jsMath-old-browsers.js','")}}},Opera',413,'if(',1683,'){',6,27,'="Opera";',458,39,2186,'("Opera 7");',2199,'=0;this.delay=10;this.operaHiddenFix="[Processing]";',751,6,2217,'")}}},Safari',413,603,'appVersion',41,'Safari\\//)){',6,27,'="Safari";',458,39,2186,'("Safari/([0-9]+)");A=(A)?A[1]:400;',733,6,1448,'B++){if(',6,1452,'B]&&',6,'TeX[',6,1452,'B]]){',6,'TeX[',6,1452,'B]].dh=0.1}}',6,'TeX.axis_height+=0.05;',6,'TeX.default_rule_thickness+=0.025;',1869,'=A>=125;this.safariIFRAMEbug=A>=312&&A<412;this.safariButtonBug=A<412;this.safariImgBug',922,1091,'=1',1930,1541,'=1}},',1867,413,603,'product&&',39,'product.match("',1867,'")){',6,27,! '="',1867,'";',2199,'=0;',1869,'=0;',603,2186,'(/',1867,'\\/(\\d+)\\.(\\d+)/)){if(RegExp.$1<3||(RegExp.$1==3&&RegExp.$2<3)){',1888,922,'valignBug=1;',6,2217,'")}}',6,'Add(',6,49,',{".',175,114,144,': ',123,', jsMath ',114,', serif',70,119,144,': jsMath-',119,2315,119,''], - [', ','jsMath','-','cmr10',', ',1,' ',3,'",".typeset .','cmti10":"','font-family: ',1,'-cmti10, ',1,' cmti10, ',1,'-',3,', ',1,' ',3,8,'cmmi10','":"',10,1,'-',23,', ',1,' ',23,8,'cmsy10','":"',10,1,'-',34,', ',1,' ',34,8,'cmex10','":"',10,1,'-','cmex10, ',1,' cmex10','"});',1,'.Font.testFont','="',1,'-',50,1,52,'"}}};',1,'.Font={testFont:"',1,'-',45,'",fallback:"symbol",register:[],message:"<b>No ',1,' TeX fonts ','found</b> -- using',' image fonts instead','.<br/>\\n"+"','These may be slow and might not print well',73,'Use the ',1,' control panel to get additional information.",','extra_message',':"Extra',70,'not found: <b><span id=\\"jsMath_ExtraFonts\\"></span></b><br/>"+"Using',72,'. This may be slow and might not print well',73,'Use the ',1,78,'print_message',':"To print higher-resolution math symbols, click the<br/>\\n"+"<b>Hi-Res Fonts for Printing</b> button on the ',1,' control panel.<br/>\\n",','alpha_message',':"If the math symbols print as black boxes, turn o! ff <b>image alpha channels</b><br/>\\n"+"using the <B>Options</B> pane of the ',1,92,'Test1',':function(','C',',F,D,E){if(F==null){F=124}if(D==null){D=2}if(E==null){E=""}var B=jsMath.BBoxFor("<span style=\\"font-family: "+E+C+", serif\\">"+jsMath.TeX[C][F].c+"</span>");var A=jsMath.BBoxFor("<span style=\\"font-family: serif\\">"+jsMath.TeX[C][F].c+"</span>");return','(B.w>D*A.w&&B.h!=0)},Test2',98,'C',100,'(A.w>D*B.w&&B.h!=0)},CheckTeX',':function(){var A=',1,'.BBoxFor("<','span style=\\"','font-family: "+',1,55,'+", serif\\">"+',1,'.TeX.',45,'[1','].c+"</span>");',1,'.nofonts=((A.w*3>A.h||A.h==0)&&!this.Test1("cmr10','",null,null,"',1,'-"));if(',1,'.nofonts','&&(',1,'.platform','!="mac"||',1,'.browser!="Mozilla"||!',1,'.Browser.','VersionAtLeast(1.5))){A=',1,'.BBoxFor("<',109,10,50,'serif\\">"+',1,115,45,'[1',118,1,120,'"));if(!',1,125,'){',1,'.Setup.','Script','("',1,'-BaKoMa-fonts.js")}}},Check',106,1,'.Controls','.cookie',';this.CheckTeX();if(',1,125,'){if(A.autofont||A! ','.font=="tex"){','A.font=this.fallback;if(A.warn){',1,'.nofo! ntMessag e=1;A.warn=0;',1,160,'.SetCookie(0);if','(',1,'.window.NoFontMessage','){',1,175,'()}else{','this.Message(this.','message)}}}}else{if(A.autofont){A.font="tex"}if(A',166,'return }}if(',1,'.noImgFonts){','A.font="unicode"}if(A','.font=="unicode','"){',1,153,154,'("',1,'-fallback','-"+',1,128,'+".js");',1,'.Box.TeXnonfallback=',1,'.Box.TeX',';',1,202,'=',1,'.Box.TeXfallback;return }','if(!A.print&&A.printwarn){this.','PrintMessage','((',1,133,'alphaPrintBug&&',1,160,161,'.alpha)?this.',89,'+this.',93,':this.',89,')}if(',1,133,'waitForImages){',1,'.Script.','Push(',1,'.',154,',"WaitForImage",',1,'.blank)}if(A.font=="symbol"){',1,153,154,'("',1,194,'-symbols.js");',1,'.Box.TeXnonfallback=',1,202,';',1,202,'=',1,208,1,'.Img.SetFont','({',3,':["all"],',23,258,34,258,45,258,'cmbx10',258,'cmti10:["all"]});',1,'.Img.LoadFont','("cm-fonts")},Message',98,'A){if(',1,'.Element("','Warning")){','return }var ','B=',1,153,'DIV("Warning','",{});B.innerHTML="<center><table><tr><td>"+"<div ','i! d=\\"jsMath_noFont\\"><div ','class=\\"message\\">"+A','+"<div style=\\"text-align:left\\"><',109,'float:left; ','margin: 8px ','0px 0px 20px\\">"+"<span onclick=\\"',1,160,'.Panel()\\" ','title=\\" Open ','the ',1,' Control Panel',' \\" class=\\"link\\">',1,295,'</span>"+"</span','><',109,287,'20px 0px 0px; float:right\\">"+"<span onclick=\\"',1,'.Font.','HideMessage','()\\" title=\\" Remove this font warning message',296,'Hide this Message',299,'></div><div style=\\"height:6px\\"></div><br clear=\\"all\\"/></div></','div>"+"<div style=\\"width:22em; height:1px\\"></div>"+"</td></tr></table></center><hr/>"},',306,106,1,274,'Warning");if(A','){A.style.display="none"}},',210,98,272,1,274,'PrintWarning','")){',276,'B=',1,153,'DIV("',324,281,283,'+"</',312,'Register',98,'H,B){if(typeof (H)=="string"){H={name:H}}if(!',1,153,'inited&&!B){','this.register','[',342,'.length]=H;',276,'I=H.name;var A=I.replace(/10$/,"");var F=',1,115,'fam.length;if(H.prefix==null){H.prefix=""}if(!H.! style){H.style="',110,'H.prefix+I+", serif"}if(!H.styles){H.st! yles={}} if(!H.macros){H.macros={}}',1,115,'fam[F]=I;',1,115,'famName[I]=F;H.macros[A]=["HandleFont",F];',1,'.Add(',1,'.Parser.prototype.macros,H.macros);H.styles[".typeset ."+I]=H.style;',1,153,'Styles(H.styles);if(',1,'.initialized){',1,229,'Push(',1,'.Setup,"TeXfont",I)}var C=',1,160,161,';var E=!',1,125,'&&H.test(I,H.testChar,H.testFactor,H.prefix);if(E&&C',166,'if(H.tex){H.tex(I,F,H)}return }if(!E&&C.warn&&C.font=="tex"&&!',1,125,'){if(!C.fonts.match("/"+I+"/")){C.fonts+=I+"/";',1,160,172,'(!',1,274,275,180,79,')}var G=',1,274,'ExtraFonts");if(G){if(G','.innerHTML','!=""){G',398,'+=","}G',398,'+=" "+H.prefix+I}}}if(C',187,'"||',1,185,'if(H.fallback){H.fallback(I,F,H)}',276,'D={};D[I]=["all"];',1,255,'(D);',1,269,'(I);if(',1,'.initialized){',1,229,'Push(',1,'.Img,"Scale");',1,229,'Push(',1,'.Img,"UpdateFonts")}},LoadRegistered',106,'0;while(A<',342,'.length){this.Register(',342,'[A++],1)}',342,'=[]},Load',98,'A){',1,153,154,'(this.URL(A))},URL',98,'A){','return ',1,'.Img.root+A+"! /def.js"}};',1,160,'={cookie:{scale:100,font:"tex",autofont:1,scaleImg:0,alpha:1,warn:1,fonts:"/",printwarn:1,stayhires:0,button:1,progress:1,asynch:0,blank:0,print:0,keep:"0D",global:"auto",hiddenGlobal:1},cookiePath:"/",','noCookiePattern',':/^(file|mk):$/,Init',':function(){','this.panel=',1,153,'DIV("panel",{display:"none"});if(!',1,133,'msieButtonBug){this.Button',179,'setTimeout("',1,160,'.Button()",500)}},Panel',453,1,'.Translate.Cancel();if(this.loaded){this.Main',179,1,229,'delayedLoad(',1,'.root+"',1,'-controls.html")}},Button',106,1,153,'DIV("button",{});A.title=" Open ',1,295,' ";A',398,'="<span onclick=\\"',1,160,'.Panel()\\">',1,'</span>";if(!',1,'.Global.','isLocal&&!',1,'.noShowGlobal){A',398,'+="<span id=\\"jsMath_global\\" ',292,1,' Global Panel \\" "+"onclick=\\"',1,492,'Show(1)\\">Global </span>"}if(A.offsetWidth<30){A.style.width="auto"}if(!','this.cookie','.button',318,'MoveButton',453,'var C=',1,160,';if(!C.button){C.button=',1,274,'button")}if(C! .button','){C.MoveElement(C.','button,3,2)}var B=20;var A=20;i! f(C.butt on){A=C.button.offsetHeight+6;B=A+5}if(C.panel',516,'panel,B,A)}},MoveElement',98,'D,C,B){if(',1,133,'IE7){var A=document.body;D.style.right','="auto";D.style.','bottom',525,'left=A.clientWidth+A.scrollLeft-D.offsetWidth-C+"px";D.style.top=A.clientHeight+A.scrollTop-D.offsetHeight-B+"px"}else{','D.style.visibility="','hidden";',529,'visible"}},GetCookie',453,'if(','this.defaults','==null){',535,'={}}',1,360,535,',',504,');this.userSet={};var C=',1,'.document.cookie',';if(',1,'.window.location','.protocol.match(this.',451,')){C=this.','localGetCookie','();','this.isLocalCookie','=1}if(C.match(/',1,'=([^;]+)/)){var D=unescape(RegExp.$1).split(/,/);for(var B=0;B<D.length;B++){var A=D[B].match(/(.*):(.*)/);if(A[2].match(/^\\d+$/)){A[2]=1*A[2]}',504,'[A[1]]=A[2];this.userSet[A[1]]=1}}},',553,453,445,1,549,'.search.substr(1)},SetCookie',98,'F){var B=[];for(var E in ',504,'){if(',535,'[E]==null||',504,'[E]!=',535,'[E]){B[B.length]=E+":"+',504,'[E]}}B=B.join(",");if(',555,'){if(F==2! ){return"',1,'="+escape(B)}','this.','localSetCookie','(B,F)}else{B=escape(B);if(B==""){F=0}if(','this.cookiePath','){B+="; path="+',586,'}if(','this.cookieDomain','){B+="; domain="+',590,'}if(',504,'.keep!="0D"){var A={D',':1000*60*60*24',',W',596,'*7,M',596,'*30,Y',596,'*365};var D=new Date;D.setTime(D.getTime()+',504,'.keep.substr(','0,1)*A[',504,605,'1,1)]);B+="; expires="+D.toGMTString()}if(B!=""){',1,546,'="',1,'="+B;var C=',1,546,';if(F&&!C.match(/',1,'=/)){alert("Cookies must be enabled in order to save ',1,' options")}}}',445,'null},',584,98,'B,C){if(!C){',276,'A=String(',1,549,').replace(/\\?.*/,"");if(B!=""){A+="?',1,582,'if(A!=',1,549,'.href){this.Reload(A)}},Reload',98,'A){if(!this.loaded){return }this.loaded=0;',1,153,'inited=-100;',1,492,'ClearCache();if(A){',1,549,'.replace(A)}else{',1,549,'.reload()}}};',1,'.Click={CheckClick',98,'A){if(!A){A=',1,'.window.event}if','(A.altKey){',1,160,'.Panel()}},CheckDblClick',98,'B){if(!B){B=',1,657,'(!',1,'.Click.DblClic! k){',1,'.Extension.Require("double-click",1);var A=B;B={};for(! var C in A){B[C]=A[C]}}',1,229,'Push(',1,'.Click,"DblClick",[B,this.alt])}};',1,'.TeX={thinmuskip:3/18,medmuskip:4/18,thickmuskip:5/18,x_height:0.430554,quad:1,num1:0.676508,num2:0.393732,num3:0.44373,denom1:0.685951,denom2:0.344841,sup1:0.412892,sup2:0.362892,sup3:0.288888,sub1:0.15,sub2:0.247217,sup_drop:0.386108,sub_drop:0.05,delim1:2.39,delim2:1,axis_height:0.25,default_rule_thickness:0.06,big_op_spacing1:0.111111,big_op_spacing2:0.166666,big_op_spacing3:0.2,big_op_spacing4:0.6,big_op_spacing5:0.1,integer:6553.6,scriptspace:0.05,nulldelimiterspace:0.12,delimiterfactor:901,delimitershortfall:0.5,scale:1,atom:["ord","op","bin","rel","open","close","punct","ord"],fam:["',3,'","',23,'","',34,'","',45,'","cmti10","","cmbx10",""],famName:{',3,':0,',23,':1,',34,':2,',45,':3,cmti10:4,cmbx10:6},encoding:["À","Á","Â","Ã","Ä","Å","Æ","Ç","È","É","Ê","Ë","Ì","Í","Î","Ï","°","Ñ","Ò","Ó","Ô! ;","Õ","Ö","·","Ø","Ù","Ú","Û","Ü","µ","¶","ß","ï","!",""","#","$","%","&","'","(",")","*","+",",","-",".","/","0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","@","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","[","\","]","^","_","`","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","{","|","}","~","ÿ"],',3,':[[0.625',',0.683],[0.','833',696,'778',696,'694',696,'667',696,'75',696,'722',696,'778',696,'722',696,'778',696,'722',696,'583',',0.694,0,{ic:0.0778,krn:{"39":0.0778,"63":0.0778,"33":0.0778,"41":0.0778,"93":0.0778},lig:{"105":','14,"108":15}}],[0.556',',0.694],[0.','556',720,'833',720,'833',720,'278',',0.431],[0.','306',',0.431,0.194],[0.','5',720,'5',720,'5,0.628],[0.5',720,'5,0.568],[0.75',720,'444,0,0.17],[0.5',720,'722',728,'778',728,'5,0.528! ,0.0972],[0.903,0.683],[1.01',696,'778,0.732,0.0486],[0.278','! ,0.431,0 ,{','krn:{"108":-0.278,"76":-0.319}}],[0.278',',0.694,0,{','lig:{"96":','60}}],[0.5',720,'833',',0.694,0.194],[','0.5',',0.75,0.0556],[0.','833',757,'778',720,'278',750,'krn:{"63":0.111,"33":0.111},lig:{"39":34}}],[0.389',',0.75,0.25],[0.','389',765,'5,0.75],[','0.778,0.583,0.0833],[','0.278,0.106',',0.194],[0.','333',748,'lig:{"45":','123}}],[',770,'],[0.5',765,'5,0.644','],[0.5,0.644],[0.5,0.','644',780,'644',780,'644',780,'644],[0.5,0.644],[0.278',728,'278',730,'278,0.5',771,'778',',0.367,-0.133],[','0.472,0.5',771,'472',750,751,'62}}],[0.778',720,'75',',0.683,0,{krn:{"','116','":-0.0278,"','67',805,'79',805,'71',805,'85',805,'81',805,'84":-0.0833,"89":-0.0833,"86":-0.111,"87":-0.111}}],[0.','708',696,'722',696,'764',803,'88',805,'87',805,'65',805,'86',805,'89":-','0.0278}}],[0.','681',696,'653',',0.683,0,{','krn:{"111":-0.0833,"101":-0.0833,"117":-0.0833,"114":-0.0833,"97":-0.0833,"65":-0.111,"79":-0.0278,"67":-0.0278,"71":-0.0278,"81":-0.0278}}],[','0.785',696,'75',696,! '361',803,'73":',832,'514',696,'778',803,'79',805,'67',805,'71',805,'81":-',832,'625',803,816,'917',696,'75',696,'778',803,'88',805,'87',805,'65',805,'86',805,'89":-',832,'681',803,'65','":-0.0833,"','111',805,'101',805,'97',805,'46',880,'44":-0.','0833}}],[0.','778,0.683',771,'736',803,'116',805,'67',805,'79',805,'71',805,'85',805,'81',805,816,'556',696,'722',803,'121',805,'101',880,'111',880,'114',880,'97',880,'65',880,'117":-0.',890,'75',696,'75',',0.683,0,{ic:0.','0139,',837,'1.03',929,'0139,',837,'0.75',803,'79',805,'67',805,'71',805,'81":-',832,'75',929,'025,krn:{"101',880,'111',880,'114',880,'97',880,'65',880,924,890,'611',696,'278',765,'5',720,'278',765,'5',720,'278,0.668],[0.','278',750,751,'92}}],[0.5',748,'krn:{"118',805,'106":0.0556,"121',805,'119":-',832,'556,0.','694,0',',{krn:{"101":0.0278,"111":0.0278,"120":-0.0278,"100":0.0278,"99":0.0278,"113":0.0278,"118":-0.0278,"106":0.0556,"121":-0.0278,"119":-0.0278}}],[0.','444',748,'krn:{"104',805,'107":-',832,'556'! ,720,'444',728,'306',718,'12,"102":11,"108":13}}],[0.5',',0.43! 1,0.194, {','ic:0.','0139,krn:{"','106":',832,'556',750,'krn:{"116',805,'117',805,'98',805,'121',805,'118',805,'119":-',832,970,'306,0.668',771,'528',750,'krn:{"97','":-0.0556,"','101',805,'97',805,'111',805,'99":-',832,'278',720,'833',748,'krn:{"116',805,'117',805,'98',805,'121',805,'118',805,'119":-',832,'556',748,'krn:{"116',805,'117',805,'98',805,'121',805,'118',805,'119":-',832,'5,0.431,0',984,982,'431,0.194',984,'528',730,'392',728,'394',728,'389,0.615,0,{krn:{"121',805,'119":-',832,'556',748,'krn:{"119":-',832,'528',',0.431,0,{ic:0.',1000,'97',1023,'101',805,'97',805,'111',805,'99":-',832,'722',1082,1000,'101',805,'97',805,'111',805,'99":-',832,'528',728,'528',998,'ic:0.',1000,'111',805,'101',805,'97',805,'46',880,'44":-0.',890,'444',728,'5',1082,'0278,',774,'124}}],[1',1082,'0278}],[0.','5',720,'5,0.668],[0.5,0.668]],',23,':[[0.615',929,'139',',krn:{"61":-0.0556,"59":-0.111,"58":-0.111,"127":0.',890,'833',803,'127":0.167}}],[0.','763',929,1125,'krn:{"127":0.0833}}],[0.','694'! ,803,1141,'742',929,'0757,',1145,'831',929,'0812,krn:{"61',1023,'59":-0.0556,"58":-0.0556,"127":0.','0556}}],[0.','78',929,'0576,',1145,'583',929,'139',1137,1158,'667',836,1145,'612',929,'11,krn:{"61',1023,1157,1158,'772',929,'0502,',1145,'64',1082,'0037,','krn:{"127":',832,'566',',0.694,0.194,{ic:0.','0528,',1145,'518',998,'ic:0.0556','}],[0.444',750,'ic:0.0378,krn:{"',1157,1158,'406',748,'krn:{"127":0.0556}}],[0.','438',1187,'0738,',1145,'497',998,'ic:0.0359',',',1200,'469',750,'ic:0.',1125,1145,'354',748,1200,'576',728,'583',720,'603',998,1184,832,'494',1082,'0637,krn:{"',1157,'0278}}],[0.','438',1187,'046,',1184,'0.111}}],[0.','57',1082,'0359}],[0.','517',998,1145,'571',1082,'0359,krn:{"59',1023,'58":-0.',1158,'437',1082,'113,krn:{"',1157,1230,'54',1082,'0359,',1184,832,'596,0.694,0.194,{',1145,'626',998,1200,'651',1187,'0359,',1184,1235,'622',1082,1238,'466',748,1145,'591',750,1145,'828',1082,1129,'517',998,1145,'363,0.431,0.0972,{ic:0.0799,',1145,'654',998,1184,'0.083! 3}}],[1',794,'1',794,'1',794,'1',794,'0.278',',0.464,-0.0363],! [','0.27 8',1297,'0.5,0.465,-0.0347],[',1300,'0.5',728,'5',728,'5',728,'5',730,'5',730,'5,0.',1065,780,1065,780,'431',771,'278,0.106],[',770,771,'778',',0.539,0.0391],[','0.5,0.75,0.25,{krn:{"1',1023,'65',1023,'77',1023,'78',1023,'89":0.0556,"90":-0.',1158,'778',1323,1300,'0.531',750,1192,',',1145,'75',803,'127":','0.','139}}],[0.','759',929,'0502,',1145,'715',929,'0715,krn:{"61',805,1157,890,'828',929,1125,1200,'738',929,'0576,',1145,'643',929,'139',1137,890,'786',836,1145,'831',929,'0812,krn:{"61',1023,1157,1158,'44',929,'0785,',1184,1235,'555',929,'0962',1137,'167}}],[0.','849',929,'0715,krn:{"61',1023,1157,1158,'681',803,1344,832,'97',929,'109,krn:{"','61',1023,1157,890,'803',929,1401,'61',880,'61',805,1157,890,'763',929,1125,1145,'642',929,'139',1137,890,'791,0.683,0.194,{',1145,'759',929,'00773,',1145,'613',929,'0576,krn:{"61',1023,1157,890,'584',929,'139,krn:{"61',805,1157,890,'683',929,1401,'59":-0.111,"',1246,'111,"61',1023,1344,832,'583',929,'222',',krn:{"59":-0.167,"58":-0! .167,"61":-0.111}}],[0.','944',929,'139',1454,'828',929,'0785,krn:{"61',880,'61',805,1157,890,'581',929,'222',1454,'683',929,'0715,krn:{"61',1023,1157,890,'389,0.75],[0.389',755,'0.389',755,'1,0.358,-0.142],[',1481,'0.417',750,1184,1235,'529',728,'429',720,'433',748,1200,'52',750,'krn:{"89":0.0556,"90',1023,'106":-0.111,"102":-0.167,"',1141,'466',748,1200,'49',1187,'108,krn:{"',1157,1388,'477',998,1207,',',1184,832,'576',750,'krn:{"127":-',832,'345,0.66],[0.412,0.66,0.194,{ic:0.0572,krn:{"59',1023,1246,1158,'521',750,'ic:0.0315}],[0.298',750,'ic:0.0197,',1145,'878',728,'6',728,'485',748,1200,'503',998,1145,'446',998,1207,',',1145,'451',1082,1125,'krn:{"',1157,1158,'469',748,1200,'361,0.615,0,{',1145,'572',748,1184,832,'485',1082,'0359,',1184,832,'716',1082,'0269,',1145,'572',748,1184,832,'49',998,1207,',',1200,'465',1082,'044,',1200,'322',748,1184,832,'384',998,1145,'636',998,1184,1235,'5,0.714,0,{ic:0.154}],[0.278',750,'ic:0.399}]],',34,':[[',769,'0.278,0.444,-0.0556],[',7! 69,1300,769,'0.5,0.444,-0.0556],[',769,769,769,769,769,769,769! ,'1',755 ,1601,1601,'0.778',1297,'0.778,0.464,-0.0363','],[0.778,0.636,0.136',1616,1616,1616,1616,1616,'],[0.778',794,'0.778,0.483,-0.0169],[0.778',1323,'0.778',1323,'1',1323,'1',1323,'0.778',1323,'0.778',1323,'1',794,'1',794,'0.5',755,'0.5',755,'1',794,'1',755,'1',755,'0.778',1297,'1',794,'1',794,'0.611',755,'0.611',755,'1',794,'1',755,'1',755,'0.778',728,'275,0.556],[1',728,'667',1323,'0.667',1323,'0.889',755,'0.889',755,'0',755,'0',794,'0.556',720,'556',720,'667',728,'5',757,'722',720,'722',720,'778',720,'778',720,'611',720,'798',803,'48":0.','194}}],[0.657',929,'0304',',krn:{"48":0.',1346,'527',929,'0583',1706,1346,'771',929,'0278',1706,890,'528',929,'0894',1706,'111}}],[0.','719',929,'0993',1706,1722,'595',',0.683,0.0972,{ic:0.','0593',1706,1722,'845',929,'00965',1706,1722,'545',929,'0738,krn:{"48":',832,'678',1729,'185',1706,1388,'762',929,'0144',1706,1158,'69',803,1702,'139}}],[1.2',803,1702,1346,'82',929,'147',1706,890,'796',929,1715,1706,1722,'696',929,'0822',1706,890,'817,0! .683,0.0972,{krn:{"48":',1235,'848',803,1702,890,'606',929,'075',1706,1346,'545',929,'254,krn:{"48":',832,'626',929,'0993',1706,890,'613',929,'0822,krn:{"48":',832,'988',929,'0822',1706,890,'713',929,'146',1706,1346,'668',1729,'0822',1706,890,'725',929,'0794',1706,1346,'667,0.556],[0.',1818,1818,1818,1818,'611',720,'611',720,'444',765,'444',765,'444',765,'444',765,'5',765,'5',765,'389',765,'389',765,'278',765,'5',765,'5',765,'611',765,'5',765,'278',755,'0.833,0.04,0.96],[0.75',696,'833',696,'417',1187,'111}],[0.',1818,'667,0.556',1616,1616,'],[0.444',755,'0.444',755,'0.444',755,'0.611',755,'0.778,0.694,0.13','],[',1874,'],[',1874,'],[',1874,']],',45,':[[0.458',',0.04,1.16,{n:','16}],[0.458',1884,'17}],[0.417',1884,'104}],[0.417',1884,'105','}],[0.472,0.04,1.16,{n:','106',1892,'107',1892,'108',1892,'109}],[0.583',1884,'110}],[0.583',1884,'111',1892,'68',1892,'69}],[0.333',',0,0.6,{delim:{','rep:12}}],[0.556',1908,'rep:13}}],[0.578',1884,'46}],[0.578',1884,'47}],[0.597',',0.0! 4,1.76,{n:','18}],[0.597',1916,'19}],[0.736',',0.04,2.36,{n:',! '32}],[0 .736',1920,'33}],[0.528',1920,'34}],[0.528',1920,'35}],[0.583',1920,'36}],[0.583',1920,'37}],[0.583',1920,'38}],[0.583',1920,'39}],[0.75',1920,'40}],[0.75',1920,'41}],[0.75',1920,'42}],[0.75',1920,'43}],[1.04',1920,'44}],[1.04',1920,'45}],[0.792',',0.04,2.96,{n:','48}],[0.792',1948,'49}],[0.583',1948,'50}],[0.583',1948,'51}],[0.639',1948,'52}],[0.639',1948,'53}],[0.639',1948,'54}],[0.639',1948,'55}],[0.806',1948,'56}],[0.806',1948,'57}],[0.806',',0.04,2.96],[','0.806',1968,'1.28',1968,'1.28',1968,'0.811',1916,'30}],[0.811',1916,'31}],[0.875',',0.04,1.76,{delim:{top:','48,bot:64,rep:66}}],[0.875',1980,'49,bot:65,','rep:67}}],[0.','667',1980,'50,bot:52,rep:54}}],[0.667',1980,'51,bot:53,rep:55','}}],[0.667,0.04,1.76,{delim:{bot:','52,rep:54',1990,'53,rep:55}}],[0.667',1908,'top:50,rep:54}}],[0.667',1908,'top:51,rep:55','}}],[0.889,0,0.9,{delim:{top:','56,mid:60,bot:58,rep:62',1998,'57,mid:61,bot:59,rep:62',1998,'56,bot:58,rep:62',1998,'57,bot:59,rep:62','}}],[0.889,0,1.8,{delim! :{rep:','63',2006,'119}}],[0.889,0,0.3,{delim:{','rep:62}}],[0.','667',1908,'top:120,bot:121,rep:63}}],[0.875',1980,'56,bot:59,',2010,'875',1980,'57,bot:58,',2010,'875',1908,'rep:66}}],[0.875',1908,1984,'611',1916,'28}],[0.611',1916,'29','}],[0.833,0,1,{n:','71}],[1.11',',0.1,1.5],[','0.472,0,1.11,{ic:0.194,n:','73}],[','0.556,0,2.22,{ic:0.444}],[1.11,0',',1,{n:75}],[1.51,0','.1,1.5],[1.11,0',',1,{n:77}],[1.51,0',2038,',1,{n:79}],[1.51',2033,'1.06,0,1,{n:88}],[0.944,0,1,{n:89}],[',2034,'90',2031,'91',2031,'92',2031,'93',2031,'94',2031,'95}],[1.44',2033,'1.28',2033,2036,2038,2038,2038,2038,'.1,1.5],[0.944,0,1,{n:97}],[1.28',2033,'0.556,0.722,0,{n:','99','}],[1,0.75,0,{n:','100}],[1.44,0.75],[',2066,'102',2068,'103}],[1.44,0.75],[0.472',1916,'20}],[0.472',1916,'21}],[0.528',1916,'22}],[0.528',1916,'23}],[0.528',1916,'24}],[0.528',1916,'25}],[0.667',1916,'26}],[0.667',1916,'27}],[1',1884,'113}],[1',1916,'114}],[1',1920,'115}],[1',1948,'116}],[1.06,0,1.8,{delim:{top:118,bot:116! ,rep:117}}],[1.06,0,0.6],[1.06,0.04,0.56],[0.778',1908,'top:12! 6,bot:12 7,rep:119}}],'], - ['[0.667',',0,0.6,{delim:{','top:120,rep:63','}}],[0.','667',1,'bot:121,rep:63',3,'45,0.12],[0.',8,8,8,'778',1,'top:126,rep:119',3,'778',1,'bot:127,rep:119}}]],cmti10:[[0.627',',0.683,0,{ic:0.','133}],[0.818,0.683],[0.767',19,'094}],[0.','692,0.683],[0.664',19,'153}],[0.743',19,'164}],[0.','716',19,'12}],[0.','767',19,'111}],[0.716',19,'0599}],[0.767',19,'111}],[0.716',19,'103}],[0.','613',',0.694',',0.194,{ic:0.','212,krn:{"39":0.104,"63":0.104,"33":0.104,"41":0.104,"93":0.104},lig:{"105":','14,"108":15',3,'562',41,42,39,'588',41,42,39,'882',41,42,39,'894',41,42,39,'307',',0.431,0,{ic:0.','0767}],[0.','332,0.431',42,'0374}],[0.511',',0.694],[0.','511',',0.694,0,{ic:0.','0969','}],[0.511,0.','628',',0,{ic:0.','083}],[0.511',70,'108',72,'562',74,39,'831',68,'46,0,0.17],[0.537',41,42,'105}],[0.','716',63,'0751','}],[0.716',63,90,72,'528,0.0972,{ic:0.0919}],[0.883',19,30,'985',19,30,'767,0.732,0.0486,{ic:0.',22,'256,0.431,0,{krn:{"108":-0.256,"76":-0.321',3,'307',70,'124,lig! :{"96":','60',3,'514',70,'0696}],[0.818',41,42,'0662}],[0.769',68,'818',',0.75,0.0556',',{ic:0.136}],[0.','767',70,'0969}],[0.307',70,'124',',krn:{"','63":0.102,"33":0.102},lig:{"39":34',3,'409',',0.75,0.25,{ic:0.','162}],[0.409',129,'0369',72,'75',74,'149}],[0.767,0.562,0.0567,{ic:0.0369','}],[0.307,0.','106',',0.194],[0.','358',63,'0283,lig:{"45":123',3,'307,0.106],[0.511',129,'162',72,'644,0',',{ic:0.136}],[0.511,0.644,0',149,149,149,'.194',149,149,149,153,149,149,119,'307',63,'0582',137,'431',42,'0582',137,'5',42,'0756}],[0.767,0.367,-0.133,{ic:0.0662',72,'5',139,'511',70,'122,lig:{"96":62',3,'767',70,'096}],[0.743,0.683,0,{','krn:{"110":-0.0256,"108":-0.0256,"114":-0.0256,"117":-0.0256,"109":-0.0256,"116":-0.0256,"105":-0.0256,"67":-0.0256,"79":-0.0256,"71":-0.0256,"104":-0.0256,"98":-0.0256,"85":-0.0256,"107":-0.0256,"118":-0.0256,"119":-0.0256,"81":-','0.0256,"84','":-0.0767,"','89',184,'86','":-0.102,"','87',188,'101":-0.0511,"97":-0.0511,"111":-0.0511,"100":-0.0511! ,"99":-0.0511,"103":-0.0511,"113":-0.0511}}],[0.','704',19,39,! '716',19 ,'145}],[0.','755',19,'094',125,'88','":-0.0256,"','87',203,'65',203,'86',203,'89','":-0.0256',3,'678',19,30,'653',19,'133',125,'111',184,'101',184,'117','":-0.0767,"114":-0.0767,"97":-0.0767,"','65',188,'79":-0.0256,"67":-0.0256,"71":-0.0256,"81":-0.0256}}],[0.','774',19,'0872}],[0.743',19,27,'386',19,'158}],[0.525',19,'14}],[0.769',19,'145',125,228,'627,0.683,0,{krn:{"84',184,'89',184,'86',188,'87',188,191,'897',19,27,'743',19,27,'767',19,'094',125,'88',203,'87',203,'65',203,'86',203,'89',211,3,'678',19,'103',125,'65":-0.0767}}],[0.','767,0.683',42,22,'729',19,'0387,',182,'0.0256,"84',184,'89',184,'86',188,'87',188,191,'562',19,30,'716',19,'133',125,'121',184,'101',184,'111',225,'117',184,277,'743',19,27,'743',19,'184',125,'111',184,'101',184,'117',225,'65',188,228,'999',19,'184',125,277,'743',19,'158',125,228,'743',19,'194',125,'101',184,'111',225,'117',184,277,'613',19,197,'307',129,'188}],[0.514',70,'169}],[0.307',129,87,'511',70,'0665',137,'668',74,'118}],[0.307',70,10! 7,'92',3,'511',63,64,'46',70,'0631',125,191,'46',63,'0565',125,191,'511',70,'103',',krn:{"108":0.0511}}],[0.','46',63,90,125,191,'307',41,42,43,'12,"102":11,"108":13}}],[0.','46,0.431',42,'0885}],[0.','511',70,64,'307,0.655',74,'102',137,'655',42,197,'46',70,'108}],[0.','256',70,'103',384,'818',63,64,'562',63,'0767',125,'39":-0.102',3,'511',63,'0631',125,191,'511,0.431',42,'0631',125,191,'46,0.431',42,397,'422',63,'108',125,191,'409',63,'0821}],[0.332,0.615',74,'0949}],[0.537',63,64,'46',63,410,'664',63,'108',384,'464',63,30,'486,0.431',42,397,'409',63,'123}],[0.511',63,'0921',',lig:{"45":124}}],[1.','02',63,'0921}],[0.511',70,'122',72,'668',74,'116',72,'668',74,'105}]],cmbx10:[[0.692',',0.686],[0.','958',481,'894',481,'806',481,'767',481,'9',481,'831',481,'894',481,'831',481,'894',481,'831',481,'671',70,'109,krn:{"39":0.109,"63":0.109,"33":0.109,"41":0.109,"93":0.109},lig:{"105":','14,"108":15',3,'639',68,'639',68,'958',68,'958',68,'319',',0.444],[0.','351,0.444',139,'575'! ,68,'575',68,'575,0.','632],[0.575',68,523,'596],[0.869',68,'5! 11,0,0.1 7],[0.597',68,'831',516,'894',516,523,'542,0.0972],[1.04,0.686],[1.17',481,'894,0.735,0.0486],[0.319',',0.444,0,{krn:{"','108":-0.319,"76":-0.378',3,'35',',0.694,0,{lig:{"96":','60',3,'603',68,'958',41,139,'575',118,'],[0.958',118,'],[0.894',68,'319',',0.694,0,{krn:{"','63":0.128,"33":0.128},lig:{"39":34',3,'447',',0.75,0.25],[0.','447',562,523,'75],[0.894,0.633,0.133],[0.','319,0.156',139,'383,0.444,0,{lig:{"45":123',3,567,'],[0.575',562,523,'644],[','0.575,0.644],[0.575,0.644],[',576,576,576,'0.',523,'644],[0.319',516,'319,0.444',139,'35,0.5',139,'894,0.391,-0.109],[0.543,0.5',139,'543',543,'62',3,'894',68,'869',',0.686,0,{krn:{"','116','":-0.0319,"','67',599,'79',599,'71',599,'85',599,'81',599,'84":-0.0958,"89":-0.0958,"86":-0.128,"87":-0.128}}],[','0.818',481,'831',481,'882',597,'88',599,'87',599,'65',599,'86',599,'89','":-0.0319}}],[0.','756',481,'724,0.686,0,{','krn:{"111":-0.0958,"101":-0.0958,"117":-0.0958,"114":-0.0958,"97":-0.0958,"65":-0.128,"79":-0.0319,"67":-0.0! 319,"71":-0.0319,"81":-0.0319}}],[','0.904',481,'9',481,'436',597,'73":0.0319',3,'594',481,'901',597,'79',599,'67',599,'71',599,'81',626,'692',597,610,'1.09',481,'9',481,'864',597,'88',599,'87',599,'65',599,'86',599,'89',626,'786',597,'65":-0.0958,"111',599,'101',599,'97',599,'46":-0.0958,"44":-0.0958}}],[0.','864,0.686',139,'862',597,'116',599,'67',599,'79',599,'71',599,'85',599,'81',599,610,'0.639',481,'8',597,'121',599,'101":-0.0958,"111":-0.0958,"114":-0.0958,"97":-0.0958,"65":-0.0958,"117":-0.0958}}],[0.','885',481,'869,0.686',74,'016,',630,'1.19,0.686',74,'016,',630,'0.869',597,'79',599,'67',599,'71',599,'81',626,'869,0.686',74,'0287',125,702,'703',481,'319',562,'603',68,'319',562,'575',68,'319',68,'319',543,'92',3,'559',539,'118',599,'106":0.0639,"121',599,'119',626,'639',41,',0',',{krn:{"101":0.0319,"111":0.0319,"120":-0.0319,"100":0.0319,"99":0.0319,"113":0.0319,"118":-0.0319,"106":0.0639,"121":-0.0319,"119":-0.0319}}],[0.','511',539,'104',599,'107',626,'639',68,'5! 27',516,'351',70,504,394,523,'444',42,'016',125,'106":0.0319',! 3,'639', 558,'116',599,'117',599,'98',599,'121',599,'118',599,'119',626,'319',68,'351',41,139,'607',558,'97":-0.0639,"101',599,'97',599,'111',599,'99',626,'319',68,'958',539,'116',599,'117',599,'98',599,'121',599,'118',599,'119',626,'639',539,'116',599,'117',599,'98',599,'121',599,'118',599,'119',626,523,'444,0',755,'639,0.444,0',153,755,'607,0.444',139,'474',516,'454',516,'447,0.635,0,{krn:{"121',599,'119',626,'639',539,'119',626,842,74,'016',125,'97":-0.0639,"101',599,'97',599,'111',599,'99',626,'831,0.444',74,'016',125,'101',599,'97',599,'111',599,'99',626,'607',516,842,42,'016',125,'111',599,'101',599,'97',599,678,'511',516,523,'444',74,'0319',467,'15,0.444',74,'0319}],[0.575',68,'575',68,'575',41,']]};','jsMath.Img','={fonts:[50,60,70,85,100,120,144,173,207,249,298,358,430],w:{"50":6.9,"60":8.3,"70":9.7,"85":11.8,"100":13.9,"120":16.7,"144":20,"173":24,"207":28.8,"249":34.6,"298":41.4,"358":49.8,"430":59.8},best:4,update:{},factor:1,loaded:0,SetFont',':function(','B){for(var A i! n B){if(!','this.update[A',']){',913,']=[]}',913,']=',913,'].concat(B[A])}},AddFont',911,'A,B){if(!',909,'[A]){',909,'[A]={}}jsMath.Add(',909,'[A],B)},UpdateFonts',':function(){','var D=this.update;','if(!this.loaded){','return }for(var A in D){for(var B=0;B<D[A].length;B++){var C=D[A][B];if(C=="all"){for(C in ','jsMath.TeX[','A]){',933,'A][C].img','={}}}else{',933,936,'={}}}}this.update={}},BestSize',929,'var B=jsMath.em*this.factor;var A=','this.w[this.fonts[','0]];for(var C=1;C<this.fonts.length;C++){if(B<(',943,'C]]+2*A)/3){return C-1}A=',943,'C]]}return C-1},Scale',929,931,'return }this.best=this.BestSize();this.em=',909,'.w[this.fonts[this.best]];','this.scale','=(jsMath.em/this.em);','if(Math.abs(',954,'-1)<0.12){',954,'=1}},URL',911,'A,B,E){var D=(','jsMath.Controls.cookie.','alpha)?"/alpha/":"/plain/";','if(E==null','){E="def.js"}else{E="char"+E+".png"}if(B!=""){B+="/"}','return this.','root+A+D+B+E},LoadFont',911,'A){',931,'this.Init()}jsMath.Setup.Script(this.URL! (A,""))},Init',929,'if(',963,'print||',963,'stayhires','){',96! 3,'print =',963,978,';this.factor*=3;if(!','jsMath.Controls.','isLocalCookie||!jsMath.Global.isLocal){',985,'SetCookie(0)}if(','jsMath.Browser.','alphaPrintBug){',963,'alpha=0}}var B="0123456789ABCDEF";this.HexCode=[];for(var C=0;C<128;C++){var D=Math.floor(C/16);var A=C-16*D;this.HexCode[C]=B.charAt(D)+B.charAt(A)}this.loaded=1}};jsMath.HTML={Em',911,'A){var C=','5;if(A<0){C++}',956,'A)<0.000001){A=0}var B=String(A);B=B.replace(/(\\.\\d\\d\\d).+/,"$1");return B+"em"},Spacer',911,'A){if(A==0){return""}return ',989,'msieSpaceFix+"<','span class=\\"spacer\\" style=\\"margin-','left:"+this.Em(','A)+"\\"></span>"},Blank',911,'B,E,G,F){var A="";var D="";if(F){D+="border-',1003,'B)+" solid;";if(',989,'widthAddsBorder){B=0}}if(B==0){if(',989,'blankWidthBug){D+="width:1px;";A="<',1002,'right:-1px\\"></span>"}}else{D+="width',':"+this.Em','(B)+";"}if(G==null){G=0}if(E){var C=this.Em(E+G);if(F&&E*jsMath.em<1.5){C="1px";E=1/jsMath.em}D+="height:"+C+";"}if(',989,'mozInlineBlockBug){G=-E}if(',989! ,'msieBorderBug&&!F){G-=jsMath.d}if(G){D+="vertical-align',1015,'(-G)}return A+"<span class=\\"blank\\" ','style=\\""+','D+"\\"></span>"},Rule',911,'A,B){if(B==null){B','=jsMath.TeX.default_rule_thickness}',967,'Blank(A,B,0,1)},Class',911,'A,B){return"<span class=\\""+A+"\\">"+B+"</span>"},Place',911,'B,A,D){',956,'A',')<0.0001){','A=0}',956,'D',1036,'D=0}if(A||D){var C','="<span style=\\"position',': relative;";if(A){C+=" margin-',1003,'A)+";"}if(D){C+=" top',1015,'(-D)+";"}B=C+"\\">"+B','+"</span>"}return ','B},PlaceSeparateSkips',911,'E,G,F,I,A,H){',956,'G',1036,'G=0}',956,'F',1036,'F=0}if(F){var D=0;var C=0;var B="";if(I!=null){C=A-H;D=I;B=" width',1015,'(A-I)+";"}E=','this.Spacer','(D-C)+"<span style=\\"position: relative; "+"top',1015,'(-F)+";"+"',1003,'C)+";"+B+"\\">"+',1062,'(-D)+E+',1062,'(C)+"</span>"}if(G){E=',1062,'(G)+E}return E},PlaceAbsolute',911,'E,B,H,G,D,C){',956,'B',1036,'B=0}',956,'H',1036,'H=0}var F="";var A="";if(',989,'msieRelativeClipBug&&G!=null){F=! ',1062,'(-G);B+=G;A=',1062,'(D-C)}E',1042,':absolute','; ',100! 3,'B)+"; "+"top',1015,'(H)+";\\">"+F+E+A','+" "+"</span','>";return E},','Absolute',911,'C,A,D,E,F,B){if(F!="none"){',956,'F',1036,'F=0}C',1042,1091,'; "+"top:"+','jsMath.HTML.','Em(F)+"; left:0em;\\">"+C',1097,'>"}if(E=="none"){E=0}C+=this.Blank(A,D-E,E);if(',989,'msieAbsoluteBug){C',1042,':relative',';\\">"+C+"</span>"}if(',989,'spanHeightVaries){','C',1042,1116,';"+" width:"+',1109,'Em(A)+";"+" height:"+',1109,'Em(B)+";"+',989,'msieInlineBlockFix+"\\">"+C+"</span>"}else{C',1042,1116,'\\">"+C',1048,'C}};','jsMath.Box','=function(C,E,A,B,D){if(D==null){D=jsMath.d}this.type="typeset";this.w=A;this.h=B;this.d=D;this.bh=B;this.bd=D;this.x=0;this.y=0;this.mw=0;this.Mw=A;this.html=E;this.format=C};jsMath.Add(',1135,',{defaultH:0,Null',929,'return new ',1135,'("null","",0,0,0)},Text',911,'J,I,A,K,H,G){var E=','jsMath.Typeset.AddClass(','I,J);E=','jsMath.Typeset.','AddStyle(','A,K,E);var B','=jsMath.EmBoxFor(','E);var C=',1147,'TeX(A,K);var F=((I=="cmsy10"||I=="cmex10")?B.h-C.h:C.d*B! .h/C.hd);var D=new ',1135,'("text",J,B.w,B.h-F,F);D.style=A;D.size=K;D.tclass=I;if(G!=null){D.d=G*C.scale}else{D.d=0}if(H==null||H==1){D.h=0.9*C.M_height}else{D.h=1.1*C.x_height+C.scale*H}return D},TeX',911,'H,A,E,B){var I=',933,'A][H];','if(I.d==null){I.d=0}','if(I.h==null){I.h=','0}if(I.img!=null&&I.c!=""){this.TeXIMG(A,H,',1147,'StyleSize(E,B))}var G=',1147,'TeX(E,B).scale;var D=I.h+',933,'A].dh;var F=new ',1135,'("text",I.c,I.w*G,D*G,I.d*G);F.style=E;F.size=B;if(I.tclass){F.tclass=I.tclass;if(I.img){F.bh=I.img.bh;F.bd=I.img.bd}else{F.bh=G*jsMath.h;F.bd=G*jsMath.d}}else{F.tclass=A;F.bh=G*',933,'A].h;F.bd=G*',933,'A].d;if(',989,'msieFontBug&&','F','.html.match(/&#/)){','F','.html+="<span style=\\"display:none\\">x</span','>"}}return F},TeXfallback',911,'A,D,B,L){var J=',933,'D][A];if(!J.tclass){J.tclass=D}if(J.img!=null){',967,'TeXnonfallback(A,D,B,L)}if(J.h!=null&&J.a==null){J.a=J.h-1.1*jsMath.TeX.x_height}var K=J.a;var I=J.d;var H=this.Text(J.c,J.tclass,B,L,K,I);var E='! ,1147,'TeX(B,L).scale;if(J.bh!=null){H.bh=J.bh*E;H.bd=J.bd*E}e! lse{var G=H.bd+H.bh;var F=',1145,'H.tclass,H.html);F=',1147,1148,'B,L,F);H.bd',1150,'F+',1109,'Blank(1,G)).h-G;H.bh=G-H.bd;if(E==1){J.bh=H.bh;J.bd=H.bd}}if(jsMath.',1176,'H',1178,'H',1180,'>"}return H},TeXIMG',911,'E,A,R){var M=',933,'E][A];if(M.img.size!=null&&M.img.size==R&&M.img.best!=null&&M.img.best==','jsMath.Img.best','){return }var F=(',909,'.scale!=1);var B=',1209,'+R-4;if(B<0){B=0;F=1','}else{if(','B>=','jsMath.Img.fonts','.length){','B=',1217,'.length-1',';F=1}}var Q=',909,'[',1217,'[B]];var I=Q[E][A];var G=1/',909,'.w[',1217,'[B]];if(B!=',1209,'+R-4){if(M.w!=null){G=M.w/I[0]}else{G*=',1217,'[R]/',1217,'[4]*',1217,'[',1209,']/',1217,'[B]}}var N=I[0]*G;var J=I[1]*G;var L=-I[2]*G;var O;var H=(M.w==null||Math.abs(M.w-N)<0.01)?"":" margin-right:"+',1109,'Em(M.w-N)+";";var D="";A=',909,'.HexCode[A];if(!F&&!',963,'scaleImg){if(2*N<J||(',989,'msieAlphaBug&&',963,'alpha)){D="height',':"+(I[1]*',989,'imgScale',')+"px;"}D+=" width:"+(I[0]*',989,1255,')+"px;";O=-I[2]+"px"}else{if(2*! N<J||(',989,'msieAlphaBug&&',963,1252,':"+',1109,'Em(J*',989,1255,')+";"}D+=" width:"+',1109,'Em(N*',989,1255,')+";";O=',1109,'Em(L)}var P=(Math.abs(L)<0.01&&!',989,'valignBug)?"":" vertical-align:"+O+";";var K=',909,'.URL(E,',1217,'[B],A);if(',989,'msieAlphaBug&&',963,'alpha){','M.c="<img src=\\""+','jsMath.blank+"\\" "+"',1023,989,'msieCenterBugFix+D+P+H','+" filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src="+"\'"+K+"\', sizingMethod=\'scale\'"+");\\" />"}else{',1287,'K+"\\" ',1023,989,1291,'+"\\" />"}M.tclass="normal";M.img.bh=J+L;M.img.bd=-L;M.img.size=R;M.img.best=',1209,'},Space',911,'A){return ','new jsMath.Box("html",',1109,'Spacer(A),A,0,0)},Rule',911,'A,C){if(C','==null){C',1027,'var B=',1109,'Rule(A,C);return ',1303,'B,A,C,0)},GetChar',911,'B,',994,933,'A][B];','if(C.img!=null){this.TeXIMG(A,B',',4)}if(C.tclass',1308,'.tclass=A}if(!C.computedW){C.w',1150,1145,'C.tclass,C.c)).w',';if(C.h',1308,'.h=',1135,'.defaultH}if(C.d',1308,'.d=0}C.computedW=1}ret! urn C},DelimBestFit',911,'E,J,D,G){if(J==0&&D==0){return null}! var I;va r F;D','=jsMath.TeX.fam[','D];var A=(G.charAt(1)=="S");var B=(G.charAt(0)=="S");while(J!=null){I=',933,'D][J];',1161,1135,'.defaultH}',1160,'F=I.h+I.d;if(I.delim){return[J,D,"",E]}if(A&&0.5*F>=E','){return[J,D,"','SS",0.5*F]}if(B&&0.7*F>=E',1345,'S",0.7*F]}if(F>=E||I.n==null',1345,'T",F]}J=I.n}return null},DelimExtendRelative',911,'I,T,O,V,D){var P=',933,'O][T];var N','=this.GetChar(','P.delim.','top?P','.delim.top:','P.delim.rep,O);var ','A',1355,1359,'M',1355,1356,'bot?P','.delim.bot:',1359,'E=',1145,'A.tclass,A.c);','var J=A.w;var S=A.h+A.d;var F;var B;var K;var L;var R;var Q;if(',1356,'mid){var U',1355,1356,'mid,O);Q','=Math.ceil((I-(','N.h+N.d)-(','U.h+U.d)-(M.h+M.d','))/(2*(A.h+A.d',')));I=2*','Q*(A.h+A.d)+(N.h+N.d)+(','U.h+U.d)+(M.h+M.d);if(D){F=0}else{F=I/2+V}B=F;K=',1109,'Place(',1145,'N.tclass,N.c),0,F-N.h',')+',1109,1386,1145,'M.tclass,M.c),-(','N.w+M.w)/2,F-(I-M.d))+',1109,1386,1145,'U.tclass,U.c),-(M.w+U.w)/2,F-(I+U.h-U.d)/2);L=(J-U','.w)/2;if(Math.abs(L)<0.0001! ){L=0}if(L){K+=jsMath.HTML.Spacer(L)}F-=N.h+N.d+A.h;for(R=0;R<Q;R++){K+=jsMath.HTML.Place(E,-J,F-R*S)}','F-=I/2-A.h/2;for(R=0;R<Q;R++){K+=',1109,1386,'E,-J,F-R*S)}}else{Q',1378,1379,'M.h+M.d))/(A.h+A.d));if(N.h+N.d<0.9*(A.h+A.d)){Q=Math.max(1,Q)}I=',1383,'M.h+M.d);if(D){F=0}else{F=I/2+V}B=F;K=',1109,1386,1145,1388,');L=(J-N',1399,'K+=',1109,1386,1145,1393,'J+M.w)/2,B-(I-M.d))}if(D){S=N.h}else{S=I/2+V}var G=',1303,'K,A.w,S,I-S);G.bh=',933,'O].h;G.bd=',933,'O].d;return G},DelimExtendAbsolute',911,'I,S,M,U,B){var R=',933,'M];var N=R[S];var J;var L',1355,'N.delim.top?N',1358,'N.delim.rep,M);var ','A',1355,1434,'K',1355,'N.delim.bot?N',1367,1434,'O;var Q;var E;var D;var P;if(N.delim.mid){var T',1355,'N.delim.mid,M);O',1378,'L.h+L.d)-(','T.h+T.d-0.05',')-(','K.h+K.d-0.05',1381,'-0.05',1382,'O*(A.h+A.d-0.05)+(L.h+L.d)+(',1448,')+(',1450,');J=','jsMath.HTML.PlaceAbsolute(',1145,'L.tclass,L.c),0,0);Q=A.h+A.d-0.05;E=L.d-0.05+A.h;D=',1145,'M,A.c);for(P=0;P<O;P++){J+=',1459,'D,0,E+P*Q)! }J+=',1459,1145,'T.tclass,T.c),0,E+O*Q-A.h+T.h);E+=O*Q+',1448,! ';for(P= 0;P<O;P++){J+=',1459,'D,0,E+P*Q)}J+=',1459,1145,'K.tclass,K.c),0,E+O*Q-A.h+K.h)}','else{O',1378,1447,1450,'))/(A.h+A.d-0.05));I=',1454,1450,');J=',1459,1145,'L.tclass,L.c),0,0);Q=A.h+A.d-0.05;E=L.d-0.05+A.h;D=',1145,1371,'for(P=0;P<O;P++){J+=',1459,'D,0,E+P*Q)}J+=',1459,1145,1475,'var G=L.w;if(B){Q=L.h;E=0}else{Q=I/2+U;E=Q-L.h}J=',1109,1099,'(J,G,R.... [truncated message content] |
From: dpvc v. a. <we...@ma...> - 2007-10-31 01:48:25
|
Log Message: ----------- Make numbers be considered coefficients of x^0 in singlePowers mode, not just LimitedPolynomial-Strict context. For LimitedPolynomials with singlePowers set to 1, you can still do addition in the constant term by using parentheses, e.g. 4x^2 + (3+4). Modified Files: -------------- pg/macros: contextLimitedPolynomial.pl Revision Data ------------- Index: contextLimitedPolynomial.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextLimitedPolynomial.pl,v retrieving revision 1.18 retrieving revision 1.19 diff -Lmacros/contextLimitedPolynomial.pl -Lmacros/contextLimitedPolynomial.pl -u -r1.18 -r1.19 --- macros/contextLimitedPolynomial.pl +++ macros/contextLimitedPolynomial.pl @@ -150,7 +150,7 @@ $self->{exponents} = [(0) x scalar(keys %{$vIndex})]; $self->{exponents}[$self->{index}] = 1; } elsif ($self->class eq 'Number') { - $self->{exponents} = [] if $self->context->flag("strictCoefficients"); + $self->{exponents} = []; } if ($self->{exponents}) { my $power = join(',',@{$self->{exponents}}); |
From: dpvc v. a. <we...@ma...> - 2007-10-31 01:42:35
|
Log Message: ----------- Fix LimitedPolynomial-Strict to check for singlePowers (there was a typo) and to consider constants to be coefficients of x^0. Give better error messages in some cases. Modified Files: -------------- pg/macros: contextLimitedPolynomial.pl Revision Data ------------- Index: contextLimitedPolynomial.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/contextLimitedPolynomial.pl,v retrieving revision 1.17 retrieving revision 1.18 diff -Lmacros/contextLimitedPolynomial.pl -Lmacros/contextLimitedPolynomial.pl -u -r1.17 -r1.18 --- macros/contextLimitedPolynomial.pl +++ macros/contextLimitedPolynomial.pl @@ -139,6 +139,7 @@ # # Mark a variable as having power 1 +# Mark a number as being present (when strict coefficients are used) # Mark a monomial as having its given powers # sub markPowers { @@ -148,6 +149,8 @@ $self->{index} = $vIndex->{$self->{name}}; $self->{exponents} = [(0) x scalar(keys %{$vIndex})]; $self->{exponents}[$self->{index}] = 1; + } elsif ($self->class eq 'Number') { + $self->{exponents} = [] if $self->context->flag("strictCoefficients"); } if ($self->{exponents}) { my $power = join(',',@{$self->{exponents}}); @@ -199,11 +202,6 @@ $self->checkPowers; } -sub checkStrict { - my $self = shift; - $self->Error("You can only use addition for the terms of a polynomial",$self->{bop}); -} - ############################################## package LimitedPolynomial::BOP::subtract; @@ -216,11 +214,6 @@ $self->checkPowers; } -sub checkStrict { - my $self = shift; - $self->Error("You can only use subtraction between the terms of a polynomial",$self->{bop}); -} - ############################################## package LimitedPolynomial::BOP::multiply; @@ -263,7 +256,7 @@ sub checkStrict { my $self = shift; - $self->Error("You can only use '%s' to form fractions",$self->{bop}) if $self->{lop}->class eq 'BOP'; + $self->Error("You can only use '%s' to form numeric fractions",$self->{bop}) if $self->{lop}->class eq 'BOP'; } ############################################## @@ -431,7 +424,7 @@ # A context where coefficients can't include operations # $context = $main::context{"LimitedPolynomial-Strict"} = $context->copy; - $context->flags->set(strictCoefficients=>1, singelPowers=>1, reduceConstants=>0); + $context->flags->set(strictCoefficients=>1, singlePowers=>1, reduceConstants=>0); $context->functions->disable("All"); # can be re-enabled if needed main::Context("LimitedPolynomial"); ### FIXME: probably should require author to set this explicitly |
From: Mike G. v. a. <we...@ma...> - 2007-10-30 16:05:33
|
Log Message: ----------- Preliminary version of Applet.pm which will provide a uniform interface for including FlashApplets (eventually other applets) in a webwork problem. This remains experimental so the interface will probably change. Added Files: ----------- pg/lib: Applet.pm Revision Data ------------- --- /dev/null +++ lib/Applet.pm @@ -0,0 +1,330 @@ +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: pg/lib/Applet.pm,v 1.1 2007/10/30 15:57:04 gage Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +=head1 NAME + +Applet.pl - Provides code for inserting FlashApplets and JavaApplets into webwork problems + +=head1 SYNPOSIS + + ################################### + # Create link to applet + ################################### + my $appletName = "LineThruPointsWW"; + $applet = new FlashApplet( + codebase => findAppletCodebase("$appletName.swf"), + appletName => $appletName, + appletId => $appletName, + submitActionAlias => 'checkAnswer', + ); + + ################################### + # Configure applet + ################################### + + #xml data to set up the problem-rac + $applet->xmlString(qq{<XML> + <point xval='$xval_1' yval='$yval_1' /> + <point xval='$xval_2' yval='$yval_2' /> + </XML>}); + + + ################################### + # insert applet header material + ################################### + HEADER_TEXT($applet->insertHeader ); + + ################################### + # Text section + # + + ################################### + #insert applet into body + ################################### + TEXT( MODES(TeX=>'object code', HTML=>$applet->insertObject)); + + +=head1 DESCRIPTION + +This file provides an object to store in one place +all of the information needed to call an applet. + +The object FlashApplet has defaults for inserting flash applets. + +=over + +=item * + +=item * + +=back + +(not yet completed) + +The module JavaApplet has defaults for inserting java applets. + +The module Applet will store common code for the two types of applet. + +=head1 USAGE + +This file is included by listing it in the modules section of global.conf. + +=cut + + + +package Applet; + + +package FlashApplet; + + +use MIME::Base64 qw( encode_base64 decode_base64); + +use constant DEFAULT_HEADER_TEXT =><<'END_HEADER_SCRIPT'; + <script language="javascript">AC_FL_RunContent = 0;</script> + <script src="http://hosted2.webwork.rochester.edu/webwork2_files/applets/AC_RunActiveContent.js" language="javascript"></script> + + <script type="text/javascript" src="http://hosted2.webwork.rochester.edu/webwork2_files/js/BrowserSniffer.js"> + </script> + <script language="JavaScript"> + + var flash; + function getFlashMovie(movieName) { + var isIE = navigator.appName.indexOf("Microsoft") != -1; + return (isIE) ? window[movieName] : window.document[movieName]; + //return window.document[movieName]; + } + function getBrowser() { + return new BrowserSniffer(); + } + + function initialize() { + getFlashMovie("$appletId").$initializeAction("$base64_xmlString"); + } + function submitAction() { + document.problemMainForm.$returnFieldName.value = getFlashMovie("$appletId").$submitAction(); + } + + </script>, + +END_HEADER_SCRIPT + + +# <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" +# width="550" height="400" id="$appletId" align="middle"> +# <param name="allowScriptAccess" value="sameDomain" /> +# <param name="allowFullScreen" value="false" /> +# <param name="movie" value="$appletName.swf" /> +# <param name="quality" value="high" /> +# <param name="bgcolor" value="#ffffcc" /> +# <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#ffffcc" width="550" height="400" name="$appletName" +# align="middle" id="$appletId", +# align="middle" allowScriptAccess="sameDomain" +# allowFullScreen="false" +# type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" /> +# <param name="quality" value="high" /><param name="bgcolor" value="#ffffcc" /> +# </object> + +use constant DEFAULT_OBJECT_TEXT =><<'END_OBJECT_TEXT'; + <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" + id="ExternalInterface" width="500" height="375" + codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab"> + <param name="movie" value="$codebase/$appletName.swf" /> + <param name="quality" value="high" /> + <param name="bgcolor" value="#869ca7" /> + <param name="allowScriptAccess" value="sameDomain" /> + <embed src="$codebase/$appletName.swf" quality="high" bgcolor="#869ca7" + width="550" height="400" name="$appletName" align="middle" id="$appletID" + play="true" loop="false" quality="high" allowScriptAccess="sameDomain" + type="application/x-shockwave-flash" + pluginspage="http://www.macromedia.com/go/getflashplayer"> + </embed> + + </object> +END_OBJECT_TEXT + + +sub new { + my $class = shift; + my $self = { + host =>'', + port => '', + path => '', + appletName =>'', + codebase=>'', + appletId =>'', + params =>undef, + base64_xmlString => 'foobar', + initializeActionAlias => 'setupProblem', + submitActionAlias => 'checkAnswer', + returnFieldName => 'receivedField', + headerText => DEFAULT_HEADER_TEXT(), + objectText => DEFAULT_OBJECT_TEXT(), + @_, + }; + bless $self, $class; + #$self -> _initialize(@_); + return $self; +} + +sub header { + my $self = shift; + if ($_[0] eq "reset") { # $applet->header('reset'); erases default header text. + $self->{headerText}=''; + } else { + $self->{headerText} .= join("",@_); # $applet->header(new_text); concatenates new_text to existing header. + } + $self->{headerText}; +} +sub object { + my $self = shift; + if ($_[0] eq "reset") { + $self->{objectText}=''; + } else { + $self->{objectText} .= join("",@_); + } + $self->{objectText}; +} +sub params { + my $self = shift; + if (ref($_[0]) =~/HASH/) { + $self->{params} = shift; + } elsif ( $_[0] =~ '') { + # do nothing (read) + } else { + warn "You must enter a reference to a hash for the parameter list"; + } + $self->{params}; +} + +sub initializeActionAlias { + my $self = shift; + $self->{initializeActionAlias} = shift ||$self->{initializeActionAlias}; # replace the current contents if non-empty + $self->{initializeActionAlias}; +} + +sub submitActionAlias { + my $self = shift; + $self->{submitActionAlias} = shift ||$self->{submitActionAlias}; # replace the current contents if non-empty + $self->{submitActionAlias}; +} +sub returnFieldName { + my $self = shift; + $self->{returnFieldName} = shift ||$self->{returnFieldName}; # replace the current contents if non-empty + $self->{returnFieldName}; +} +sub codebase { + my $self = shift; + $self->{codebase} = shift ||$self->{codebase}; # replace the current codebase if non-empty + $self->{codebase}; +} +sub appletName { + my $self = shift; + $self->{appletName} = shift ||$self->{appletName}; # replace the current appletName if non-empty + $self->{appletName}; +} +sub appletId { + my $self = shift; + $self->{appletId} = shift ||$self->{appletId}; # replace the current appletName if non-empty + $self->{appletId}; +} +sub xmlString { + my $self = shift; + my $str = shift; + $self->{base64_xmlString} = encode_base64($str) ||$self->{base64_xmlString}; # replace the current string if non-empty + $self->{base64_xmlString} =~ s/\n//g; + decode_base64($self->{base64_xmlString}); +} + +sub base64_xmlString{ + my $self = shift; + $self->{base64_xmlString} = shift ||$self->{base64_xmlString}; # replace the current string if non-empty + $self->{base64_xmlString}; +} + +#FIXME +# need to be able to adjust header material + +sub insertHeader { + my $self = shift; + my $codebase = $self->{codebase}; + my $appletId = $self->{appletId}; + my $appletName = $self->{appletName}; + my $base64_xmlString = $self->{base64_xmlString}; + my $initializeAction = $self->{initializeActionAlias}; + my $submitAction = $self->{submitActionAlias}; + my $returnFieldName= $self->{returnFieldName}; + my $headerText = $self->header(); + $headerText =~ s/(\$\w+)/$1/gee; # interpolate variables p17 of Cookbook + + return $headerText; + + +} + + +# <script language="javascript"> +# if (AC_FL_RunContent == 0) { +# alert("This page requires AC_RunActiveContent.js."); +# } else { +# AC_FL_RunContent( +# 'codebase', 'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0', +# 'width', '100%', +# 'height', '100%', +# 'src', 'http://$codebase/$appletName', +# 'quality', 'high', +# 'pluginspage', 'http://www.macromedia.com/go/getflashplayer', +# 'align', 'middle', +# 'play', 'true', +# 'loop', 'true', +# 'scale', 'showall', +# 'wmode', 'window', +# 'devicefont', 'false', +# 'id', '$appletId', +# 'bgcolor', '#ffffcc', +# 'name', '$appletName', +# 'menu', 'true', +# 'allowFullScreen', 'false', +# 'allowScriptAccess','sameDomain', +# 'movie', '$appletName', +# 'salign', '' +# ); //end AC code +# } +# </script> +sub insertObject { + my $self = shift; + my $codebase = $self->{codebase}; + my $appletId = $self->{appletId}; + my $appletName = $self->{appletName}; + $codebase = findAppletCodebase("$appletName.swf") unless $codebase; + $objectText = $self->{objectText}; + $objectText =~ s/(\$\w+)/$1/gee; + return $objectText; +} + +sub initialize { + my $self = shift; + return q{ + <script> + initialize(); + // this should really be done in the <body> tag + </script> + }; + +} + +1; \ No newline at end of file |
From: Mike G. v. a. <we...@ma...> - 2007-10-29 02:41:46
|
Log Message: ----------- Modifications PGgraphicsmacros.pl suggested by Davide Cervone. 1. Don't load MathObjects (since this causes conflicts if the webwork question also uses Matrices as well as GraphObjects). (This incompatibility is itself a bug, but not one we can solve immediately.) 2. Make sure that the variable is defined by defining the new rule in a local context and insuring that the variable is defined. (Unfortunately we don't have the original Formula, just the normalString created by the Formula so we won't be able to guarantee the same context that created the original Formula. However we can get the current context and add the independent variable if it is missing.) 3. Evaluate using Parser::Evaluate so that the errors are trapped if the input is not in the domain of definition of the function. ------- A reasonable next step would be to define plot_formula with syntax something like plot_formula($formula, domain=>[0,10],color=>'red',weight=>2) which could take further advantage of the MathObjects paradigm, but we'll probably have to find a more robust solution to the Matrix confusion at the same time. --Mike Modified Files: -------------- pg/macros: PGgraphmacros.pl Revision Data ------------- Index: PGgraphmacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGgraphmacros.pl,v retrieving revision 1.8 retrieving revision 1.9 diff -Lmacros/PGgraphmacros.pl -Lmacros/PGgraphmacros.pl -u -r1.8 -r1.9 --- macros/PGgraphmacros.pl +++ macros/PGgraphmacros.pl @@ -47,7 +47,9 @@ # 'axes' ######################################################### -loadMacros("MathObjects.pl"); # need this to handle problems that don't otherwise use MathObjects +#loadMacros("MathObjects.pl"); # avoid loading the entire package + # of MathObjects since that can mess up + # problems that don't use MathObjects but use Matrices. my %images_created = (); # this keeps track of the base names of the images created during this session. # We tack on @@ -317,8 +319,15 @@ } else { $weight =2; } - my $subRef = Formula($rule)->perlFunction(undef,[$var]); - # my $subRef = string_to_sub($rule,$var); + # a workaround to call Parser code without loading MathObjects. + my $localContext= Parser::Context->current(\%main::context)->copy; + $localContext->variables->add($var=>'Real') unless $localContext->variables->get($var); + my $formula = Value->Package("Formula()")->new($localContext,$rule); + my $subRef = sub {my $x=shift; Parser::Evaluate($formula, $var=>$x)}; + #traps errors when + # graph domain is larger than the function's domain. + + #my $subRef = string_to_sub($rule,$var); my $funRef = new Fun($subRef,$graph); $funRef->color($color); $funRef->weight($weight); |
From: Mike G. v. a. <we...@ma...> - 2007-10-28 17:03:32
|
Log Message: ----------- Cosmetic fixes to global.conf Change blankProblem.pg to blankProblem2.pg to take advantage of the new MathObject paradigm in the blankProblem template. Modified Files: -------------- webwork2/conf: global.conf.dist Revision Data ------------- Index: global.conf.dist =================================================================== RCS file: /webwork/cvs/system/webwork2/conf/global.conf.dist,v retrieving revision 1.201 retrieving revision 1.202 diff -Lconf/global.conf.dist -Lconf/global.conf.dist -u -r1.201 -r1.202 --- conf/global.conf.dist +++ conf/global.conf.dist @@ -142,6 +142,7 @@ # %r = recitation # %% = literal percent sign # + $mail{feedbackSubjectFormat} = "[WWfeedback] course:%c user:%u set:%s prob:%p sec:%x rec:%r"; # feedbackVerbosity: @@ -203,7 +204,9 @@ # $webworkDirs{valid_symlinks} = ["$webworkDirs{courses}/modelCourse/templates","/ww2/common/sets"]; $webworkDirs{valid_symlinks} = []; +################################################################################ ##### The following locations are web-accessible. +################################################################################ # The root URL (usually /webwork2), set by <Location> in Apache configuration. $webworkURLs{root} = "$webwork_url"; @@ -226,7 +229,7 @@ $webworkURLs{local_help} = "$webworkURLs{htdocs}/helpFiles"; # URL of general WeBWorK documentation. -$webworkURLs{docs} = "http://webhost.math.rochester.edu/webworkdocs/docs"; +$webworkURLs{docs} = "http://webwork.maa.org"; # URL of WeBWorK Bugzilla database. $webworkURLs{bugReporter} = "http://bugs.webwork.rochester.edu/"; @@ -306,9 +309,10 @@ # don't want to use the equation cache file. $webworkFiles{equationCacheDB} = ""; # "$webworkDirs{DATA}/equationcache"; -##### Hardcopy snippets are used in constructing a TeX file for hardcopy output. -##### They should contain TeX code unless otherwise noted. - +################################################################################ +# Hardcopy snippets are used in constructing a TeX file for hardcopy output. +# They should contain TeX code unless otherwise noted. +################################################################################ # The preamble is the first thing in the TeX file. $webworkFiles{hardcopySnippets}{preamble} = "$webworkDirs{conf}/snippets/hardcopyPreamble.tex"; @@ -336,7 +340,7 @@ $webworkFiles{screenSnippets}{setHeader} = "$webworkDirs{conf}/snippets/setHeader.pg"; # screenSetHeader.pg" # A PG template for creation of new problems. -$webworkFiles{screenSnippets}{blankProblem} = "$webworkDirs{conf}/snippets/blankProblem.pg"; # screenSetHeader.pg" +$webworkFiles{screenSnippets}{blankProblem} = "$webworkDirs{conf}/snippets/blankProblem2.pg"; # screenSetHeader.pg" # A site info "message of the day" file $webworkFiles{site_info} = "$webworkDirs{htdocs}/site_info.txt"; @@ -895,6 +899,8 @@ [qw(VectorField)], [qw(Parser Value)], [qw(Parser::Legacy)], +# [qw(SaveFile)], +# [qw(Applet FlashApplet)], ]; ##### Answer evaluatior defaults |
From: Mike G. v. a. <we...@ma...> - 2007-10-28 16:59:00
|
Log Message: ----------- Modified this blankProblem2.pg to use more MathObject techniques. You can make this the default problem template by adjusting the reference to blankProblem in global.conf Modified Files: -------------- webwork2/conf/snippets: blankProblem2.pg Revision Data ------------- Index: blankProblem2.pg =================================================================== RCS file: /webwork/cvs/system/webwork2/conf/snippets/blankProblem2.pg,v retrieving revision 1.1 retrieving revision 1.2 diff -Lconf/snippets/blankProblem2.pg -Lconf/snippets/blankProblem2.pg -u -r1.1 -r1.2 --- conf/snippets/blankProblem2.pg +++ conf/snippets/blankProblem2.pg @@ -27,7 +27,10 @@ #"PGcourse.pl", # Customization file for the course ); +# Print problem number and point value (weight) for the problem TEXT(beginproblem()); + +# Show which answers are correct and which ones are incorrect $showPartialCorrectAnswers = 1; ############################################################## @@ -35,6 +38,9 @@ # Setup # # +Context("Numeric"); + +$pi = Real("pi"); ############################################################## # @@ -42,17 +48,26 @@ # # +Context()->texStrings; BEGIN_TEXT +Enter a value for \(\pi\) + +\{$pi->ans_rule\} END_TEXT + + ############################################################## # # Answers # # +ANS($pi->with(tolerance=>.0001)->cmp); +# relative tolerance --3.1412 is incorrect but 3.1413 is correct +# default tolerance is .01 or one percent. ENDDOCUMENT(); |
From: Mike G. v. a. <we...@ma...> - 2007-10-28 16:41:56
|
Log Message: ----------- Added explicit loadMacros("MathObject.pl") to handle webwork questions which don't use math objects for any other purpose other than graphs. CVS: ---------------------------------------------------------------------- Modified Files: -------------- pg/macros: PGgraphmacros.pl Revision Data ------------- Index: PGgraphmacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGgraphmacros.pl,v retrieving revision 1.7 retrieving revision 1.8 diff -Lmacros/PGgraphmacros.pl -Lmacros/PGgraphmacros.pl -u -r1.7 -r1.8 --- macros/PGgraphmacros.pl +++ macros/PGgraphmacros.pl @@ -47,6 +47,8 @@ # 'axes' ######################################################### +loadMacros("MathObjects.pl"); # need this to handle problems that don't otherwise use MathObjects + my %images_created = (); # this keeps track of the base names of the images created during this session. # We tack on # $imageNum = ++$images_created{$imageName} to keep from overwriting files |
From: Mike G. v. a. <we...@ma...> - 2007-10-27 14:21:53
|
Log Message: ----------- Changed plot_functions so that it uses the Formula MathObject to parse the the function in $f1 = qq! x^2 - 3*x + 45 for x in [0, 45) using color:red and weight:2! instead of using the built in perl parser. This allows things such as $formula=Formula("|x|"); $f1 = qq! $formula for x in [0, 45) using color:red and weight:2! to be evaluated. There should be no apparent change to old problems since the Formula MathObject parser handles a superset of the builtin perl parser syntax. This is not yet the most efficient method to have GraphObjects and Formula's interact since the same string is being recompiled several times, but it is a useful hack which preserves backward compatibility. Modified Files: -------------- pg/macros: PGgraphmacros.pl Revision Data ------------- Index: PGgraphmacros.pl =================================================================== RCS file: /webwork/cvs/system/pg/macros/PGgraphmacros.pl,v retrieving revision 1.6 retrieving revision 1.7 diff -Lmacros/PGgraphmacros.pl -Lmacros/PGgraphmacros.pl -u -r1.6 -r1.7 --- macros/PGgraphmacros.pl +++ macros/PGgraphmacros.pl @@ -16,7 +16,7 @@ This collection of macros provides easy access to the facilities provided by the graph module WWPlot and the modules for objects which can be drawn on a graph: functions (Fun.pm) -labels (Label.pm) and images. The only image implemented currently are open and closed circles +labels (Label.pm) and images. The only images implemented currently are open and closed circles (Circle) which can be used to mark graphs of functions defined on open and closed intervals. These macros provide an easy ability to graph simple functions. More complicated projects @@ -315,8 +315,8 @@ } else { $weight =2; } - - my $subRef = string_to_sub($rule,$var); + my $subRef = Formula($rule)->perlFunction(undef,[$var]); + # my $subRef = string_to_sub($rule,$var); my $funRef = new Fun($subRef,$graph); $funRef->color($color); $funRef->weight($weight); @@ -343,6 +343,9 @@ @functions; # return function references unless there is an error. } + + + =head2 insertGraph $filePath = insertGraph(graphObject); |