| … | |
… | |
| 1110 | $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('NUMBER'); } ); |
1110 | $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('NUMBER'); } ); |
| 1111 | $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('STRING'); } ); |
1111 | $answer_evaluator->install_post_filter(sub {my $rh_ans = shift; $rh_ans->clear_error('STRING'); } ); |
| 1112 | $answer_evaluator; |
1112 | $answer_evaluator; |
| 1113 | } |
1113 | } |
| 1114 | |
1114 | |
| 1115 | sub fix_answers_for_display { |
|
|
| 1116 | my ($rh_ans, %options) = @_; |
|
|
| 1117 | if ( $rh_ans->{answerIsString} ==1) { |
|
|
| 1118 | $rh_ans = evaluatesToNumber ($rh_ans, %options); |
|
|
| 1119 | } |
|
|
| 1120 | if (defined ($rh_ans->{student_units})) { |
|
|
| 1121 | $rh_ans->{student_ans} = $rh_ans->{student_ans}. ' '. $rh_ans->{student_units}; |
|
|
| 1122 | } |
|
|
| 1123 | $rh_ans->{correct_ans} = $rh_ans->{original_correct_ans}; |
|
|
| 1124 | |
|
|
| 1125 | $rh_ans; |
|
|
| 1126 | } |
|
|
| 1127 | |
1115 | |
| 1128 | sub evaluatesToNumber { |
|
|
| 1129 | my ($rh_ans, %options) = @_; |
|
|
| 1130 | if (is_a_numeric_expression($rh_ans->{student_ans})) { |
|
|
| 1131 | my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($rh_ans->{student_ans}); |
|
|
| 1132 | if ($PG_eval_errors) { # this if statement should never be run |
|
|
| 1133 | # change nothing |
|
|
| 1134 | } else { |
|
|
| 1135 | # change this |
|
|
| 1136 | $rh_ans->{student_ans} = prfmt($inVal,$options{format}); |
|
|
| 1137 | } |
|
|
| 1138 | } |
|
|
| 1139 | $rh_ans; |
|
|
| 1140 | } |
|
|
| 1141 | |
|
|
| 1142 | sub is_a_numeric_expression { |
|
|
| 1143 | my $testString = shift; |
|
|
| 1144 | my $is_a_numeric_expression = 0; |
|
|
| 1145 | my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($testString); |
|
|
| 1146 | if ($PG_eval_errors) { |
|
|
| 1147 | $is_a_numeric_expression = 0; |
|
|
| 1148 | } else { |
|
|
| 1149 | $is_a_numeric_expression = 1; |
|
|
| 1150 | } |
|
|
| 1151 | $is_a_numeric_expression; |
|
|
| 1152 | } |
|
|
| 1153 | |
1116 | |
| 1154 | ########################################################################## |
1117 | ########################################################################## |
| 1155 | ########################################################################## |
1118 | ########################################################################## |
| 1156 | ## Function answer evaluators |
1119 | ## Function answer evaluators |
| 1157 | |
1120 | |
| … | |
… | |
| 3449 | return @out; |
3412 | return @out; |
| 3450 | } |
3413 | } |
| 3451 | } |
3414 | } |
| 3452 | } |
3415 | } |
| 3453 | |
3416 | |
| 3454 | sub check_option_list { |
3417 | #sub check_option_list { |
| 3455 | my $size = scalar(@_); |
3418 | # my $size = scalar(@_); |
| 3456 | if( ( $size % 2 ) != 0 ) { |
3419 | # if( ( $size % 2 ) != 0 ) { |
| 3457 | warn "ERROR in answer evaluator generator:\n" . |
3420 | # warn "ERROR in answer evaluator generator:\n" . |
| 3458 | "Usage: <CODE>str_cmp([\$ans1, \$ans2],%options)</CODE> |
3421 | # "Usage: <CODE>str_cmp([\$ans1, \$ans2],%options)</CODE> |
| 3459 | or <CODE> num_cmp([\$num1, \$num2], %options)</CODE><BR> |
3422 | # or <CODE> num_cmp([\$num1, \$num2], %options)</CODE><BR> |
| 3460 | A list of inputs must be inclosed in square brackets <CODE>[\$ans1, \$ans2]</CODE>"; |
3423 | # A list of inputs must be inclosed in square brackets <CODE>[\$ans1, \$ans2]</CODE>"; |
| 3461 | } |
3424 | # } |
| 3462 | } |
3425 | #} |
| 3463 | |
3426 | |
| 3464 | # simple subroutine to display an error message when |
3427 | # simple subroutine to display an error message when |
| 3465 | # function compares are called with invalid parameters |
3428 | # function compares are called with invalid parameters |
| 3466 | sub function_invalid_params { |
3429 | sub function_invalid_params { |
| 3467 | my $correctEqn = shift @_; |
3430 | my $correctEqn = shift @_; |
| … | |
… | |
| 3471 | return ( 0, $correctEqn, "", $PGanswerMessage ); |
3434 | return ( 0, $correctEqn, "", $PGanswerMessage ); |
| 3472 | }; |
3435 | }; |
| 3473 | return $error_response; |
3436 | return $error_response; |
| 3474 | } |
3437 | } |
| 3475 | |
3438 | |
|
|
3439 | sub clean_up_error_msg { |
|
|
3440 | my $msg = $_[0]; |
|
|
3441 | $msg =~ s/^\[[^\]]*\][^:]*://; |
|
|
3442 | $msg =~ s/Unquoted string//g; |
|
|
3443 | $msg =~ s/may\s+clash.*/does not make sense here/; |
|
|
3444 | $msg =~ s/\sat.*line [\d]*//g; |
|
|
3445 | $msg = 'error: '. $msg; |
|
|
3446 | |
|
|
3447 | return $msg; |
|
|
3448 | } |
|
|
3449 | |
|
|
3450 | #formats the student and correct answer as specified |
|
|
3451 | #format must be of a form suitable for sprintf (e.g. '%0.5g'), |
|
|
3452 | #with the exception that a '#' at the end of the string |
|
|
3453 | #will cause trailing zeros in the decimal part to be removed |
|
|
3454 | sub prfmt { |
|
|
3455 | my($number,$format) = @_; # attention, the order of format and number are reversed |
|
|
3456 | my $out; |
|
|
3457 | if ($format) { |
|
|
3458 | warn "Incorrect format used: $format. <BR> Format should look something like %4.5g<BR>" |
|
|
3459 | unless $format =~ /^\s*%\d*\.?\d*\w#?\s*$/; |
|
|
3460 | |
|
|
3461 | if( $format =~ s/#\s*$// ) { # remove trailing zeros in the decimal |
|
|
3462 | $out = sprintf( $format, $number ); |
|
|
3463 | $out =~ s/(\.\d*?)0+$/$1/; |
|
|
3464 | $out =~ s/\.$//; # in case all decimal digits were zero, remove the decimal |
|
|
3465 | } |
|
|
3466 | else { |
|
|
3467 | $out = sprintf( $format, $number ); |
|
|
3468 | } |
|
|
3469 | $out =~ s/e/E/g; # only use capital E's for exponents. Little e is for 2.71828... |
|
|
3470 | } |
|
|
3471 | else { |
|
|
3472 | $out = $number; |
|
|
3473 | $out =~ s/e/E/g; # only use capital E's for exponents. Little e is for 2.71828... |
|
|
3474 | |
|
|
3475 | } |
|
|
3476 | return $out; |
|
|
3477 | } |
| 3476 | ######################################################################### |
3478 | ######################################################################### |
| 3477 | # Filters for answer evaluators |
3479 | # Filters for answer evaluators |
| 3478 | ######################################################################### |
3480 | ######################################################################### |
|
|
3481 | |
|
|
3482 | =head2 Filters |
|
|
3483 | |
|
|
3484 | =pod |
|
|
3485 | |
|
|
3486 | A filter is a short subroutine with the following structure. It accepts an |
|
|
3487 | AnswerHash, followed by a hash of options. It returns an AnswerHash |
|
|
3488 | |
|
|
3489 | $ans_hash = filter($ans_hash, %options); |
|
|
3490 | |
|
|
3491 | See the AnswerHash.pm file for a list of entries which can be expected to be found |
|
|
3492 | in an AnswerHash, such as 'studen_abs', 'score' and so forth. Other entries |
|
|
3493 | may be present for specialized answer evaluators. |
|
|
3494 | |
|
|
3495 | The hope is that a well designed set of filters can easily be combined to form |
|
|
3496 | a new answer_evaluator and that this method will produce answer evaluators which are |
|
|
3497 | are more robust than the method of copying existing answer evaluators and modifying them. |
|
|
3498 | |
|
|
3499 | Here is an outline of how a filter is constructed: |
|
|
3500 | |
|
|
3501 | sub filter{ |
|
|
3502 | my $rh_ans = shift; |
|
|
3503 | my %options = @_; |
|
|
3504 | assign_option_aliases(\%options, |
|
|
3505 | 'alias1' => 'option5' |
|
|
3506 | 'alias2' => 'option7' |
|
|
3507 | ); |
|
|
3508 | set_default_options(\%options, |
|
|
3509 | '_filter_name' => 'filter', |
|
|
3510 | 'option5' => .0001, |
|
|
3511 | 'option7' => 'ascii', |
|
|
3512 | 'allow_unknown_options => 0, |
|
|
3513 | } |
|
|
3514 | .... body code of filter ....... |
|
|
3515 | if ($error) { |
|
|
3516 | $rh_ans->throw_error("FILTER_ERROR", "Something went wrong"); |
|
|
3517 | # see AnswerHash.pm for details on using the throw_error method. |
|
|
3518 | |
|
|
3519 | $rh_ans; #reference to an AnswerHash object is returned. |
|
|
3520 | } |
|
|
3521 | |
|
|
3522 | =cut |
|
|
3523 | |
|
|
3524 | =head4 fix_answer_for_display |
|
|
3525 | |
|
|
3526 | =cut |
|
|
3527 | |
|
|
3528 | sub fix_answers_for_display { |
|
|
3529 | my ($rh_ans, %options) = @_; |
|
|
3530 | if ( $rh_ans->{answerIsString} ==1) { |
|
|
3531 | $rh_ans = evaluatesToNumber ($rh_ans, %options); |
|
|
3532 | } |
|
|
3533 | if (defined ($rh_ans->{student_units})) { |
|
|
3534 | $rh_ans->{student_ans} = $rh_ans->{student_ans}. ' '. $rh_ans->{student_units}; |
|
|
3535 | } |
|
|
3536 | $rh_ans->{correct_ans} = $rh_ans->{original_correct_ans}; |
|
|
3537 | |
|
|
3538 | $rh_ans; |
|
|
3539 | } |
|
|
3540 | |
|
|
3541 | =head4 evaluatesToNumber |
|
|
3542 | |
|
|
3543 | =cut |
|
|
3544 | |
|
|
3545 | sub evaluatesToNumber { |
|
|
3546 | my ($rh_ans, %options) = @_; |
|
|
3547 | if (is_a_numeric_expression($rh_ans->{student_ans})) { |
|
|
3548 | my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($rh_ans->{student_ans}); |
|
|
3549 | if ($PG_eval_errors) { # this if statement should never be run |
|
|
3550 | # change nothing |
|
|
3551 | } else { |
|
|
3552 | # change this |
|
|
3553 | $rh_ans->{student_ans} = prfmt($inVal,$options{format}); |
|
|
3554 | } |
|
|
3555 | } |
|
|
3556 | $rh_ans; |
|
|
3557 | } |
|
|
3558 | |
|
|
3559 | =head4 is_numeric_expression |
|
|
3560 | |
|
|
3561 | =cut |
|
|
3562 | |
|
|
3563 | sub is_a_numeric_expression { |
|
|
3564 | my $testString = shift; |
|
|
3565 | my $is_a_numeric_expression = 0; |
|
|
3566 | my ($inVal,$PG_eval_errors,$PG_full_error_report) = PG_answer_eval($testString); |
|
|
3567 | if ($PG_eval_errors) { |
|
|
3568 | $is_a_numeric_expression = 0; |
|
|
3569 | } else { |
|
|
3570 | $is_a_numeric_expression = 1; |
|
|
3571 | } |
|
|
3572 | $is_a_numeric_expression; |
|
|
3573 | } |
|
|
3574 | |
|
|
3575 | =head4 is_a_number |
|
|
3576 | |
|
|
3577 | =cut |
| 3479 | |
3578 | |
| 3480 | sub is_a_number { |
3579 | sub is_a_number { |
| 3481 | my ($num,%options) = @_; |
3580 | my ($num,%options) = @_; |
| 3482 | my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; |
3581 | my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; |
| 3483 | my ($rh_ans); |
3582 | my ($rh_ans); |
| … | |
… | |
| 3507 | } |
3606 | } |
| 3508 | } else { |
3607 | } else { |
| 3509 | return $is_a_number; |
3608 | return $is_a_number; |
| 3510 | } |
3609 | } |
| 3511 | } |
3610 | } |
|
|
3611 | |
|
|
3612 | =head4 is_a_fraction |
|
|
3613 | |
|
|
3614 | =cut |
| 3512 | |
3615 | |
| 3513 | sub is_a_fraction { |
3616 | sub is_a_fraction { |
| 3514 | my ($num,%options) = @_; |
3617 | my ($num,%options) = @_; |
| 3515 | my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; |
3618 | my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; |
| 3516 | my ($rh_ans); |
3619 | my ($rh_ans); |
| … | |
… | |
| 3541 | } else { |
3644 | } else { |
| 3542 | return $is_a_fraction; |
3645 | return $is_a_fraction; |
| 3543 | } |
3646 | } |
| 3544 | } |
3647 | } |
| 3545 | |
3648 | |
|
|
3649 | =head4 is_an_arithemetic_expression |
|
|
3650 | |
|
|
3651 | =cut |
| 3546 | |
3652 | |
| 3547 | sub is_an_arithmetic_expression { |
3653 | sub is_an_arithmetic_expression { |
| 3548 | my ($num,%options) = @_; |
3654 | my ($num,%options) = @_; |
| 3549 | my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; |
3655 | my $process_ans_hash = ( ref( $num ) eq 'AnswerHash' ) ? 1 : 0 ; |
| 3550 | my ($rh_ans); |
3656 | my ($rh_ans); |
| … | |
… | |
| 3576 | } else { |
3682 | } else { |
| 3577 | return $is_an_arithmetic_expression; |
3683 | return $is_an_arithmetic_expression; |
| 3578 | } |
3684 | } |
| 3579 | } |
3685 | } |
| 3580 | |
3686 | |
|
|
3687 | # |
|
|
3688 | |
|
|
3689 | =head4 math_constants |
|
|
3690 | |
| 3581 | #replaces pi, e, and ^ with their Perl equivalents |
3691 | replaces pi, e, and ^ with their Perl equivalents |
|
|
3692 | |
|
|
3693 | =cut |
|
|
3694 | |
| 3582 | sub math_constants { |
3695 | sub math_constants { |
| 3583 | my($in,%options) = @_; |
3696 | my($in,%options) = @_; |
| 3584 | my $rh_ans; |
3697 | my $rh_ans; |
| 3585 | my $process_ans_hash = ( ref( $in ) eq 'AnswerHash' ) ? 1 : 0 ; |
3698 | my $process_ans_hash = ( ref( $in ) eq 'AnswerHash' ) ? 1 : 0 ; |
| 3586 | if ($process_ans_hash) { |
3699 | if ($process_ans_hash) { |
| 3587 | $rh_ans = $in; |
3700 | $rh_ans = $in; |
| 3588 | $in = $rh_ans->{student_ans}; |
3701 | $in = $rh_ans->{student_ans}; |
| 3589 | } |
3702 | } |
| 3590 | |
3703 | # The code fragment above allows this filter to be used when the input is simply a string |
|
|
3704 | # as well as when the input is an AnswerHash, and options. |
| 3591 | $in =~s/\bpi\b/(4*atan2(1,1))/ge; |
3705 | $in =~s/\bpi\b/(4*atan2(1,1))/ge; |
| 3592 | $in =~s/\be\b/(exp(1))/ge; |
3706 | $in =~s/\be\b/(exp(1))/ge; |
| 3593 | $in =~s/\^/**/g; |
3707 | $in =~s/\^/**/g; |
| 3594 | |
3708 | |
| 3595 | if ($process_ans_hash) { |
3709 | if ($process_ans_hash) { |
| … | |
… | |
| 3598 | } else { |
3712 | } else { |
| 3599 | return $in; |
3713 | return $in; |
| 3600 | } |
3714 | } |
| 3601 | } |
3715 | } |
| 3602 | |
3716 | |
| 3603 | sub clean_up_error_msg { |
3717 | =head2 Utility subroutines |
| 3604 | my $msg = $_[0]; |
|
|
| 3605 | $msg =~ s/^\[[^\]]*\][^:]*://; |
|
|
| 3606 | $msg =~ s/Unquoted string//g; |
|
|
| 3607 | $msg =~ s/may\s+clash.*/does not make sense here/; |
|
|
| 3608 | $msg =~ s/\sat.*line [\d]*//g; |
|
|
| 3609 | $msg = 'error: '. $msg; |
|
|
| 3610 | |
|
|
| 3611 | return $msg; |
|
|
| 3612 | } |
|
|
| 3613 | |
|
|
| 3614 | #formats the student and correct answer as specified |
|
|
| 3615 | #format must be of a form suitable for sprintf (e.g. '%0.5g'), |
|
|
| 3616 | #with the exception that a '#' at the end of the string |
|
|
| 3617 | #will cause trailing zeros in the decimal part to be removed |
|
|
| 3618 | sub prfmt { |
|
|
| 3619 | my($number,$format) = @_; # attention, the order of format and number are reversed |
|
|
| 3620 | my $out; |
|
|
| 3621 | if ($format) { |
|
|
| 3622 | warn "Incorrect format used: $format. <BR> Format should look something like %4.5g<BR>" |
|
|
| 3623 | unless $format =~ /^\s*%\d*\.?\d*\w#?\s*$/; |
|
|
| 3624 | |
|
|
| 3625 | if( $format =~ s/#\s*$// ) { # remove trailing zeros in the decimal |
|
|
| 3626 | $out = sprintf( $format, $number ); |
|
|
| 3627 | $out =~ s/(\.\d*?)0+$/$1/; |
|
|
| 3628 | $out =~ s/\.$//; # in case all decimal digits were zero, remove the decimal |
|
|
| 3629 | } |
|
|
| 3630 | else { |
|
|
| 3631 | $out = sprintf( $format, $number ); |
|
|
| 3632 | } |
|
|
| 3633 | $out =~ s/e/E/g; # only use capital E's for exponents. Little e is for 2.71828... |
|
|
| 3634 | } |
|
|
| 3635 | else { |
|
|
| 3636 | $out = $number; |
|
|
| 3637 | $out =~ s/e/E/g; # only use capital E's for exponents. Little e is for 2.71828... |
|
|
| 3638 | |
|
|
| 3639 | } |
|
|
| 3640 | return $out; |
|
|
| 3641 | } |
|
|
| 3642 | |
3718 | |
| 3643 | =head4 |
3719 | =head4 |
| 3644 | |
3720 | |
| 3645 | pretty_print() |
3721 | warn pretty_print( $rh_hash_input) |
| 3646 | |
3722 | |
|
|
3723 | This can be very useful for printing out messages about objects while debugging |
| 3647 | |
3724 | |
| 3648 | =cut |
3725 | =cut |
| 3649 | |
3726 | |
| 3650 | sub pretty_print { |
3727 | sub pretty_print { |
| 3651 | my $r_input = shift; |
3728 | my $r_input = shift; |
| … | |
… | |
| 3672 | $out = $r_input; |
3749 | $out = $r_input; |
| 3673 | } |
3750 | } |
| 3674 | $out; |
3751 | $out; |
| 3675 | } |
3752 | } |
| 3676 | |
3753 | |
| 3677 | # Use this to set default options |
3754 | =head2 Filter utilities |
| 3678 | sub set_default_options { |
3755 | |
| 3679 | my $rh_options = shift; |
3756 | These two subroutines can be used in filters to set default options. They |
| 3680 | warn "The first entry to set_default_options must be a reference to the option hash" unless ref($rh_options) eq 'HASH'; |
3757 | help make filters perform in uniform, predictable ways, and also make it |
| 3681 | my %default_options = @_; |
3758 | easy to recognize from the code which options a given filter expects. |
| 3682 | unless ( defined($default_options{allow_unknown_options}) and $default_options{allow_unknown_options} == 1 ) { |
3759 | |
| 3683 | foreach my $key1 (keys %$rh_options) { |
3760 | |
| 3684 | warn "This option |$key1| is not recognized in this subroutine<br> ", pretty_print($rh_options) unless exists($default_options{$key1}); |
3761 | =head4 assign_option_aliases |
|
|
3762 | |
|
|
3763 | Use this to assign aliases for the standard options. It must come before set_default_options |
|
|
3764 | within the subroutine. |
|
|
3765 | |
|
|
3766 | assign_option_aliases(\%options, |
|
|
3767 | 'alias1' => 'option5' |
|
|
3768 | 'alias2' => 'option7' |
|
|
3769 | ); |
| 3685 | } |
3770 | |
| 3686 | } |
3771 | If the subroutine is called with an option " alias1 => 23 " it will behave as if it had been |
| 3687 | foreach my $key (keys %default_options) { |
3772 | called with the option " option5 => 23 " |
| 3688 | if ( not defined($rh_options->{$key} ) and defined( $default_options{$key} ) ) { |
3773 | |
| 3689 | $rh_options->{$key} = $default_options{$key}; #this allows tol => undef to allow the tol option, but doesn't define |
3774 | =cut |
| 3690 | # this key unless tol is explicitly defined. |
3775 | |
| 3691 | } |
3776 | |
| 3692 | } |
3777 | |
| 3693 | } |
|
|
| 3694 | # Use this to assign aliases for the standard options |
|
|
| 3695 | sub assign_option_aliases { |
3778 | sub assign_option_aliases { |
| 3696 | my $rh_options = shift; |
3779 | my $rh_options = shift; |
| 3697 | warn "The first entry to set_default_options must be a reference to the option hash" unless ref($rh_options) eq 'HASH'; |
3780 | warn "The first entry to set_default_options must be a reference to the option hash" unless ref($rh_options) eq 'HASH'; |
| 3698 | my @option_aliases = @_; |
3781 | my @option_aliases = @_; |
| 3699 | while (@option_aliases) { |
3782 | while (@option_aliases) { |
| … | |
… | |
| 3714 | delete($rh_options->{$alias}); # remove the alias from the initial list |
3797 | delete($rh_options->{$alias}); # remove the alias from the initial list |
| 3715 | } |
3798 | } |
| 3716 | |
3799 | |
| 3717 | } |
3800 | } |
| 3718 | |
3801 | |
|
|
3802 | =head4 set_default_options |
|
|
3803 | |
|
|
3804 | set_default_options(\%options, |
|
|
3805 | '_filter_name' => 'filter', |
|
|
3806 | 'option5' => .0001, |
|
|
3807 | 'option7' => 'ascii', |
|
|
3808 | 'allow_unknown_options => 0, |
|
|
3809 | } |
|
|
3810 | |
|
|
3811 | Note that the first entry is a reference to the options with which the filter was called. |
|
|
3812 | |
|
|
3813 | The option5 is set to .0001 unless the option is explicitly set when the subroutine is called. |
|
|
3814 | |
|
|
3815 | The b<'_filter_name'> option should always be set, although there is no error if it is missing. |
|
|
3816 | It is used mainly for debugging answer evaluators and allows |
|
|
3817 | you to keep track of which filter is currently processing the answer. |
|
|
3818 | |
|
|
3819 | If b<'allow_unknown_options'> is set to 0 then if the filter is called with options which do NOT appear in the |
|
|
3820 | set_default_options list an error will be signaled and a warning message will be printed out. This provides |
|
|
3821 | error checking against misspelling an option and is generally what is desired for most filters. |
|
|
3822 | |
|
|
3823 | Occasionally one wants to write a filter which accepts a long list of options, but only uses a subset of the options |
|
|
3824 | provided. In this case, setting 'allow_unkown_options' prevents the error from being signaled. |
|
|
3825 | |
|
|
3826 | =cut |
|
|
3827 | |
|
|
3828 | sub set_default_options { |
|
|
3829 | my $rh_options = shift; |
|
|
3830 | warn "The first entry to set_default_options must be a reference to the option hash" unless ref($rh_options) eq 'HASH'; |
|
|
3831 | my %default_options = @_; |
|
|
3832 | unless ( defined($default_options{allow_unknown_options}) and $default_options{allow_unknown_options} == 1 ) { |
|
|
3833 | foreach my $key1 (keys %$rh_options) { |
|
|
3834 | warn "This option |$key1| is not recognized in this subroutine<br> ", pretty_print($rh_options) unless exists($default_options{$key1}); |
|
|
3835 | } |
|
|
3836 | } |
|
|
3837 | foreach my $key (keys %default_options) { |
|
|
3838 | if ( not defined($rh_options->{$key} ) and defined( $default_options{$key} ) ) { |
|
|
3839 | $rh_options->{$key} = $default_options{$key}; #this allows tol => undef to allow the tol option, but doesn't define |
|
|
3840 | # this key unless tol is explicitly defined. |
|
|
3841 | } |
|
|
3842 | } |
|
|
3843 | } |
|
|
3844 | |
|
|
3845 | |
| 3719 | |
3846 | |
| 3720 | 1; |
3847 | 1; |