\n",
- );
- $out;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/compositionAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/compositionAnswer.pl
deleted file mode 100755
index 1fad973813..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/compositionAnswer.pl
+++ /dev/null
@@ -1,154 +0,0 @@
-loadMacros('answerUtils.pl');
-
-sub _compositionAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# An answer checker that determines if two functions compose
-# to form a given function. (For use in problems where you ask
-# a student to break a given function into a composition of two
-# simpler functions, neither of which is allowed to be the identity
-# function.)
-#
-
-######################################################################
-#
-# An answer checked to see if f composed with g matches a given function.
-#
-# Usage: COMPOSITION_ANS(f,g,options)
-#
-# where f and g are one possible decomposition of the target function
-# (these are used to display the "correct" answer, and the composition
-# is computed from them) and options are any of the options allowed
-# by composition_ans_list below.
-#
-# This function actually supplies TWO answer checkers, for the two
-# previous answer blanks. So be sure to call it immediately after
-# the answer blanks have been supplied. (It may be best to use the
-# NAMED_COMPOSITION_ANS checker below, which specifies the answer
-# blanks explicitly.)
-#
-# Example:
-#
-# BEGIN_TEXT
-# \(f\circ g = (1+x)^2\) when
-# \(f(x)\) = \{ans_rule(20)\} and \(g(x)\) = \{ans_rule(20)\}
-# END_TEXT
-# COMPOSITION_ANS("x^2","1+x");
-#
-#
-sub COMPOSITION_ANS {
- my $f = shift; my $g = shift;
- my $fID = ANS_NUM_TO_NAME($main::ans_rule_count-1);
- my $gID = ANS_NUM_TO_NAME($main::ans_rule_count);
- my %ans = composition_ans_list($fID=>$f,$gID=>$g,@_);
- ANS(values(%ans));
-}
-
-
-######################################################################
-#
-# An answer checked to see if f composed with g matches a given function.
-#
-# Usage: NAMED_COMPOSITION_ANS(fID=>f,gID->g,options)
-#
-# where fID and gID are the names of the answer rules for the functions
-# f and g, and f and g are the answers for the functions. Options are
-# any of the options allowed by composition_ans_list below.
-#
-# This routine allows you to put the f and g answer blanks at any
-# location in the problem, and in any order.
-#
-# Example:
-#
-# BEGIN_TEXT
-# \(g\circ f = (1+x)^2\) when
-# \(f(x)\) = \{NAMED_ANS('f',20)\} and \(g(x)\) = \{NAMED_ANS('g',20)\}
-# END_TEXT
-# NAMED_COMPOSITION_ANS(f => "x^2", g => "1+x");
-
-sub NAMED_COMPOSITION_ANS {NAMED_ANS(composition_ans_list(@_))}
-
-
-######################################################################
-#
-# This is an internal routine that returns the named answer checkers
-# used by COMPOSITION_ANS and NAMED_COMPOSITION_ANS above.
-#
-# Usage: composition_ans_list(fID=>f,gID=>g,options)
-#
-# where fID and gID are the names of the answer rules for the functions
-# and f and g are the answers for these functions. Options are from
-# among:
-#
-# var => 'x' the name of the variable to use (both
-# functions use the same variable -- this
-# should probably be improved).
-#
-# or any parameters that can be passed to fun_cmp.
-#
-sub composition_ans_list {
- my ($fID,$f,$gID,$g,%params) = @_;
- my ($i,$ident,$comp,$eval,$field,$fog,$student_ans);
- my @IDs = ($fID,$gID);
- my @cmp = (composition_cmp($f),composition_cmp($g));
- my @ans = ($fID => $cmp[0], $gID => $cmp[1]);
- my $error = 0;
- my $var = "x"; $var = $params{'var'} if (defined($params{'var'}));
-
- #
- # Check that the answers exist (otherwise it's our first time through)
- #
- foreach $i (@IDs) {return(@ans) if (!defined($inputs_ref->{$i}))}
-
- $ident = fun_cmp($var,%params);
- foreach $i (0,1) {
- $eval = evaluateAnswer($ident,$inputs_ref->{$IDs[$i]});
- if ($eval->{ans_message} ne "") {$error = 1}
- elsif ($eval->{score} == 1) {
- $eval->{ans_message} = "The identity function is not allowed";
- $error = 1; $eval->{score} = 0;
- }
- foreach $field ('ans_message','error_message','preview_latex_string',
- 'preview_text_string','student_ans') {
- $cmp[$i]->rh_ans->{$field} = $eval->{$field}; $eval->{$field} = "";
- }
- }
-
- if (!$error) {
- $fog = $f; $fog =~ s/$var/($g)/g;
- $student_ans = $inputs_ref->{$fID};
- $student_ans =~ s/$var/($inputs_ref->{$gID})/g;
- if (isCorrectAnswer(fun_cmp($fog,%params),$student_ans)) {
- $cmp[0]->rh_ans->{score} = $cmp[1]->rh_ans->{score} = 1;
- }
- }
- return (@ans);
-}
-
-
-######################################################################
-#
-# Evaluator that always returns correct or always returns incorrect,
-# depending on the parameter passed to it. Used by COMPOSITION_ANS
-# to produce "dummy" answer checkers for the two parts of the
-# composition.
-#
-sub composition_cmp {
- my $score = shift;
- my %params = @_;
- $params{debug} = 0 unless defined($params{debug});
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(type => "composition", correct_ans => $score);
- $answerEvaluator->install_evaluator(\&composition_cmp_check,%params);
- return $answerEvaluator;
-}
-
-sub composition_cmp_check {
- my $ans = shift;
- my %params = @_;
- return($ans);
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/compoundProblem.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/compoundProblem.pl
deleted file mode 100755
index 3538bfef48..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/compoundProblem.pl
+++ /dev/null
@@ -1,617 +0,0 @@
-sub _compoundProblem_init {}; # don't reload this file
-
-#####################################################################
-#
-# This package implements a method of handling multi-part problems
-# that show only a single part at any one time. The students can
-# work on one part at a time, and then when they get it right (or
-# under other circumstances deterimed by the professor), they can
-# move on to the next part. Students can not return to earlier parts
-# once they have been completed. The score for problem as a whole is
-# made up from the scores on the individual parts, and the relative
-# weighting of the various parts can be specified by the problem
-# author.
-#
-# To use the compoundProblem library, use
-#
-# loadMacros("compoundProblem.pl");
-#
-# at the top of your file, and then create a compoundProblem object
-# via the command
-#
-# $cp = new compoundProblem(options)
-#
-# where '$cp' is the name of a variable that you will use to
-# refer to the compound problem, and 'options' can include:
-#
-# parts => n The number of parts in the problem.
-# Default: 1
-#
-# weights => [n1,...,nm] The relative weights to give to each
-# part in the problem. For example,
-# weights => [2,1,1]
-# would cause the first part to be worth 50%
-# of the points (twice the amount for each of
-# the other two), while the second and third
-# part would be worth 25% each. If weights
-# are not supplied, the parts are weighted
-# by the number of answer blanks in each part
-# (and you must provide the total number of
-# blanks in all the parts by supplying the
-# totalAnswers option).
-#
-# totalAnswers => n The total number of answer blanks in all
-# the parts put together (this is used when
-# computing the per-part scores, if part
-# weights are not provided).
-#
-# saveAllAnswers => 0 or 1 Usually, the contents of named answer blanks
-# from previous parts are made available to
-# later parts using variables with the
-# same name as the answer blank. Setting
-# saveAllAnswers to 1 will cause ALL answer
-# blanks to be available (via variables
-# like $AnSwEr1, and so on).
-# Default: 0
-#
-# parserValues => 0 or 1 Determines whether the answers from previous
-# parts are returned as MathObjects (like
-# those returned from Real(), Vector(), etc)
-# or as strings (the unparsed contents of the
-# student answer). If you intend to use the
-# previous answers as numbers, for example,
-# you would want to set this to 1 so that you
-# would get the final result of any formula
-# the student typed, rather than the formula
-# itself as a character string.
-# Default: 0
-#
-# nextVisible => type Tells when the "go on to the next part" option
-# is available to the student. The possible
-# types include:
-#
-# 'ifCorrect' next is available only when
-# all the answers are correct.
-#
-# 'Always' next is always available
-# (but remember that students
-# can't go back once they go
-# on.)
-#
-# 'Never' next is never allowed (the
-# problem will control going
-# on to the next part itself).
-#
-# Default: 'ifCorrect'
-#
-# nextStyle => type Determines the style of "next" indicator to display
-# (when it is available). The type can be one of:
-#
-# 'CheckBox' a checkbox that allows the students
-# to go on to the next part when they
-# submit their answers.
-#
-# 'Button' a button that submits their answers
-# and goes on to the next part.
-#
-# 'Forced' forces the student to go on to the
-# next part the next time they submit
-# answers.
-#
-# 'HTML' allows you to provide an arbitrary
-# HTML string of your own.
-#
-# Default: 'Checkbox'
-#
-# nextLabel => string Specifies the string to use as the label for the checkbox,
-# the name of the button, the text of the message indicating
-# that the next submit will move to the next part, or the
-# HTML string, depending on the setting of nextStyle above.
-#
-# nextNoChange => 0 or 1 Since the students must submit their answers again to go on
-# to the next part, it is possible for them to change their
-# answers before they submit, and if nextVisible is 'ifCorrect'
-# they might go on to the next without having correct answers
-# stored. This option lets you control whether the answers
-# are checked against the previous ones before going on to the
-# next part. If the answers don't match, a warning is issued
-# and they are not allowed to move on.
-# Default: 1
-#
-# allowReset => 0 or 1 Determines whether a "Go back to the first part" checkbox
-# is provided on parts 2 and later. This is intended for
-# the professor during testing of the problem (otherwise
-# it would be impossible to go back to earlier parts).
-# Default: 0
-#
-# resetLabel => string The string used to label the reset checkbox.
-#
-# Once you have created a compoundProblem object, you can use $cp->part to
-# determine the part that the student is working on, and use 'if' statements
-# to display the proper information for the given part. The compoundProblem
-# object takes care of maintaining the data as the parts change. (See the
-# compoundProblem.pg file for an example of a compound problem.)
-#
-# In order to handle the scoring of the problem as a whole when only part is
-# showing, the compoundProblem object uses its own problem grader to manage
-# the scores, and calls your own grader from there. The default is to use
-# the one that was installed before the compoundProblem object was created,
-# or avg_problem_grader if none was installed. You can specify a different
-# one using the $cp->useGrader() method (see below). It is important that
-# you NOT call install_problem_grader() yourself once you have created the
-# compoundProblem object, as that would disable the special grader, causing
-# the compound problem to fail to work properly.
-#
-# You may call the following methods once you have a compoundProblem:
-#
-# $cp->part Returns the part the student is working on.
-# $cp->part(n) Sets the part to be part n, as long as the
-# student has finished the preceeding parts.
-# If not, the part is set to the highest
-# one the student hasn't completed, and he
-# can work up to the given part. (The
-# nextVisible option is set to 'ifCorrect' if
-# it was 'Never' so that students can go on
-# once they finish the earlier parts.)
-#
-# $cp->useGrader(code_ref) Supplies your own grader to use in
-# place of the default one. For example:
-# $cp->useGrader(~~&std_problem_grader);
-#
-# $cp->score Returns the (weighted) score for this part.
-# Note that this is the score shown at the bottom
-# of the page on which the student pressed submit
-# (not the score for the answers the student is
-# submitting -- that is not available until
-# after the body of the problem has been created).
-#
-# $cp->scoreRaw Returns the unweighted score for this part.
-#
-# $cp->scoreOverall Returns the overall score for the problem
-# so far.
-#
-# $cp->addAnswers(list) Make additional answer blanks be available
-# from one part to another. E.g.,
-# $cp->addAnswers('AnSwEr1');
-# would make the first unnamed blank be available
-# in later parts as well. (This command should
-# be issued only when the part containing the
-# given answer blank is displayed.)
-#
-# $cp->nextCheckbox(label) Returns the HTML string for the "go on to next
-# part" checkbox so you can use it in the body of
-# the problem if you wish. This should not be
-# inserted when the $displayMode is 'TeX'. If the
-# label is not given or is blank, the default label
-# is used.
-#
-# $cp->nextButton(label) Returns the HTML string for the "go on to next
-# part" button so you can use it in the body of
-# the problem if you wish. This should not be
-# inserted when the $displayMode is 'TeX'. If the
-# label is not given or is blank, the default label
-# is used.
-#
-# $cp->nextForces(label) Returns the HTML string for the forced "go on to
-# next part" so you can use it in the body of
-# the problem if you wish. This should not be
-# inserted when the $displayMode is 'TeX'. If the
-# label is not given or is blank, the default label
-# is used.
-#
-# $cp->reset Go back to part 1, clearing the answers
-# and score. (Best used when debugging problems.)
-#
-# $cp->resetCheckbox(label) Returns the HTML string for the reset checkbox
-# so that you can provide one within the body
-# of the problem if you wish. This should not be
-# inserted when the $displayMode is 'TeX'. If the
-# label is not given or is blank, the default label
-# will be used.
-#
-######################################################################
-
-package compoundProblem;
-#
-# The state data that is stored between invocations of
-# the problem.
-#
-our %defaultStatus = (
- part => 1, # the current part
- answers => "", # answer labels from previous parts
- new_answers => "", # answer labels for THIS part
- ans_rule_count => 0, # the ans_rule count from previous parts
- new_ans_rule_count => 0, # the ans_rule count from THIS part
- score => 0, # the (weighted) score on this part
- total => 0, # the total on previous parts
- raw => 0, # raw score on this part
-);
-#
-# Create a new instance of the compound Problem and initialize
-# it. This includes reading the status from the previous
-# parts, defining the variables from the answers to previous parts,
-# and setting up the grader so that the current data can be saved.
-#
-
-sub new {
- my $self = shift; my $class = ref($self) || $self;
- my $cp = bless {
- parts => 1,
- totalAnswers => undef,
- weights => undef, # array of weights per part
- saveAllAnswers => 0, # usually only save named answers
- parserValues => 0, # make Parser objects from the answers?
- nextVisible => "ifCorrect", # or "Always" or "Never"
- nextStyle => "Checkbox", # or "Button", "Forced", or "HTML"
- nextLabel => undef, # Checkbox text or button name or HTML
- nextNoChange => 1, # true if answer can't change for new part
- allowReset => 0, # true to show "back to part 1" button
- resetLabel => undef, # label for reset button
- grader => $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} || \&main::avg_problem_grader,
- @_,
- status => $defaultStatus,
- }, $class;
- die "You must provide either the totalAnswers or weights"
- unless $cp->{totalAnswers} || $cp->{weights};
- $cp->getTotalWeight if $cp->{weights};
- main::loadMacros("Parser.pl") if $cp->{parserValues};
- $cp->reset if $cp->{allowReset} && $main::inputs_ref->{_reset};
- $cp->getStatus;
- $cp->initPart;
- return $cp;
-}
-
-#
-# Compute the total of the weights so that the parts can
-# be properly scaled.
-#
-sub getTotalWeight {
- my $self = shift;
- $self->{totalWeight} = 0; $self->{totalAnswers} = 1;
- foreach my $w (@{$self->{weights}}) {$self->{totalWeight} += $w}
- $self->{totalWeight} = 1 if $self->{totalWeight} == 0;
-}
-
-#
-# Look up the status from the previous invocation
-# and see if we need to go on to the next part.
-#
-sub getStatus {
- my $self = shift;
- main::RECORD_FORM_LABEL("_next");
- main::RECORD_FORM_LABEL("_status");
- $self->{status} = $self->decode;
- $self->{isNew} = $main::inputs_ref->{_next} || ($main::inputs_ref->{submitAnswers} &&
- $main::inputs_ref->{submitAnswers} eq ($self->{nextLabel} || "Go on to Next Part"));
- if ($self->{isNew}) {
- $self->checkAnswers;
- $self->incrementPart unless $self->{nextNoChange} && $self->{answersChanged};
- }
-}
-
-#
-# Initialize the current part by setting the ans_rule
-# count (so that later parts will get unique answer names),
-# installing the grader (to save the data), and setting
-# the variables for previous answers.
-#
-sub initPart {
- my $self = shift;
- $main::ans_rule_count = $self->{status}{ans_rule_count};
- main::install_problem_grader(\&compoundProblem::grader);
- $main::PG_FLAGS{compoundProblem} = $self;
- $self->initAnswers($self->{status}{answers});
-}
-
-#
-# Look through the list of answer labels and set
-# the variables for them to be the associated student
-# answer. Make it a Parser value if requested.
-# Record the value so that is will be available
-# again on the next invocation.
-#
-sub initAnswers {
- my $self = shift; my $answers = shift;
- foreach my $id (split(/;/,$answers)) {
- my $value = $main::inputs_ref->{$id}; $value = '' unless defined($value);
- if ($self->{parserValues}) {
- my $parser = Parser::Formula($value);
- $parser = Parser::Evaluate($parser) if $parser && $parser->isConstant;
- $value = $parser if $parser;
- }
- ${"main::$id"} = $value unless $id =~ m/$main::ANSWER_PREFIX/o;
- $value = quoteHTML($value);
- main::TEXT(qq!!);
- main::RECORD_FORM_LABEL($id);
- }
-}
-
-#
-# Look to see is any answers have changed on this
-# invocation of the problem.
-#
-sub checkAnswers {
- my $self = shift;
- foreach my $id (keys(%{$main::inputs_ref})) {
- if ($id =~ m/^previous_(.*)$/) {
- if ($main::inputs_ref->{$id} ne $main::inputs_ref->{$1}) {
- $self->{answersChanged} = 1;
- $self->{isNew} = 0 if $self->{nextNoChange};
- return;
- }
- }
- }
-}
-
-#
-# Go on to the next part, updating the status
-# to include the data from the old part so that
-# it will be properly preserved when the next
-# part is showing.
-#
-sub incrementPart {
- my $self = shift;
- my $status = $self->{status};
- if ($status->{part} < $self->{parts}) {
- $status->{part}++;
- $status->{answers} .= ';' if $status->{answers};
- $status->{answers} .= $status->{new_answers};
- $status->{ans_rule_count} = $status->{new_ans_rule_count};
- $status->{total} += $status->{score};
- $status->{score} = $status->{raw} = 0;
- $status->{new_answers} = '';
- }
-}
-
-######################################################################
-#
-# Encode all the status information so that it can be
-# maintained as the student submits answers. Since this
-# state information includes things like the score from
-# the previous parts, it is "encrypted" using a dumb
-# hex encoding (making it harder for a student to recognize
-# it as valuable data if they view the page source).
-#
-sub encode {
- my $self = shift; my $status = shift || $self->{status};
- my @data = (); my $data = "";
- foreach my $id (main::lex_sort(keys(%defaultStatus))) {push(@data,$status->{$id})}
- foreach my $c (split(//,join('|',@data))) {$data .= toHex($c)}
- return $data;
-}
-
-#
-# Decode the data and break it into the status hash.
-#
-sub decode {
- my $self = shift; my $status = shift || $main::inputs_ref->{_status};
- return {%defaultStatus} unless $status;
- my @data = (); foreach my $hex (split(/(..)/,$status)) {push(@data,fromHex($hex)) if $hex ne ''}
- @data = split('\\|',join('',@data)); $status = {%defaultStatus};
- foreach my $id (main::lex_sort(keys(%defaultStatus))) {$status->{$id} = shift(@data)}
- return $status;
-}
-
-#
-# Hex encoding is shifted by 10 to obfuscate it further.
-# (shouldn't be a problem since the status will be made of
-# printable characters, so they are all above ASCII 32)
-#
-sub toHex {main::spf(ord(shift)-10,"%X")}
-sub fromHex {main::spf(hex(shift)+10,"%c")}
-
-#
-# Make sure the data can be properly preserved within
-# an HTML tag.
-#
-sub quoteHTML {
- my $string = shift;
- $string =~ s/&/\&/g; $string =~ s/"/\"/g;
- $string =~ s/>/\>/g; $string =~ s/\</g;
- return $string;
-}
-
-######################################################################
-#
-# Set the grader for this part to the specified one.
-#
-sub useGrader {
- my $self = shift;
- $self->{grader} = shift;
-}
-
-#
-# Make additional answer blanks from the current part
-# be preserved for use in future parts.
-#
-sub addAnswers {
- my $self = shift;
- $self->{extraAnswers} = [] unless $self->{extraAnswers};
- push(@{$self->{extraAnswers}},@_);
-}
-
-#
-# Go back to part 1 and clear the answers and scores.
-#
-sub reset {
- my $self = shift;
- if ($main::inputs_ref->{_status}) {
- my $status = $self->decode($main::inputs_ref->{_status});
- foreach my $id (split(/;/,$status->{answers})) {delete $main::inputs_ref->{$id}}
- foreach my $id (1..$status->{ans_rule_count})
- {delete $main::inputs_ref->{"${main::QUIZ_PREFIX}${main::ANSWER_PREFIX}$id"}}
- }
- $main::inputs_ref->{_status} = $self->encode(\%defaultStatus);
- $main::inputs_ref->{_next} = 0;
-}
-
-#
-# Return the HTML for the "Go back to part 1" checkbox.
-#
-sub resetCheckbox {
- my $self = shift;
- my $label = shift || " Go back to Part 1 (when you submit your answers).";
- my $par = shift; $par = ($par ? $main::PAR : '');
- qq'$par$label';
-}
-
-#
-# Return the HTML for the "next part" checkbox.
-#
-sub nextCheckbox {
- my $self = shift;
- my $label = shift || " Go on to next part (when you submit your answers).";
- my $par = shift; $par = ($par ? $main::PAR : '');
- $self->{nextInserted} = 1;
- qq!$par$label!;
-}
-
-#
-# Return the HTML for the "next part" button.
-#
-sub nextButton {
- my $self = shift;
- my $label = quoteHTML(shift || "Go on to Next Part");
- my $par = shift; $par = ($par ? $main::PAR : '');
- $par . qq!!;
-}
-
-#
-# Return the HTML for when going to the next part is forced.
-#
-sub nextForced {
- my $self = shift;
- my $label = shift || "Submit your answers again to go on to the next part.";
- $label = $main::PAR . $label if shift;
- $self->{nextInserted} = 1;
- qq!$label!;
-}
-
-#
-# Return the raw HTML provided
-#
-sub nextHTML {shift; shift}
-
-######################################################################
-#
-# Return the current part, or try to set the part to the given
-# part (returns the part actually set, which may be earlier if
-# the student didn't complete an earlier part).
-#
-sub part {
- my $self = shift; my $status = $self->{status};
- my $part = shift;
- return $status->{part} unless defined $part && $main::displayMode ne 'TeX';
- $part = 1 if $part < 1; $part = $self->{parts} if $part > $self->{parts};
- if ($part > $status->{part} && !$main::inputs_ref->{_noadvance}) {
- unless ((lc($self->{nextVisible}) eq 'ifcorrect' && $status->{raw} < 1) ||
- lc($self->{nextVisible}) eq 'never') {
- $self->initAnswers($status->{new_answers});
- $self->incrementPart; $self->{isNew} = 1;
- }
- }
- if ($part != $status->{part}) {
- main::TEXT('');
- $self->{nextVisible} = 'IfCorrect' if lc($self->{nextVisible}) eq 'never';
- }
- return $status->{part};
-}
-
-#
-# Return the various scores
-#
-sub score {shift->{status}{score}}
-sub scoreRaw {shift->{status}{raw}}
-sub scoreOverall {
- my $self = shift;
- return $self->{status}{score} + $self->{status}{total};
-}
-
-######################################################################
-#
-# The custom grader that does the work of computing the scores
-# and saving the data.
-#
-sub grader {
- my $self = $main::PG_FLAGS{compoundProblem};
-
- #
- # Get the answer names and the weight for the current part.
- #
- my @answers = keys(%{$_[0]});
- my $weight = scalar(@answers)/$self->{totalAnswers};
- $weight = $self->{weights}[$self->{status}{part}-1]/$self->{totalWeight}
- if $self->{weights} && defined($self->{weights}[$self->{status}{part}-1]);
- @answers = grep(!/$main::ANSWER_PREFIX/o,@answers) unless $self->{saveAllAnswers};
- push(@answers,@{$self->{extraAnswers}}) if $self->{extraAnswers};
- my $space = '';
-
- #
- # Call the original grader, but put back the old recorded_score
- # (the grader will have updated it based on the score for the PART,
- # not the problem as a whole).
- #
- my $oldScore = ($_[1])->{recorded_score};
- my ($result,$state) = &{$self->{grader}}(@_);
- $state->{recorded_score} = $oldScore;
-
- #
- # Update that state information and encode it.
- #
- my $status = $self->{status};
- $status->{raw} = $result->{score};
- $status->{score} = $result->{score}*$weight;
- $status->{new_ans_rule_count} = $main::ans_rule_count;
- $status->{new_answers} = join(';',@answers);
- my $data = quoteHTML($self->encode);
-
- #
- # Update the recorded score
- #
- my $newScore = $status->{total} + $status->{score};
- $state->{recorded_score} = $newScore if $newScore > $oldScore;
- $state->{recorded_score} = 0 if $self->{allowReset} && $main::inputs_ref->{_reset};
-
- #
- # Add the compoundProblem message and data
- #
- $result->{type} = "compoundProblem ($result->{type})";
- $result->{msg} .= '
Note:' if $result->{msg};
- $result->{msg} .= 'This problem has more than one part.'
- . ' '.$space.'Your score for this attempt is for this part only;'
- . ' '.$space.'your overall score is for all the parts combined.'
- . qq!!;
-
- #
- # Warn if the answers changed when they shouldn't have
- #
- $result->{msg} .= '
You may not change your answers when going on to the next part!'
- if $self->{nextNoChange} && $self->{answersChanged};
-
- #
- # Include the "next part" checkbox, button, or whatever.
- #
- my $par = 1;
- if ($self->{parts} > $status->{part} && !$main::inputs_ref->{previewAnswers}) {
- if (lc($self->{nextVisible}) eq 'always' ||
- (lc($self->{nextVisible}) eq 'ifcorrect' && $result->{score} >= 1)) {
- my $method = "next".$self->{nextStyle}; $par = 0;
- $result->{msg} .= $self->$method($self->{nextLabel},1).' ';
- }
- }
-
- #
- # Add the reset checkbox, if needed
- #
- $result->{msg} .= $self->resetCheckbox($self->{resetLabel},$par)
- if $self->{allowReset} && $status->{part} > 1;
-
- #
- # Make sure we don't go on unless the next button really is checked
- #
- $result->{msg} .= ''
- unless $self->{nextInserted};
-
- return ($result,$state);
-}
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/contextFunctionAssign.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/contextFunctionAssign.pl
deleted file mode 100755
index 6a7dfcc54e..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/contextFunctionAssign.pl
+++ /dev/null
@@ -1,20 +0,0 @@
-######################################################################
-#Description: macro to load parserAssignment and change the error
-# message to be more specific for a function. Requires
-# answers be submitted in the form:
-# y=formula or f(x)=formula
-######################################################################
-loadMacros("parserAssignment.pl");
-
- sub parser::Assignment::Formula::cmp_equal {
- my $self = shift; my $ans = shift;
- Value::cmp_equal($self,$ans);
- if ($ans->{ans_message} =~ m/Your answer isn't.*it looks like/s) {
- $ans->{ans_message} =
- "Warning: Your answer should be of the form: '".$self->{tree}{lop}->string."= formula'";
- }
- }
-
-######################################################################
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/contextInequalitiesAllowStrings.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/contextInequalitiesAllowStrings.pl
deleted file mode 100755
index 40fc80351d..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/contextInequalitiesAllowStrings.pl
+++ /dev/null
@@ -1,55 +0,0 @@
-###
-
-=head1 NAME
-
- extra macros for Intermediate Algebra problems at CofI
-
-=head1 Synposis
- macros by R Cruz -- The College of Idaho
-=cut
-
-=head3 Allows string answers for the set of real numbers and the empty set
-
-=pod
- Adds the string "All real numbers" to the Inequalities context
- NOT WORKING: Adds the string "No solution" to the Inequalities context
-
-=cut
-
-loadMacros("contextInequalities.pl");
-
-sub _contextInequalitiesAllowStrings_init {
- my $context = $main::context{"Inequalities-AllowStrings"} =
- Parser::Context->getCopy("Inequalities");
-
- $context->constants->{namePattern} = qr/.*/;
-
-#----Add variations of "All real numbers"
-
- $context->constants->redefine("All real numbers",from=>"Interval",using=>"R");
- $context->constants->set("All real numbers"=>{TeX=>"\\mbox{All real numbers}"});
-
- $context->constants->redefine("all real numbers",from=>"Interval",using=>"R");
- $context->constants->set("all real numbers"=>{TeX=>"\\mbox{all real numbers}"});
-
- $context->constants->redefine("All Real numbers",from=>"Interval",using=>"R");
- $context->constants->set("All Real numbers"=>{TeX=>"\\mbox{All Real numbers}"});
-
- $context->constants->redefine("ALL REAL NUMBERS",from=>"Interval",using=>"R");
- $context->constants->set("ALL REAL NUMBERS"=>{TeX=>"\\mbox{ALL REAL NUMBERS}"});
-
-#-----Add variations of "No solution" = NONE
-#************This part does not work. Can't get it to "take" the empty set
-# Tried Set(), NONE and DNE
-#
-# $context->constants->redefine("No solution"",from=>"Interval",using=>"{}");
-# $context->constants->set("No solution"=>{TeX=>"\\mbox{No solution}"});
-#
-# $context->constants->redefine("no solution"",from=>"Interval",using=>"{}");
-# $context->constants->set("no solution"=>{TeX=>"\\mbox{no solution}"});
-#
-# $context->constants->redefine("NO SOLUTION"",from=>"Interval",using=>"{}");
-# $context->constants->set("NO SOLUTION"=>{TeX=>"\\mbox{NO SOLUTION}"});
-
- }
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/courseHeaders.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/courseHeaders.pl
deleted file mode 100755
index 164f683961..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/courseHeaders.pl
+++ /dev/null
@@ -1,193 +0,0 @@
-#!/usr/local/bin/perl
-
-sub _courseHeaders_init {
-#
-# This is the hint to display in screen headers. You can change this
-# in the specific header .pg file for a problem set, provided you do so
-# after the call to loadMacros that loads this file.
-#
-
-$HINT =
- "Give 4 or 5 significant digits when entering decimal numbers. ".
- "For most problems, you can enter elementary expressions such as ".
- "${BTT}2^3${ETT} instead of ${BTT}8${ETT}, ${BTT}sin(3pi/2)${ETT} ".
- "instead of ${BTT}-1${ETT}, ${BTT}e^(ln(2))${ETT} instead of ${BTT}2${ETT}, ".
- "${BTT}(2+tan(3))*(4-sin(5))^6-7/8${ETT} instead of ${BTT}27620.3413${ETT}, ".
- "etc. Consult WeBWorK's ".
- htmlLink('http://webwork.math.rochester.edu/webwork_system_html/docs/docs/pglanguage/availablefunctions.html','list of functions').
- " or review the problems in the orientation homework set for more ".
- "information on the functions and values that WeBWorK understands.";
-
-};
-
-######################################################################
-#
-# This file implements a standard format for the screen and paper
-# headers. The same file works for both, so there is no need to
-# make duplicate files. See courseHeader() below for details.
-#
-
-loadMacros(
- "PG.pl",
- "PGbasicmacros.pl",
- "PGunion.pl"
-);
-
-#
-# Get the course name from the course ID
-#
-$course = $courseName;
-$course =~ s/\d\d(FA|WI|SP|SU)-//; # Union-sepcific
-$course =~ s/-.*//; # Union-specific
-$course = protect_underbar($course); # just in case
-
-#
-# Set some variables to use in headers
-#
-$dateTime = $formatedDueDate;
-$sectionNumber = protect_underbar($sectionNumber);
-$setNumber = protect_underbar($setNumber);
-
-#
-# Evaluate the string as in PG, then trim white space from the ends
-#
-sub EV_trim {
- my $string = EV2(@_);
- $string =~ s/(^\s+|\s+$)//g;
- return $string;
-}
-
-#
-# Get a number sign in all modes
-#
-$NUMBER = MODES(TeX => '\#', HTML => '#');
-
-#
-# couseHeader creates the header based on values passed to it.
-# It works for both screen and paper headers, so you only need
-# one header file. The options you can pass it are:
-#
-# topic => '...' a short string to be used in
-# "this is an assignment on ..."
-#
-# preposition => 'on'
-# what word to use before the topic
-#
-# bookinfo => '...' the section of the book to refer to for more
-# information.
-#
-# bookprobs => ['...','...',]
-# a list of strings giving problems from
-# various sections of the book. As many
-# strings can be supplied as you want.
-# They will be placed on separate lines in
-# the screen header, but on one line in the PDF
-# file. If left empty, the word "none" will be
-# supplied automatically. If set to undef,
-# no book problems will be given.
-#
-# moreprobs => ['...','...',]
-# a list of strings giving problems from
-# various sections of the book. (See bookprobs
-# for details of how this works.)
-#
-# text => '...' This is additional text to be inserted
-# after the book assignment. It can explain
-# more about the problems, give hints, etc.
-#
-# showhint => 0 or 1 Indicates whether the message about typing
-# webwork answers should be shown in the screen
-# header. It defaults to 1 (yes).
-# You can change the variable $HINT to be
-# a different hint, if you want. Be sure
-# to do this AFTER the loadMacros call.
-#
-#
-sub courseHeader {
- my %ops = (
- topic => "",
- preposition => "on",
- bookinfo => "",
- bookprobs => [],
- moreprobs => undef,
- text => "",
- showhint => 1,
-
- topic_text => 'This is a collection of WeBWorK problems ',
- bookinfo_text => 'Relevant information can be found in %s of your text.',
- bookprobs_text => 'Book problems to do as part of this assignment:',
- moreprobs_text => 'Additional problems to do with this assignment:',
- @_
- );
-
- if ($displayMode =~ m/^HTML/ || $displayMode eq "Latex2HTML") {
-# TEXT($BBLOCKQUOTE);
- TEXT(EV_trim($ops{topic_text}.$ops{preposition}.' '.$ops{topic}).".\n")
- if (defined($ops{topic}) && $ops{topic} ne "");
- TEXT(sprintf($ops{bookinfo_text},$ops{bookinfo}))
- if (defined($ops{bookinfo}) && $ops{bookinfo} ne "");
- TEXT($BR,$PAR,"\n\n");
- if (ref($ops{bookprobs}) eq "ARRAY") {
- TEXT($ops{bookprobs_text}."\n");
- if (scalar(@{$ops{bookprobs}}) == 0) {TEXT("none.\n\n")} else {
- TEXT(
- $BBLOCKQUOTE,
- EV_trim(join($BR."\n",@{$ops{bookprobs}})),
- $EBLOCKQUOTE,"\n"
- );
- }
- TEXT($PAR,"\n\n");
- }
- if (ref($ops{moreprobs}) eq "ARRAY") {
- TEXT($ops{moreprobs_text}."\n");
- if (scalar(@{$ops{moreprobs}}) == 0) {TEXT("none.\n\n")} else {
- TEXT(
- $BBLOCKQUOTE,
- EV_trim(join($BR."\n",@{$ops{moreprobs}})),
- $EBLOCKQUOTE,"\n"
- );
- }
- }
- TEXT($HR,$PAR,EV_trim($ops{text})) if ($ops{text} ne "");
- TEXT($HR,$PAR."\n\n",$BSMALL.$HINT.$ESMALL."\n\n",$PAR)
- if ($ops{showhint});
-# TEXT($EBLOCKQUOTE);
- } elsif ($displayMode eq "TeX") {
- TEXT(
- $BEGIN_ONE_COLUMN,
- '{\parindent=0pt \parskip=4pt',"\n",
- '{\large\bf '.$studentName.'\hfill '.$course.' '.$sectionNumber.'}',
- '\break\null\hfill '.
- "WeBWorK assignment $setNumber due $dateTime".'\par'."\n",
- );
- TEXT(EV_trim($ops{topic_text}.$ops{preposition}.' '.$ops{topic}).".\n")
- if (defined($ops{topic}) && $ops{topic} ne "");
- TEXT(sprintf($ops{bookinfo_text},$ops{bookinfo}))
- if (defined($ops{bookinfo}) && $ops{bookinfo} ne "");
- TEXT('\par',"\n\n");
- if (ref($ops{bookprobs}) eq "ARRAY") {
- TEXT($ops{bookprobs_text}.' ');
- if (scalar(@{$ops{bookprobs}}) == 0) {TEXT("none.\\par\n\n")} else {
- TEXT(
- EV_trim(join("; ",@{$ops{bookprobs}})).
- '.\par'."\n\n"
- );
- }
- }
- if (ref($ops{moreprobs}) eq "ARRAY") {
- TEXT($ops{moreprobs_text}.' ');
- if (scalar(@{$ops{moreprobs}}) == 0) {TEXT("none.\\par\n\n")} else {
- TEXT(
- EV_trim(join("; ",@{$ops{moreprobs}})).
- '.\par'."\n\n"
- );
- }
- }
- TEXT(EV_trim($ops{text}).'\par'."\n\n") if ($ops{text} ne "");
- TEXT('\par}',$END_ONE_COLUMN);
- } else {
- warn "courseHeader: Unknown display mode: $displayMode"
- }
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/diffquotientAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/diffquotientAnswer.pl
deleted file mode 100755
index 21d246d8dd..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/diffquotientAnswer.pl
+++ /dev/null
@@ -1,119 +0,0 @@
-loadMacros('answerUtils.pl');
-
-sub _diffquotientAnswer_init {}; # don't reload this file
-
-#########################################################################
-##
-## An answer checker for handling difference quotients. It requires
-## that the student simplify the equation (at least far enough to
-## cancel the dx in the bottom).
-##
-
-
-#########################################################################
-#
-# Usage: diff_quotient_cmp(ans,options)
-#
-# where ans is the correct difference quotient, and options are
-# from among:
-#
-# var => 'x' specifies the variable for the difference quotient
-#
-# limits => [a,b] gives the lower and upper limits of the domain
-# to use for checking the student's response.
-#
-# or any of the parameters that can be passed to fun_cmp().
-#
-# This checker checks that the student answer is the correct difference
-# and that it doesn't contain dx in the denominator (i.e., they will
-# have had to simplify it at least far enough to cancel the dx).
-#
-# The checker accepts 'dx' or 'H' as the difference in the x variable.
-# (This is a bit of a hack, and there is a chance that the student could
-# receive odd error messages because it it.)
-#
-# Example:
-#
-# BEGIN_TEXT
-# Find the simplified difference quotient for \(f(x)=x^2\):
-# \{ans_rule(30)\}.
-# END_TEXT
-#
-# ANS(diff_quotient_cmp("2x+dx"));
-#
-#
-
-sub diff_quotient_cmp {
- my $answer = shift || '';
- my %params = (
- debug => 0,
- var => 'x',
- limits => [$functLLimitDefault,$functULimitDefault],
- @_
- );
- #
- # Get the variable and limits
- #
- my $x = $params{var}; delete $params{var};
- my ($ll,$ul) = @{$params{limits}};
- $params{vars} = [$x,'H'];
- $params{limits} = [[$ll,$ul],[$functLLimitDefault,$functULimitDefault]];
- #
- # Convert dx to H
- #
- my $answer_h = $answer; $answer_h =~ s/d$x/H/g;
- #
- # The answer checker that tests for division by zero
- #
- my $zero = fun_cmp($answer_h,%params);
- $zero->{rh_ans}{evaluation_points} = [[($ul+$ll)/2,0]];
-
- my $ans = new AnswerEvaluator;
- $ans->{debug} = $params{debug};
- $ans->ans_hash(
- type => "difference quotient",
- correct_ans => $answer,
- cmp => fun_cmp($answer_h,%params),
- zero_cmp => $zero,
- var => $x,
- );
- $ans->install_evaluator(\&diff_quotient_cmp_check,%params);
- return $ans;
-}
-
-#
-# The guts of the checker
-#
-sub diff_quotient_cmp_check {
- my $ans = shift;
- my $x = $ans->{var};
- my $answer = $ans->{student_ans}; $answer =~ s/d$x/H/g;
-
- #
- # Check the answer, and copy the score and messages
- #
- my $hash = evaluateAnswer($ans->{cmp},$answer);
- foreach my $id ('score','student_ans','ans_message','error_message',
- 'error_flags','preview_text_string','preview_latex_string') {
- $ans->{$id} = $hash->{$id};
- $ans->{$id} =~ s/H/d$x/g if defined($ans->{$id});
- }
-
- #
- # If the function matches, check that it is simplified
- # (no division by zero when dx = 0). Otherwise, give an
- # appropriate error message.
- #
- if ($hash->{score} == 1) {
- $hash = evaluateAnswer($ans->{zero_cmp},$answer);
- if ($hash->{ans_message} =~ m/division by zero/) {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} =
- "It looks like you didn't finish simplifying your answer\n";
- }
- }
-
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/ev3p.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/ev3p.pl
deleted file mode 100755
index 0311a71969..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/ev3p.pl
+++ /dev/null
@@ -1,103 +0,0 @@
-sub _EV3P_init {}
-
-######################################################################
-#
-# New version of EV3 that allows `...` and ``...`` to insert TeX produced
-# by the new Parser (in math and display modes).
-#
-# Format: EV3P(string,...);
-# EV3P({options},string,...);
-#
-# where options can include:
-#
-# processCommands => 0 or 1 Indicates if the student's answer will
-# be allowed to process \{...\}.
-# Default: 1
-#
-# processVariables => 0 1 Indicates whether variable substitution
-# should be performed on the student's
-# answer.
-# Default: 1
-#
-# processMath => 0 or 1 Indicates whether \(...\), \[...\],
-# `...` and ``...`` will be processed
-# in the student's answer.
-# Default: 1
-#
-# processParser => 0 or 1 Indicates if `...` and ``...`` should
-# be processed when math is being
-# processed.
-# Default: 1
-#
-# fixDollars => 0 or 1 Specifies whether dollar signs not followed
-# by a letter should be replaced by ${DOLLAR}
-# prior to variable substitution (to prevent
-# accidental substitution of strange Perl
-# values).
-# Default: 1
-#
-sub EV3P {
- my $option_ref = {}; $option_ref = shift if ref($_[0]) eq 'HASH';
- my %options = (
- processCommands => 1,
- processVariables => 1,
- processParser => 1,
- processMath => 1,
- fixDollars => 1,
- %{$option_ref},
- );
- my $string = join(" ",@_);
- $string = ev_substring($string,"\\\\{","\\\\}",\&safe_ev) if $options{processCommands};
- if ($options{processVariables}) {
- my $eval_string = $string;
- $eval_string =~ s/\$(?![a-z])/\${DOLLAR}/gi if $options{fixDollars};
- my ($evaluated_string,$PG_eval_errors,$PG_full_errors) =
- PG_restricted_eval("</>/g;
- $evaluated_string = $BBOLD."(Error: $error in '$string')".$EBOLD;
- }
- $string = $evaluated_string;
- }
- if ($options{processMath}) {
- $string = EV3P_parser($string) if $options{processParser};
- $string = ev_substring($string,"\\(","\\)",\&math_ev3);
- $string = ev_substring($string,"\\[","\\]",\&display_math_ev3);
- }
- return $string;
-}
-
-#
-# Look through a string for ``...`` or `...` and use
-# the parser to produce TeX code for the specified mathematics.
-# ``...`` does display math, `...` does in-line math. They
-# can also be used within math mode already, in which case they
-# use whatever mode is already in effect.
-#
-sub EV3P_parser {
- my $string = shift;
- return $string unless $string =~ m/`/;
- my $start = ''; my %end = ('\('=>'\)','\['=>'\]');
- my @parts = split(/(``.*?``\*?|`.+?`\*?|(?:\\[()\[\]]))/s,$string);
- foreach my $part (@parts) {
- if ($part =~ m/^(``?)(.*)\1(\*?)$/s) {
- my ($delim,$math,$star) = ($1,$2,$3);
- my $f = Parser::Formula($math);
- if (defined($f)) {
- $f = $f->reduce if $star;
- $part = $f->TeX;
- $part = ($delim eq '`' ? '\('.$part.'\)': '\['.$part.'\]') if (!$start);
- } else {
- ## FIXME: use context->{error}{ref} to highlight error in $math.
- $part = $BBOLD."(Error: $$Value::context->{error}{message} '$math')".$EBOLD;
- $part = $end{$start}." ".$part." ".$start if $start;
- }
- }
- elsif ($start) {$start = '' if $part eq $end{$start}}
- elsif ($end{$part}) {$start = $part}
- }
- return join('',@parts);
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/imageChoice.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/imageChoice.pl
deleted file mode 100755
index 178f473e16..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/imageChoice.pl
+++ /dev/null
@@ -1,91 +0,0 @@
-loadMacros(
- 'PGchoicemacros.pl',
- 'unionUtils.pl',
- 'choiceUtils.pl',
-);
-
-sub _imageChoice_init {}; # don't reload this file
-
-######################################################################
-#
-# Create a match list where the answers are images
-#
-# Usage: $ml = new_image_match_list(options);
-#
-# where options are those that can be supplied to image_print_a below.
-# The answers should be an image name or reference to to a plot object
-# (or a reference to a pair of either of these), and they are passed
-# to the Image function for processing. See unionUtils.pl for more
-# information on how these are handled.
-#
-sub new_image_match_list {
- my $ml = new Match(random(1,2000,1), \&alt_print_q, \&img_print_a);
- $ml->{ImageOptions} = [@_];
- $ml;
-}
-
-######################################################################
-#
-# A print routine for image matching. This is designed to display
-# four graphs per row. More can be included by setting the ImageOptions
-# variable in the match list. For example:
-#
-# $ml->{ImageOptions} = [size => [100,100]]
-#
-# You can include the following options:
-#
-# size => [w,h] the width and height of the images
-# width => n the width of the images (obsolete)
-# height => n the height of the images (obsolete)
-# tex_size => n the size for the TeX version of the image
-# separation => n the spacing between the images in a row
-# vseparation => n the spacing between the images and captions
-# link => 0 or 1 1 to make a link to the original image
-# columns => n the number of images in each row (defaults to 4)
-# border => n the width of the image border
-#
-
-sub img_print_a {
- my $self = shift;
- $self->{ImageOptions} = [] unless defined($self->{ImageOptions});
- my %options = (
- width => 150, height => 150, tex_size => 200, columns => 4,
- separation => 15, vseparation => 5, link => 0, @{$self->{ImageOptions}});
- my ($w,$h,$m) = ($options{width},$options{height},$options{columns});
- ($w,$h) = @{$options{size}} if defined($options{size});
- my ($sep,$vsep) = ($options{separation},$options{vseparation});
- my ($tsize,$link) = ($options{tex_size},$options{link});
- my $border = $options{border}; $border = ($link?2:1) unless defined($border);
- my $HTML; my @images = (); my @labels = (); my $i = 0;
- my $out;
-
- $out = BeginTable(tex_spacing => "5pt", tex_border => "5pt");
- while ($image = shift) {
- push(@images,Image(
- $image, size => [$w,$h], tex_size => $tsize,
- link => $link, border => $border
- ));
- push(@labels,MODES(
- TeX => "\\hfil \\textbf{$main::ALPHABET[$i]}",
- Latex2HTML=>$bHTML."
$main::ALPHABET[$i]
".$eHTML,
- HTML => "
$main::ALPHABET[$i]
"
- ));
- if ((++$i % $m) == 0) {
- $out .= TableSpace(2*$vsep,6) if ($i > $m);
- $out .= Row([@images], separation => $sep).
- TableSpace($vsep,0).
- Row([@labels], separation => $sep);
- @images = (); @labels = ();
- }
- }
- if (scalar(@images) > 0) {
- $out .= TableSpace(2*$vsep) if ($i > $m && $displayMode ne "TeX");
- $out .= Row([@images], separation => $sep).
- TableSpace($vsep,0).
- Row([@labels], separation => $sep);
- }
- $out .= EndTable(tex_border => "5pt");
- $out;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/infiniteAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/infiniteAnswer.pl
deleted file mode 100755
index 2625b8557e..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/infiniteAnswer.pl
+++ /dev/null
@@ -1,131 +0,0 @@
-loadMacros('unionUtils.pl','answerUtils.pl');
-
-sub _infiniteAnswer_init {
-
- #$INFINITY_WORD = "INF";
- $INFINITY_WORD = "infinity" unless defined($INFINITY_WORD);
-
- #
- # A message that can be inclued (within BEGIN_TEXT and END_TEXT)
- # to tell the student how to enter infinity and minus infinity
- #
- $INFINITY_MESSAGE =
- $BITALIC.$BSMALL.
- "Use ${LQ}$INFINITY_WORD${RQ} for $LQ\\(\\infty\\)$RQ ".
- "and ${LQ}-$INFINITY_WORD${RQ} for $LQ\\(-\\infty\\)$RQ." .
- $ESMALL.$EITALIC;
-
- $DNE_MESSAGE =
- $BITALIC.$BSMALL.
- "Use ${LQ}DNE${RQ} for ${LQ}Does not exist${RQ}.".
- $ESMALL.$EITALIC;
-
- $INFINITY_MESSAGE = "" if $displayMode eq 'TeX';
- $DNE_MESSAGE = "" if $displayMode eq 'TeX';
-
-};
-
-##########################################################################
-#
-# Check for a number or "-INF", "INF", "DNE" or several synonyms.
-#
-# WeBWorK's std_num_str_cmp doesn't allow for strings like "-INF", so it
-# uses the unsatisfying "MINF" instead. This answer checker provides
-# for both MINF and -INF to mean negative infinity, and INF or NaN for
-# positive infinity, and similarly INFINITY or -INFINITY. It also
-# allows for DNE as an answer. The strings can be entered in upper-
-# or lower-case and still be recognized.
-#
-# Usage: infinite_num_cmp(number, options)
-#
-# where number is a number or one of the words for infinity, and options
-# are chosen from
-#
-# allowDNE => 0 or 1 whether to accept DNE as a valid entry
-# (default is 0)
-#
-# DNEisINF => 0 or 1 whether to treat DNE as INF or as a
-# separate word (default is 0)
-#
-#
-sub infinite_num_cmp {
- my $infPattern = '^(INF|INFINITY|\+INF|\+INFINITY|NaN)$';
- my $neginfPattern = '^(-INF|-INFINITY|MINF)$';
- my $num = shift;
- my %params = (allowDNE => 0, DNEisINF => 0,
- infPattern => $infPattern,
- neginfPattern => $neginfPattern, @_);
- my %numops = @_;
- delete($numops{allowDNE}) if (defined($numops{allowDNE}));
- delete($numops{DNEisINF}) if (defined($numops{DNEisINF}));
- $params{debug} = 0 unless defined($params{debug});
- $num = "-$INFINITY_WORD" if ($num =~ m/$neginfPattern/i);
- $num = $INFINITY_WORD if ($num =~ m/$infPattern/i);
- if ($params{allowDNE}) {
- $params{strings} = ["INF","-INF","+INF","+INFINITY","INFINITY","-INFINITY","DNE"];
- $params{num_cmp} = num_cmp($num,
- strings => ["INF","-INF","+INF","MINF","NaN","INFINITY","-INFINITY","+INFINITY","DNE"],
- %numops);
- } else {
- $params{strings} = ["INF","-INF","+INF","INFINITY","-INFINITY","+INFINITY"];
- $params{num_cmp} = num_cmp($num,
- strings => ["INF","-INF","+INF","MINF","NaN","INFINITY","-INFINITY","+INFINITY"],
- %numops);
- }
- $params{num_cmp}->install_post_filter('reset'); # to prevent NUM_CMP from putting
- # error messages in student_ans
- $params{isString} = 0;
- foreach my $string (@{$params{strings}}) {
- if (uc($string) eq uc($num)) {$params{isString} = 1; last}
- }
-
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(correct_ans => $num, type => "infinite number");
- $answerEvaluator->install_evaluator(\&infinite_num_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the checker
-#
-sub infinite_num_check {
- my $ans = shift;
- my %params = @_;
- $ans->{student_ans} = trimString($ans->{student_ans});
- my $answer = $ans->{student_ans};
- my $realAnswer = $ans->{correct_ans};
- my $isString = 0;
- $realAnswer = "DNE"
- if (uc($answer) eq "DNE" && $params{DNEisINF} &&
- $realAnswer =~ m/$params{infPattern}/i);
- $answer = "-$INFINITY_WORD" if ($answer =~ m/$params{neginfPattern}/i);
- $answer = $INFINITY_WORD if ($answer =~ m/$params{infPattern}/i);
- if ($params{isString} && uc($answer) eq uc($realAnswer)) {
- $ans->score(1); $isString = 1
- } else {
- foreach my $string (@{$params{strings}}) {
- if (uc($answer) eq uc($string)) {$ans->score(0); $isString = 1}
- }
- }
- if ($isString) {
- $ans->{student_ans} = $answer;
- $ans->{preview_text_string} = $answer;
- $ans->{preview_latex_string} = $answer;
- return $ans;
- }
- #
- # transfer the NUM_CMP error message to the answer message
- # so we can report it correctly in other checkers
- #
- my $hash = evaluateAnswer($params{num_cmp},$ans->{student_ans});
- $hash->{ans_message} = trimString($hash->{error_message})
- if ($hash->{ans_message} eq '');
- $hash->{ans_message} =
- "Your answer does not seem to be a number or infinity"
- if ($hash->{ans_message} =~ m/recognized answer/);
- $hash->clear_error('EVAL'); # in case one was left over from std_num_cmp
- return $hash;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/integerAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/integerAnswer.pl
deleted file mode 100755
index 8148f01cc5..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/integerAnswer.pl
+++ /dev/null
@@ -1,52 +0,0 @@
-sub _integerAnswer_init {
- $INTEGER_TOLERANCE = 1E-14;
-};
-
-######################################################################
-#
-# Integer answer checker.
-#
-# integer_cmp(ans,options)
-#
-# where options are those allowed by num_cmp().
-#
-# This provided an answer checker that compares against an integer.
-# it is really just a shell around num_cmp() that sets the tolerance to
-# an absolute tolerance of .5 (so that only the correct integer
-# would be correct). It also adds a post-filter to check that
-# the student answer actually IS an integer.
-#
-# Note, the checker is only good to about 12 digits.
-#
-
-sub integer_cmp {
- my $cmp = num_cmp(@_,tol => .5);
- $cmp->install_post_filter(\&check_integer_answer);
- my $x = $cmp->{rh_ans}{correct_ans};
- warn "Professor's answer is too large for integer comparison"
- if (abs($x) > (1/$INTEGER_TOLERANCE)/100);
- if (abs($x - int($x+$x*$INTEGER_TOLERANCE)) > $x*$INTEGER_TOLERANCE) {
- warn "Professor's answer is not an integer";
- } else {
- $cmp->{rh_ans}{original_correct_ans} =
- $cmp->{rh_ans}{correct_ans} = sprintf("%.0f",$x);
- }
- return $cmp;
-}
-
-sub check_integer_answer {
- my $ans = shift;
- if ($ans->{ans_message} eq "" && $ans->{error_message} eq "") {
- my $x = $ans->{student_ans};
- if (abs($x - int($x+$x*$INTEGER_TOLERANCE)) > $x*$INTEGER_TOLERANCE) {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} =
- "Your answer is not an integer";
- } else {
- $ans->{student_ans} = sprintf("%.0f",$x);
- }
- }
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/intervalAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/intervalAnswer.pl
deleted file mode 100755
index 352b02a1a9..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/intervalAnswer.pl
+++ /dev/null
@@ -1,258 +0,0 @@
-loadMacros('infiniteAnswer.pl');
-
-sub _intervalAnswer_init {}; # don't reload this file
-
-######################################################################
-##
-## Interval answer checkers.
-##
-## num_interval_cmp() intervals with numeric or infinite endpoints
-## fun_interval_cmp() intervals with functions as endpoints
-##
-## interval_cmp() provide your own endpoint checkers
-##
-
-######################################################################
-#
-# num_interval_cmp(answer,options)
-#
-# where options are from among:
-#
-# cmp_params => [list] parameters to be passed to infinite_num_cmp
-# for each coordinate
-#
-# or any of the options to interval_cmp (see below).
-#
-# This provided an answer checker that compares against an interval
-# with numeric or infinite endpoints.
-#
-# e.g. num_point_cmp("(1,10)");
-# num_point_cmp("(-INF,10)");
-#
-
-sub num_interval_cmp {
- my $ans = shift;
- std_interval_cmp($ans, cmp => \&infinite_num_cmp, @_);
-}
-
-
-######################################################################
-#
-# num_interval_cmp(answer,options)
-#
-# where options are from among:
-#
-# cmp_params => [list] parameters to be passed to infinite_num_cmp
-# for each coordinate
-#
-# vars => [list] the variables for the formulas
-#
-# or any of the options to interval_cmp (see below).
-#
-# This provided an answer checker that compares against an interval
-# with numeric or infinite endpoints.
-#
-# e.g. fun_point_cmp("(x,2x)");
-# fun_point_cmp("(-t,t+2)", vars => 't');
-#
-
-sub fun_interval_cmp {
- my $ans = shift;
- my %params = (cmp_params => [], @_);
- if (defined($params{vars})) {
- $params{cmp_params} = [vars => $params{vars}, @{$params{cmp_params}}];
- delete $params{vars};
- }
- std_interval_cmp($ans, cmp => \&fun_cmp, %params);
-}
-
-
-######################################################################
-#
-# std_interval_cmp(ans,options)
-#
-# where ans is the correct answer as a string (e.g. "(1,INF)"), and
-# options are from among the following:
-#
-# cmp => \&cmp a reference to the answer checker to use for each
-# endpoint (e.g., \&std_num_cmp, or ~~&std_num_cmp
-# in a .pg file)
-#
-# cmp_params => [...] is a reference to a list of parameters for the
-# answer checker (e.g., [vars => 'x'])
-#
-# or any of the options allowed by interval_cmp (see below).
-#
-# This returns an answer checker that compares the interval using the
-# given answer checker on each endpoint.
-#
-# e.g. std_interval_cmp("(1,INF)",cmp => ~~&infinite_num_cmp);
-#
-
-sub std_interval_cmp {
- my $ans = shift;
- my %params = (
- cmp => \&infinite_num_cmp,
- cmp_params => [],
- debug => 0,
- @_
- );
- my ($cmp,$cmp_params) = ($params{cmp},$params{cmp_params});
- delete $params{cmp}; delete $params{cmp_params};
- die "The correct answer doesn't look like an interval"
- if ($ans !~ m/^(\[|\()([^,]*),([^,]*)(\]|\))$/);
- my ($left,$a,$b,$right) = ($1,$2,$3,$4);
- interval_cmp(&{$cmp}($a,@{$cmp_params}),&{$cmp}($b,@{$cmp_params}),
- ends => "$left$right", %params);
-}
-
-
-##########################################################################
-#
-# Check if an answer is an interval
-#
-# Format:
-#
-# interval_cmp(left_evaluator,right_evaluator, options)
-#
-# where "left_evaluator" is an answer checker for the left endpoint
-# and "right_evaluator" is an answer checker for the right endpoint,
-#
-# Options can be taken from:
-#
-# ends => string indicates the type of interval, where
-# "string" is one of '()', '(]', '[)', or '[]'.
-#
-# showHints => 0 or 1 indicates whether to show hints about
-# the correctness of the endpoints
-# (default is 1).
-#
-# showOrderHints => 0 or 1
-# indicates whether to show hints about
-# the order of the endpoints
-# (default is $showHints).
-#
-# Example:
-#
-# interval_cmp(std_num_cmp(0),std_num_cmp(1), ends=>'[)');
-#
-sub interval_cmp {
- my $lendpnt = shift;
- my $rendpnt = shift;
- my %params = @_;
- set_default_options(\%params,
- ends => '()',
- showHints => 1,
- showOrderHints => undef,
- debug => 0
- );
- $params{lendpnt} = $lendpnt;
- $params{rendpnt} = $rendpnt;
-
- my $ends = $params{ends};
- my ($ltype,$rtype) = (substr($ends,0,1),substr($ends,-1));
- my ($lhash,$rhash) = (hashFor($lendpnt),hashFor($rendpnt));
- #
- # Needed to get preview to work properly
- #
- my $type = "interval";
- $type .= " (number)"
- if ($lhash->{type} =~ m/number/ || $rhash->{type} =~ m/number/);
-
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => $ltype . $lhash->{correct_ans} . "," .
- $rhash->{correct_ans} . $rtype,
- type => $type
- );
- $answerEvaluator->install_evaluator(\&interval_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the checker
-#
-sub interval_check {
- my $ans = shift;
- my %params = @_;
- my ($lendpnt,$rendpnt) = ($params{lendpnt},$params{rendpnt});
- my $ends = $params{ends};
-
- my $showHints = defined($params{showHints})?
- $params{showHints} : $showPartialCorrectAnswers;
- my $showOrderHints = defined($params{showOrderHints})?
- $params{showOrderHints} : $showPartialCorrectAnswers;
- $showHints = $showOrderHints = 0 if (isPreviewMode());
-
- $ans->{student_ans} = trimString($ans->{student_ans});
- my $answer = $ans->{student_ans};
- my ($sl,$sa,$sb,$sr) = ($answer =~ m/^(\[|\()([^,]*),([^,]*)(\]|\))$/);
- my @errors = (); my $score = 1;
-
- if (!defined($sl)) {
- push(@errors,"Your answer doesn't look like an interval.");
- } else {
- my ($lhash,$rhash) =
- (evaluateAnswer($lendpnt,$sa),evaluateAnswer($rendpnt,$sb));
- #
- # (Second check is a hack since std_num_cmp with strings
- # doesn't always set the error message when an error
- # occurs. Grrr!)
- #
- if ($lhash->{ans_message} ne "" ||
- $lhash->{student_ans} =~ m/ Your answer/) {
- push(@errors,"Error evaluating left endpoint: ");
- push(@errors,IndentError($lhash->{student_ans}));
- push(@errors,IndentError($lhash->{ans_message}));
- } else {
- $sa = $lhash->{student_ans};
- if ($lhash->{score} != 1) {
- push(@errors,"The left endpoint is incorrect") if ($showHints);
- $score = 0;
- }
- }
- if ($rhash->{ans_message} ne "" ||
- $rhash->{student_ans} =~ m/ Your answer/) {
- push(@errors,"Error evaluating right endpoint:");
- push(@errors,IndentError($rhash->{student_ans}));
- push(@errors,IndentError($rhash->{ans_message}));
- } else {
- $sb = $rhash->{student_ans};
- if ($rhash->{score} != 1) {
- push(@errors,"The right endpoint is incorrect") if ($showHints);
- $score = 0;
- }
- }
- $ans->setKeys(student_ans => $sl.$sa.",".$sb.$sr);
- my ($la,$ra) = ($lhash->{student_ans},$rhash->{student_ans});
- push(@errors,"Note: The left endpoint is greater than ".
- "the right endpoint (empty interval)")
- if ($showOrderHints && isNumber($la) && isNumber($ra) && $la > $ra);
- if ($sl.$sr ne $ends) {
- push(@errors,"The type of interval is incorrect") if ($showHints);
- $score = 0;
- }
- $ans->setKeys(
- preview_text_string =>
- $sl . StringOrBlank($lhash->{preview_text_string},$sa) . "," .
- StringOrBlank($rhash->{preview_text_string},$sb) . $sr,
- preview_latex_string =>
- $sl . StringOrBlank($lhash->{preview_latex_string},$sa) . "," .
- StringOrBlank($rhash->{preview_latex_string},$sb) . $sr
- );
- clearEvaluator($lendpnt);
- clearEvaluator($rendpnt);
- }
-
- if (scalar(@errors) == 0) {
- $ans->score($score);
- $ans->{ans_message} = $ans->{error_message} = '';
- } else {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} = join("\n",@errors);
- }
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/lineAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/lineAnswer.pl
deleted file mode 100755
index a17348e4d0..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/lineAnswer.pl
+++ /dev/null
@@ -1,73 +0,0 @@
-loadMacros('vectorAnswer.pl');
-
-sub _lineAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# Compare a parametric formula to a given line
-# (allows any parallel vector, and any point on the line).
-#
-# Usage: parametric_line_cmp(ans,options)
-#
-# where ans is the answer in vector parametric form (e.g., "<1+3t,2-t>")
-# or as a Vector object, and options are those that are allowed by
-# point_cmp. The variable is assumed to be 't', but that can be changed
-# using the cmp_params option.
-#
-
-sub parametric_line_cmp {
- my $answer = shift;
- my $ans = fun_point_cmp($answer,
- post_process => \&checkParametricLine,
- showHints => 0, showLengthHints => 1,
- cmp_params => [vars => 't'],
- @_
- );
- foreach my $cmp (@{$ans->{rh_ans}->{components}}) {
- #
- # We evaluate the functions at t=0 and t=1 to get
- # p = L(0) and v = L(1)-L(0).
- #
- $cmp->{rh_ans}->{evaluation_points} = [[0],[1]];
- }
- return $ans;
-}
-
-#
-# The guts of the checker (called as a post-processor by
-# the point checker).
-#
-sub checkParametricLine {
- my $ans = shift;
- my (@p,@cp,@v,@cv);
- #
- # Get the P and V for each line
- # (we arranged above to evaluate at t=0 and t=1).
- #
- foreach my $cmp (@{$ans->{components}}) {
- push(@cp,$cmp->{rh_ans}->{ra_instructor_values}->[0]);
- push(@cv,$cmp->{rh_ans}->{ra_instructor_values}->[1]);
- push(@p,$cmp->{rh_ans}->{ra_student_values}->[0]);
- push(@v,$cmp->{rh_ans}->{ra_student_values}->[1]);
- }
- #
- # Get the vector (v = L(1)-L(0)).
- #
- $v = vDiff(Point(@v),Point(@p)); $cv = vDiff(Point(@cv),Point(@cp));
- #
- # The vectors must be parallel to be equal.
- #
- return 0 if (!areParallel($v,$cv));
- #
- # If the points are equal, the lines are.
- #
- my $w = vDiff(Point(@cp),Point(@p));
- return 1 if (isCorrectAnswer(std_num_cmp(0),Norm($w)));
- #
- # Otherwise, if the vector between the two points is
- # parallel to the direction vectors, the lines are equal.
- #
- return (areParallel($v,$w));
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/listAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/listAnswer.pl
deleted file mode 100755
index cbaf9079b1..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/listAnswer.pl
+++ /dev/null
@@ -1,580 +0,0 @@
-sub _listAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# This file implements a general list answer checker, which allows
-# you to specify how the answer is to be split up, whether
-# the entries must appear in the same order as the correct answer,
-# whether informational messages are to be produced for incorrect
-# entries, and what answer checker to call on each entry.
-#
-# The list_cmp() and std_list_cmp() functions are very general, and
-# could be used to implement a variety of special cases of lists.
-# A number of these are given below, including:
-#
-# num_list_cmp() a list of numeric values
-# infinite_num_list_cmp() a list of numeric values or infinities
-# fun_list_cmp() a list of formulas
-# num_interval_list_cmp() a list of intervals with numeric endpoints
-# fun_interval_list_cmp() a list of intervals with endpoint equations
-# num_union_list_cmp() a list of unions of numeric intervals
-# fun_union_list_cmp() a list of unions of variable intervals
-# num_point_list_cmp() a list of numeric points
-# fun_point_list_cmp() a list of formulaic points
-# num_vector_list_cmp() a list of numeric vectors
-# fun_vector_list_cmp() a list of formulaic vectors
-#
-# Some of these require that you load the .pl file for the
-# associated answer checker as well. For example, to use
-# num_point_list_cmp(), you must include
-#
-# loadMacros("pointAnswer.pl");
-#
-# in your .pg file.
-#
-# Partial credit is given for getting some entries correct, unless
-# $showParialCorrectAnswers is set to 0. A system level change to
-# displayMacros.pl is required to make the system indicate this in
-# a meaningful way. You can prevent partial credit by using the
-# partialCredit => 0 option to any of the *_cmp() routines.
-#
-
-######################################################################
-
-
-loadMacros(
- "unionUtils.pl",
- "answerUtils.pl",
-);
-
-######################################################################
-#
-# Usage: num_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "10, -3, 5")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_list_cmp {std_list_cmp(@_)}
-
-
-######################################################################
-#
-# Usage: infinite_num_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "10, -INF, 5")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub infinite_num_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&infinite_num_cmp,
- type => "infinite number", @_);
-}
-
-
-######################################################################
-#
-# Usage: fun_list_cmp(ans,options)
-#
-# where ans is the string indicating the correct list and options are
-# any of those that can be passed to std_list_cmp.
-#
-# Options can also include:
-#
-# vars => [list] the variables for the function checker
-#
-# or any of the options allowed by list_cmp (see below).
-#
-
-sub fun_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_cmp,
- entry_type => 'equation',
- fun_var_params(@_));
-}
-
-#
-# Put the function's 'vars' option into the 'cmp_params' option.
-#
-sub fun_var_params {
- my %params = (cmp_defaults => [], @_);
- if (defined($params{vars})) {
- $params{cmp_defaults} = [vars => $params{vars}, @{$params{cmp_defaults}}];
- delete $params{vars}
- }
- return %params;
-}
-
-
-######################################################################
-#
-# Usage: num_interval_list_cmp(ans,options)
-# fun_interval_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "[1,3), (-inf,-5)")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_interval_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_interval_cmp,
- type => "number interval",
- entry_type => 'interval',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_interval_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_interval_cmp,
- type => "function interval",
- entry_type => 'interval',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-
-######################################################################
-#
-# Usage: num_union_list_cmp(ans,options)
-# fun_union_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g.,
-# "[1,3) U (-inf,-5), [10,11]") and options are any of those that can
-# be passed to std_list_cmp.
-#
-
-sub num_union_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_union_cmp,
- type => "number union",
- entry_type => 'interval or union',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0, showLengthHints => 0],
- @_);
-}
-
-sub fun_union_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_union_cmp,
- type => "fun union",
- entry_type => 'interval or union',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- fun_var_params(
- cmp_defaults => [showHints => 0, showLengthHints => 0],
- @_
- ));
-}
-
-
-######################################################################
-#
-# Usage: num_point_list_cmp(ans,options)
-# fun_point_list_cmp(ans,options)
-# num_vector_list_cmp(ans,options)
-# fun_vector_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "(1,2,3), (3,-2,4)")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_point_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_point_cmp,
- type => "number point",
- entry_type => 'point',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => undef,
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_point_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_point_cmp,
- type => "function point",
- entry_type => 'point',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => undef,
- fun_var_params(cmp_defaults => [showHints => 0],@_));
-}
-
-sub num_vector_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_vector_cmp,
- type => "number vector",
- entry_type => 'vector',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [
- separator => ',',
- open => '[(<',
- close => '])>',
- ],
- cmp_ans => undef,
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_vector_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_vector_cmp,
- type => "function vector",
- entry_type => 'vector',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [
- separator => ',',
- open => '[(<',
- close => '])>',
- ],
- cmp_ans => undef,
- fun_var_params(cmp_defaults => [showHints => 0],@_));
-}
-
-
-######################################################################
-#
-# std_list_cmp(ans,options)
-#
-# where ans is the correct answer as a string (e.g. "10, -5"), and
-# options are from among the following:
-#
-# cmp => \&cmp a reference to the answer checker to use for each
-# list element (eg, \&std_num_cmp or \&fun_cmp)
-#
-# cmp_params => [...] a reference to a list of parameters for the
-# answer checker (e.g., cmp_params => [vars => 'x'])
-#
-# or any of the options allowed by list_cmp (see below).
-#
-# This returns an answer checker that compares the list using the
-# given answer checker on each element in the list.
-#
-# e.g. std_list_cmp("10, -5",cmp => ~~&std_num_cmp);
-#
-
-sub std_list_cmp {
- my $ans = shift;
- my %params = (
- cmp => \&std_num_cmp,
- cmp_ans => "0",
- cmp_params => [],
- cmp_defaults => [],
- split => \&std_split,
- split_params => [],
- split_defaults => [separator => ','],
- debug => 0,
- @_
- );
- my $cmp = $params{cmp};
- my @cmp_params = (@{$params{cmp_defaults}},@{$params{cmp_params}});
- my $split = $params{split};
- my @split_params = (@{$params{split_defaults}},@{$params{split_params}});
- my $ans_ref = &{$split}($ans,@split_params);
- warn "Error in professor's answer: $ans_ref" if (ref($ans_ref) ne "ARRAY");
- my @list = ();
- foreach my $element (@{$ans_ref}) {
- $element = trimString($element);
- push(@list,&{$cmp}($element,@cmp_params));
- }
- $params{cmp_ans} = hashFor($list[0])->{correct_ans}
- if (!defined($params{cmp_ans}) && scalar(@list));
- list_cmp([@list],%params);
-}
-
-
-######################################################################
-#
-# Usage: list_cmp([list],options)
-#
-# where list is the array of checkers for the elements in the list
-# and options are among:
-#
-# showHints => 0 or 1 indicates whether to show messages about
-# which elements are correct.
-#
-# showLengthHints => 0 or 1
-# indicates whether to show messages about
-# having too many entries in the list
-#
-# ordered => 0 or 1 specifies if the order of the student's
-# answers must match thos of the professor.
-# If 0, they can be in any order, if 1, they
-# must be in the same order. Defaut: 0.
-#
-# partialCredit => 0 or 1 indicates if scores other than 0 and 1 are
-# to be used (to provide for partial credit
-# when some of the answers are correct).
-#
-# cmp => \&cmp reference to a comparison
-# for doing syntax checking on the
-# elements given by the student.
-#
-# cmp_params => [...] parameters to pass to the answer checker
-# for syntax checking.
-#
-# cmp_defaults => [...] default parameters for the syntax answer check
-#
-# cmp_ans => "..." a string to use for the answer when checking
-# for syntax errors in the entries that aren't
-# correct.
-#
-# split => \&split a reference to a routine to split the
-# answer string into elements (by default, it
-# uses the standard perl split() funciton
-# splitting at commas)
-#
-# split_params => [...] a reference to a list of parameters for the
-# split routine (e.g.,
-# split_params => [separator => ','])
-#
-# split_defaults => [...] a reference to a list of defaults for the
-# split_params list above.
-#
-# separator => ', ' the formatted specifier for use when
-# creating the string to display (it can
-# contain spaces, whereas the separator
-# in split_defaults or split_params
-# should not). Note that split_defaults
-# usually includes the separator used
-# for the actual splitting.
-#
-
-sub list_cmp {
- my $elements = shift;
- $elements = [$elements] unless ref($elements) eq 'ARRAY';
- my %params = @_;
- set_default_options(\%params,
- cmp => \&std_num_cmp,
- cmp_params => [],
- cmp_defaults => [],
- cmp_ans => "0",
- split => \&std_split,
- split_params => [],
- split_defaults => [separator => ','],
- separator => ', ',
- debug => 0,
- type => "number",
- entry_type => "number",
- list_type => "list",
- showHints => undef,
- showLengthHints => undef,
- ordered => undef,
- );
- my $type = "list ($params{type})";
- my @list = ();
- foreach my $cmp (@{$elements}) {push(@list,hashFor($cmp)->{correct_ans})}
-
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => join($params{separator},@list),
- elements => $elements,
- type => $type,
- );
- $answerEvaluator->install_evaluator(\&list_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the list checker.
-#
-sub list_check {
- my $ans = shift;
- my %params = @_;
- my $value = $params{entry_type}; my $ltype = $params{list_type};
- my $cmp = $params{cmp}; my $cmp_ans = $params{cmp_ans};
- my @cmp_params = (@{$params{cmp_defaults}},@{$params{cmp_params}});
- my $split = $params{split};
- my @split_params = (@{$params{split_defaults}},@{$params{split_params}});
- my @cmp = @{$ans->{elements}};
- my (@errors,@list,@text,@latex);
- my $ordered = $params{ordered};
- my $showHints = defined($params{showHints})?
- $params{showHints} : $showPartialCorrectAnswers;
- my $showLengthHints = defined($params{showLengthHints})?
- $params{showLengthHints} : $showPartialCorrectAnswers;
- my $partialCredit = defined($params{partialCredit})?
- $params{partialCredit} : $showPartialCorrectAnswers;
- $showHints = $showLengthHints = 0 if (isPreviewMode());
-
- my $list_ref = &{$split}($ans->{student_ans},@split_params);
- if (ref($list_ref) ne "ARRAY") {
- $ans->score(0); $ans->{error} = 1;
- $ans->{error_message} = $ans->{ans_message} = $list_ref;
- return $ans;
- }
-
- my $maxscore = scalar(@cmp);
- my $m = scalar(@{$list_ref});
- $maxscore = $m if ($m > $maxscore);
- my $i = 0; my $score = 0; my $hash;
- my $indent = ($m > 1)? 4: 0;
-
- ELEMENT: foreach my $element (@{$list_ref}) {
- $element = trimString($element); $i++;
- if ($element eq '') {
- push(@errors,"Your ".NameForNumber($i)." $value is blank");
- push(@list,''); push(@text,''); push(@latex,'');
- next ELEMENT;
- }
- if ($ordered) {
- $hash = evaluateAnswer(shift(@cmp),$element);
- if ($hash && $hash->{score} == 1) {
- push(@list,$hash->{student_ans});
- push(@text,StringOrBlank($hash->{preview_text_string}));
- push(@latex,StringOrBlank($hash->{preview_latex_string}));
- $score++; next ELEMENT;
- }
- } else {
- foreach my $k (0..$#cmp) {
- $hash = evaluateAnswer($cmp[$k],$element);
- if ($hash && $hash->{score} == 1) {
- splice(@cmp,$k,1);
- push(@list,$hash->{student_ans});
- push(@text,StringOrBlank($hash->{preview_text_string}));
- push(@latex,StringOrBlank($hash->{preview_latex_string}));
- $score++; next ELEMENT;
- }
- }
- }
- $hash = evaluateAnswer(&{$cmp}($cmp_ans,@cmp_params),$element)
- if (!$ordered || !$hash);
- if ($hash->{ans_message} ne '') {
- push(@errors,"Error evaluating the ".NameForNumber($i)." $value:")
- if ($m > 1);
- push(@errors,IndentError($hash->{student_ans},$indent))
- if ($m > 1 || $hash->{student_ans} =~ m/error/i);
- push(@errors,IndentError($hash->{ans_message},$indent));
- push(@list,$element);
- } else {
- push(@list,$hash->{student_ans});
- push(@errors,"Your ".NameForNumber($i)." $value is incorrect")
- if $showHints && $m > 1;
- }
- push(@text,StringOrBlank($hash->{preview_text_string}));
- push(@latex,StringOrBlank($hash->{preview_latex_string}));
- }
-
- if ($showLengthHints) {
- $value =~ s/ or /s or /; # fix "interval or union"
- push(@errors,"There should be more ${value}s in your $ltype")
- if ($score == $m && scalar(@cmp) > 0);
- push(@errors,"There should be fewer ${value}s in your $ltype")
- if ($score < $maxscore && $score == scalar(@{$ans->{elements}}));
- }
-
- $ans->{student_ans} = join($params{separator},@list);
- $ans->{preview_text_string} = join($params{separator},@text);
- $ans->{preview_latex_string} = join($params{separator},@latex);
-
- $score = 0 if ($score != $maxscore && !$partialCredit);
- $ans->score($score/$maxscore);
- $ans->{error_message} = $ans->{ans_message} = join("\n",@errors);
-
- return $ans;
-}
-
-
-######################################################################
-#
-# Do a split at a specific character
-# (routine should return a reference to the split list of
-# answers, or a string that is an error message indicating
-# a syntax error in the string).
-#
-
-sub std_split {
- my $s = shift;
- my %params = (separator => ',', @_);
- return [split($params{separator},$s)];
-}
-
-
-######################################################################
-#
-# Split at commas between intervals or points.
-# (Try to match parentheses, and only split when not within an
-# open set of parentheses).
-#
-# Paremeters can include:
-#
-# separator => ',' the character to split at (you can use
-# a regexp like '[,;]' to allow several
-# characters). Default: ','
-#
-# open => '...' the characters that count as open
-# parentheses. Default: '[('
-#
-# close => '...' the characters that count as close
-# parentheses. Default: '])'
-#
-# spaceSeparates => 0 or 1
-# indicates whether a space can be used to
-# separate entries in the list (when the regular
-# separator is not already there). This will
-# only occur at spaces between unnested close
-# and open parens (with nothing but spaces in
-# between). Default: 1
-#
-
-sub paren_split {
- my $s = shift;
- my %params = @_;
- set_default_options(\%params,
- separator => ',',
- open => '[(',
- close => '])',
- spaceSeparates => 1,
- );
- my $separator = $params{separator};
- my ($open,$close) = ($params{open},$params{close});
- $open =~ s/\]/\\\]/g; $close =~ s/\]/\\\]/g;
- my $spaceSeparates = $params{spaceSeparates};
- my $parens = 0; my $c;
- my @list; my $element; my $space = 0;
-
- foreach $c (split('',$s)) {
- if ($c =~ m/[$open]/) {
- if ($spaceSeparates && $space == 2) {push(@list,$element); $element = ''}
- $parens++; $space = 0;
- }
- elsif ($c =~ m/[$close]/) {
- $parens-- if $parens;
- $space = ($parens == 0);
- }
- elsif ($c =~ m/$separator/) {
- $space = 0;
- if ($parens == 0) {push(@list,$element); $element = ''; next}
- }
- elsif ($c eq ' ' && $space) {$space = 2}
- elsif ($c ne ' ') {$space = 0}
- $element .= $c;
- }
- push (@list,$element);
- return [@list];
-}
-
-######################################################################
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/parallelAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/parallelAnswer.pl
deleted file mode 100755
index 704864c253..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/parallelAnswer.pl
+++ /dev/null
@@ -1,47 +0,0 @@
-loadMacros("vectorAnswer.pl");
-
-sub _parallelAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# Check if the student's vector is parallel to the answer vector.
-#
-# Usage: parallel_vector_cmp(ans,options)
-#
-# Where ans is the vector to compare against (e.g., "<1,2,3>" or a
-# Vector object), and options are any of the options allowed
-# by point_cmp. The vector must be a constant, not a formula.
-# One additional option is allowed:
-#
-# same_direction => 0 or 1 indicates if the two vectors must
-# also point in the same (not
-# opposite) direction. Default: 0.
-#
-
-sub parallel_vector_cmp {
- my $answer = shift;
- my %params = (same_direction => 0, @_);
- my $sameDirection = $params{same_direction};
- delete $params{same_direction};
- my $cmp = num_point_cmp($answer,
- post_process => \&checkParallel,
- showHints => 0,
- %params
- );
- $cmp->{rh_ans}{same_direction} = $sameDirection;
- return $cmp;
-}
-
-#
-# The parallel check, as a post-processor to point_cmp
-#
-sub checkParallel {
- my $ans = shift;
- areParallel(
- Point(@{$ans->{correct_point}}),
- Point(@{$ans->{answer_point}}),
- $ans->{same_direction}
- );
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/parserImplicitEquation.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/parserImplicitEquation.pl
deleted file mode 100755
index 69a59da3ff..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/parserImplicitEquation.pl
+++ /dev/null
@@ -1,340 +0,0 @@
-loadMacros("MathObjects.pl");
-
-sub _parserImplicitEquation_init {ImplicitEquation::Init()}; # don't reload this file
-
-=head1 DESCRIPTION
-
- ######################################################################
- #
- # This is a MathObject class that implements an answer checker for
- # implicitly defined equations. The checker looks for the zeros of
- # the equation and tests that the student and professor equations
- # both have the same solutions.
- #
- # This type of check is very subtle, and there are important issues
- # that you may have to take into account. The solutions to the
- # equations are found numerically, and so they will not be exact;
- # that means that there are tolerances that may need to be adjusted
- # for your particular equation. Also, it is always possible for the
- # student to represent the function in a form that will exceed those
- # tolerances, and so be marked as incorrect. The answer checker
- # attempts to set the parameters based on the values of the functions
- # involved, but this may not work perfectly.
- #
- # The method used to locate the solutions of A=B is by finding zeros
- # of A-B, and it requires this function to take on both positive and
- # negative values (that is, it can only find transverse intersections
- # of the surface A-B=0 and the plane at height 0). For example, even
- # though the solutions of (x^2+y^1-1)^2=0 form a circle, the
- # algorithm will fail to find any solutions for this equation.
- #
- # In order to locate the zeros, you may need to change the limits so
- # that they include regions where the function is both positive and
- # negative (see below). The algorithm will avoid discontinuities, so
- # you can specify things like x-y=1/(x+y) rather than x^2-y^2=1.
- #
- # Because the solutions are found using a random search, it is
- # possible the randomly chosen starting points don't locate enough
- # zeros for the function, in which case the check will fail. This
- # can happen for both the professor's function and the student's,
- # since zeros are found for both. This means that a correct answer
- # can sometimes be marked incorrect depending on the random points
- # chosen initially. These points also affect the values selected for
- # the tolerances used to determine when a function's value is zero,
- # and so can affect whether the student's function is marked as
- # correct or not.
- #
- # If an equation has several components or branches, it is possible
- # that the random location of solutions will not find zeros on some
- # of the branches, and so might incorrectly mark as correct an
- # equation that only is zero on one of the components. For example,
- # x^2-y^2=0 has solutions along the lines y=x and y=-x, so it is
- # possible that x-y=0 or x+y=0 will be marked as correct if the
- # random points are unluckily chosen. One way to reduce this problem
- # is to increase the number of solutions that are required (by
- # setting the ImplicitPoints flag in the Context). Another is to
- # specify the solutions yourself, so that you are sure there are
- # points on each component.
- #
- # These problems should be rare, and the values for the various
- # parameters have been set in an attempt to minimize the possibility
- # of these errors, but they can occur, and you should be aware of
- # them, and their possible solutions.
- #
- #
- # Usage examples:
- #
- # Context("ImplicitEquation");
- # $f = ImplicitEquation("x^2 = cos(y)");
- # $f = ImplicitEquation("x^2 - 2y^2 = 5",limits=>[[-3,3],[-2,2]]);
- # $f = ImplicitEquation("x=1/y",tolerance=>.0001);
- #
- # Then use
- #
- # ANS($f->cmp);
- #
- # to get the answer checker for $f.
- #
- # There are a number of Context flags that control the answer checker.
- # These include:
- #
- # ImplicitPoints => 7 (the number of solutions to test)
- # ImplicitTolerance => 1E-6 (relative tolerance value for when
- # the tested function is zero)
- # ImplicitAbsoluteMinTolerance => 1E-3 (the minimum tolerance allowed)
- # ImplicitAbsoluteMaxTolerance => 1E-3 (the maximum tolerance allowed)
- # ImplicitPointTolerance => 1E-9 (relative tolerance for how close
- # the solution point must be to an
- # actual solution)
- # BisectionTolerance => .01 (extra factor used for the tolerance
- # when finding the solutions)
- # BisectionCutoff => 40 (maximum number of bisections to
- # perform when looking for a solution)
- #
- # You may set any of these using Context()->flags->set(...).
- #
- # In addition to the Context flags, you can set some values within
- # the ImplicitEquation itself:
- #
- # tolerance (the absolute tolerance for zeros of the function)
- # bisect_tolerance (the tolerance used when searching for zeros)
- # point_tolerance (the absolute tolerance for how close to an
- # actual solution the located solution must be)
- # limits (the domain to use for the function; see the
- # documentation for the Formula object)
- # solutions (a reference to an array of references to arrays
- # that contain the coordinates of the points
- # that are the solutions of the equation)
- #
- # These can be set in the in the ImplicitEquation() call that creates
- # the object, as in the examples below:
- #
- # For example:
- #
- # $f = ImplicitEquation("x^2-y^2=0",
- # solutions => [[0,0],[1,1],[-1,1],[-1,-1],[1,-1]],
- # tolerance => .001
- # );
- #
- #
- # $f = ImplicitEquation("xy=5",limits=>[-3,3]);
- #
- # The limits value can be set globally within the Context, if you wish,
- # and the others can be controlled by the Context flags discussed
- # above.
- #
- ######################################################################
-
-=cut
-
-#
-# Create the ImplicitEquation package
-#
-package ImplicitEquation;
-our @ISA = qw(Value::Formula);
-
-sub Init {
- my $context = $main::context{ImplicitEquation} = Parser::Context->getCopy("Numeric");
- $context->{name} = "ImplicitEquation";
- $context->variables->are(x=>'Real',y=>'Real');
- $context{precedence}{ImplicitEquation} = $context->{precedence}{special};
- Parser::BOP::equality->Allow($context);
- $context->flags->set(
- ImplicitPoints => 10,
- ImplicitTolerance => 1E-6,
- ImplicitAbsoluteMinTolerance => 1E-3,
- ImplicitAbsoluteMaxTolerance => 1,
- ImplicitPointTolerance => 1E-9,
- BisectionTolerance => .01,
- BisectionCutoff => 40,
- );
-
- main::Context("ImplicitEquation"); ### FIXEME: probably should require author to set this explicitly
-
- main::PG_restricted_eval('sub ImplicitEquation {ImplicitEquation->new(@_)}');
-}
-
-sub new {
- my $self = shift; my $class = ref($self) || $self;
- my $context = (Value::isContext($_[0]) ? shift : $self->context);
- my $f = shift; return $f if ref($f) eq $class;
- $f = main::Formula($f);
- Value::Error("Your formula doesn't look like an implicit equation")
- unless $f->type eq 'Equality';
- my $F = ($context->Package("Formula")->new($context,$f->{tree}{lop}) -
- $context->Package("Formula")->new($context,$f->{tree}{rop}))->reduce;
- $F = $context->Package("Formula")->new($F) unless Value::isFormula($F);
- Value::Error("Your equation must be real-valued") unless $F->isRealNumber;
- Value::Error("Your equation should not be constant") if $F->isConstant;
- Value::Error("Your equation can not contain adaptive parameters")
- if ($F->usesOneOf($context->variables->parameters));
- $F = bless $F, $class;
- my %options = (@_); # user can supply limits, tolerance, etc.
- foreach my $id (keys %options) {$F->{$id} = $options{$id}}
- $F->{F} = $f; $F->{isValue} = $F->{isFormula} = 1;
- $F->createPoints unless $F->{solutions};
- return $F;
-}
-
-#
-# Override the comparison method.
-#
-# Turn the right-hand equation into an ImplicitEquation. This creates
-# the test points (i.e., finds the solution points). Then check
-# the professor's function on the student's test points and the
-# student's function on the professor's test points.
-#
-
-sub compare {
- my ($l,$r) = @_; my $self = $l; my $tolerance;
- my @params; @params = (limits=>$l->{limits}) if $l->{limits};
- $r = ImplicitEquation->new($r,@params);
- Value::Error("Functions from different contexts can't be compared")
- unless $l->{context} == $r->{context};
-
- #
- # They are not equal if couldn't get solutions for one of them
- #
- return 1 unless $l->{solutions} && $r->{solutions};
-
- #
- # Test the right-hand function on the solutions of the left-hand one
- # and vice-versa
- #
- my $rzeros = $r->createPointValues($l->{solutions});
- my $lzeros = $l->createPointValues($r->{solutions});
- return 1 unless $lzeros && $rzeros;
-
- #
- # Check that the values are, in fact, zeros
- #
- $tolerance = $r->getFlag('tolerance',1E-3);
- foreach my $v (@{$rzeros}) {return 1 unless abs($v) < $tolerance}
- $tolerance = $l->getFlag('tolerance',1E-3);
- foreach my $v (@{$lzeros}) {return 1 unless abs($v) < $tolerance}
-
- return 0; # equal
-}
-
-#
-# Use the original equation for these (but not for perl(), since we
-# need that to use perlFunction).
-#
-sub string {shift->{F}->string}
-sub TeX {shift->{F}->TeX}
-
-sub cmp_class {'an Implicit Equation'}
-sub showClass {shift->cmp_class}
-
-#
-# Locate points that satisfy the equation
-#
-sub createPoints {
- my $self = shift;
- my $num_points = int($self->getFlag('ImplicitPoints',10));
- $num_points = 1 if $num_points < 1;
-
- #
- # Get some positive and negative test points (try up to 5 times)
- #
- my ($OK,$p,$n,$z,$f,@zero); my $k = 5;
- while (!$OK && --$k) {($OK,$p,$n,$z,$f) = $self->getPositiveNegativeZero($num_points)}
- Value::Error("Can't find any solutions to your equation") unless $OK;
- my ($P,@intervals) = $self->getIntervals($p,$n);
-
- #
- # Get relative tolerance values and make them absolute
- #
- my $minTolerance = $self->getFlag('ImplicitAbsoluteMinTolerance');
- my $maxTolerance = $self->getFlag('ImplicitAbsoluteMaxTolerance');
- my $tolerance = $f * $self->getFlag('ImplicitTolerance');
- $tolerance = $minTolerance if $tolerance < $minTolerance;
- $tolerance = $maxTolerance if $tolerance > $maxTolerance;
- $self->{tolerance} = $tolerance unless $self->{tolerance};
- $self->{bisect_tolerance} = $self->{tolerance} * $self->getFlag('BisectionTolerance')
- unless $self->{bisect_tolerance};
- $self->{point_tolerance} = $P * $self->getFlag('ImplicitPointTolerance')
- unless $self->{point_tolerance};
-
- #
- # Locate solutions to be used for comparison test
- #
- @zero = @{$z}; @zero = $zero[0..$num_points-1] if (scalar(@zero) > $num_points);
- for ($i = 0; scalar(@zero) < $num_points && $i < scalar(@intervals); $i++) {
- my $Q = $self->Bisect($intervals[$i][0],$intervals[$i][1]);
- push(@zero,$Q) if $Q;
- }
- Value::Error("Can't find enough solutions for an effective test")
- unless scalar(@zero) == $num_points;
-
- #
- # Save the solutions to the equation
- #
- $self->{solutions} = [@zero];
-}
-
-#
-# Get random points and sort them by sign of the function.
-# Also, get the average function value, and indicate if
-# we actually did find both positive and negative values.
-#
-sub getPositiveNegativeZero {
- my $self = shift; my $n = shift;
- my ($p,$v) = $self->SUPER::createRandomPoints(3*$n);
- my (@pos,@neg,@zero);
- my $f = 0; my $k = 0;
- foreach my $i (0..scalar(@{$v})-1) {
- if ($v->[$i] == 0) {push(@zero,$p->[$i])} else {
- $f += abs($v->[$i]); $k++;
- if ($v->[$i] > 0) {push(@pos,$p->[$i])} else {push(@neg,$p->[$i])}
- }
- }
- $f /= $k if $k;
- return (scalar(@pos) && scalar(@neg),[@pos],[@neg],[@zero],$f);
-}
-
-#
-# Make a list of positive and negative points sorted by
-# the distance between them. Also return the average distance
-# between points.
-#
-sub getIntervals {
- my $self = shift; my $pos = shift; my $neg = shift;
- my @intervals = (); my $D = 0;
- my $point = $self->Package("Point");
- my $context = $self->context;
- foreach my $p (@{$pos}) {
- foreach my $n (@{$neg}) {
- my $d = abs($point->make($context,@{$p}) - $point->make($context,@{$n}));
- push(@intervals,[$p,$n,$d]); $D += $d;
- }
- }
- @intervals = main::PGsort(sub {$_[0]->[2] < $_[1]->[2]},@intervals);
- return($D/scalar(@intervals),@intervals);
-}
-
-#
-# Use bisection algorithm to find a point where the function is zero
-# (i.e., where the original equation is an equality)
-# If we can't find a point (e.g., we are at a discontinuity),
-# return an undefined value.
-#
-sub Bisect {
- my $self = shift;
- my $tolerance = $self->getFlag('bisect_tolerance',1E-5);
- my $ptolerance = $self->getFlag('point_tolerance',1E-9);
- my $m = $self->getFlag('BisectionCutoff',30); my ($P,$f);
- my $point = $self->Package("Point"); my $context = $self->context;
- my $P0 = $point->make($context,@{$_[0]}); my $P1 = $point->make($context,@{$_[1]});
- my ($f0,$f1) = @{$self->createPointValues([$P0->data,$P1->data],1)};
- for (my $i = 0; $i < $m; $i++) {
- $P = ($P0+$P1)/2; $f = $self->createPointValues([$P->data]);
- return unless ref($f);
- $f = $f->[0];
- return [$P->value] if abs($f) < $tolerance && abs($P1-$P0) < $ptolerance;
- if ($f > 0) {$P0 = $P; $f0 = $f} else {$P1 = $P; $f1 = $f}
- }
- return;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/parserTables.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/parserTables.pl
deleted file mode 100755
index bd382392f6..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/parserTables.pl
+++ /dev/null
@@ -1,87 +0,0 @@
-loadMacros("parserUtils.pl");
-
-#############################################
-#
-# For Parser example tables:
-#
-
-$BTT = MODES(TeX=>'{\tt ', Latex2HTML => $bHTML.''.$eHTML, HTML => '');
-$ETT = MODES(TeX=>'}', Latex2HTML => $bHTML.''.$eHTML, HTML => '');
-
-$BC = MODES(
- TeX=>'{\small\it ',
- Latex2HTML => $bHTML.''.$eHTML,
- HTML => ''
-);
-$EC = MODES(
- TeX=>'}',
- Latex2HTML => $bHTML.''.$eHTML,
- HTML => ''
-);
-
-$LT = MODES(TeX => "<", Latex2HTML => "<", HTML => '<');
-$GT = MODES(TeX => ">", Latex2HTML => ">", HTML => '>');
-
-$TEX = MODES(TeX => '{\TeX}', HTML => 'TeX', HTML_dpng => '\(\bf\TeX\)');
-
-@rowOptions = (
- indent => 0,
- separation => 0,
- align => 'LEFT" NOWRAP="1', # alignment hack to get NOWRAP
-);
-
-sub ParserRow {
- my $f = shift; my $t = '';
- Context()->clearError;
- my ($s,$err) = PG_restricted_eval($f);
- if (defined $s) {
- my $ss = $s;
- if (ref($s) && \&{$s->string}) {
- $t = '\('.$s->TeX.'\)';
- $s = $s->string;
- } elsif ($s !~ m/^[a-z]+$/i) {
- $t = '\('.Formula($s)->TeX.'\)';
- $s = Formula($s)->string;
- }
- $s =~ s/$LT/g; $s =~ s/>/$GT/g;
- if (ref($ss) && \&{$ss->class}) {
- if ($ss->class eq 'Formula') {
- $s .= ' '.$BC.'(Formula returning '.$ss->showType.')'.$EC;
- } else {
- $s .= ' '.$BC.'('.$ss->class.' object)'.$EC;
- }
- }
- } else {
- $s = $BC. (Context()->{error}{message} || $err) . $EC;
- $t = '';
- }
- $f =~ s/$LT/g; $f =~ s/>/$GT/g;
- if ($displayMode eq 'TeX') {
- $f =~ s/\^/\\char`\\^/g; $s =~ s/\^/\\char`\\^/g;
- $f =~ s/#/\\#/g; $s =~ s/#/\\#/g;
- }
- my $row = Row([$BTT.$f.$ETT,$BTT.$s.$ETT,$t],@rowOptions);
- $row =~ s/\$/\${DOLLAR}/g;
- return $row;
-}
-
-sub ParserTable {
- my $table =
- BeginTable(border=>1, padding=>20).
- Row([$BBOLD."Perl Code".$EBOLD,
- $BBOLD."Result".$EBOLD,
- $BBOLD.$TEX.' version'.$EBOLD],@rowOptions);
- foreach my $f (@_) {$table .= ParserRow($f)}
- $table .= EndTable();
- return $table;
-}
-
-sub Title {
- my $title = shift;
-
- MODES(
- TeX => "\\par\\centerline{\\bf $title}\\par\\nobreak\n",
- Latex2HTML => $bHTML.'
'.$title.'
'.$eHTML,
- HTML => '
'.$title.'
'
- );
-}
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/parserUtils.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/parserUtils.pl
deleted file mode 100755
index 4db7dd5c4d..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/parserUtils.pl
+++ /dev/null
@@ -1,61 +0,0 @@
-loadMacros(
- "unionImage.pl",
- "unionTables.pl",
-);
-
-$bHTML = '\begin{rawhtml}';
-$eHTML = '\end{rawhtml}';
-
-# HTML(htmlcode)
-# HTML(htmlcode,texcode)
-#
-# Insert $html in HTML mode or \begin{rawhtml}$html\end{rawhtml} in
-# Latex2HTML mode. In TeX mode, insert nothing for the first form, and
-# $tex for the second form.
-#
-sub HTML {
- my ($html,$tex) = @_;
- return('') unless (defined($html) && $html ne '');
- $tex = '' unless (defined($tex));
- MODES(TeX => $tex, Latex2HTML => $bHTML.$html.$eHTML, HTML => $html);
-}
-
-#
-# Begin and end mode
-#
-$BTT = HTML('','\texttt{');
-$ETT = HTML('','}');
-
-#
-# Begin and end mode
-#
-$BSMALL = HTML('','{\small ');
-$ESMALL = HTML('','}');
-
-#
-# Block quotes
-#
-$BBLOCKQUOTE = HTML('
','\hskip3em ');
-$EBLOCKQUOTE = HTML('
');
-
-#
-# Smart-quotes in TeX mode, regular quotes in HTML mode
-#
-$LQ = MODES(TeX => '``', Latex2HTML => '"', HTML => '"');
-$RQ = MODES(TeX => "''", Latex2HTML => '"', HTML => '"');
-
-#
-# make sure all characters are displayed
-#
-sub protectHTML {
- my $string = shift;
- $string =~ s/&/\&/g;
- $string =~ s/\</g;
- $string =~ s/>/\>/g;
- $string;
-}
-
-sub _parserUtils_init {}
-
-1;
-
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/piecewiseFunctions.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/piecewiseFunctions.pl
deleted file mode 100755
index 3a903640d0..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/piecewiseFunctions.pl
+++ /dev/null
@@ -1,97 +0,0 @@
-#! /usr/local/bin/perl
-
-sub _piecewiseFunctions_init {}; # don't reload this file
-
-#
-# Implements a method of producing piecewise-defined functions that
-# works in all modes (TeX, Latex2HTML and HTML).
-#
-
-##################################################
-#
-# piecewiseFunction(name, [part1, part1-x, ...], options)
-#
-# Here, "name" is a string like "f(x)" that is the name of the
-# function,
-#
-# "part1" is the function's definition for piece one, e.g. "x+4".
-# (It is put in math mode automatically.)
-#
-# "part1-x" is the function's domain description, e.g., "if \(x $LTS 3\)".
-# (It is NOT in math mode automatically.)
-#
-# You can supply as many partN,partN-x pairs as needed.
-#
-# The options are:
-#
-# bracesize => n specifies height of braces for HTML modes
-# spacing => n gives row spacing for HTML
-#
-sub piecewiseFunction {
- my $f = shift;
- my $arrayref = shift; my @array = @{$arrayref};
- my %options = @_;
- set_default_options(\%options, bracesize => 0, spacing => 5);
- my ($size,$sep) = ($options{bracesize},$options{spacing});
- my ($output,$fx,$ifx) = ('','','');
-
- if ($displayMode eq 'HTML' || $displayMode eq 'HTML_tth') {
- #
- # A
hack to handle piecewise functions in HTML
- #
- $output =
- '
";
- } elsif ($displayMode =~ m/^HTML/ ||
- $displayMode eq "Latex2HTML" || $displayMode eq "TeX") {
- $output = '\[' . $f . '= \begin{cases}';
- while (@array) {
- $fx = shift(@array); $ifx = shift(@array);
- $ifx =~ s/\\\(/\}/g; $ifx =~ s/\\\)/\\text\{/g;
- $output .= $fx . '&\text{' . $ifx . '}\\\\' . "\n";
- }
- $output =~ s/\\text\{\}//g; $output =~ s/\\\\$//;
- $output .= '\end{cases}\]';
- } else {
- warn "piecewiseFunction: Unknown display mode: $displayMode"
- }
- return($output);
-}
-
-#
-# Characters that make up the brace in the symbol font
-#
-($brt,$brm,$brb,$brc) = ('','','','');
-
-#
-# Braces of different sizes (an alternative would be to
-# add $brc characters to extend the vertical parts).
-# If you want additional sizes, you can push more onto the end
-# of the array from within the .pg file, or add them here.
-#
-#
-@braceHTML = (
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb}
-);
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/planeAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/planeAnswer.pl
deleted file mode 100755
index 2efeccd883..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/planeAnswer.pl
+++ /dev/null
@@ -1,147 +0,0 @@
-loadMacros(
- 'unionAnswer.pl',
- 'unionMacros.pl',
- 'unionVectors.pl',
- 'vectorUtils.pl',
-);
-
-sub _planeAnswer_init {}; # don't reload this file
-
-#
-# Check that a formula represents a given plane implicitly
-#
-# Usage: implicit_plane_cmp(N,P);
-#
-# where N is a normal vector to the plane and P is a point on the
-# plane. Ex: plane_cmp(Vector(1,2,3),Point(0,0,0)); or
-# plane_cmp([1,2,3],[0,0,0]);
-#
-# The student enter's an answer in the form "a x + b y + c z = d",
-# or anything equivalent to that. This answer checking will properly
-# recognize the plane even if it is given as a different multiple of
-# the equation, or if it is reorganized, or has computations within it.
-# E.g., the student could enter "0 = 20 -(x + 3y + z)".
-#
-# The answer checker will produce the string used for displaying the
-# correct answer for you automatically, properly handling zero coefficients.
-#
-
-sub implicit_plane_cmp {
- my $N = Vector(shift); my $P = Point(shift);
- my %params = @_;
- set_default_options(\%params,
- showHints => 1,
- debug => 0,
- );
- my $answer = Plane($N,$P);
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => $answer,
- type => "implicit plane",
- N => $N, P => $P,
- );
- $answerEvaluator->install_evaluator(\&implicit_plane_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the implicit plane checker
-#
-sub implicit_plane_check {
- my $ans = shift;
- my %params = @_;
- my @errors = (); my $score = 0;
- my $showHints = $params{showHints};
- $showHints = 0 if ($showPartialCorrectAnswers == 0 || isPreviewMode());
- my ($text,$latex);
- my ($a,$b,$c,$d);
- my ($N,$P) = ($ans->{N}->data,$ans->{P}->data);
-
- my $student_ans = trimString($ans->{student_ans});
- #
- # Find the left- and right-hand sides
- #
- if ($student_ans !~ m/^(.*)=(.*)$/) {
- push(@errors,"Your answer is not of the form 'ax + by + cz = d'")
- if ($showHints);
- } else {
- my ($lhs,$rhs) = (trimString($1),trimString($2));
- push(@errors,"The left-hand side is blank") if $lhs eq '';
- push(@errors,"The right-hand side is blank") if $rhs eq '';
- if (scalar(@errors) == 0) {
- #
- # Do a syntax check on the two sides
- #
- my $cmp = fun_cmp("0",vars=>['x','y','z']);
- my $hash = evaluateAnswer($cmp,$lhs,1);
- if ($hash->{ans_message} eq "") {
- $lhs = $hash->{student_ans};
- $text = $hash->{preview_text_string};
- $latex = $hash->{preview_latex_string};
- } else {
- push(@errors,"Error evaluating left-hand side:");
- push(@errors,IndentError($hash->{student_ans}));
- push(@errors,IndentError($hash->{ans_message}));
- }
- clearEvaluator($cmp);
- $hash = evaluateAnswer($cmp,$rhs,1);
- if ($hash->{ans_message} eq "") {
- $rhs = $hash->{student_ans};
- $text .= " = ".$hash->{preview_text_string};
- $latex .= " = ".$hash->{preview_latex_string};
- } else {
- push(@errors,"Error evaluating right-hand side:");
- push(@errors,IndentError($hash->{student_ans}));
- push(@errors,IndentError($hash->{ans_message}));
- }
- clearEvaluator($cmp);
-
- if (scalar(@errors) == 0) {
- #
- # Use $cmp to evaluate student function to obtain coefficients
- #
- $cmp->{rh_ans}{evaluation_points} = [[0,0,0],[1,0,0],[0,1,0],[0,0,1]];
- $hash = evaluateAnswer($cmp,"($lhs)-($rhs)");
- # check for errors here, too?
- $d = $hash->{ra_student_values}->[0];
- $a = $hash->{ra_student_values}->[1] - $d;
- $b = $hash->{ra_student_values}->[2] - $d;
- $c = $hash->{ra_student_values}->[3] - $d;
- #
- # Check that the student function really IS a plane
- #
- $cmp = fun_cmp("$a x + $b y + $c z + $d",vars => ['x','y','z']);
- if (isCorrectAnswer($cmp,"($lhs)-($rhs)")) {
- #
- # Check that is is the RIGHT plane
- #
- $score = (areParallel($N,Point($a,$b,$c)) &&
- isCorrectAnswer(std_num_cmp(-$d),vDot($P,Point($a,$b,$c))));
- } else {
- push(@errors,
- "Your answer does not seem to be of the form 'ax + by + cz = d'")
- if ($showHints);
- }
- }
- $ans->setKeys(
- student_ans => $lhs." = ".$rhs,
- preview_text_string => $text,
- preview_latex_string => $latex,
- );
- }
- }
- if (scalar(@errors) == 0) {
- $ans->score($score);
- $ans->{ans_message} = $ans->{error_message} = '';
- $ans->{error} = 0;
- } else {
- $ans->score(0);
- $ans->{error_message} = join("\n",@errors);
- $ans->{ans_message} = join("\n",@errors);
- $ans->{error} = 1;
- }
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/pointAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/pointAnswer.pl
deleted file mode 100755
index f441598abd..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/pointAnswer.pl
+++ /dev/null
@@ -1,300 +0,0 @@
-loadMacros(
- "unionMacros.pl",
- "unionUtils.pl",
- "unionVectors.pl",
- "answerUtils.pl",
-);
-
-sub _pointAnswer_init {}; # don't reload this file
-
-######################################################################
-##
-## Point (and Vector) answer checkers
-##
-## num_point_cmp() check for a point with numeric coordinates
-## fun_point_cmp() check for a point with coordinate functions
-##
-## std_point_cmp() provide your own coordinate checker
-## point_cmp() provide array of coordiante checkers
-
-
-######################################################################
-#
-# num_point_cmp(answer,options)
-#
-# where options are from among:
-#
-# extra_cmp => cmp an answer checker to use for extra coordinates
-# supplied by the student (for syntax checking)
-#
-# cmp_params => [list] parameters to be passed to std_num_cmp
-# for each coordinate
-#
-# format => string an sprintf format string used to format
-# the answer (for display purposes only).
-# Default: "%.6g"
-#
-# or any of the options to point_cmp (see below).
-#
-# This provides an answer checker that compares against a point
-# or vector with numeric coordinates.
-#
-# e.g. num_point_cmp("(1,0,0)")
-#
-
-sub num_point_cmp {
- my $ans = shift;
- std_point_cmp($ans,cmp => \&std_num_cmp, format => '%.6g', @_);
-}
-
-
-######################################################################
-#
-# fun_point_cmp(answer,options)
-#
-# where options are from among:
-#
-# extra_cmp => cmp an answer checker to use for extra coordinates
-# supplied by the student (for syntax checking)
-#
-# cmp_params => [list] parameters to be passed to fun_cmp
-# for each coordinate
-#
-# vars => [list] the variables used in the functions
-#
-# or any of the options to point_cmp (see below).
-#
-# This provides an answer checker that compares against a point
-# or vector with functional coordinates.
-#
-# e.g. fun_point_cmp("(t,t^2,t^3)", vars => 't');
-#
-
-sub fun_point_cmp {
- my $ans = shift;
- my %params = (cmp_params => [], @_);
- if (defined($params{vars})) {
- $params{cmp_params} = [vars => $params{vars}, @{$params{cmp_params}}];
- delete $params{vars};
- }
- std_point_cmp($ans, cmp => \&fun_cmp, %params);
-}
-
-
-######################################################################
-#
-# std_point_cmp(ans,options)
-#
-# where ans is the correct answer as a string (e.g. "(1,0,0)") and
-# options are taken from among the following:
-#
-# cmp => \&cmp a reference to the answer checker to use for each
-# endpoint (e.g., \&std_num_cmp, or ~~&std_num_cmp
-# in a .pg file)
-#
-# cmp_params => [...] is a reference to a list of parameters for the
-# answer checker (e.g., [vars => 'x'])
-#
-# default => ans is the answer to use for any extra coordinates
-# supplied by the student (for syntax checking only)
-#
-# or any of the options allowed by point_cmp (see below)
-#
-# This returns an answer checker that compares the point using the
-# given answer checker on each coordinate.
-#
-# e.g. std_point_cmp("(1,0,0)",cmp => ~~&strict_num_cmp, default => 0);
-#
-sub std_point_cmp {
- my $ans = shift; $ans = $ans->answer if isVector($ans);
- my %params = (
- cmp => \&std_num_cmp,
- cmp_params => [],
- default => 0,
- @_
- );
- my ($cmp,$cmp_params) = ($params{cmp},$params{cmp_params});
- delete $params{cmp}; delete $params{cmp_params};
- my $default = $params{default}; delete $params{default};
- $params{extra_cmp} = &{$cmp}($default,@{$cmp_params})
- unless $params{extra_cmp};
- if ($ans =~ s/^(\[|\(|<)(.*)(>|\]|\))$/$2/)
- {$params{left} = $1; $params{right} = $3}
- my @answers = (); my $answer;
- foreach $answer (split(',',$ans))
- {push(@answers,&{$cmp}($answer,@{$cmp_params}))}
- point_cmp([@answers],%params);
-}
-
-
-######################################################################
-#
-# point_cmp(cmps,options)
-#
-# where
-#
-# cmps is a reference to an array of answer checkers, one
-# for each component of the answer
-#
-# and options are taken from:
-#
-# showHints => 0 or 1 determines if coordinate-by-coordinate
-# hints are given (tells whether each
-# coordinate is correct or not).
-# (default: 1)
-#
-# showLengthHints => 0 or 1 determines if messages about incorrect
-# number of components should be issued
-# (default: 1)
-#
-# extra_cmp => cmp an answer checker to use for any extra
-# coordinates supplied by the student
-# (for syntax checking purposes)
-#
-# format => string sprintf format for the coordinates
-#
-# post_process => code routine to determine the score once
-# the point passes the syntax checking
-# of the individual components. This
-# can be used to change the score
-# after the fact (e.g., to check for
-# parallel vectors, etc.)
-#
-sub point_cmp {
- my $compref = shift;
- my %params = @_;
- set_default_options(\%params,
- showHints => 1,
- showLengthHints => 1,
- extra_cmp => undef,
- post_process => undef,
- format => undef,
- debug => 0,
- left => '(',
- right => ')',
- );
- $params{components} = $compref;
- $params{pattern} = "\\$params{left}(.*)\\$params{right}"
- unless defined($params{pattern});
-
- #
- # Needed to get preview to work properly
- #
- my $type = "point"; my $hash;
- foreach $hash (@{$compref}) {
- if ((hashFor($hash))->{type} =~ m/number/) {
- $type .= " (number)";
- last;
- }
- }
-
- my @ans = (); my @ans_point = ();
- my $format = $params{format}; my $correct_ans;
- foreach $hash (@{$compref}) {
- $correct_ans = (hashFor($hash))->{correct_ans};
- push(@ans_point,$correct_ans);
- $correct_ans = sprintf($format,$correct_ans) if ($format);
- push(@ans,$correct_ans);
- }
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => $params{left}.' '.join(", ",@ans).' '.$params{right},
- correct_point => [@ans_point],
- components => $compref,
- type => $type,
- );
- $answerEvaluator->install_evaluator(\&point_check,%params);
- return $answerEvaluator;
-}
-
-######################################################################
-#
-# The guts of the point checker
-#
-sub point_check {
- my $ans = shift;
- my %params = @_;
- my @errors = (); my $score = 1;
- my $showHints = defined($params{showHints})?
- $params{showHints} : $showPartialCorrectAnswers;
- my $showLengthHints = defined($params{showLengthHints})?
- $params{showLengthHints} : $showPartialCorrectAnswers;
- $showHints = $showLengthHints = 0 if isPreviewMode();
-
- my $extra_cmp = $params{extra_cmp};
- $extra_comp = std_num_cmp(0) unless $extra_cmp;
- my ($lp,$rp) = ($params{left},$params{right});
- my ($addparens) = 1;
- my $format = $params{format};
- my (@new_ans,@new_ans_point);
-
- my $student_ans = trimString($ans->{student_ans});
- if ($student_ans !~ s/^$params{pattern}$/$1/) {
- my %parens = ('(' => "parentheses",
- '<' => "angle brackets",
- '[' => "square brackets");
- $parens{$lp} = "the proper characters" unless defined($parens{$lp});
- push(@errors,
- showHTML("Your answer is not enclosed in $parens{$lp}: $lp and $rp"));
- $score = 0;
- } else {
- my $i = 0; my @answers = split(',',$student_ans);
- my ($answer, $answer_full, $correct_cmp, @text, @latex);
-
- foreach $answer (@answers) {
- $correct_cmp = (@{$ans->{components}})[$i++] || $extra_cmp;
- $hash = evaluateAnswer($correct_cmp,$answer);
- $answer_full = $answer;
- if ($hash->{ans_message} eq "") {
- $answer_full = $answer = $hash->{student_ans};
- $answer = sprintf($format,$answer) if ($format);
- } else {$hash->{score} = 0}
- push(@new_ans,$answer); push(@new_ans_point,$answer_full);
- push(@text,StringOrBlank($hash->{preview_text_string},$answer));
- push(@latex,StringOrBlank($hash->{preview_latex_string},$answer));
- if ($hash->{score} != 1 || $correct_cmp == $extra_cmp) {
- $score = 0;
- if ($hash->{ans_message} ne "") {
- push(@errors,"Error evaluating the ".NameForNumber($i).
- " coordinate:");
- push(@errors,IndentError($answer));
- push(@errors,IndentError($hash->{ans_message}));
- } else {
- push(@errors,"The ".NameForNumber($i)." coordinate is incorrect.")
- if ($showHints);
- }
- }
- clearEvaluator($correct_cmp);
- }
-
- if (scalar(@answers) != scalar(@{$ans->{components}})) {
- push(@errors,"The number of coordinates is not correct.")
- if ($showLengthHints);
- $score = 0;
- }
- $ans->setKeys(student_ans => $lp . join(', ',@new_ans) . $rp)
- if (scalar(@new_ans) > 0);
- $ans->setKeys(
- preview_text_string => $lp . join(', ',@text) . $rp,
- preview_latex_string => $lp . join(', ',@latex) . $rp,
- );
- }
-
- # make sure vectors aren't interpretted as HTML tags
- $ans->setKeys(student_ans => showHTML($ans->{student_ans}));
-
- if (scalar(@errors) == 0) {
- $ans->score($score);
- $ans->{ans_message} = $ans->{error_message} = '';
- $ans->{answer_point} = [@new_ans_point];
- if ($params{post_process}) {$ans->score(&{$params{post_process}}($ans))}
- } else {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} = join("\n",@errors);
- }
-
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/unionAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/unionAnswer.pl
deleted file mode 100755
index 3b3f1a6a0e..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/unionAnswer.pl
+++ /dev/null
@@ -1,56 +0,0 @@
-######################################################################
-#
-# Implements answer checkers for unions of intervals
-#
-
-loadMacros(
- "intervalAnswer.pl",
- "listAnswer.pl"
-);
-
-sub _unionAnswer_init {
- $INFINITY_UNION_MESSAGE =
- "$BBOLD Note: $EBOLD ".
- "If the answer includes more than one interval, write the intervals ".
- "separated by the ${LQ}union$RQ symbol, ${BITALIC}U${EITALIC}. If needed, enter ".
- "\\(\\infty\\) as ${BITALIC}$INFINITY_WORD${EITALIC} and \\(-\\infty\\) as ".
- "${BITALIC}-$INFINITY_WORD${EITALIC}.";
-
- $INFINITY_UNION_MESSAGE = "" if $displayMode eq 'TeX';
-};
-
-######################################################################
-#
-# Usage: num_union_cmp(ans,options)
-# fun_union_cmp(ans,options)
-#
-# where ans is the string indicating the union (e.g., "[1,3) U (-inf,-5)")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_union_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_interval_cmp,
- type => "number interval union",
- entry_type => 'interval',
- list_type => 'union',
- separator => ' U ',
- split_defaults => [separator => 'U'],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_union_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_interval_cmp,
- type => "function interval union",
- entry_type => 'interval',
- list_type => 'union',
- separator => ' U ',
- split_defaults => [separator => 'U'],
- cmp_ans => "(0,1]",
- fun_var_params(cmp_defaults => [showHints => 0],@_));
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/unorderedAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/unorderedAnswer.pl
deleted file mode 100755
index 477ac31a18..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/unorderedAnswer.pl
+++ /dev/null
@@ -1,162 +0,0 @@
-##########################################################################
-##########################################################################
-##
-## Routines for groups of answer blanks where the user can enter
-## answers in any order in the blanks.
-##
-
-loadMacros("answerUtils.pl");
-
-sub _unorderedAnswer_init {}; # don't reload this file
-
-##########################################################################
-#
-# Collect a group of answer checkers for use with answers that can be given
-# in any order. If N answer checkers are given, then the last N answer
-# rules will be used. It is beter to use named rules and UNORDERED_NAMED_ANS
-# below. Otherwise, be sure to use UNORDERED_ANS right after the answer
-# rules for the answers you want to compare.
-#
-# Format:
-#
-# UNORDERED_ANS(checker1, checker2, ...);
-#
-# Example:
-#
-# BEGIN_TEXT
-# The function \(f(x) = \frac{1}{x^2-$a}\) is defined except
-# for \(x =\) \{ans_rule(10)\} and \(x =\) \{ans_rule(10)\}.
-# END_TEXT
-#
-# UNORDERED_ANS(std_num_cmp(sqrt($a)), std_num_cmp(-sqrt($a)));
-#
-# (the student can enter the solutions in either order.)
-#
-sub UNORDERED_ANS {
- my @cmp = @_; my @params = (); my $i; my $n = scalar(@cmp);
- #
- # The best thing would be to use the size of @PG_ANSWERS in place of
- # $main::ans_rule_count, but we don't have access to that
- #
- foreach $i (1..$n)
- {push(@params,ANS_NUM_TO_NAME($i+main::ans_rule_count()-$n),$cmp[$i-1])}
- my @results = unordered_answer_list(@params);
- while (scalar(@results) > 0) {shift(@results), ANS(shift(@results))}
-}
-
-##########################################################################
-#
-# Collect a group of answer checkers for use with named answers that
-# can be given in any order.
-#
-# Format:
-#
-# UNORDERED_NAMED_ANS(name1 => checker1, name2 => checker2, ...);
-#
-# Example:
-#
-# BEGIN_TEXT
-# The function \(f(x) = \frac{1}{x^2-$a}\) is defined except
-# for \(x =\) \{NAMED_ANS_RULE(A1,10)\}
-# and \(x =\) \{NAMED_ANS_RULE(A2,10)\}.
-# END_TEXT
-#
-# UNORDERED_NAMED_ANS(
-# A1 => std_num_cmp(sqrt($a)),
-# A2 => std_num_cmp(-sqrt($a))
-# );
-#
-# (the student can enter the solutions in either blank.)
-#
-sub UNORDERED_NAMED_ANS {
- NAMED_ANS(unordered_answer_list(@_));
-}
-
-##########################################################################
-#
-# Low-level routine for handling unordered collections of answer checkers
-#
-sub unordered_answer_list {
- my %params = @_; my @args = @_;
- my (@cmp,@ids);
- while (scalar(@_) > 0) {push(@ids,shift); push(@cmp,shift)}
- #
- # Setup
- #
- my ($i,$j,$k);
- my $n = scalar(@cmp);
- my @cmpi = (0..$n-1);
- my @skipped = ();
- #
- # Check that the answers exist (otherwise it's our first time through)
- #
- foreach $i (@ids) {return(@args) if (!defined($inputs_ref->{$i}))}
- #
- # Check each answer against the available answer checkers.
- # Keep track of the ones that match and that don't.
- #
- ANSWER: foreach $i (0..$n-1) {
- $k = 0;
- foreach $j (@cmpi) {
- if (isCorrectAnswer($cmp[$j],$inputs_ref->{$ids[$i]}))
- {$ans[$i] = $j; splice(@cmpi,$k,1); next ANSWER}
- $k++;
- }
- push(@skipped,$i);
- }
- #
- # Check if the unmatched checkers are all blank checkers.
- # If so, let them report blanks as correct answers.
- #
- my $blankOK = 1;
- foreach $i (@cmpi) {
- if (ref($cmp[$i]) ne "AnswerEvaluator" ||
- ($cmp[$i]->rh_ans)->{type} ne "blank") {$blankOK = 0; last}
- }
- if ($blankOK) {foreach $i (@cmpi) {($cmp[$i]->rh_ans)->{blankOK} = 1}}
- #
- # Assign the unmatching answers to umatched checkers
- #
- foreach $i (0..scalar(@skipped)-1) {$ans[$skipped[$i]] = $cmpi[$i]}
- #
- # Make the final list of answer checkers in their proper order
- #
- my (@list) = ();
- foreach $i (0..$n-1)
- {clearEvaluator($cmp[$ans[$i]]); push(@list,$ids[$i],$cmp[$ans[$i]])}
- return (@list);
-}
-
-##################################################
-#
-# AnswerChecker that allows a blank answer in a collection of unordered
-# answer checkers. It will return "correct" for a blank answer only if
-# all the other answers are correct. (The blankOK value is set by
-# unordered_answer_list when this is true.) This lets you ask a question
-# where the number of answers is not known (by the student) ahead of time.
-#
-sub blank_cmp {
- my %params = @_;
- $params{debug} = 0 unless defined($params{debug});
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- type => "blank", blankOK => 0,
- correct_ans => '', weight => 0
- );
- $answerEvaluator->install_pre_filter('reset'); # remove the blank filter
- $answerEvaluator->install_evaluator(\&blank_cmp_check,%params);
- $answerEvaluator->install_post_filter('reset'); # remove the blank filter
- return $answerEvaluator;
-}
-
-sub blank_cmp_check {
- my $ans = shift;
- my %params = @_;
- $ans->{student_ans} = trimString($ans->{student_ans});
- if ($ans->{student_ans} eq "") {$ans->score($ans->{blankOK})}
- else {$ans->score(0)}
- return($ans);
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/variableAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/variableAnswer.pl
deleted file mode 100755
index 88f68bd8bc..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/variableAnswer.pl
+++ /dev/null
@@ -1,94 +0,0 @@
-sub _variableAnswer_init {}; # don't reload this file
-
-##################################################
-#
-# A match on a collection of comma- or space-separated
-# strings, optionally enclosed in parentheses.
-# The match can be case insensitive, and order insensitive.
-#
-# Usage: variable_cmp(ans,options)
-#
-# where ans is the correct answer string (or an array of the answers,
-# which will be made into a comma-separated string), and options
-# are taken from:
-#
-# ignore_case => 0 or 1 determines wether upper- and
-# lower-case are to be distinguished or not
-# (Default: 0)
-#
-# ignore_order => 0 or 1 determines whether the order of the
-# answers matters or not
-# (Default: 0)
-#
-# allow_parens => 0 or 1 determines whether parens are stripped
-# from around the answer automatically
-# (Default: 1)
-#
-# force_parens => 0 or 1 determines whether parens are
-# required in the student's answer
-# (Default: 0)
-
-sub variable_cmp {
- my $answer = shift || '';
- $answer = join(',',@{$answer}) if ref($answer) eq 'ARRAY';
- $answer = trimString($answer);
- my %params = @_;
- set_default_options(\%params,
- ignore_case => 0,
- ignore_order => 0,
- allow_parens => 1,
- force_parens => 0,
- );
- $answer = '('.$answer.')' if $params{force_parens} && $answer !~ m/^\(.*\)$/;
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug} || 0;
- $answerEvaluator->ans_hash(type => "variable", correct_ans => $answer);
- $answerEvaluator->install_evaluator(\&variable_cmp_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the checker
-#
-sub variable_cmp_check {
- my $ans = shift;
- my %option = @_;
- my $student_ans = $ans->{student_ans};
- my $correct_ans = $ans->{correct_ans};
- $student_ans = trimString($student_ans);
- $ans->setKeys(
- student_ans => $student_ans,
- original_student_ans => $student_ans,
- preview_text_string => $student_ans,
- preview_latex_string => $student_ans,
- ans_message => ''
- );
- if ($option{force_parens}) {
- if ($student_ans !~ m/^\(.*\)$/) {
- $ans->{ans_message} = "Your answer isn't enclosed in parentheses";
- $ans->{error} = 1; $ans->score(0); return $ans;
- }
- $option{allow_parens} = 1;
- }
- if ($option{allow_parens}) {
- $student_ans =~ s/^\((.*)\)$/$1/; $correct_ans =~ s/^\((.*)\)$/$1/;
- if ($student_ans =~ m/^\(|\)$/) {
- $ans->{ans_message} = "Incorrect parentheses";
- $ans->{error} = 1; $ans->score(0); return $ans;
- }
- }
- $student_ans =~ s/,/ /g; $correct_ans =~ s/,/ /g;
- $student_ans =~ s/\s+/ /g; $correct_ans =~ s/\s+/ /g;
- if ($option{ignore_case}) {
- $student_ans = lc($student_ans);
- $correct_ans = lc($correct_ans);
- }
- if ($option{ignore_order}) {
- $student_ans = join(' ',lex_sort(split(' ',$student_ans)));
- $correct_ans = join(' ',lex_sort(split(' ',$correct_ans)));
- }
- $ans->score($student_ans eq $correct_ans);
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/vectorAnswer.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/vectorAnswer.pl
deleted file mode 100755
index f08a9dec80..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/vectorAnswer.pl
+++ /dev/null
@@ -1,11 +0,0 @@
-loadMacros("pointAnswer.pl","vectorUtils.pl");
-
-#
-# Just a renaming of the point comparisons.
-#
-sub num_vector_cmp {num_point_cmp(@_)}
-sub fun_vector_cmp {fun_point_cmp(@_)}
-sub std_vector_cmp {std_point_cmp(@_)}
-sub vector_cmp {point_cmp(@_)}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/vectorUtils.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/vectorUtils.pl
deleted file mode 100755
index f537c5bca4..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/vectorUtils.pl
+++ /dev/null
@@ -1,121 +0,0 @@
-#####################################################################
-#
-# Some utility routines that are useful in vector problems
-#
-
-sub _vectorUtils_init {}; # don't reload this file
-
-##################################################
-
-#
-# formats a vector name (should be used in math mode)
-#
-# Vectors will be in bold italics in HTML modes, and
-# will be overlined in TeX modes. (Bold italic could also work in
-# TeX modes, but the low resolution on screen made it less easy
-# to distinguish the difference between bold and regular letters.)
-#
-sub Overline {
- my $v = shift;
- my $HTML = ''.$v.'';
- MODES(
- TeX => "\\overline{$v}",
- HTML => $HTML,
- HTML_tth => '\begin{rawhtml}'.$HTML.'\end{rawhtml}',
- HTML_dpng => "\\overline{$v}",
- );
-}
-
-#
-# This gets a bold letter in TeX as well as HTML modes.
-# Although \boldsymbol{} works fine on screen in latex2html mode,
-# the PDF file produces non-bold letters. I haven't been able to
-# track this down, so used \mathbf{} in TeX mode, which produces
-# roman bold, not math-italic bold.
-#
-sub BoldMath {
- my $v = shift;
- my $HTML = ''.$v.'';
- MODES(
- TeX => "\\boldsymbol{$v}", # doesn't seem to work in TeX mode
-# TeX => "\\mathbf{$v}", # gives non-italic bold in TeX mode
- Latex2HTML => "\\boldsymbol{$v}",
- HTML => $HTML,
- HTML_tth => '\begin{rawhtml}'.$HTML.'\end{rawhtml}',
- HTML_dpng => "\\boldsymbol{$v}",
- );
-}
-
-#
-# The coordinate unit vectors
-#
-#if ($main::displayMode eq "TeX") {
- $i = BoldMath('i');
- $j = BoldMath('j');
- $k = BoldMath('k');
-#} else {
-# $i = Overline(MODES(TeX=>'\imath',HTML=>'i'));
-# $j = Overline(MODES(TeX=>'\jmath',HTML=>'j'));
-# $k = Overline('k');
-#}
-
-#
-# Grad sumbol
-#
-$GRAD = '\nabla ';
-
-#
-# Create a non-zero point with the given number of coordinates
-# with the given random range (which defaults to (-5,5,1)).
-#
-# non_zero_point(n,a,b,c)
-#
-sub non_zero_point {
- my $n = shift; my $k = $n; my @v = ();
- my $a = shift || -5; my $b = shift || $a + 10; my $c = shift || 1;
- while ($k--) {push(@v,random($a,$b,$c))}
- if (Norm(@v) == 0) {$v[random(0,$n-1,1)] = non_zero_random($a,$b,$c)}
- return Point(@v);
-}
-sub non_zero_point2D {non_zero_point(2,@_)}
-sub non_zero_point3D {non_zero_point(3,@_)}
-
-#
-# Same but for Vectors
-#
-sub non_zero_vector {Vector(non_zero_point(@_))}
-sub non_zero_vector2D {non_zero_vector(2,@_)}
-sub non_zero_vector3D {non_zero_vector(3,@_)}
-
-#
-# Form the string for a line given its point and vector
-#
-# Usage: line(P,V); or line(P,V,'t');
-#
-# where P is the point and V the direction vector for the line, and
-# t is the variable to use (default is 't').
-#
-# Ex: Line([1,-3],[2,1]) produces Vectir("1+2t","-3+t").
-# Ex: Line(Point(1,-3),Vector(2,1)) produces Vector("1+2t","-3+t").
-#
-sub Line {
- my @p = Point(shift)->value; my @v = Vector(shift)->value;
- my $t = shift; $t = 't' unless $t;
- my @coords = ();
- if ($#p != $#v) {die "Dimensions of point and vector don't match"}
- foreach my $i (0..$#p) {push(@coords,FPOLY("$p[$i]+$v[$i]$t",$t))}
- return Vector(@coords);
-}
-
-#
-# Creates a displayable string for a plane given its
-# normal vector and a point on the plane.
-#
-# Usage: plane(N,P);
-#
-sub Plane {
- my $N = Vector(shift); my $P = Point(shift); my @N = $N->value;
- FPOLY("$N[0] x + $N[1] y + $N[2] z = ".vDot($N,$P));
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/CollegeOfIdaho/weightedGrader.pl b/OpenProblemLibrary/macros/CollegeOfIdaho/weightedGrader.pl
deleted file mode 100755
index e294444051..0000000000
--- a/OpenProblemLibrary/macros/CollegeOfIdaho/weightedGrader.pl
+++ /dev/null
@@ -1,331 +0,0 @@
-loadMacros('unionUtils.pl');
-
-sub _weightedGrader_init {}; # don't reload this file
-
-######################################################################
-#
-# A weighted grader that allows you to assign arbitrary percentages
-# to the various answers in a problem. It also allows you to indicate
-# that answering one part correctly will give you credit for some
-# other part(s). This way, if there are several parts leading up to
-# a "goal" answer, and the student produces the goal answer by
-# some other means, he can be given full credit for the problem anyway.
-#
-#
-# WEIGHTED ANSWERS:
-#
-# Each problem is assigned a weight (the default is 1). The
-# student's score is then the sum of the weights for his correct
-# answers divided by the total of the weights for all answers. (To
-# assign weights as percentages, use integers that add up to 100, eg,
-# use 40 and 60 for the weights for two answers.)
-#
-# There are two ways to assign weights. The first is to use the
-# WEIGHTED_ANS() routine (in place of ANS) to give an answer checker
-# plus a weight.
-#
-# Example:
-#
-# WEIGHTED_ANS(std_num_cmp($ans1),2);
-#
-# This assigns a weight of 2 to the corresponding numeric answer.
-#
-# As with ANS(), WEIGHTED_ANS() can take more than one answer checker and
-# weight.
-#
-# Example:
-#
-# WEIGHTED_ANS(
-# std_num_cmp($ans1), 40,
-# std_num_cmp($ans2), 60
-# );
-#
-# This assigns 40% to the first answer and 60% to the second answer.
-#
-# The second way of assigning a weight is through the weight_ans()
-# function. This takes a single answer checker and weight and returns
-# a new answer checker of the same type that has the desired weight.
-# Thus
-#
-# ANS(weight_ans(std_num_cmp($ans1),2));
-#
-# is equivalent to the first example above.
-#
-# The main purpose for weighted_ans() is so that weights can be used
-# with UNORDERED_ANS(), or in other places where you want to use the
-# weighted answer checker directly. For example:
-#
-# UNORDERED_ANS(
-# weight_ans(std_num_cmp($ans1),40),
-# weight_ans(std_num_cmp($ans2),60),
-# );
-#
-# produces two answers whose order doesn't matter, but the student
-# will get 40% for getting $ans1 and 60% for getting $ans2 (no matter
-# what order they appear in).
-#
-# Note that the blank_cmp() answer checker has a weight of 0 by
-# default. You can override this using weight_ans(); for example,
-# weight_ans(blank_cmp(),1) makes the blank count the same as all
-# the other answers. (If there are two or more non-blank answers,
-# then having the blanks with weight 0 will allow the observant
-# student to deduce the number of blank answers from the percentage
-# for a single correct answer, provided all the non-blank answers are
-# equally weighted).
-#
-# Once you have given weights to the answers, you also need to
-# install the weighted grader. Do this using the command
-#
-# install_weighted_grader();
-#
-#
-# HAVING ONE ANSWER PROVIDE CREDIT FOR ANOTHER:
-#
-# You may want to have a correct answer for one problem automatically
-# give credit for one or more other parts of the problem. For example
-# If several parts are used to lead up to the "real" answer to the
-# problem, and the student produces that final answer without doing
-# the intermediate parts (perhaps using some other method), then you
-# may want to give the student full credit for the problem anyway.
-# You can do so in the following way.
-#
-# First, let us call the final answer the "goal" answer, and the
-# answer that it would give automatic credit for the "optional" answer.
-#
-# The optional answer blank must be a named answer, e.g.,
-#
-# BEGIN_TEXT
-# You get credit for this answer: \{NAMED_ANS_RULE('optional',10)\}
-# When you answer this one: \{ans_rule(10)\}
-# END_TEXT
-# NAMED_ANS('optional',std_num_cmp(5));
-#
-# Then for the goal answer, in place of ANS, use CREDIT_ANS, listing the
-# optional answer as the second argument:
-#
-# CREDIT_ANS(std_num_cmp(10),'optional');
-#
-# You could also use NAMED_WEIGHTED_ANS for the optional answer, and
-# supply a third argument for CREDIT_ANS, which is the weight for the
-# goal answer. For example:
-#
-# NAMED_WEIGHTED_ANS('optional',std_num_cmp(5),20);
-# CREDIT_ANS(std_num_cmp(10),'optional',80);
-#
-# This way, if the student gets the optional part right (but not the
-# goal), he gets 20%, and if he gets the goal right, he gets 100%.
-#
-# One can use CREDIT_ANS to give credit for several other (named)
-# answers at once by passing a list of names rather than a single one,
-# as in:
-#
-# CREDIT_ANS(std_num_cmp(10),['optional1','optional2'],80);
-#
-# The weight_ans() routine, described in the section above, also can
-# be used to give credit to another answer. In addition to the
-# answer-checker and the weight, you can pass an answer name (or
-# list of names) that should get credit when this one is right.
-# For example
-#
-# ANS(weight_ans(std_num_cmp(10),80,'optional'));
-#
-# is equivalent to
-#
-# CREDIT_ANS(std_num_cmp(10),'optional',80);
-#
-# One caveat to keep in mind is that credit is given to the optional
-# answer ONLY if the answer is left blank (or is actually correct).
-# Credit will NOT be given if the answer is incorrect, even if the
-# goal answer IS correct.
-#
-# When credit IS given, the blank answer is still marked as incorrect
-# in the grey answer report at the top of the page, but the student
-# gets awarded the points for that answer anyway (with no other
-# indication). It is possible to cause the blank to be marked as
-# correct, but this seemed confusing to the students.
-#
-# Once you have issued the various ANS calls, you also need to
-# install the weighted grader. Do this using the command
-#
-# install_weighted_grader();
-#
-
-##################################################
-#
-# Issue ANS() calls for the weighted checkers
-#
-sub WEIGHTED_ANS {
- my ($checker,$weight);
- while (@_) {
- $checker = shift; $weight = shift;
- ANS(weight_ans($checker,$weight));
- }
-}
-
-##################################################
-#
-# Issue NAMED_ANS() calls for the weighted checkers
-#
-sub NAMED_WEIGHTED_ANS {
- my ($name,$checker,$weight);
- while (@_) {
- $name = shift; $checker = shift; $weight = shift;
- NAMED_ANS($name,weight_ans($checker,$weight));
- }
-}
-
-##################################################
-#
-# Issue an ANS() call for the checker, giving
-# credit to the given answers.
-#
-sub CREDIT_ANS {
- my $checker = shift;
- my $credit = shift;
- $credit = [$credit] if defined($credit) && ref($credit) ne "ARRAY";
- my $weight = shift;
- ANS(weight_ans($checker,$weight,$credit));
-}
-
-
-##################################################
-#
-# Either add a weight to an AnswerEvaluator, or return a
-# new checker that adds the weight to its result. Also,
-# add the "credit" field, if supplied.
-#
-sub weight_ans {
- my $checker = shift; my $weight = shift;
- my $credit = shift;
- $credit = [$credit] if defined($credit) && ref($credit) ne "ARRAY";
- if (ref($checker) eq "AnswerEvaluator") {
- $checker->{rh_ans}->{weight} = $weight;
- $checker->{rh_ans}->{credit} = $credit if defined($credit);
- return $checker;
- } else {
- my $newChecker = sub {
- my $hash = &{$checker}(@_);
- $hash->{weight} = $weight;
- $checker->{rh_ans}->{credit} = $credit if defined($credit);
- return $hash;
- };
- return $newChecker;
- }
-}
-
-
-##################################################
-#
-# This is the weighted grader. It uses an extra field added to the
-# AnswerHash (named "weight") to tell how much weight to give each
-# problem. The grader adds up the total weights for the correct
-# answers. For partially correct ones, it uses the score for that
-# answer to give a portion of that weight. For example, if the
-# weight is 40 and the score for the answer is .5, then 20 is added
-# to the total for the problem. (Note that most answer checkers only
-# return 1 or 0, but they are allowed to return partial credit as
-# well.)
-#
-# When the student's total is computed, it is divided by the sum of
-# all the weights in order to determine the final score.
-#
-# It also uses a special field called "credit" that determines
-# what other (named) answers are given full credit if the given
-# answer is correct. This can be used to make "optional" answers,
-# where getting the "final" answer right gives credit for the other parts.
-#
-
-sub weighted_grader {
- my $rh_evaluated_answers = shift;
- my $rh_problem_state = shift;
- my %form_options = @_;
- my %answers = %{$rh_evaluated_answers};
- my %problem_state = %{$rh_problem_state};
-
- my %problem_result = (
- score => 0,
- errors => '',
- type => 'weighted_grader',
- msg => '',
- );
-
- if (scalar(keys(%answers)) == 0) {
- $problem_result{msg} = "This problem did not ask any questions.";
- return(\%problem_result,\%problem_state);
- }
-
- return(\%problem_result,\%problem_state)
- if (!$form_options{answers_submitted});
-
- my ($score,$total) = (0,0);
- my ($weight,$ans_name,$credit_name);
- my (%credit);
-
- #
- # Get the score for each answer
- # (error if can't recognize the answer format).
- #
- foreach $ans_name (keys %answers) {
- if (ref($answers{$ans_name}) =~ m/^(HASH|AnswerHash)$/) {
- $credit{$ans_name} = $answers{$ans_name}->{score};
- } else {
- die "Error at file ",__FILE__,"line ", __LINE__,": Answer |$ans_name| " .
- "is not a hash reference\n" . $answers{$ans_name} .
- "\nThis probably means that the answer evaluator for ".
- "this answer is not working correctly.";
- $problem_result{error} =
- "Error: Answer $ans_name is not a hash: $answers{$ans_name}";
- }
- }
-
- #
- # Mark any optional answers as correct, if the goal answers
- # are right and the optional ones are blank.
- #
- foreach $ans_name (keys %answers) {
- if ($credit{$ans_name} == 1 &&
- defined($answers{$ans_name}->{credit})) {
- foreach $credit_name (@{$answers{$ans_name}->{credit}}) {
- $credit{$credit_name} = 1
- if (trimString($answers{$credit_name}->{student_ans}) eq "");
- }
- }
- }
-
- #
- # Add up the weighted scores
- #
- foreach $ans_name (keys %answers) {
- $weight = $answers{$ans_name}->{weight};
- $weight = 1 unless (defined($weight));
- $total += $weight;
- $score += $weight * $credit{$ans_name};
- }
-
- $problem_result{score} = $score/$total if $total;
-
- # This gets rid of non-numeric scores
- $problem_state{recorded_score} = 0
- unless (defined($problem_state{recorded_score}) &&
- isNumber($problem_state{recorded_score}));
-
- $problem_state{recorded_score} = $problem_result{score}
- if ($problem_result{score} > $problem_state{recorded_score});
-
- $problem_state{num_of_correct_ans}++ if ($score == $total);
- $problem_state{num_of_incorrect_ans}++ if ($score < $total);
- warn "Error in grading this problem: ".
- "the score is larger than the total ($score > $total)"
- if $score > $total;
-
- (\%problem_result, \%problem_state);
-}
-
-
-##################################################
-#
-# Syntactic sugar to avoid ugly ~~& construct in PG.
-#
-sub install_weighted_grader {install_problem_grader(\&weighted_grader)}
-
-1;
diff --git a/OpenProblemLibrary/macros/Dartmouth/Dartmouthmacros.pl b/OpenProblemLibrary/macros/Dartmouth/Dartmouthmacros.pl
deleted file mode 100755
index a1a6ce63d2..0000000000
--- a/OpenProblemLibrary/macros/Dartmouth/Dartmouthmacros.pl
+++ /dev/null
@@ -1,313 +0,0 @@
-#!/usr/bin/perl
-
-# this is equivalent to use strict, but can be used within the Safe compartment.
-BEGIN{
- be_strict;
-}
-
-## Some local macros
-
-sub trs_mod{
- my @inputs = @_;
- my $a = $inputs[0];
- my $b = $inputs[1];
- my $zero = 1e-12;
- if ($b < 0) {$b = - $b;}
-
-## Want mod(a,b) but perl and int are flawed
- my $modvalue = $a;
-# if ($a >= 0 && $a < $b) {$modvalue = $a;}
-
- while ($modvalue >= $b){$modvalue = $modvalue - $b;}
- while ($modvalue < 0) {$modvalue = $modvalue + $b;}
- if (abs($modvalue) <= $zero){$modvalue = 0;}
- if (abs($modvalue - $b) <= $zero){$modvalue = 0;}
-## Fudge for roundoff error
- return $modvalue;
-}
-
-## Compute the product of a scalar and a vector (scalar first)
-sub scalar_mult_vector{
- ## Put the parameters passed into an array of values
- my @vector = @_;
-
- ## Split off the first entry as the scalar, and the rest as the vector
- my $scalar = $vector[0];
- my @vectorb = @vector[(1 .. $#vector )];
-
- ## Initialize scalar multiple as empty vector
- my @scalar_multiple=();
-
- my $i;
- for ($i=0; $i <= $#vectorb; $i++)
- {
- $scalar_multiple[$i] = $scalar * $vectorb[$i];
- }
- return @scalar_multiple;
-}
-
-
-
-## Compute the sum of two vectors
-## Perl doesn't seem to have builtin array arithmetic
-sub vector_sum {
- ## Put the parameters passed into an array of values
- my @vector = @_;
- ## $#vector is the number of elements in vector minus 1
- my $halflength = ($#vector - 1)/2;
- ## Slice the input into two equal length vectors
- my @vectora = @vector[(0 .. $halflength)];
- my @vectorb = @vector[($halflength+1 .. $#vector )];
-
- ## Initialize vector sum to empty array
- my @vector_sum=();
-
- my $i;
- for ($i=0; $i <= $#vectora; $i++)
- {
- $vector_sum[$i] = $vectora[$i] + $vectorb[$i];
- }
- return @vector_sum;
-}
-
-## Compute the difference of two vectors
-sub vector_diff{
- ## Put the parameters passed into an array of values
- my @vector = @_;
- ## $#vector is the number of elements in vector minus 1
- my $halflength = ($#vector - 1)/2;
- ## Slice the input into two equal length vectors
- my @vectora = @vector[(0 .. $halflength)];
- my @vectorb = @vector[($halflength+1 .. $#vector )];
-
- return vector_sum(@vectora, scalar_mult_vector(-1, @vectorb));
-}
-
-
-## Compute the length of a vector
-sub vec_length {
- ## Put the paramaters passed into an array of values
- my @vector = @_;
-
- ## Initialize maximum value to first element
- my $vector_length = 0;
-
- my $i;
- for ($i=0; $i <= $#vector; $i++)
- {
- $vector_length = $vector_length + $vector[$i] * $vector[$i];
- }
- $vector_length = sqrt($vector_length);
- return $vector_length;
-}
-
-sub vector_length {
- my @vector = @_;
- return vec_length(@vector);
-}
-
-## Computes the dot product of two vectors (assumed of the same dimension)
-sub dot_product {
- ## Put the parameters passed into an array of values
- my @vector = @_;
- ## $#vector is the number of elements in vector minus 1
- my $halflength = ($#vector - 1)/2;
- ## Split the input into two equal length vectors
- my @vectora = @vector[(0 .. $halflength)];
- my @vectorb = @vector[($halflength+1 .. $#vector )];
-
- ## Initialize dot product to zero
- my $dot = 0;
-
- my $i;
- for ($i=0; $i <= $#vectora; $i++)
- {
- $dot = $dot + $vectora[$i] * $vectorb[$i];
- }
- return $dot;
-}
-
-sub cross_product {
- ## Put the parameters passed into an array of values
- my @vector = @_;
-
- ## Slice the input into two equal length vectors
- my @vectora = @vector[(0 .. 2)];
- my @vectorb = @vector[(3 .. 5)];
-
- ## Initialize dot product to zero
- my @cross = ();
-
- $cross[0] = $vectora[1]*$vectorb[2] - $vectora[2]*$vectorb[1];
- $cross[1] = $vectora[2]*$vectorb[0] - $vectora[0]*$vectorb[2];
- $cross[2] = $vectora[0]*$vectorb[1] - $vectora[1]*$vectorb[0];
- return @cross;
-}
-
-## Compute the maximum value in a list
-#sub max {
-# ## Put the paramters passed into an array of values
-# my @values = @_;
-#
-# ## Initialize maximum value to first element
-# my $max = $values[0];
-#
-# my $i;
-# for ($i=1; $i <= $#values; $i++)
-# {
-# if ($values[$i] > $max) {
-# $max = $values[$i];
-# }
-# }
-# return $max;
-#}
-
-## Compute the minimum value in a list
-#sub min {
-# ## Put the paramters passed into an array of values
-# my @values = @_;
-#
-# ## Initialize minimum value to first element
-# my $min = $values[0];
-#
-# my $i;
-# for ($i=1; $i <= $#values; $i++)
-# {
-# if ($values[$i] < $min) {
-# $min = $values[$i];
-# }
-# }
-# return $min
-#}
-
-
-## clean_scalar_string is invoked to make expressions like "$a x" look
-## better when $a = 0, -1, 1
-## Usage: clean_scalar_string(scalar, "quoted string");
-## Example: clean_scalar_string(-1,"\pi") returns "-\pi"
-sub clean_scalar_string{
- my $local_scalar = shift;
- my $local_fixed_object = shift;
- my $return_object;
-
- if ($local_scalar == 0) {$return_object = "0";}
- elsif ($local_scalar == 1) {$return_object = "$local_fixed_object";}
- elsif ($local_scalar == -1) {$return_object = "-$local_fixed_object";}
- else {$return_object = "${local_scalar}${local_fixed_object}";}
- return $return_object;
-}
-
-## Computes the greatest common divisor of two integers
-## Example: gcd(-300, 125) returns 25
-sub trs_gcd{
- my $a = shift;
- my $b = shift;
- my $c;
- my $abs_a = abs($a);
- my $abs_b = abs($b);
- if ($abs_b == 0) {return $abs_a;}
- else {$c = $abs_a % $abs_b;
- return trs_gcd($abs_b, $c);}
-}
-
-## reduced_fraction takes a pair of integers $numerator, $denominator
-## ($denominator != 0) and returns an array of two elements @fraction
-## $fraction[0] is the reduced numerator; $fraction[1] the reduced
-## denominator
-## Puts the sign of the fraction, if negative, in the numerator
-##
-## Usage: @fraction = reduced_fraction($numerator, $denominator)
-##
-sub reduced_fraction{
- my $local_numerator = shift;
- my $local_denominator = shift;
- my $sign_of_num = 1;
- my $sign_of_denom = 1;
- my $sign_of_quotient;
- my @local_fraction = ();
-
- if ($local_numerator < 0) {$sign_of_num = -1;}
- if ($local_denominator < 0) {$sign_of_denom = -1;}
- $sign_of_quotient = $sign_of_num * $sign_of_denom;
-
- my $local_gcd = trs_gcd($local_numerator, $local_denominator);
-## reduced numerator
- $local_fraction[0] = ($sign_of_quotient * abs($local_numerator)) / $local_gcd;
-## reduced denominator
- $local_fraction[1] = abs($local_denominator) / $local_gcd;
- return @local_fraction;
-}
-
-
-## Given Cartesian coordinates x and y returns an
-## array the zeroth element which is the radius
-## and the first element which is the argument
-## 0 <= theta < 2*pi
-##
-## Returns r=0 theta=0 for the origin
-##
-sub coordinates_polar{
- my $x = shift;
- my $y = shift;
- my @polar=();
- my $radius = 0;
- my $theta = 0;
- my $pi = acos(-1);
-
- $radius = sqrt($x**2 + $y**2);
- if ($radius != 0){
- if ($x == 0) {if ($y > 0) {$theta = $pi/2;}
- else {$theta = 3*$pi/2;}}
- else
- {
- if ($y > 0){if ($x > 0){$theta = atan($y/$x);}
- else {$theta = $pi - atan(-$y/$x);}}
- else {if ($x > 0){$theta = 2*$pi + atan($y/$x);}
- else {$theta = $pi + atan($y/$x);}}
- }
- }
- @polar=($radius, $theta);
- return @polar;
-}
-
-
-## Cylindarical coordinates from polar routine
-sub coordinates_cylindrical{
- my $x = shift;
- my $y = shift;
- my $z = shift;
- my @cylindrical=(coordinates_polar($x, $y), $z);
- return @cylindrical;
-}
-
-## Spherical Coordinates from polar routine
-##
-sub coordinates_spherical{
- my $x = shift;
- my $y = shift;
- my $z = shift;
- my $rho = 0;
- my $phi = 0;
- $rho = sqrt($x*$x + $y*$y + $z*$z);
- my @npolar = ();
- @npolar = coordinates_polar($x, $y);
- my @spherical=();
- if ($x ==0 && $y == 0){if ($z >= 0) {$phi = 0;}
- else {$phi = acos(-1);}
- @spherical=($rho,0,$phi);}
- else{
- $rho = sqrt($x*$x + $y*$y + $z*$z);
-
- @spherical=($rho, $npolar[1], acos($z/$rho));
- }
- return @spherical;
-}
-
-
-
-
-
-1;
-
-
-
diff --git a/OpenProblemLibrary/macros/FortLewis/AnswerFormatHelp.pl b/OpenProblemLibrary/macros/FortLewis/AnswerFormatHelp.pl
deleted file mode 100755
index 8a077d39bb..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/AnswerFormatHelp.pl
+++ /dev/null
@@ -1,921 +0,0 @@
-=head1 NAME
-
-AnswerFormatHelp.pl
-
-=head1 SYNOPSIS
-
-Creates links for students to help documentation on formatting
-answers and allows for custom help links.
-
-=head1 DESCRIPTION
-
-There are 16 predefined help links: angles, decimals, equations,
-exponents, formulas, fractions, inequalities, intervals, limits,
-logarithms, matrices, numbers, points, syntax, units, vectors.
-
-Usage:
-
- DOCUMENT();
- loadMacros("PGstandard.pl","AnswerFormatHelp.pl",);
- TEXT(beginproblem());
- BEGIN_TEXT
- \{ ans_rule(20) \}
- \{ AnswerFormatHelp("formulas") \} $PAR
- \{ ans_rule(20) \}
- \{ AnswerFormatHelp("equations","help entering equations") \} $PAR
- END_TEXT
- ENDDOCUMENT();
-
-
-The first example use defaults and displays the help link right next to
-the answer blank, which is recommended. The second example customizes
-the link text displayed to the student, but the actual help document
-is unaffected.
-
-=head1 AUTHOR
-
-Paul Pearson, Hope College, Department of Mathematics
-
-=cut
-
-
-
-###########################
-
- ###########################
- # Site administration
- #
- # The only thing you may need to modify is the value
- # of $helpurl near the end of this file.
- #
- ###########################
- # Usage
- #
- # DOCUMENT();
- # loadMacros("PGstandard.pl","AnswerFormatHelp.pl",);
- # TEXT(beginproblem());
- # BEGIN_TEXT
- # \{ AnswerFormatHelp("formulas") \} $PAR
- # \{ AnswerFormatHelp("equations","help entering equations") \} $PAR
- # \{ AnswerFormatHelp("formulas","help (formulas)","http://webwork.someschool.edu/dir/subdir/") \}
- # END_TEXT
- # ENDDOCUMENT();
- #
- # First example: use defaults.
- #
- # Second example: use customized text displayed to the student
- # as the html link.
- #
- # Third example: additionally points to a particular URL where
- # html help files are located. The URL must end with a forward slash.
- #
- # The third method is not recommended, as a universal, site-wide,
- # or course-wide solution obtained by modifying the value of
- # $helpdir in AnswerFormatHelp.pl is preferable to setting the
- # URL in every individual PG file manually.
- #
- ###########################
-
-our ($syntaxHelpExists, $angleHelpExists, $decimalHelpExists,
- $equationHelpExists, $exponentHelpExists, $formulaHelpExists, $fractionHelpExists, $inequalitiesHelpExists,
- $intervalHelpExists, $limitsHelpExists, $logarithmsHelpExists, $numberHelpExists, $pointsHelpExists,
- $unitsHelpExists, $vectorsHelpExists,
- ) = (0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, );
-
-sub _AnswerFormatHelp_init {}; # don't reload this file
-
-sub AnswerFormatHelp {
-
-#
-# Define some local variables
-#
-my $helptype = shift;
-my $customstring = shift;
-
-my $helpstring = "";
-
-# If producing PTX output, omit any formatting help.
-# (PTX output is used to produce non-interactive presentations of a problem,
-# so there is no need to give syntax formatting help.)
-if ($main::displayMode eq "PTX") {
- return;
-}
-
-
-
-####################################
-# Angles
-
-if ($helptype =~ m/angle/i) {
-
-if ($angleHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$angleHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (angles)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpAngles()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-
-
-####################################
-# Decimals
-
-} elsif ($helptype =~ m/decimal/i) {
-
-if ($decimalHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$decimalHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (decimals)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpDecimals()';");
-} else { return $helpstring; }
-
-
-
-
-
-#########################################
-# Equations
-
-} elsif ($helptype =~ m/equation/i) {
-
-if ($equationHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$equationHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (equations)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpEquations()';");
-} else { return $helpstring; }
-
-
-
-
-
-###############################################
-# Exponents
-
-} elsif ($helptype =~ m/exponent/i) {
-
-if ($exponentHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$exponentHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (exponents)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpExponents()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-#######################################
-# Formulas
-
-} elsif ($helptype =~ m/formula/i) {
-
- my $local1UseBaseTenLogHelp = Context()->flags->get("useBaseTenLog");
- my $local2UseBaseTenLogHelp = main::Context()->flags->get("useBaseTenLog");
- my $globalUseBaseTenLogHelp = $useBaseTenLog;
-
- if ($local1UseBaseTenLogHelp == 1 || $local2UseBaseTenLogHelp == 1 || $globalUseBaseTenLogHelp == 1) {
- $useBaseTenLogHelpString = "
Entering logarithms:
In this question, use ln(x) for natural log, and log(x), logten(x) or log10(x) for the base 10 logarithm. Enter log base b as ln(x)/ln(b)
";
- } else {
- $useBaseTenLogHelpString = "
Entering logarithms:
Caution: In this question, use ln(x) or log(x) for natural log, and logten(x) or log10(x) for the base 10 logarithm. Enter log base b as ln(x)/ln(b)
Entering natural logarithm: In this question, use ln(x)
";
- $basetenLogHelpString = "
Entering base 10 logarithm: In this question, use log(x), log10(x), or logten(x).
";
- } else {
- $naturalLogHelpString = "
Caution: In this question log(x) is the same as ln(x)
Entering natural logarithm: In this question, use ln(x) or log(x)
";
- $basetenLogHelpString = "
Entering base 10 logarithm: In this question, use log10(x) or logten(x).
";
- }
-
-if ($logarithmsHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$logarithmsHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (logarithms)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpLogarithms()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-
-
-
-###########################################
-# Matrices
-
-} elsif ($helptype =~ m/matri/i) {
-
-if ($matricesHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$matricesHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (matrices)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpMatrices()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-
-
-
-
-
-##########################################
-# Numbers
-
-} elsif ($helptype =~ m/number/i) {
-
-if ($numberHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
- $numberHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (numbers)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpNumbers()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-#######################################
-# Points
-
-} elsif ($helptype =~ m/point/i) {
-
-if ($pointsHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$pointsHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (points)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpPoints()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-
-
-
-####################################
-# Units
-
-} elsif ($helptype =~ m/unit/i) {
-
-if ($unitsHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$unitsHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (units)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpUnits()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-
-########################################
-# Vectors
-
-} elsif ($helptype =~ m/vector/i) {
-
-if ($vectorsHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$vectorsHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (vectors)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpVectors()';");
-} else { return $helpstring; }
-
-
-
-
-
-
-
-
-#########################################
-# Syntax (the catch all)
-
-#} elsif ($helptype =~ m/syntax/i) {
-} else {
-
-if ($syntaxHelpExists != 1) {
-
-HEADER_TEXT(<
-
-
-END_HEADER_TEXT
-
-$syntaxHelpExists = 1;
-}
-
-if (!$customstring) { $helpstring = "help (syntax)"; } else { $helpstring = $customstring; }
-
-if ($main::displayMode ne "TeX") {
- return htmlLink( "#", "$helpstring","onClick='return openhelpSyntax()';");
-} else { return $helpstring; }
-
-}
-
-
-
-
-
-
-} # end AnswerFormatHelp
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/AnswerFormatHelpHTML.tgz b/OpenProblemLibrary/macros/FortLewis/AnswerFormatHelpHTML.tgz
deleted file mode 100755
index bc7fbbae93..0000000000
Binary files a/OpenProblemLibrary/macros/FortLewis/AnswerFormatHelpHTML.tgz and /dev/null differ
diff --git a/OpenProblemLibrary/macros/FortLewis/ConditionalHint.pl b/OpenProblemLibrary/macros/FortLewis/ConditionalHint.pl
deleted file mode 100755
index e527f6bfa2..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/ConditionalHint.pl
+++ /dev/null
@@ -1,174 +0,0 @@
-sub _ConditionalHint_init {}; # don't reload this file
-
-=head1 ConditionalHint.pl
-
-################################################################################
-# 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.
-################################################################################
-
-=head2 NAME
-
-ConditionalHint.pl - Allows a hint to be revealed after a student
-has entered an answer correctly.
-
-=head2 DESCRIPTION
-
-The subroutine ConditionalHint() allows a hint to be revealed
-after a student has entered an answer correctly. It is useful
-for multi-part questions in which a hint for answering one part
-should not be revealed until a previous part has been answered
-correctly.
-
-A subroutine IsAnswerCorrect() that returns 0 or 1 is also
-provided.
-
-=head2 USAGE
-
-=head3 Synopsis of ConditionalHint
-
-loadMacros("ConditionalHint.pl");
-
-$ans = Compute("x^2");
-
-BEGIN_TEXT
-Enter \( x^2 \) \{ ans_rule(20) \}
-\{
-ConditionalHint(
- ans_name=>$ans,
- ans_number=>1,
- html_hint=>"$BR ${BBOLD}Hint:${EBOLD}
- \( \displaystyle \int x^2 \, dx = \frac{x^3}{3} + C.\) $BR",
- tex_hint=>'',
-);
-\}
-END_TEXT
-
-ANS( $ans->cmp() );
-
-
-=head3 Complete Working Example of ConditionalHint
-
-DOCUMENT();
-
-loadMacros(
-"PGstandard.pl",
-"MathObjects.pl",
-"ConditionalHint.pl",
-);
-
-TEXT( beginproblem() );
-
-###################################
-# Setup
-
-Context("Numeric");
-
-@answers = ();
-$answers[1] = Compute("x^2");
-$answers[2] = Compute("4^3 / 3");
-
-#$hint = IsAnswerCorrect(ans_name=>$answers[1],ans_number=>1);
-
-$myhint = ConditionalHint(
-ans_name=>$answers[1],
-ans_number=>1,
-html_hint=>"$BR ${BBOLD}Hint:${EBOLD} \( \displaystyle \int x^2 \, dx = \frac{x^3}{3} + C.\) $BR"
-);
-
-
-##################################
-# Main text
-
-Context()->texStrings;
-BEGIN_TEXT
-(a) Enter \( x^2 \).
-\{ ans_rule(30) \}
-$BR
-$BR
-(b) When you answer part (a) correctly, a hint will appear here with an integral formula.
-$BR
-$myhint
-$BR
-\( \displaystyle \int_0^4 \frac{x^3}{3} \, dx = \)
-\{ans_rule(20)\}
-END_TEXT
-Context()->normalStrings;
-
-
-##################################
-# Answer evaluation
-
-$showPartialCorrectAnswers = 1;
-
-ANS( $answers[1]->cmp() );
-ANS( $answers[2]->cmp() );
-
-COMMENT('When the first answer is correct, a hint appears with an integral formula (using ConditionalHint.pl).');
-
-ENDDOCUMENT();
-
-=head2 AUTHOR
-
-Paul Pearson
-
-=cut
-
-
-sub ConditionalHint {
-
- my %options = (
- ans_name => '',
- ans_number => '',
- html_hint => '',
- tex_hint => '',
- @_
- );
-
- my $showhint = $options{ans_name} ->cmp()->evaluate($inputs_ref->{ANS_NUM_TO_NAME( $options{ans_number} )})->{score};
-
- my $hint;
-
- if ($showhint == 1) {
- $hint = MODES(HTML=>$options{html_hint},TeX=>$options{tex_hint});
- } else {
- $hint = '';
- }
-
- return $hint;
-
-}
-
-
-sub IsAnswerCorrect {
-
- my %options = (
- ans_name => '',
- ans_number => '',
- @_
- );
-
-# my $name_of_correct_answer = shift;
-# my $answer_rule_number = shift;
-
-# return $name_of_correct_answer->cmp()->evaluate($inputs_ref->{ANS_NUM_TO_NAME($answer_rule_number)})->{score};
-
- return $options{ans_name} ->cmp()->evaluate($inputs_ref->{ANS_NUM_TO_NAME( $options{ans_number} )})->{score};
-
-
-}
-
-
-1;
-
diff --git a/OpenProblemLibrary/macros/FortLewis/JavaView.pl b/OpenProblemLibrary/macros/FortLewis/JavaView.pl
deleted file mode 100755
index 881406c53a..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/JavaView.pl
+++ /dev/null
@@ -1,190 +0,0 @@
-sub _JavaView_init {}; # don't reload this file
-
-###########################################################################
-#
-# Macros for handling interactive 3D graphics via the LiveGraphics3D
-# Java applet. The applet needs to be in the course html directory.
-# (If it is in the system html area, you will need to change the
-# default below or supply the jar option explicitly).
-#
-# The LiveGraphics3D applet displays a mathematica Graphics3D object
-# that is stored in a .m file (or a compressed one). Use Mathematica
-# to create one. (In the future, I plan to write a perl class that
-# will create these for you on the fly. -- DPVC)
-#
-# The main routines are
-#
-# Live3Dfile load a data file
-# Live3Ddata load raw Graphics3D data
-# LiveGraphics3D access to all parameters
-#
-
-#
-# LiveGraphics3D(options)
-#
-# Options are from:
-#
-# file => name name of .m file to load
-#
-# archive => name name of a .zip file to load
-#
-# input => 3Ddata string containing Graphics3D data to
-# be displayed by the applet
-#
-# size => [w,h] width and height of applet
-#
-# vars => [vars] hash of variables to pass as independent
-# variables to the applet, togther with
-# their initial values
-# e.g., vars => [a=>1,b=>1]
-#
-# depend => [list] list of dependent variables to pass to
-# the applet with their replacement strings
-# (see LiveGraphics3D documentation)
-#
-# jar => URL where to find the live.jar file
-#
-# background=>"#RRGGBB" the background color to use (default is white)
-#
-# scale => n scaling factor for applet (default is 1.)
-#
-# image => file a file containing an image to use in TeX mode
-# or when Java is disabled
-#
-# tex_size => ratio a scaling factor for the TeX image (as a portion
-# of the line width).
-# 1000 is 100%, 500 is 50%, etc.
-#
-# tex_center => 0 or 1 center the image in TeX mode or not
-#
-# parameters => [params] hash of additional parameters to pass to
-# the JavaView applet. For example,
-# parameters => [VISIBLE_FACES => "FRONT"]
-#
-# CAS => maple, Option when including plot data as an
-# ASCII string.
-#
-# CAS can be either maple or mathematica
-#
-# If CAS => maple, then the JavaView applet
-# expects maple plot geometry as an ASCII
-# string "Plot3D( )" passed to it via
-# input => or file => above.
-#
-# If CAS => mathematica, then the JavaView
-# applet expects a mathematica graphics
-# object as an ASCII string "Graphics3D[ ]"
-# passed to it via input => or file => above.
-
-sub JavaView {
- my %options = (
- size => [250,250],
- jar => "${htmlURL}jv_lite.zip", # "${htmlURL}live.jar",
- codebase => "${htmlURL}", # findAppletCodebase("jv_lite.jar"),
- background => "#FFFFFF",
- scale => 1.,
- tex_size => 500,
- tex_center => 0,
- CAS => maple, # CAS = Computer Algebra System
- @_
- );
- my $out = ""; my $p; my %pval;
- my $ratio = $options{tex_size} * (.001);
-
- if ($main::displayMode eq "TeX") {
- #
- # In TeX mode, include the image, if there is one, or
- # else give the user a message about using it on line
- #
- if ($options{image}) {
- $out = "\\includegraphics[width=$ratio\\linewidth]{$options{image}}";
- $out = "\\centerline{$out}" if $options{tex_center};
- $out .= "\n";
- } else {
- $out = "\\vbox{
- \\hbox{[ This image is created by}
- \\hbox{\\quad an interactive applet;}
- \\hbox{you must view it on line ]}
- }";
- }
- } else {
- my ($w,$h) = @{$options{size}};
- $out .= $bHTML if ($main::displayMode eq "Latex2HTML");
- #
- # Put the applet in a table
- #
- $out .= qq{\n
\n";
- $out .= $eHTML if ($main::displayMode eq "Latex2HTML");
- }
-
- return $out;
-}
-
-#
-# Syntactic sugar to make it easier to pass files and data to
-# LiveGraphics3D.
-#
-sub JVfile {
- my $file = shift;
- JavaView(file => $file, @_);
-}
-
-#
-# Syntactic sugar to make it easier to pass raw Graohics3D data
-# to LiveGraphics3D.
-#
-sub JVdata {
- my $data = shift;
- JavaView(input => $data, @_);
-}
-
-
-#
-# A message you can use for a caption under a graph
-#
-$LIVEMESSAGE = MODES(
- TeX => '',
- Latex2HTML =>
- $BCENTER.$BSMALL."Drag the surface to rotate it".$ESMALL.$ECENTER,
- HTML => $BCENTER.$BSMALL."Drag the surface to rotate it".$ESMALL.$ECENTER
-);
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/JavaViewRectangularPlot3D.pl b/OpenProblemLibrary/macros/FortLewis/JavaViewRectangularPlot3D.pl
deleted file mode 100755
index 72f1541ee7..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/JavaViewRectangularPlot3D.pl
+++ /dev/null
@@ -1,551 +0,0 @@
-sub _JavaViewRectangularPlot3D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","JavaView.pl");
-
-###########################################################################
-#
-# JavaViewRectangularPlot3D.pl provides two macros for creating an
-# interactive plot of a function of two variables z = f(x,y) in
-# Rectangular (Cartesian) coordinates via the JavaView applet.
-# The routine RectangularDomainPlot3D() takes a MathObject Formula of
-# two variables defined over a rectangular domain and some plot options
-# as input and returns a string of plot data that can be displayed
-# using the JVdata() routine of the JavaView.pl macro.
-# The routine AnnularDomainPlot3D works similarly for a function
-# z = f(x,y) over an annular domain specified in polar by
-# rmin < r < rmax and tmin < theta < tmax.
-#
-# JavaViewRectangularPlot3D.pl automatically loads
-# MathObjects.pl and JavaView.pl.
-#
-###########################################################################
-#
-# The first routine is
-#
-# RectangularPlot3DRectangularDomain
-#
-#
-# Usage: RectangularPlot3DRectangularDomain(options);
-#
-# Options are:
-#
-# function => $f, $f is a MathObjects Formula
-# For example, in the setup section define
-#
-# Context("Numeric");
-# Context()->variables->add(s=>"Real",t=>"Real");
-# $a = random(1,3,1);
-# $f = Formula("$a*s^2-2*t"); # use double quotes!
-#
-# before calling RectangularPlot3DRectangularDomain()
-#
-# xvar => "s", independent variable name, default "x"
-# yvar => "t", independent variable name, default "y"
-#
-# xmin => -3, domain for xvar
-# xmax => 3,
-#
-# ymin => -3, domain for yvar
-# ymax => 3,
-#
-# xsamples => 20, deltax = (xmax - xmin) / xsamples
-# ysamples => 20, deltay = (ymax - ymin) / ysamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "S", Capital letters may be easier to read
-# yaxislabel => "T",
-# zaxislabel => "Z",
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-#######################################################################################
-#######################################################################################
-#
-# The second routine is
-#
-# RectangularPlot3DAnnularDomain create a plotstring from a function
-#
-#
-# Usage: RectangularPlot3DAnnularDomain(options);
-#
-# Options are:
-#
-# function => $f, $f is a MathObjects Formula
-# For example, in the setup section define
-#
-# Context("Numeric");
-# Context()->variables->add(y=>"Real",r=>"Real",t=>"Real");
-# $a = random(1,3,1);
-# $f = Formula("$a*e^(- x^2 - y^2)"); # use double quotes!
-#
-# before calling RectangularPlot3DAnnularDomain()
-#
-# xvar => "x", independent variable name, default "x"
-# yvar => "y", independent variable name, default "y"
-#
-# rvar => "r", independent variable name, default "r"
-# tvar => "t", independent variable name, default "t" (for theta)
-#
-# rmin => -3, domain for rvar
-# rmax => 3,
-#
-# tmin => -3, domain for tvar
-# tmax => 3,
-#
-# rsamples => 20, deltar = (rmax - rmin) / rsamples
-# tsamples => 20, deltat = (tmax - tmin) / tsamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "X", Capital letters may be easier to read
-# yaxislabel => "Y",
-# zaxislabel => "Z",
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 3D graphing! - Paul Pearson
-#
-
-
-
-
-
-
-
-$beginplot = "PLOT3D(";
-$endplot = ")";
-
-
-###########################################
-###########################################
-# Begin RectangularPlot3DRectangularDomain
-
-sub RectangularPlot3DRectangularDomain {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-function => Formula("1"),
-xvar => 'x',
-yvar => 'y',
-xmin => -3,
-xmax => 3,
-ymin => -3,
-ymax => 3,
-xsamples => 20,
-ysamples => 20,
-axes => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-outputtype => 4,
-@_
-);
-
-
-############################################
-#
-# Reset to Context("Numeric") just to be
-# sure that everything will work properly.
-#
-
-#Context("Numeric");
-#Context()->variables->are($options{xvar}=>"Real",$options{yvar}=>"Real");
-
-
-my $fsubroutine;
-$options{function}->perlFunction('fsubroutine',["$options{xvar}","$options{yvar}"]);
-
-######################################################
-#
-# Generate a plot data array z, which has two indices
-#
-
-my $dx = ($options{xmax} - $options{xmin}) / $options{xsamples};
-my $dy = ($options{ymax} - $options{ymin}) / $options{ysamples};
-
-my $x;
-my $y;
-my $z;
-my $zmin = floor(sprintf("%.3f", fsubroutine($options{xmin},$options{ymin})->value ));
-my $zmax = ceil(sprintf("%.3f", fsubroutine($options{xmin},$options{ymin})->value ));
-
-
-foreach my $i (0..$options{xsamples}) {
- $x[$i] = $options{xmin} + $i * $dx;
- foreach my $j (0..$options{ysamples}) {
- $y[$j] = $options{ymin} + $j * $dy;
- # Use sprintf to round to three decimal places
- $z[$i][$j] = sprintf("%.3f", fsubroutine($x[$i],$y[$j])->value );
- $y[$j] = sprintf("%.3f",$y[$j]);
- if ($z[$i][$j]<$zmin) { $zmin = sprintf("%.2f",$z[$i][$j]); }
- if ($z[$i][$j]>$zmax) { $zmax = sprintf("%.2f",$z[$i][$j]); }
- }
- $x[$i] = sprintf("%.3f",$x[$i]);
-}
-
-
-
-###########################################################################
-#
-# Generate a plotstring from the plot data arrays x, y, z.
-#
-# The plotstring is a list of polygons
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstring, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstring
-#
-
-my $plotstring = "MESH([";
-
-foreach my $i (0..$options{xsamples}) {
- $plotstring = $plotstring . "[";
- foreach my $j (0..$options{ysamples}) {
-
- $plotstring = $plotstring . "[$x[$i],$y[$j],$z[$i][$j]]";
-
- if ($j<$options{ysamples}) { $plotstring = $plotstring . ","; }
- }
- $plotstring = $plotstring . "]";
- if ($i<$options{xsamples}) { $plotstring = $plotstring . ","; }
-}
-
-$plotstring = $plotstring . "])";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axes}==1) ) {
-
-$xmax = $options{xmax};
-$xmin = $options{xmin};
-$ymax = $options{ymax};
-$ymin = $options{ymin};
-
-my $axisx; my $naxisx;
-my $axisy; my $naxisy;
-my $axisz; my $naxisz;
-
-if ($xmin*$xmax<0) { $axisx=0; } else { $axisx=$xmin; }
-if ($ymin*$ymax<0) { $axisy=0; } else { $axisy=$ymin; }
-if ($zmin*$zmax<0) { $axisz=0; } else { $axisz=$zmin; }
-
-$naxisx = $axisx-($xmax - $xmin)/50;
-$naxisy = $axisy+($ymax - $ymin)/25;
-$naxisz = $axisz-($zmax - $zmin)/50;
-
-foreach my $i (0..5) {
- $xhere = sprintf( "%.1f", ($xmin + $i*($xmax - $xmin)/5) );
- $yhere = sprintf( "%.1f", ($ymin + $i*($ymax - $ymin)/5) );
- $zhere = sprintf( "%.1f", ($zmin + $i*($zmax - $zmin)/5) );
-
- $plotoptions = $plotoptions .
- "TEXT([$xhere,$naxisy,$naxisz],\'$xhere\')," .
- "TEXT([$naxisx,$yhere,$naxisz],\'$yhere\')," .
- "TEXT([$naxisx,$naxisy,$zhere],\'$zhere\'),";
-}
-
-my $xexpand = ($xmax - $xmin)/20;
-my $yexpand = ($ymax - $ymin)/20;
-my $zexpand = ($zmax - $zmin)/20;
-
-$xmax = $xmax + $xexpand;
-$xmin = $xmin - $xexpand;
-my $xlabel = $xmax+$xexpand;
-
-$ymax = $ymax + $yexpand;
-$ymin = $ymin - $yexpand;
-my $ylabel = $ymax+$yexpand;
-
-$zmax = $zmax + $zexpand;
-$zmin = $zmin - $zexpand;
-my $zlabel = $zmax+$zexpand;
-
-$plotoptions = $plotoptions .
-"TEXT([$xlabel,$axisy,$axisz],\'X\')," .
-"TEXT([$axisx,$ylabel,$axisz],\'Y\')," .
-"TEXT([$axisx,$axisy,$zlabel],\'Z\')," .
-"POLYGONS([[$xmin,$axisy,$axisz],[$xmax,$axisy,$axisz]])," .
-"POLYGONS([[$axisx,$ymin,$axisz],[$axisx,$ymax,$axisz]])," .
-"POLYGONS([[$axisx,$axisy,$zmin],[$axisx,$axisy,$zmax]])";
-
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstring;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstring . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstring . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End RectangularPlot3DRectangularDomain
-##############################################
-##############################################
-
-
-
-
-
-
-
-
-
-
-
-#############################################
-#############################################
-# Begin RectangularPlot3DAnnularDomain
-
-
-sub RectangularPlot3DAnnularDomain {
-
-#############################################
-#
-# Set default options
-#
-
-my %options = (
-function => Formula("1"),
-xvar => "x",
-yvar => "y",
-rvar => "r",
-tvar => "t",
-rmin => 0.001,
-rmax => 3,
-tmin => 0,
-tmax => 6.28,
-rsamples => 20,
-tsamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-outputtype => 4,
-@_
-);
-
-
-############################################
-#
-# Reset to Context("Numeric") just to be
-# sure that everything will work properly.
-#
-
-#Context("Numeric");
-#Context()->variables->are(
-#$options{xvar}=>"Real",
-#$options{yvar}=>"Real",
-#$options{rvar}=>"Real",
-#$options{tvar}=>"Real"
-#);
-
-my $fsubroutine;
-$options{function}->perlFunction('fsubroutine',["$options{xvar}","$options{yvar}"]);
-
-
-######################################################
-#
-# Generate a plot data array, which has two indices
-#
-
-my $dr = ($options{rmax} - $options{rmin}) / $options{rsamples};
-my $dt = ($options{tmax} - $options{tmin}) / $options{tsamples};
-
-my $t;
-my $r;
-
-foreach my $i (0..$options{rsamples}) { $r[$i] = $options{rmin} + $i * $dr; }
-foreach my $j (0..$options{tsamples}) { $t[$j] = $options{tmin} + $j * $dt; }
-
-my $x;
-my $y;
-my $z;
-
-my $zmin = floor(sprintf("%.3f", fsubroutine($r[0]*cos($t[0]),$r[0]*sin($t[0]))->value ));
-my $zmax = ceil(sprintf("%.3f", fsubroutine($r[0]*cos($t[0]),$r[0]*sin($t[0]))->value ));
-
-foreach my $i (0..$options{tsamples}) {
- foreach my $j (0..$options{rsamples}) {
- $x[$i][$j] = $r[$j] * cos($t[$i]);
- $y[$i][$j] = $r[$j] * sin($t[$i]);
- # Use sprintf to round to three decimal places
- $z[$i][$j] = sprintf("%.3f", fsubroutine($x[$i][$j],$y[$i][$j])->value );
- $x[$i][$j] = sprintf("%.3f",$x[$i][$j]);
- $y[$i][$j] = sprintf("%.3f",$y[$i][$j]);
- if ($z[$i][$j]<$zmin) { $zmin = sprintf("%.2f",$z[$i][$j]); }
- if ($z[$i][$j]>$zmax) { $zmax = sprintf("%.2f",$z[$i][$j]); }
- }
-}
-
-
-###########################################################################
-#
-# Generate a plotstring from the plot data arrays x, y, z.
-#
-# The plotstring is a list of polygons that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstring, see
-# http://www.maplesoft.com/support/help/AddOns/view.aspx?path=plot/structure
-#
-###########################################
-#
-# Generate the polygons in the plotstring
-#
-
-my $plotstring = "MESH([";
-
-foreach my $i (0..$options{tsamples}) {
- $plotstring = $plotstring . "[";
- foreach my $j (0..$options{rsamples}) {
-
- $plotstring = $plotstring . "[$x[$i][$j],$y[$i][$j],$z[$i][$j]]";
-
- if ($j<$options{rsamples}) { $plotstring = $plotstring . ","; }
- }
- $plotstring = $plotstring . "]";
- if ($i<$options{tsamples}) { $plotstring = $plotstring . ","; }
-}
-
-$plotstring = $plotstring . "])";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axes}==1) ) {
-
-$xmax = $options{rmax};
-$xmin = - $options{rmin};
-$ymax = $options{rmax};
-$ymin = - $options{rmin};
-
-my $axisx; my $naxisx;
-my $axisy; my $naxisy;
-my $axisz; my $naxisz;
-
-if ($xmin*$xmax<0) { $axisx=0; } else { $axisx=$xmin; }
-if ($ymin*$ymax<0) { $axisy=0; } else { $axisy=$ymin; }
-if ($zmin*$zmax<0) { $axisz=0; } else { $axisz=$zmin; }
-
-$naxisx = $axisx-($xmax - $xmin)/50;
-$naxisy = $axisy+($ymax - $ymin)/25;
-$naxisz = $axisz-($zmax - $zmin)/50;
-
-foreach my $i (0..5) {
- $xhere = sprintf( "%.1f", ($xmin + $i*($xmax - $xmin)/5) );
- $yhere = sprintf( "%.1f", ($ymin + $i*($ymax - $ymin)/5) );
- $zhere = sprintf( "%.1f", ($zmin + $i*($zmax - $zmin)/5) );
-
- $plotoptions = $plotoptions .
- "TEXT([$xhere,$naxisy,$naxisz],\'$xhere\')," .
- "TEXT([$naxisx,$yhere,$naxisz],\'$yhere\')," .
- "TEXT([$naxisx,$naxisy,$zhere],\'$zhere\'),";
-}
-
-my $xexpand = ($xmax - $xmin)/20;
-my $yexpand = ($ymax - $ymin)/20;
-my $zexpand = ($zmax - $zmin)/20;
-
-$xmax = $xmax + $xexpand;
-$xmin = $xmin - $xexpand;
-my $xlabel = $xmax+$xexpand;
-
-$ymax = $ymax + $yexpand;
-$ymin = $ymin - $yexpand;
-my $ylabel = $ymax+$yexpand;
-
-$zmax = $zmax + $zexpand;
-$zmin = $zmin - $zexpand;
-my $zlabel = $zmax+$zexpand;
-
-$plotoptions = $plotoptions .
-"TEXT([$xlabel,$axisy,$axisz],\'X\')," .
-"TEXT([$axisx,$ylabel,$axisz],\'Y\')," .
-"TEXT([$axisx,$axisy,$zlabel],\'Z\')," .
-"POLYGONS([[$xmin,$axisy,$axisz],[$xmax,$axisy,$axisz]])," .
-"POLYGONS([[$axisx,$ymin,$axisz],[$axisx,$ymax,$axisz]])," .
-"POLYGONS([[$axisx,$axisy,$zmin],[$axisx,$axisy,$zmax]])";
-
-}
-
-
-
-#if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
-# $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
-# "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-#}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstring;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstring . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstring . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End RectangularPlot3DAnnularDomain
-#####################################################
-#####################################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsCylindricalPlot3D.pl b/OpenProblemLibrary/macros/FortLewis/LiveGraphicsCylindricalPlot3D.pl
deleted file mode 100755
index 6147975aa5..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsCylindricalPlot3D.pl
+++ /dev/null
@@ -1,221 +0,0 @@
-sub _LiveGraphicsCylindricalPlot3D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","LiveGraphics3D.pl");
-
-###########################################################################
-#
-# LiveGraphicsCylindricalPlot3D.pl provides a macros for creating an
-# interactive plot of a function of two variables z = f(r,t)
-# (where r is the radius and t=theta is the angle) via the LiveGraphics3D
-# Java applet. The routine CylindricalPlot3D() takes a MathObject Formula
-# of two variables defined over an annular domain and some plot options
-# as input and returns a string of plot data that can be displayed
-# using the Live3Ddata() routine of the LiveGraphics3D.pl macro.
-#
-# LiveGraphicsCylindricalPlot3D.pl automatically loads
-# MathObjects.pl and LiveGraphics3D.pl.
-#
-###########################################################################
-#
-# The main routine is
-#
-# CylindricalPlot3D
-#
-#
-# Usage: CylindricalPlot3D(options)
-#
-# Options are:
-#
-# function => $f, $f is a MathObjects Formula
-# For example, in the setup section define
-#
-# Context("Numeric");
-# Context()->variables->add(r=>"Real",t=>"Real");
-# $a = random(1,3,1);
-# $f = Formula("$a*r + t"); # use double quotes!
-#
-# before calling CylindricalPlot3D()
-#
-# rvar => "r", independent variable name, default "r"
-# tvar => "t", independent variable name, default "t"
-#
-# rmin => 0, domain for rvar
-# rmax => 3,
-#
-# tmin => -3, domain for tvar
-# tmax => 3,
-#
-# rsamples => 20, deltar = (rmax - rmin) / rsamples
-# tsamples => 20, deltat = (tmax - tmin) / tsamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "X", Capital letters may be easier to read
-# yaxislabel => "Y",
-# zaxislabel => "Z",
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 3D graphing! -Paul Pearson
-#
-#######################################################################################
-
-
-
-
-
-
-
-$beginplot = "Graphics3D[";
-$endplot = "]";
-
-#############################################
-# Begin CylindricalPlot3D
-
-
-sub CylindricalPlot3D {
-
-#############################################
-#
-# Set default options
-#
-
-my %options = (
-function => Formula("1"),
-rvar => "r",
-tvar => "t",
-rmin => 0.001,
-rmax => 3,
-tmin => 0,
-tmax => 6.28,
-rsamples => 20,
-tsamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-outputtype => 4,
-@_
-);
-
-
-my $fsubroutine;
-$options{function}->perlFunction('fsubroutine',["$options{rvar}","$options{tvar}"]);
-
-
-######################################################
-#
-# Generate a plotdata array, which has two indices
-#
-
-my $rsamples1 = $options{rsamples} - 1;
-my $tsamples1 = $options{tsamples} - 1;
-
-my $dr = ($options{rmax} - $options{rmin}) / $options{rsamples};
-my $dt = ($options{tmax} - $options{tmin}) / $options{tsamples};
-
-my $r;
-my $t;
-
-my $x;
-my $y;
-my $z;
-
-foreach my $i (0..$options{tsamples}) {
- $t[$i] = $options{tmin} + $i * $dt;
- foreach my $j (0..$options{rsamples}) {
- $r[$j] = $options{rmin} + $j * $dr;
- $x[$i][$j] = $r[$j] * cos($t[$i]);
- $y[$i][$j] = $r[$j] * sin($t[$i]);
- $z[$i][$j] = sprintf("%.3f", fsubroutine($r[$j],$t[$i])->value );
- $x[$i][$j] = sprintf("%.3f",$x[$i][$j]);
- $y[$i][$j] = sprintf("%.3f",$y[$i][$j]);
- }
-}
-
-
-
-###########################################################################
-#
-# Generate a plotstring from the plotdata.
-#
-# The plotstring is a list of polygons that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstring, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstring
-#
-
-my $plotstructure = "{";
-
-foreach my $i (0..$tsamples1) {
- foreach my $j (0..$rsamples1) {
-
- $plotstructure = $plotstructure . "Polygon[{" .
- "{$x[$i][$j],$y[$i][$j],$z[$i][$j]}," .
- "{$x[$i+1][$j],$y[$i+1][$j],$z[$i+1][$j]}," .
- "{$x[$i+1][$j+1],$y[$i+1][$j+1],$z[$i+1][$j+1]}," .
- "{$x[$i][$j+1],$y[$i][$j+1],$z[$i][$j+1]}" .
- "}]";
-
- if (($i<$tsamples1) || ($j<$rsamples1)) {
- $plotstructure = $plotstructure . ","
- }
-
- }
-}
-
-$plotstructure = $plotstructure . "}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
- $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
- "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End CylindricalPlot3D
-#####################################################
-#####################################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsParametricCurve3D.pl b/OpenProblemLibrary/macros/FortLewis/LiveGraphicsParametricCurve3D.pl
deleted file mode 100755
index 15929a1b8c..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsParametricCurve3D.pl
+++ /dev/null
@@ -1,209 +0,0 @@
-sub _LiveGraphicsParametricCurve3D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","LiveGraphics3D.pl");
-
-###########################################################################
-#
-# LiveGraphicsParametricCurve3D.pl provides a macros for creating an
-# interactive plot of a vector field via the LiveGraphics3D Java applet.
-# The routine ParametricCurve3D() takes three MathObject Formulas of
-# 3 variables as input and returns a string of plot data that can be
-# displayed using the Live3Ddata() routine of the LiveGraphics3D.pl macro.
-#
-# LiveGraphicsParametricCurve3D.pl automatically loads
-# MathObjects.pl and LiveGraphics3D.pl.
-#
-###########################################################################
-#
-# The main routine is
-#
-# ParametricCurve3D()
-#
-#
-# Usage: ParametricCurve3D(options);
-#
-# Options are:
-#
-# Fx => Formula("t*cos(t)"), F = < Fx, Fy, Fz > where Fx, Fy, Fz are each
-# Fy => Formula("t*sin(t)"), functions of tvar
-# Fz => Formula("t"),
-#
-# tvar => "t", independent variable name, default "t"
-# tmin => -3, domain for tvar
-# tmax => 3,
-# tsamples => 3, deltat = (tmax - tmin) / tsamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "X", Capital letters may be easier to read
-# yaxislabel => "Y",
-# zaxislabel => "Z",
-#
-# orientation => 0, do not show any orientation arrows
-# => 1, show only one arrow in the middle
-# => 2, make the curve entirely of arrows
-#
-# curvecolor => "RGBColor[1.0,0.0,0.0]",
-# curvethickness => 0.001,
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 3D graphing! -Paul Pearson
-#
-#######################################################################################
-
-
-$beginplot = "Graphics3D[";
-$endplot = "]";
-
-
-###########################################
-###########################################
-# Begin ParametricCurve3D
-
-sub ParametricCurve3D {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-Fx => Formula("1"),
-Fy => Formula("1"),
-Fz => Formula("1"),
-tvar => 't',
-tmin => -3,
-tmax => 3,
-tsamples => 20,
-orientation => 0,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-curvecolor => "RGBColor[1.0,0.0,0.0]",
-curvethickness => 0.001,
-outputtype => 4,
-@_
-);
-
-
-my $Fxsubroutine;
-my $Fysubroutine;
-my $Fzsubroutine;
-
-$options{Fx}->perlFunction('Fxsubroutine',["$options{tvar}"]);
-$options{Fy}->perlFunction('Fysubroutine',["$options{tvar}"]);
-$options{Fz}->perlFunction('Fzsubroutine',["$options{tvar}"]);
-
-
-
-######################################################
-#
-# Generate plot data
-#
-
-my $dt = ($options{tmax} - $options{tmin}) / $options{tsamples};
-
-my $t;
-
-# The curve data
-foreach my $i (0..$options{tsamples}) {
- $t[$i] = $options{tmin} + $i * $dt;
-
- $FX[$i] = sprintf("%.3f", (Fxsubroutine($t[$i])->value) );
- $FY[$i] = sprintf("%.3f", (Fysubroutine($t[$i])->value) );
- $FZ[$i] = sprintf("%.3f", (Fzsubroutine($t[$i])->value) );
-
-}
-
-if ($options{orientation}>0) {
-#
-# The arrow head data
-#
-my $tmidindex = sprintf("%.0f", $options{tsamples}/2 );
-
-}
-
-
-###########################################################################
-#
-# Generate plotstructure from the plotdata.
-#
-# The plotstucture is a list of arrows (made of lines) that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstructure, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the line segments in the plotstructure
-#
-
-my $plotstructure = "{$options{curvecolor},Thickness[$options{curvethickness}],";
-
-my $tsamples1 = $options{tsamples} - 1;
-
-foreach my $i (0..$tsamples1) {
-
- $plotstructure = $plotstructure .
- "Line[{" .
- "{$FX[$i],$FY[$i],$FZ[$i]}," .
- "{$FX[$i+1],$FY[$i+1],$FZ[$i+1]}" .
- "}]";
-
- if ($i<$tsamples1) { $plotstructure = $plotstructure . "," }
-
-}
-
-$plotstructure = $plotstructure . "}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
- $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
- "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End ParametricCurve3D
-##############################################
-##############################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsParametricSurface3D.pl b/OpenProblemLibrary/macros/FortLewis/LiveGraphicsParametricSurface3D.pl
deleted file mode 100755
index dc7166fff1..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsParametricSurface3D.pl
+++ /dev/null
@@ -1,270 +0,0 @@
-sub _LiveGraphicsParametricSurface3D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","LiveGraphics3D.pl");
-
-###########################################################################
-#
-# LiveGraphicsParametricSurface3D.pl provides a macro for creating an
-# interactive plot of a parametric surface via the LiveGraphics3D Java applet.
-# The routine ParametricSurface3D() takes three MathObject Formulas of
-# 2 variables as input and returns a string of plot data that can be
-# displayed using the Live3Ddata() routine of the LiveGraphics3D.pl macro.
-#
-# LiveGraphicsParametricSurface3D.pl automatically loads
-# MathObjects.pl and LiveGraphics3D.pl.
-#
-###########################################################################
-#
-# The main routine is
-#
-# ParametricSurface3D()
-#
-#
-# Usage: ParametricSurface3D(options);
-#
-# Options are:
-#
-# Fx => Formula("cos(u)*cos(v)"), x-coordinate function
-# Fy => Formula("sin(u)*cos(v)"), y-coordinate function
-# Fz => Formula("sin(v)"), z-coordinate function
-# F(u,v) = < Fx, Fy, Fz >
-# = < Fx(u,v), Fy(u,v), Fz(u,v) >
-#
-# uvar => "u", parameter name, default "u"
-# vvar => "v", parameter name, default "v"
-#
-# umin => -3, domain for uvar
-# umax => 3,
-#
-# vmin => -3, domain for vvar
-# vmax => 3,
-#
-# usamples => 3, deltau = (umax - umin) / usamples
-# vsamples => 3, deltav = (vmax - vmin) / vsamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "X", Capital letters may be easier to read
-# yaxislabel => "Y",
-# zaxislabel => "Z",
-#
-# edges => 0, 1 displays edges of polygons, 0 hides them
-# edgecolor => "RGBColor[0.2,0.2,0.2]",
-# edgethickness => "Thickness[0.001]",
-#
-# mesh => 0, 1 displays open mesh, 0 displays filled polygons
-# meshcolor => "RGBColor[0.7,0.7,0.7]", three values between 0 and 1
-# meshthickness => 0.001,
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 3D graphing! -Paul Pearson
-#
-#######################################################################################
-
-
-$beginplot = "Graphics3D[";
-$endplot = "]";
-
-
-###########################################
-###########################################
-# Begin ParametricSurface3D
-
-sub ParametricSurface3D {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-Fx => Formula("1"),
-Fy => Formula("1"),
-Fz => Formula("1"),
-uvar => 'u',
-vvar => 'v',
-umin => -3,
-umax => 3,
-vmin => -3,
-vmax => 3,
-usamples => 20,
-vsamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-edges => 0,
-edgecolor => "RGBColor[0.2,0.2,0.2]",
-edgethickness => "Thickness[0.001]",
-mesh => 0,
-meshcolor => "RGBColor[0.7,0.7,0.7]",
-meshthickness => 0.001,
-outputtype => 4,
-@_
-);
-
-
-my $Fxsubroutine;
-my $Fysubroutine;
-my $Fzsubroutine;
-
-$options{Fx}->perlFunction('Fxsubroutine',["$options{uvar}","$options{vvar}"]);
-$options{Fy}->perlFunction('Fysubroutine',["$options{uvar}","$options{vvar}"]);
-$options{Fz}->perlFunction('Fzsubroutine',["$options{uvar}","$options{vvar}"]);
-
-
-
-######################################################
-#
-# Generate plot data
-#
-
-my $du = ($options{umax} - $options{umin}) / $options{usamples};
-my $dv = ($options{vmax} - $options{vmin}) / $options{vsamples};
-
-my $u;
-my $v;
-
-foreach my $i (0..$options{usamples}) {
- $u[$i] = $options{umin} + $i * $du;
- foreach my $j (0..$options{vsamples}) {
- $v[$j] = $options{vmin} + $j * $dv;
-
- $FX[$i][$j] = sprintf("%.3f", (Fxsubroutine($u[$i],$v[$j])->value) );
- $FY[$i][$j] = sprintf("%.3f", (Fysubroutine($u[$i],$v[$j])->value) );
- $FZ[$i][$j] = sprintf("%.3f", (Fzsubroutine($u[$i],$v[$j])->value) );
-
- $u[$i] = sprintf("%.3f",$u[$i]);
- $v[$j] = sprintf("%.3f",$v[$j]);
- }
-}
-
-
-
-###########################################################################
-#
-# Generate plotstructure from the plotdata.
-#
-# The plotstucture is a list of arrows (made of lines) that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstructure, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstructure
-#
-
-my $plotstructure = "{";
-
-if ($options{edges}==0 && $options{mesh}==0) {
- $plotstructure = $plotstructure . "EdgeForm[],";
-} elsif ($options{edges}==1 && $options{mesh}==0) {
- $plotstructure = $plotstructure . "EdgeForm[{$options{edgecolor},$options{edgethickness}}],";
-}
-
-if ($options{mesh}==1) {
- $plotstructure = $plotstructure . "$options{meshcolor},Thickness[$options{meshthickness}],";
-}
-
-my $usamples1 = $options{usamples} - 1;
-my $vsamples1 = $options{vsamples} - 1;
-
-if ($options{mesh}==0) {
-
-foreach my $i (0..$usamples1) {
- foreach my $j (0..$vsamples1) {
-
- $plotstructure = $plotstructure . "Polygon[{" .
- "{$FX[$i][$j],$FY[$i][$j],$FZ[$i][$j]}," .
- "{$FX[$i+1][$j],$FY[$i+1][$j],$FZ[$i+1][$j]}," .
- "{$FX[$i+1][$j+1],$FY[$i+1][$j+1],$FZ[$i+1][$j+1]}," .
- "{$FX[$i][$j+1],$FY[$i][$j+1],$FZ[$i][$j+1]}" .
- "}]";
-
- if (($i<$usamples1) || ($j<$vsamples1)) {
- $plotstructure = $plotstructure . ","
- }
-
- }
-}
-
-# end mesh == 0
-} else {
-# begin mesh == 1
-
-foreach my $i (0..$usamples1) {
- foreach my $j (0..$vsamples1) {
-
- # this could be made more efficient
- $plotstructure = $plotstructure .
- "Line[{" .
- "{$FX[$i][$j],$FY[$i][$j],$FZ[$i][$j]}," .
- "{$FX[$i+1][$j],$FY[$i+1][$j],$FZ[$i+1][$j]}," .
- "{$FX[$i+1][$j+1],$FY[$i+1][$j+1],$FZ[$i+1][$j+1]}," .
- "{$FX[$i][$j+1],$FY[$i][$j+1],$FZ[$i][$j+1]}," .
- "{$FX[$i][$j],$FY[$i][$j],$FZ[$i][$j]}" .
- "}]";
-
- if (($i<$usamples1) || ($j<$vsamples1)) {
- $plotstructure = $plotstructure . ","
- }
-
- }
-}
-
-
-} # end mesh == 1
-
-$plotstructure = $plotstructure . "}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
- $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
- "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End ParametricSurface3D
-##############################################
-##############################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsRectangularPlot3D.pl b/OpenProblemLibrary/macros/FortLewis/LiveGraphicsRectangularPlot3D.pl
deleted file mode 100755
index 4d0f47a25d..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsRectangularPlot3D.pl
+++ /dev/null
@@ -1,450 +0,0 @@
-sub _LiveGraphicsRectangularPlot3D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","LiveGraphics3D.pl");
-
-###########################################################################
-#
-# LiveGraphicsRectangularPlot3D.pl provides two macros for creating an
-# interactive plot of a function of two variables z = f(x,y) in
-# Rectangular (Cartesian) coordinates via the LiveGraphics3D Java applet.
-# The routine RectangularDomainPlot3D() takes a MathObject Formula of
-# two variables defined over a rectangular domain and some plot options
-# as input and returns a string of plot data that can be displayed
-# using the Live3Ddata() routine of the LiveGraphics3D.pl macro.
-# The routine AnnularDomainPlot3D works similarly for a function
-# z = f(x,y) over an annular domain specified in polar by
-# rmin < r < rmax and tmin < theta < tmax.
-#
-# LiveGraphicsRectangularPlot3D.pl automatically loads
-# MathObjects.pl and LiveGraphics3D.pl.
-#
-###########################################################################
-#
-# The first routine is
-#
-# RectangularPlot3DRectangularDomain
-#
-#
-# Usage: RectangularPlot3DRectangularDomain(options);
-#
-# Options are:
-#
-# function => $f, $f is a MathObjects Formula
-# For example, in the setup section define
-#
-# Context("Numeric");
-# Context()->variables->add(s=>"Real",t=>"Real");
-# $a = random(1,3,1);
-# $f = Formula("$a*s^2-2*t"); # use double quotes!
-#
-# before calling RectangularPlot3DRectangularDomain()
-#
-# xvar => "s", independent variable name, default "x"
-# yvar => "t", independent variable name, default "y"
-#
-# xmin => -3, domain for xvar
-# xmax => 3,
-#
-# ymin => -3, domain for yvar
-# ymax => 3,
-#
-# xsamples => 20, deltax = (xmax - xmin) / xsamples
-# ysamples => 20, deltay = (ymax - ymin) / ysamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "S", Capital letters may be easier to read
-# yaxislabel => "T",
-# zaxislabel => "Z",
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-#######################################################################################
-#######################################################################################
-#
-# The second routine is
-#
-# RectangularPlot3DAnnularDomain create a plotstring from a function
-#
-#
-# Usage: RectangularPlot3DAnnularDomain(options);
-#
-# Options are:
-#
-# function => $f, $f is a MathObjects Formula
-# For example, in the setup section define
-#
-# Context("Numeric");
-# Context()->variables->add(y=>"Real",r=>"Real",t=>"Real");
-# $a = random(1,3,1);
-# $f = Formula("$a*e^(- x^2 - y^2)"); # use double quotes!
-#
-# before calling RectangularPlot3DAnnularDomain()
-#
-# xvar => "x", independent variable name, default "x"
-# yvar => "y", independent variable name, default "y"
-#
-# rvar => "r", independent variable name, default "r"
-# tvar => "t", independent variable name, default "t" (for theta)
-#
-# rmin => -3, domain for rvar
-# rmax => 3,
-#
-# tmin => -3, domain for tvar
-# tmax => 3,
-#
-# rsamples => 20, deltar = (rmax - rmin) / rsamples
-# tsamples => 20, deltat = (tmax - tmin) / tsamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "X", Capital letters may be easier to read
-# yaxislabel => "Y",
-# zaxislabel => "Z",
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 3D graphing! - Paul Pearson
-#
-
-
-
-
-
-
-
-$beginplot = "Graphics3D[";
-$endplot = "]";
-
-
-###########################################
-###########################################
-# Begin RectangularPlot3DRectangularDomain
-
-sub RectangularPlot3DRectangularDomain {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-function => Formula("1"),
-xvar => 'x',
-yvar => 'y',
-xmin => -3,
-xmax => 3,
-ymin => -3,
-ymax => 3,
-xsamples => 20,
-ysamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-outputtype => 4,
-@_
-);
-
-
-############################################
-#
-# Reset to Context("Numeric") just to be
-# sure that everything will work properly.
-#
-
-#Context("Numeric");
-#Context()->variables->are($options{xvar}=>"Real",$options{yvar}=>"Real");
-
-
-my $fsubroutine;
-$options{function}->perlFunction('fsubroutine',["$options{xvar}","$options{yvar}"]);
-
-######################################################
-#
-# Generate a plotdata array, which has two indices
-#
-
-my $xsamples1 = $options{xsamples} - 1;
-my $ysamples1 = $options{ysamples} - 1;
-
-my $dx = ($options{xmax} - $options{xmin}) / $options{xsamples};
-my $dy = ($options{ymax} - $options{ymin}) / $options{ysamples};
-
-my $x;
-my $y;
-
-my $z;
-
-foreach my $i (0..$options{xsamples}) {
- $x[$i] = $options{xmin} + $i * $dx;
- foreach my $j (0..$options{ysamples}) {
- $y[$j] = $options{ymin} + $j * $dy;
- # Use sprintf to round to three decimal places
- $z[$i][$j] = sprintf("%.3f", fsubroutine($x[$i],$y[$j])->value );
- $y[$j] = sprintf("%.3f",$y[$j]);
- }
- $x[$i] = sprintf("%.3f",$x[$i]);
-}
-
-
-
-###########################################################################
-#
-# Generate a plotstring from the plotdata.
-#
-# The plotstring is a list of polygons
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstring, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstring
-#
-
-my $plotstructure = "{";
-
-foreach my $i (0..$xsamples1) {
- foreach my $j (0..$ysamples1) {
-
- $plotstructure = $plotstructure . "Polygon[{" .
- "{$x[$i],$y[$j],$z[$i][$j]}," .
- "{$x[$i+1],$y[$j],$z[$i+1][$j]}," .
- "{$x[$i+1],$y[$j+1],$z[$i+1][$j+1]}," .
- "{$x[$i],$y[$j+1],$z[$i][$j+1]}" .
- "}]";
-
- if (($i<$xsamples1) || ($j<$ysamples1)) {
- $plotstructure = $plotstructure . ","
- }
-
- }
-}
-
-$plotstructure = $plotstructure . "}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
- $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
- "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End RectangularPlot3DRectangularDomain
-##############################################
-##############################################
-
-
-
-
-
-
-
-
-
-
-
-#############################################
-#############################################
-# Begin RectangularPlot3DAnnularDomain
-
-
-sub RectangularPlot3DAnnularDomain {
-
-#############################################
-#
-# Set default options
-#
-
-my %options = (
-function => Formula("1"),
-xvar => "x",
-yvar => "y",
-rvar => "r",
-tvar => "t",
-rmin => 0.001,
-rmax => 3,
-tmin => 0,
-tmax => 6.28,
-rsamples => 20,
-tsamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-outputtype => 4,
-@_
-);
-
-
-############################################
-#
-# Reset to Context("Numeric") just to be
-# sure that everything will work properly.
-#
-
-#Context("Numeric");
-#Context()->variables->are(
-#$options{xvar}=>"Real",
-#$options{yvar}=>"Real",
-#$options{rvar}=>"Real",
-#$options{tvar}=>"Real"
-#);
-
-my $fsubroutine;
-$options{function}->perlFunction('fsubroutine',["$options{xvar}","$options{yvar}"]);
-
-
-######################################################
-#
-# Generate a plotdata array, which has two indices
-#
-
-my $rsamples1 = $options{rsamples} - 1;
-my $tsamples1 = $options{tsamples} - 1;
-
-my $dr = ($options{rmax} - $options{rmin}) / $options{rsamples};
-my $dt = ($options{tmax} - $options{tmin}) / $options{tsamples};
-
-my $t;
-my $r;
-
-my $x;
-my $y;
-
-my $z;
-
-foreach my $i (0..$options{tsamples}) {
- $t[$i] = $options{tmin} + $i * $dt;
- foreach my $j (0..$options{rsamples}) {
- $r[$j] = $options{rmin} + $j * $dr;
- $x[$i][$j] = $r[$j] * cos($t[$i]);
- $y[$i][$j] = $r[$j] * sin($t[$i]);
- $z[$i][$j] = sprintf("%.3f", fsubroutine($x[$i][$j],$y[$i][$j])->value );
- $x[$i][$j] = sprintf("%.3f",$x[$i][$j]);
- $y[$i][$j] = sprintf("%.3f",$y[$i][$j]);
- }
-}
-
-
-
-###########################################################################
-#
-# Generate a plotstring from the plotdata.
-#
-# The plotstring is a list of polygons that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstring, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstring
-#
-
-my $plotstructure = "{";
-
-foreach my $i (0..$tsamples1) {
- foreach my $j (0..$rsamples1) {
-
- $plotstructure = $plotstructure . "Polygon[{" .
- "{$x[$i][$j],$y[$i][$j],$z[$i][$j]}," .
- "{$x[$i+1][$j],$y[$i+1][$j],$z[$i+1][$j]}," .
- "{$x[$i+1][$j+1],$y[$i+1][$j+1],$z[$i+1][$j+1]}," .
- "{$x[$i][$j+1],$y[$i][$j+1],$z[$i][$j+1]}" .
- "}]";
-
- if (($i<$tsamples1) || ($j<$rsamples1)) {
- $plotstructure = $plotstructure . ","
- }
-
- }
-}
-
-$plotstructure = $plotstructure . "}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
- $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
- "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End RectangularPlot3DAnnularDomain
-#####################################################
-#####################################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsVectorField2D.pl b/OpenProblemLibrary/macros/FortLewis/LiveGraphicsVectorField2D.pl
deleted file mode 100755
index dc4caa6e77..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsVectorField2D.pl
+++ /dev/null
@@ -1,231 +0,0 @@
-sub _LiveGraphicsVectorField2D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","LiveGraphics3D.pl");
-
-###########################################################################
-#
-# LiveGraphicsVectorField2D.pl provides a macros for creating an
-# interactive plot of a vector field via the LiveGraphics3D Java applet.
-# The routine VectorField2D() takes two MathObject Formulas of
-# 2 variables as input and returns a string of plot data that can be
-# displayed using the Live3Ddata() routine of the LiveGraphics3D.pl macro.
-#
-# LiveGraphicsVectorField2D.pl automatically loads
-# MathObjects.pl and LiveGraphics3D.pl.
-#
-###########################################################################
-#
-# The main routine is
-#
-# VectorField2D()
-#
-#
-# Usage: VectorField2D(options);
-#
-# Options are:
-#
-# Fx => Formula("y"), F = < Fx, Fy, Fz > where Fx, Fy, Fz are each
-# Fy => Formula("-x"), functions of 3 variables
-#
-# xvar => "r", independent variable name, default "x"
-# yvar => "s", independent variable name, default "y"
-#
-# xmin => -3, domain for xvar
-# xmax => 3,
-#
-# ymin => -3, domain for yvar
-# ymax => 3,
-#
-# xsamples => 3, deltax = (xmax - xmin) / xsamples
-# ysamples => 3, deltay = (ymax - ymin) / ysamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "R", Capital letters may be easier to read
-# yaxislabel => "S",
-#
-# vectorcolor => "RGBColor[1.0,0.0,0.0]",
-# vectorscale => 0.2,
-# vectorthickness => 0.001,
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 2D graphing! -Paul Pearson
-#
-#######################################################################################
-
-
-$beginplot = "Graphics3D[";
-$endplot = "]";
-
-
-###########################################
-###########################################
-# Begin VectorField2D
-
-sub VectorField2D {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-Fx => Formula("1"),
-Fy => Formula("1"),
-xvar => 'x',
-yvar => 'y',
-xmin => -3,
-xmax => 3,
-ymin => -3,
-ymax => 3,
-xsamples => 20,
-ysamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-vectorcolor => "RGBColor[1.0,0.0,0.0]",
-vectorscale => 0.2,
-vectorthickness => 0.001,
-outputtype => 4,
-@_
-);
-
-
-my $Fxsubroutine;
-my $Fysubroutine;
-
-$options{Fx}->perlFunction('Fxsubroutine',["$options{xvar}","$options{yvar}"]);
-$options{Fy}->perlFunction('Fysubroutine',["$options{xvar}","$options{yvar}"]);
-
-
-######################################################
-#
-# Generate plot data
-#
-
-my $dx = ($options{xmax} - $options{xmin}) / $options{xsamples};
-my $dy = ($options{ymax} - $options{ymin}) / $options{ysamples};
-
-my $xtail;
-my $ytail;
-
-foreach my $i (0..$options{xsamples}) {
- $xtail[$i] = $options{xmin} + $i * $dx;
- foreach my $j (0..$options{ysamples}) {
- $ytail[$j] = $options{ymin} + $j * $dy;
-
- $FX[$i][$j] = sprintf("%.3f", $options{vectorscale}*(Fxsubroutine($xtail[$i],$ytail[$j])->value) );
- $FY[$i][$j] = sprintf("%.3f", $options{vectorscale}*(Fysubroutine($xtail[$i],$ytail[$j])->value) );
-
- $xtail[$i] = sprintf("%.3f",$xtail[$i]);
- $ytail[$j] = sprintf("%.3f",$ytail[$j]);
-
- $xtip[$i][$j] = $xtail[$i] + sprintf("%.3f", $FX[$i][$j] );
- $ytip[$i][$j] = $ytail[$j] + sprintf("%.3f", $FY[$i][$j] );
-
- $xleftbarb[$i][$j] = sprintf("%.3f", $xtail[$i] + 0.8*$FX[$i][$j] - 0.2*$FY[$i][$j] );
- $yleftbarb[$i][$j] = sprintf("%.3f", $ytail[$j] + 0.8*$FY[$i][$j] + 0.2*$FX[$i][$j] );
-
- $xrightbarb[$i][$j] = sprintf("%.3f", $xtail[$i] + 0.8*$FX[$i][$j] + 0.2*$FY[$i][$j] );
- $yrightbarb[$i][$j] = sprintf("%.3f", $ytail[$j] + 0.8*$FY[$i][$j] - 0.2*$FX[$i][$j] );
- }
-}
-
-
-
-###########################################################################
-#
-# Generate plotstructure from the plotdata.
-#
-# The plotstucture is a list of arrows (made of lines) that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstructure, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstructure
-#
-
-my $plotstructure = "{{{{$options{vectorcolor},EdgeForm[],Thickness[$options{vectorthickness}],";
-
-foreach my $i (0..$options{xsamples}) {
- foreach my $j (0..$options{ysamples}) {
-
- $plotstructure = $plotstructure .
- "Line[{" .
- "{$xtail[$i],$ytail[$j],0}," .
- "{$xtip[$i][$j],$ytip[$i][$j],0}" .
- "}]," .
- "Line[{" .
- "{$xleftbarb[$i][$j],$yleftbarb[$i][$j],0}," .
- "{$xtip[$i][$j],$ytip[$i][$j],0}," .
- "{$xrightbarb[$i][$j],$yrightbarb[$i][$j],0}" .
- "}]";
-
- if ( ($i<$options{xsamples}) || ($j<$options{ysamples}) ) {
- $plotstructure = $plotstructure . ","
- }
-
- }
-}
-
-$plotstructure = $plotstructure . "}}}}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
-
- $plotoptions = $plotoptions .
- "PlotRange->{{$options{xmin},$options{xmax}},{$options{ymin},$options{ymax}},{-0.1,0.1}}," .
- "ViewPoint->{0,0,1000}," .
- "ViewVertical->{0,1,0}," .
- "Lighting->False," .
- "AxesLabel->{$options{xaxislabel},$options{yaxislabel},Z}," . #; # .
- "Axes->{True,True,False}";
-
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End VectorField2D
-##############################################
-##############################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsVectorField3D.pl b/OpenProblemLibrary/macros/FortLewis/LiveGraphicsVectorField3D.pl
deleted file mode 100755
index 4aba989243..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/LiveGraphicsVectorField3D.pl
+++ /dev/null
@@ -1,265 +0,0 @@
-sub _LiveGraphicsVectorField3D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","LiveGraphics3D.pl");
-
-###########################################################################
-#
-# LiveGraphicsVectorField3D.pl provides a macros for creating an
-# interactive plot of a vector field via the LiveGraphics3D Java applet.
-# The routine VectorField3D() takes three MathObject Formulas of
-# 3 variables as input and returns a string of plot data that can be
-# displayed using the Live3Ddata() routine of the LiveGraphics3D.pl macro.
-#
-# LiveGraphicsVectorField3D.pl automatically loads
-# MathObjects.pl and LiveGraphics3D.pl.
-#
-###########################################################################
-#
-# The main routine is
-#
-# VectorField3D()
-#
-#
-# Usage: VectorField3D(options);
-#
-# Options are:
-#
-# Fx => Formula("y"), F = < Fx, Fy, Fz > where Fx, Fy, Fz are each
-# Fy => Formula("-x"), functions of 3 variables
-# Fz => Formula("z"),
-#
-# xvar => "r", independent variable name, default "x"
-# yvar => "s", independent variable name, default "y"
-# zvar => "t", independent variable name, default "z"
-#
-# xmin => -3, domain for xvar
-# xmax => 3,
-#
-# ymin => -3, domain for yvar
-# ymax => 3,
-#
-# zmin => -3, domain for zvar
-# zmax => 3,
-#
-# xsamples => 3, deltax = (xmax - xmin) / xsamples
-# ysamples => 3, deltay = (ymax - ymin) / ysamples
-# zsamples => 3, deltaz = (zmax - zmin) / zsamples
-#
-# axesframed => 1, 1 displays framed axes, 0 hides framed axes
-#
-# xaxislabel => "R", Capital letters may be easier to read
-# yaxislabel => "S",
-# zaxislabel => "T",
-#
-# vectorcolor => "RGBColor[0.0,0.0,1.0]",
-# vectorscale => 0.2,
-# vectorthickness => 0.001,
-#
-# outputtype => 1, return string of only polygons (or mesh)
-# 2, return string of only plotoptions
-# 3, return string of polygons (or mesh) and plotoptions
-# 4, return complete plot
-#
-# Happy 3D graphing! -Paul Pearson
-#
-#######################################################################################
-
-
-$beginplot = "Graphics3D[";
-$endplot = "]";
-
-
-###########################################
-###########################################
-# Begin VectorField3D
-
-sub VectorField3D {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-Fx => Formula("1"),
-Fy => Formula("1"),
-Fz => Formula("1"),
-xvar => 'x',
-yvar => 'y',
-zvar => 'z',
-xmin => -3,
-xmax => 3,
-ymin => -3,
-ymax => 3,
-zmin => -3,
-zmax => 3,
-xsamples => 20,
-ysamples => 20,
-zsamples => 20,
-axesframed => 1,
-xaxislabel => "X",
-yaxislabel => "Y",
-zaxislabel => "Z",
-vectorcolor => "RGBColor[0.0,0.0,1.0]",
-vectorscale => 0.2,
-vectorthickness => 0.001,
-xavoid => 1000000,
-yavoid => 1000000,
-zavoid => 1000000,
-outputtype => 4,
-@_
-);
-
-
-my $Fxsubroutine;
-my $Fysubroutine;
-my $Fzsubroutine;
-
-$options{Fx}->perlFunction('Fxsubroutine',["$options{xvar}","$options{yvar}","$options{zvar}"]);
-$options{Fy}->perlFunction('Fysubroutine',["$options{xvar}","$options{yvar}","$options{zvar}"]);
-$options{Fz}->perlFunction('Fzsubroutine',["$options{xvar}","$options{yvar}","$options{zvar}"]);
-
-
-
-######################################################
-#
-# Generate plot data
-#
-
-my $dx = ($options{xmax} - $options{xmin}) / $options{xsamples};
-my $dy = ($options{ymax} - $options{ymin}) / $options{ysamples};
-my $dz = ($options{zmax} - $options{zmin}) / $options{zsamples};
-
-my $xtail;
-my $ytail;
-my $ztail;
-
-foreach my $i (0..$options{xsamples}) {
- $xtail[$i] = $options{xmin} + $i * $dx;
- foreach my $j (0..$options{ysamples}) {
- $ytail[$j] = $options{ymin} + $j * $dy;
- foreach my $k (0..$options{zsamples}) {
- $ztail[$k] = $options{zmin} + $k * $dz;
-
- if ( $xtail[$i]==$options{xavoid} && $ytail[$j]==$options{yavoid} && $ztail[$k]==$options{zavoid} ) {
-
- $FX[$i][$j][$k] = 0;
- $FY[$i][$j][$k] = 0;
- $FZ[$i][$j][$k] = 0;
-
- } else {
-
- $FX[$i][$j][$k] = sprintf("%.3f", $options{vectorscale}*(Fxsubroutine($xtail[$i],$ytail[$j],$ztail[$k])->value) );
- $FY[$i][$j][$k] = sprintf("%.3f", $options{vectorscale}*(Fysubroutine($xtail[$i],$ytail[$j],$ztail[$k])->value) );
- $FZ[$i][$j][$k] = sprintf("%.3f", $options{vectorscale}*(Fzsubroutine($xtail[$i],$ytail[$j],$ztail[$k])->value) );
-
- }
-
- $xtail[$i] = sprintf("%.3f",$xtail[$i]);
- $ytail[$j] = sprintf("%.3f",$ytail[$j]);
- $ztail[$k] = sprintf("%.3f",$ztail[$k]);
-
- $xtip[$i][$j][$k] = $xtail[$i] + sprintf("%.3f", $FX[$i][$j][$k] );
- $ytip[$i][$j][$k] = $ytail[$j] + sprintf("%.3f", $FY[$i][$j][$k] );
- $ztip[$i][$j][$k] = $ztail[$k] + sprintf("%.3f", $FZ[$i][$j][$k] );
-
- $xleftbarb[$i][$j][$k] = sprintf("%.3f", $xtail[$i] + 0.8*$FX[$i][$j][$k] - 0.2*$FY[$i][$j][$k] );
- $yleftbarb[$i][$j][$k] = sprintf("%.3f", $ytail[$j] + 0.8*$FY[$i][$j][$k] + 0.2*$FX[$i][$j][$k] );
-
- $xrightbarb[$i][$j][$k] = sprintf("%.3f", $xtail[$i] + 0.8*$FX[$i][$j][$k] + 0.2*$FY[$i][$j][$k] );
- $yrightbarb[$i][$j][$k] = sprintf("%.3f", $ytail[$j] + 0.8*$FY[$i][$j][$k] - 0.2*$FX[$i][$j][$k] );
-
- $zbarb[$i][$j][$k] = sprintf("%.3f", $ztail[$k] + 0.8*$FZ[$i][$j][$k] );
-
- }
- }
-}
-
-
-
-###########################################################################
-#
-# Generate plotstructure from the plotdata.
-#
-# The plotstucture is a list of arrows (made of lines) that
-# LiveGraphics3D reads as input.
-#
-# For more information on the format of the plotstructure, see
-# http://www.math.umn.edu/~rogness/lg3d/page_NoMathematica.html
-# http://www.vis.uni-stuttgart.de/~kraus/LiveGraphics3D/documentation.html
-#
-###########################################
-#
-# Generate the polygons in the plotstructure
-#
-
-my $plotstructure = "{{{{$options{vectorcolor},Thickness[$options{vectorthickness}],";
-
-foreach my $i (0..$options{xsamples}) {
- foreach my $j (0..$options{ysamples}) {
- foreach my $k (0..$options{zsamples}) {
-
- $plotstructure = $plotstructure .
- "Line[{" .
- "{$xtail[$i],$ytail[$j],$ztail[$k]}," .
- "{$xtip[$i][$j][$k],$ytip[$i][$j][$k],$ztip[$i][$j][$k]}" .
- "}]," .
- "Line[{" .
- "{$xleftbarb[$i][$j][$k],$yleftbarb[$i][$j][$k],$zbarb[$i][$j][$k]}," .
- "{$xtip[$i][$j][$k],$ytip[$i][$j][$k],$ztip[$i][$j][$k]}," .
- "{$xrightbarb[$i][$j][$k],$yrightbarb[$i][$j][$k],$zbarb[$i][$j][$k]}" .
- "}]";
-
- if (($i<$options{xsamples}) || ($j<$options{ysamples}) || ($k<$options{zsamples})) {
- $plotstructure = $plotstructure . ","
- }
- }
- }
-}
-
-$plotstructure = $plotstructure . "}}}}";
-
-
-
-##############################################
-#
-# Add plot options to the plotoptions string
-#
-
-my $plotoptions = "";
-
-if ( ($options{outputtype}>1) || ($options{axesframed}==1) ) {
- $plotoptions = $plotoptions . "Axes->True,AxesLabel->" .
- "{$options{xaxislabel},$options{yaxislabel},$options{zaxislabel}}";
-}
-
-
-####################################################
-#
-# Return only the plotstring (if outputtype=>1),
-# or only plotoptions (if outputtype=>2),
-# or plotstring, plotoptions (if outputtype=>2),
-# or the entire plot (default) (if outputtype=>4)
-
-if ($options{outputtype}==1) {
- return $plotstructure;
-} elsif ($options{outputtype}==2) {
- return $plotoptions;
-} elsif ($options{outputtype}==3) {
- return "{" . $plotstructure . "," . $plotoptions . "}";
-} elsif ($options{outputtype}==4) {
- return $beginplot . $plotstructure . "," . $plotoptions . $endplot;
-} else {
- return "Invalid outputtype (outputtype should be a number 1 through 4).";
-}
-
-
-
-
-} # End VectorField3D
-##############################################
-##############################################
-
-
-
-1;
diff --git a/OpenProblemLibrary/macros/FortLewis/MatrixUnimodular.pl b/OpenProblemLibrary/macros/FortLewis/MatrixUnimodular.pl
deleted file mode 100755
index 7d5f6511e4..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/MatrixUnimodular.pl
+++ /dev/null
@@ -1,248 +0,0 @@
-sub _MatrixUnimodular_init {}; # don't reload this file
-
-
-sub xgcd ($$) {
-
- # Extended greatest common divisor
- # xgcd( a , b ) = ( d , x , y , s , t )
- # where
- # gcd(a,b) = d = a (x + s k) + b (y + t k) for any integer k
-
- my ($a, $x, $y) = ( int(shift) , 1 , 0 ) ;
- my ($b, $s, $t) = ( int(shift) , 0 , 1 ) ;
-
- my ($A,$B) = ($a,$b) ;
-
- while ( $b != 0 ) {
- my $q = int( $a / $b ) ;
- ($a, $x, $y, $b, $s, $t) = ($b, $s, $t, $a-$q*$b, $x-$q*$s, $y-$q*$t);
- }
-
- if ($a < 0) {
- return ( -$a, -$x, -$y, $s, $t ) ; }
- else {
- return ( $a, $x, $y, $s, $t ) ;
- }
-}
-
-
-
-sub unimodular_SL2Z_specific {
-
- # Unimodular 2x2 matrix in SL_2(Z)
- # unimodular( a11, a21 )
- # returns a determinant 1 matrix object
- # [ a11 a12 ]
- # [ a21 a22 ]
- # The inputs a11 and a12 must be relatively prime
- # integers, and could be thought of as an eigenvector.
- # If they are not relatively prime, then the identity
- # matrix will be returned.
-
- my $a11 = shift;
- my $a21 = shift;
-
- my @w = xgcd($a11,$a21); # "weights"
-
- if ($w[0] != 1) { return (1,0,0,1); }
- # my $a12 = -($w[2]);
- # my $a22 = $w[1];
-
- @A = ( $a11, $a21, -($w[2]), $w[1] );
-
- return @A;
-
-}
-
-
-
-sub unimodular_SL2Z {
-
- # Unimodular 2x2 matrix in SL_2(Z)
- # unimodular ( A, B ) = ( a11, a21, a12, a22 )
- # where
- # [ a11 a12 ]
- # [ a21 a22 ]
- # is a determinant one matrix with integer entries
- # and the inputs A < B are the limits of the size of the entries
- # If they are not relatively prime, then the identity
- # matrix will be returned.
- # Note: it returns a matrix listed by columns (not rows)
- # so that you can easily use the columns as eigenvectors
-
- my $a11 = list_random(-7,-5,-3,-2,2,3,5,7);
- my $a21 = list_random(-7,-5,-3,-2,2,3,5,7);
- while ($a11 == $a21 || $a11 == -($a21)) {
- $a21 = list_random(-7,-5,-3,-2,2,3,5,7);
- };
-
- my @w = xgcd($a11,$a21);
-
- # my $a12 = -($w[2]);
- # my $a22 = $w[1];
-
- my @A = ( $a11, $a21, -($w[2]), $w[1] );
-
- return @A;
-
-}
-
-
-
-sub unimodular_GL2Z {
-
- # Unimodular 2x2 matrix in GL_2(Z)
- # unimodular ( A, B ) = ( a11, a21, a12, a22, det )
- # where
- # [ a11 a12 ]
- # [ a21 a22 ]
- # is a determinant 1 or -1 matrix with integer entries
- # and det is the determinant.
- # If they are not relatively prime, then the identity
- # matrix will be returned.
- # Note: it returns a matrix listed by columns (not rows)
- # so that you can easily use the columns as eigenvectors.
-
- my $a11 = list_random(-7,-5,-3,-2,2,3,5,7);
- my $a21 = list_random(-7,-5,-3,-2,2,3,5,7);
- while ($a11 == $a21 || $a11 == -($a21)) {
- $a21 = list_random(-7,-5,-3,-2,2,3,5,7);
- };
-
- my @w = xgcd($a11,$a21);
-
- # my $a12 = -($w[2]);
- # my $a22 = $w[1];
-
- my $s = random(-1,1,2); # randomize the sign for the first column
-
- my @A = ( $s * $a11, $s * $a21, -($w[2]), $w[1] );
-
- return @A;
-
-}
-
-
-sub unimodular_diagonalization_SL2Z {
-
- # input: two distinct integer eigenvalues (lambda1, lambda2)
- #
- # output: a single array with the following entries in order:
- # 2x2 matrix listed by columns (A11,A21,A12,A22),
- # first eigenvalue lambda1, first eigenvector (P11,P21),
- # second eigenvalue lambda2, second eigenvector (P12,P22)
-
- my $lambda1 = shift;
- my $lambda2 = shift;
-
- my @P = unimodular_SL2Z();
-
- # A = P D P^(-1), where D is diagonal with $lambda1 and $lambda2
-
- my @A = (
- $P[0] * $P[3] * $lambda1 - $P[1] * $P[2] * $lambda2,
- $P[1] * $P[3] * $lambda1 - $P[1] * $P[3] * $lambda2,
- $P[0] * $P[2] * $lambda2 - $P[0] * $P[2] * $lambda1,
- $P[0] * $P[3] * $lambda2 - $P[1] * $P[2] * $lambda1
- );
-
- return ( @A, @P, $lambda1, $lambda2 );
-
-}
-
-
-sub unimodular_diagonalization_GL2Z {
-
- # input: two distinct integer eigenvalues (lambda1, lambda2)
- #
- # output: a single array with the following entries in order:
- # 2x2 matrix listed by columns (M11,M21,M12,M22),
- # first eigenvalue lambda1, first eigenvector (P11,P21),
- # second eigenvalue lambda2, second eigenvector (P12,P22)
-
- my $lambda1 = shift;
- my $lambda2 = shift;
-
- my @P = unimodular_GL2Z();
- my $detP = $P[0] * $P[3] - $P[1] * $P[2];
-
- # A = P D P^(-1), where D is diagonal [ [lambda1,0], [0,lambda1] ]
- my @A = (
- $detP * $P[0] * $P[3] * $lambda1 - $detP * $P[1] * $P[2] * $lambda2,
- $detP * $P[1] * $P[3] * $lambda1 - $detP * $P[1] * $P[3] * $lambda2,
- $detP * $P[0] * $P[2] * $lambda2 - $detP * $P[0] * $P[2] * $lambda1,
- $detP * $P[0] * $P[3] * $lambda2 - $detP * $P[1] * $P[2] * $lambda1
- );
-
- return ( @A, @P, $lambda1, $lambda2 );
-
-}
-
-
-
-###############################################################
-# Versions with small integer entries
-
-sub small_unimodular_GL2Z {
-
- # Unimodular 2x2 matrix in GL_2(Z)
- # unimodular ( A, B ) = ( a11, a21, a12, a22, det )
- # where
- # [ a11 a12 ]
- # [ a21 a22 ]
- # is a determinant 1 or -1 matrix with integer entries
- # and det is the determinant.
- # If they are not relatively prime, then the identity
- # matrix will be returned.
- # Note: it returns a matrix listed by columns (not rows)
- # so that you can easily use the columns as eigenvectors.
-
- my $a11 = list_random(-4,-3,-2,2,3,4);
- my $a21 = list_random(-4,-3,-2,2,3,4);
- while ($a11 == $a21 || $a11 == -($a21) || gcd($a11,$a21) != 1) {
- $a21 = list_random(-4,-3,-2,2,3,4);
- };
-
- my @w = xgcd($a11,$a21);
-
- # my $a12 = -($w[2]);
- # my $a22 = $w[1];
-
- my $s = random(-1,1,2); # randomize the sign for the first column
-
- my @A = ( $s * $a11, $s * $a21, -($w[2]), $w[1] );
-
- return @A;
-
-}
-
-
-sub small_unimodular_diagonalization_GL2Z {
-
- # input: two distinct integer eigenvalues (lambda1, lambda2)
- #
- # output: a single array with the following entries in order:
- # 2x2 matrix listed by columns (M11,M21,M12,M22),
- # first eigenvalue lambda1, first eigenvector (P11,P21),
- # second eigenvalue lambda2, second eigenvector (P12,P22)
-
- my $lambda1 = shift;
- my $lambda2 = shift;
-
- my @P = small_unimodular_GL2Z();
- my $detP = $P[0] * $P[3] - $P[1] * $P[2];
-
- # A = P D P^(-1), where D is diagonal [ [lambda1,0], [0,lambda1] ]
- my @A = (
- $detP * $P[0] * $P[3] * $lambda1 - $detP * $P[1] * $P[2] * $lambda2,
- $detP * $P[1] * $P[3] * $lambda1 - $detP * $P[1] * $P[3] * $lambda2,
- $detP * $P[0] * $P[2] * $lambda2 - $detP * $P[0] * $P[2] * $lambda1,
- $detP * $P[0] * $P[3] * $lambda2 - $detP * $P[1] * $P[2] * $lambda1
- );
-
- return ( @A, @P, $lambda1, $lambda2 );
-
-}
-
-
-1;
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/FortLewis/PeriodicRerandomization.pl b/OpenProblemLibrary/macros/FortLewis/PeriodicRerandomization.pl
deleted file mode 100755
index 514ac336d7..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/PeriodicRerandomization.pl
+++ /dev/null
@@ -1,185 +0,0 @@
-=head1 NAME
-
-PeriodicRerandomization.pl - forced re-randomization of the
-problem every p submissions.
-
-=head1 SYNOPSIS
-
-Let p be a positive integer. This macro provides the ability
-to force a re-randomization of the question every p attempts.
-For example, this macro can be used to create a practice exercise
-that provides a new version of the question every 4 attempts
-and displays a solution every fourth attempt.
-
-=head1 DESCRIPTION
-
-Usage:
-
- DOCUMENT();
- loadMacros(
- "PGstandard.pl",
- "MathObjects.pl",
- "PeriodicRerandomization.pl",
- );
- TEXT(beginproblem());
-
- PeriodicRerandomization("4");
-
- $a = random(2,9,1);
- do { $b = random(2,9,1); } until ($b != $a);
-
- BEGIN_TEXT
- An equation for a line in the xy-plane with slope \( $a \)
- and y-intercept \( $b \) is
- $BR
- $BR
- \( y = \) \{ ans_rule(20) \}
- $BR
- $BR
- END_TEXT
-
- PeriodicStatus(
- "Generate a new version of this problem",
- "You have ${attempts_modp_remaining} attempt(s) remaining
- before you will receive a new version of this problem."
- );
-
- if ($attempts_modp == 0) {
- BEGIN_TEXT
- $BR
- $BR
- ${BBOLD}Solution:${EBOLD} Multiply \( x \) by \( $a \)
- and add \( $b \).
- $BR
- $BR
- END_TEXT
- }
-
- ANS( Compute("$a x + $b")->cmp() );
-
- COMMENT('Periodically re-randomizes.');
-
- ENDDOCUMENT();
-
-
-The argument of C is a number p (the period)
-that is the number of attempts allowed before the problem is
-re-randomized. C must be called before
-any random parameters are defined.
-
-The two arguments of C are (1) the text that will
-appear on the button for a new version of the problem when the number
-of attempts is 0 mod p, and (2) a message that will appear when the
-number of attempts is not 0 mod N. If C has no
-arguments, then it will use defaults.
-
-There are several globally defined variables. C<$rerand_period> is
-the period p. C<$attempts_modp> is the total number of attempts modulo
-the period except for when the problem is first accessed, in which case
-its value is -p (the rationale behind this is that the case when the
-problem is first accessed often needs to be handled separately.)
-C<$attempts_modp_remaining> is the number of attempts
-remaining before re-randomization. C<$problem_version_number> is the
-floor function applied to the total number of attempts divided by the
-period p. C<$newProblemSeed> is the problem seed for the current
-version of the problem, whereas C<$problemSeed> is the original
-problem seed (which does not change with different versions of the
-problem). You can access the total number of attempts using
-C<$envir{numOfAttempts}>, which is a sequence 0,0,1,2,3,... (not
-0,1,2,3,...).
-
-=head1 AUTHOR
-
-Paul Pearson, Fort Lewis College, Department of Mathematics
-
-=cut
-
-
-
-###########################
-
-
-
-sub _PeriodicRerandomization_init {}; # don't reload this file
-
-sub PeriodicRerandomization {
-
- #
- # define some global variables
- #
-
- $rerand_period = shift;
- $attempts_modp = ($envir{numOfAttempts}+1) % $rerand_period;
- $attempts_modp_remaining = $rerand_period - $attempts_modp;
-
- #
- # a correction because the $envir{numOfAttempts} progression is 0,0,1,2,3... instead of 0,1,2,3,...
- #
- if ( $envir{numOfAttempts}==0 && !defined(${$inputs_ref}{'hasBeenAttempted'}) ) {
-
- TEXT(MODES(
- HTML => qq!!,
- HTML_dpng => qq!!,
- TeX => "")
- );
-
- $attempts_modp += -(1+$rerand_period);
- $attempts_modp_remaining += 1;
-
- } else {
-
- TEXT(MODES(
- HTML => qq!!,
- HTML_dpng => qq!!,
- TeX => "")
- );
-
- }
-
- $problem_version_number = floor($envir{'numOfAttempts'} / $rerand_period);
-
- if ($problemSeed < 2000) {
- $newProblemSeed = $problemSeed + $problem_version_number;
- } else {
- $newProblemSeed = $problemSeed - $problem_version_number;
- }
-
- $main::PG_random_generator -> srand( $newProblemSeed );
-
-
-}
-
-
-
-
-
-sub PeriodicStatus {
-
- my $button_text = shift;
- my $status_text = shift;
-
- if ( !defined($button_text) ) { $button_text = "Generate a new version of this problem"; }
-
- if ( !defined($status_text) ) {
- $status_text =
- "You have ${attempts_modp_remaining} attempt(s) remaining before you will receive a new version of this problem.";
- }
-
-
- if ($attempts_modp == 0 && defined(${$inputs_ref}{'hasBeenAttempted'}) ) {
-
- TEXT(MODES(
- HTML =>"",
- HTML_dpng=>"",
- TeX => "")
- );
-
- } else {
-
- TEXT(EV3($status_text));
-
- }
-
-}
-
-1;
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/FortLewis/VectorField2D.pl b/OpenProblemLibrary/macros/FortLewis/VectorField2D.pl
deleted file mode 100755
index 0f13640ab6..0000000000
--- a/OpenProblemLibrary/macros/FortLewis/VectorField2D.pl
+++ /dev/null
@@ -1,110 +0,0 @@
-sub _VectorField2D_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl","PGgraphmacros.pl");
-
-
-sub VectorField2D {
-
-###########################################
-#
-# Set default options
-#
-
-my %options = (
-graphobject => $gr,
-Fx => Formula("1"),
-Fy => Formula("1"),
-xvar => 'x',
-yvar => 'y',
-xmin => -5,
-xmax => 5,
-ymin => -5,
-ymax => 5,
-xsamples => 10,
-ysamples => 10,
-vectorcolor => "blue",
-vectorscale => 0.25,
-vectorthickness => 2,
-vectortipwidth => 0.08,
-vectortiplength => 0.65,
-xavoid=>1000000,
-yavoid=>1000000,
-@_
-);
-
-
-my $Fxsubroutine;
-my $Fysubroutine;
-
-$options{Fx}->perlFunction('Fxsubroutine',["$options{xvar}","$options{yvar}"]);
-$options{Fy}->perlFunction('Fysubroutine',["$options{xvar}","$options{yvar}"]);
-
-
-######################################################
-#
-# Generate plot data
-#
-
-my $dx = ($options{xmax} - $options{xmin}) / $options{xsamples};
-my $dy = ($options{ymax} - $options{ymin}) / $options{ysamples};
-
-my $xtail;
-my $ytail;
-my $FX;
-my $FY;
-my $xtip;
-my $xstem;
-my $ystem;
-my $xmidtip;
-my $ymidtip;
-my $xleftbarb;
-my $xrightbarb;
-my $yleftbarb;
-my $yrightbarb;
-
-
-foreach my $i (0..$options{xsamples}) {
- $xtail[$i] = $options{xmin} + $i * $dx;
- foreach my $j (0..$options{ysamples}) {
- $ytail[$j] = $options{ymin} + $j * $dy;
-
- if (($options{xavoid} == $xtail[$i]) && ($options{yavoid} == $ytail[$j])) {
- $FX[$i][$j] = 0;
- $FY[$i][$j] = 0;
- } else {
- $FX[$i][$j] = $options{vectorscale}*(Fxsubroutine($xtail[$i],$ytail[$j])->value);
- $FY[$i][$j] = $options{vectorscale}*(Fysubroutine($xtail[$i],$ytail[$j])->value);
- }
-
- $xtip[$i][$j] = $xtail[$i] + $FX[$i][$j];
- $ytip[$i][$j] = $ytail[$j] + $FY[$i][$j];
-
- $xstem[$i][$j] = $xtail[$i] + $options{vectortiplength}*$FX[$i][$j];
- $ystem[$i][$j] = $ytail[$j] + $options{vectortiplength}*$FY[$i][$j];
-
- $xmidtip[$i][$j] = $xtail[$i] + (($options{vectortiplength} + 1)/2)*$FX[$i][$j];
- $ymidtip[$i][$j] = $ytail[$j] + (($options{vectortiplength} + 1)/2)*$FY[$i][$j];
-
- $xleftbarb[$i][$j] = $xtail[$i] + $options{vectortiplength}*$FX[$i][$j] - $options{vectortipwidth}*$FY[$i][$j];
- $yleftbarb[$i][$j] = $ytail[$j] + $options{vectortiplength}*$FY[$i][$j] + $options{vectortipwidth}*$FX[$i][$j];
-
- $xrightbarb[$i][$j] = $xtail[$i] + $options{vectortiplength}*$FX[$i][$j] + $options{vectortipwidth}*$FY[$i][$j];
- $yrightbarb[$i][$j] = $ytail[$j] + $options{vectortiplength}*$FY[$i][$j] - $options{vectortipwidth}*$FX[$i][$j];
-
-
- $options{graphobject}->moveTo($xtail[$i],$ytail[$j]);
-# $options{graphobject}->lineTo($xstem[$i][$j],$ystem[$i][$j],$options{vectorcolor},$options{vectorthickness});
- $options{graphobject}->lineTo($xtip[$i][$j],$ytip[$i][$j],$options{vectorcolor},$options{vectorthickness});
-
- $options{graphobject}->moveTo($xleftbarb[$i][$j],$yleftbarb[$i][$j]);
- $options{graphobject}->lineTo($xtip[$i][$j],$ytip[$i][$j],$options{vectorcolor},$options{vectorthickness});
- $options{graphobject}->lineTo($xrightbarb[$i][$j],$yrightbarb[$i][$j],$options{vectorcolor},$options{vectorthickness});
-# $options{graphobject}->lineTo($xleftbarb[$i][$j],$yleftbarb[$i][$j],$options{vectorcolor},$options{vectorthickness});
-# $options{graphobject}->fillRegion([$xmidtip[$i][$j],$ymidtip[$i][$j],$options{vectorcolor}]);
-
- }
-}
-
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Hope/MatrixCheckers.pl b/OpenProblemLibrary/macros/Hope/MatrixCheckers.pl
deleted file mode 100644
index 92cffd8628..0000000000
--- a/OpenProblemLibrary/macros/Hope/MatrixCheckers.pl
+++ /dev/null
@@ -1,467 +0,0 @@
-sub _MatrixCheckers_init {}; # don't reload this file
-
-=pod
-
-=head1 NAME
-
-MatrixCheckers.pl
-
-=head1 SYNOPSIS
-
-Provides subroutines for answer checking using MathObjects
-matrices with real entries. (Sadly, it does not provide
-routines for using matrices to win at the game of checkers.)
-
-=head1 DESCRIPTION
-
-First, load the C macro file. If the basis has
-more than one vector, also load C.
-
-=over 12
-
-=item C
-
-= back
-
-For a matrix that has a single column or row, the way to use the
-answer checkers is the same as using a custom answer checker
-inside of C~~&name_of_answer_checker_subroutine)>
-such as
-
-=over 12
-
-=item Ccmp( checker=~~&basis_checker_one_column ) );>
-
-=item Ccmp( checker=~~&unit_basis_checker_one_column ) );>
-
-=back
-
-The "one column" at the end of the checker name refers to the
-fact that the student answer is a one-column matrix. The "unit
-basis checker" ensures that the student answer has unit length.
-
-For answers that are a collection of column or row vectors, the
-way to use the answer checkers is inside of a MultiAnswer object.
-The macro C should also be loaded.
-The answer checkers that should be used inside a MultiAnswer
-object are:
-
-=over 12
-
-=item C
-
-=item C
-
-=item C
-
-=item C
-
-=item C
-
-=back
-
-Here is an example of how to use these answer checkers.
-In the setup section of the PG file we create two 3 x 1 MathObject
-matrices with real-entries that serve as basis vectors. The object
-C<$multians> takes the basis vectors as input and passes them
-to the custom answer checker called by C...>.
-
-=over 12
-
-$basis1 = Matrix([1/sqrt(2), 0, 1/sqrt(2)])->transpose;
-$basis2 = Matrix([0,1,0])->transpose;
-
-$multians = MultiAnswer($basis1, $basis2)->with(
- singleResult => 1,
- separator => ', ',
- tex_separator => ', ',
- allowBlankAnswers=>0,
- checker => ~~&orthonormal_basis_checker_columns,
-);
-
-=back
-
-In the main text portion of the PG file, we use C<\{ $multians-ans_array(15) \}>
-to create an array of text boxes that are 15 characters wide and have square
-brackets around them to look like a matrix. The braces around the vectors, which
-are produced by C<\(\Bigg\lbrace\)> and C<\(\Bigg\rbrace\)>, are a matter of personal
-preference (since a basis is an ordered set, I like to include braces).
-
-=over 12
-
-Context()->texStrings;
-BEGIN_TEXT
-Find an orthonormal basis for...
-$BR
-$BR
-$BCENTER
-\(\Bigg\lbrace\)
-\{ $multians->ans_array(15) \},
-\{ $multians->ans_array(15) \}
-\(\Bigg\rbrace.\)
-$ECENTER
-END_TEXT
-Context()->normalStrings;
-
-=back
-
-The answer evaluation section of the PG file is totally standard.
-
-=over 12
-
-ANS( $multians->cmp );
-
-=back
-
-The C should be used for
-solutions to non-homogeneous systems of linear equations for
-which the solution is essentially a point plus the span of
-several linearly independent vectors. When using the parametric
-plane checker, the first vector input always serves as a point
-on the hyperplane (i.e., the first vector input is always a
-particular solution), while the remaining vectors are a basis for
-the hyperplane (i.e., they span the homogeneous solution set).
-
-=head1 AUTHORS
-
-Paul Pearson, Hope College, Department of Mathematics
-
-=cut
-
-
-
-################################################
-
-loadMacros("MathObjects.pl",); # , will "parserMultiAnswer.pl" create an infinite loop?
-
-
-################################################
-
-sub concatenate_columns_into_matrix {
-
- my @c = @_;
- my @temp = ();
- for my $column (@c) {
- push(@temp,Matrix($column)->transpose->row(1));
- }
- return Matrix(@temp)->transpose;
-
-}
-
-##########################################
-
-sub basis_checker_one_column {
-
- my ( $correct, $student, $answerHash ) = @_;
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- #my $C = Matrix($context,$correct);
- #my $S = Matrix($context,$student);
- my $C = Vector($context,$correct);
- my $S = Vector($context,$student);
- return $S->isParallel($C);
-
-}
-
-##########################################
-
-sub basis_checker_columns {
-
- my ( $correct, $student, $answerHash ) = @_;
- my @c = @{$correct};
- my @s = @{$student};
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- return 0 if scalar(@s) < scalar(@c); # count the number of vector inputs
-
- my $C = concatenate_columns_into_matrix(@c);
- my $S = concatenate_columns_into_matrix(@s);
-
- # Put $C and $S into the local context so that
- # all of the computations that follow will also be in
- # the local context.
- $C = Matrix($context,$C);
- $S = Matrix($context,$S);
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors are linearly dependent");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- return $S == $C * $X;
-
-}
-
-
-#############################################
-
-sub unit_basis_checker_one_column {
-
- my ( $correct, $student, $answerHash ) = @_;
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- my $C = Vector($context,$correct);
- my $S = Vector($context,$student);
- return ($S->isParallel($C) and norm($S)==1);
-
-}
-
-###############################################
-
-sub orthonormal_basis_checker_columns {
-
- my ( $correct, $student, $answerHash ) = @_;
- my @c = @{$correct};
- my @s = @{$student};
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- return 0 if scalar(@s) < scalar(@c); # count the number of vector inputs
-
- my $C = concatenate_columns_into_matrix(@c);
- my $S = concatenate_columns_into_matrix(@s);
-
- # Put $C and $S into the local context so that
- # all of the computations that follow will also be in
- # the local context.
- $C = Matrix($context,$C);
- $S = Matrix($context,$S);
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors are linearly dependent");
- return 0;
- }
-
- my $identity = Value::Matrix->I(scalar(@c));
- # Check that the student's vectors are orthonormal
- if ( (($S->transpose) * $S) != $identity) {
- Value->Error("Your vectors are not orthonormal (or you may need to enter more decimal places)");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- return $S == $C * $X;
-
-}
-
-##############################################
-
-sub basis_checker_rows {
-
- my ( $correct, $student, $answerHash ) = @_;
- my @c = @{$correct};
- my @s = @{$student};
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- return 0 if scalar(@s) < scalar(@c); # count the number of vector inputs
-
- # These two lines are what is different from basis_checker_columns
- my $C = Matrix(@c)->transpose; # put the rows of @c into columns of $C.
- my $S = Matrix(@s)->transpose; # put the rows of @s into columns of $S.
-
- # Put $C and $S into the local context so that
- # all of the computations that follow will also be in
- # the local context.
- $C = Matrix($context,$C);
- $S = Matrix($context,$S);
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors are linearly dependent");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- return $S == $C * $X;
-
-}
-
-#############################################
-
-sub orthonormal_basis_checker_rows {
-
- my ( $correct, $student, $answerHash ) = @_;
- my @c = @{$correct};
- my @s = @{$student};
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- return 0 if scalar(@s) < scalar(@c); # count the number of vector inputs
-
- # These two lines are what is different from basis_checker_columns
- my $C = Matrix(@c)->transpose; # put the rows of @c into columns of $C.
- my $S = Matrix(@s)->transpose; # put the rows of @s into columns of $S.
-
- # Put $C and $S into the local context so that
- # all of the computations that follow will also be in
- # the local context.
- $C = Matrix($context,$C);
- $S = Matrix($context,$S);
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors are linearly dependent");
- return 0;
- }
-
- my $identity = Value::Matrix->I(scalar(@c));
- # Check that the student's vectors are orthonormal
- if ( (($S->transpose) * $S) != $identity) {
- Value->Error("Your vectors are not orthonormal (or you may need to enter more decimal places)");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- return $S == $C * $X;
-
-}
-
-##############################################
-
-sub parametric_plane_checker_columns {
-
- my ( $correct, $student, $answerHash ) = @_;
- my @c = @{$correct};
- my @s = @{$student};
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- return 0 if scalar(@s) < scalar(@c); # count the number of vector inputs
-
- # pull off the first vector as the displacement vector
- my $C0 = Matrix(shift(@c));
- my $S0 = Matrix(shift(@s));
-
- # put the remaining vectors into the columns of a matrix.
- my $C = concatenate_columns_into_matrix(@c);
- my $S = concatenate_columns_into_matrix(@s);
-
- # Put $C and $S into the local context so that
- # all of the computations that follow will also be in
- # the local context.
- $C0 = Matrix($context,$C0);
- $S0 = Matrix($context,$S0);
- $C = Matrix($context,$C);
- $S = Matrix($context,$S);
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors are linearly dependent");
- return 0;
- }
-
- # solve (S_0 = C_0 + C A) for the column vector A of weights using
- # (S_0 - C_0) = C A
- # C^T (S_0 - C_0) = C^T C A
- # (C^T C)^{-1} C^T (S_0 - C_0) = A
- my $A = ($CTC->inverse) * ($C->transpose) * ($S0 - $C0);
- if ($S0 != $C0 + $C*$A) {
- Value->Error("Your particular solution is incorrect");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- return $S == $C * $X;
-
-}
-
-
-########################################################
-
-1;
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/Hope/MatrixReduce.pl b/OpenProblemLibrary/macros/Hope/MatrixReduce.pl
deleted file mode 100644
index b286f1f71e..0000000000
--- a/OpenProblemLibrary/macros/Hope/MatrixReduce.pl
+++ /dev/null
@@ -1,349 +0,0 @@
-sub _MatrixReduce_init {}; # don't reload this file
-
-=pod
-
-=head1 NAME
-
-MatrixReduce.pl - reduced row echelon form, row
-operations, and elementary matrices.
-
-=head1 SYNOPSIS
-
-Provides subroutines for elementary matrix
-computations using MathObjects matrices.
-
-=over 12
-
-=item Get the reduced row echelon form: C<$Areduced = rref($A);> Should be used in the fraction context with all entries of $A made into fractions.
-
-=item Make matrix entries do fraction arithmetic (rather than decimal arithmetic): After selecting the Fraction context using Context('Fraction')->parens->set("[" => {formMatrix => 1}), C<$A = apply_fraction_to_matrix_entries($A);> applies Fraction() to all of the entries of $A, which makes subsequent matrix algebra computations with $A use fraction arithmetic.
-
-=item Get the reduced column echelon form: C<$Areduced = rcef($A);>
-
-=item Change the value of a matrix entry: C changes the [2,3] entry to the value 50.
-
-=item Construct an n x n identity matrix: C<$E = identity_matrix(5);>
-
-=item Construct an n x n elementary matrix that will permute rows i and j: C<$E = elem_matrix_row_switch(5,2,4);> creates a 5 x 5 identity matrix and swaps rows 2 and 4.
-
-=item Construct an n x n elementary matrix that will multiply row i by s: C<$E = elem_matrix_row_mult(5,2,4);> creates a 5 x 5 identity matrix and swaps puts 4 in the second spot on the diagonal.
-
-=item Construct an n x n elementary matrix that will multiply row i by s: C<$E3 = elem_matrix_row_add(5,3,1,35);> creates a 5 x 5 identity matrix and swaps puts 35 in the (3,1) position.
-
-=item Perform the row switch transform that swaps (row i) with (row j): C<$Areduced = row_switch($A,2,4);> swaps rows 2 and 4 in matrix $A.
-
-=item Perform the row multiplication transform s * (row i) placed into (row i): C<$Areduced = row_mult(A,2,10);> multiplies every entry in row 2 of $A by 10.
-
-=item Perform the row addition transform (row i) + s * (row j) placed into (row i): C<$Areduced = row_add($A,2,1,10);> adds 10 times row 1 to row 2 and places the result in row 2. (Same as constructing $E to be the identity with 10 placed in entry (2,1), then multiplying $E * $A.)
-
-=back
-
-=head1 DESCRIPTION
-
-Usage:
-
-=over 12
-
-DOCUMENT();
-loadMacros(
-"PGstandard.pl",
-"MathObjects.pl",
-"MatrixReduce.pl", # automatically loads contextFraction.pl and MathObjects.pl
-"PGcourse.pl",
-);
-$showPartialCorrectAnswers = 0;
-TEXT(beginproblem());
-
-# Context('Matrix'); # for decimal arithmetic
-Context('Fraction'); # for fraction arithmetic
-
-$A = Matrix([
-[random(-5,5,1),random(-5,5,1),random(-5,5,1),3],
-[random(-5,5,1),random(-5,5,1),random(-5,5,1),0.75],
-[random(-5,5,1),random(-5,5,1),random(-5,5,1),9/4],
-]);
-
-$A = apply_fraction_to_matrix_entries($A); # try commenting this line out for different results
-
-$Arref = rref($A);
-
-$Aswitch = row_switch($A, 2, 3);
-
-$Amult = row_mult($A, 2, 4);
-
-$Aadd = row_add($A, 2, 1, 10);
-
-$E = elem_matrix_row_add(3,2,1,10);
-$EA = $E * $A;
-
-$E1 = elem_matrix_row_switch(5,2,4);
-$E2 = elem_matrix_row_mult(5,4,Fraction(1/10));
-$E3 = elem_matrix_row_add(5,3,1,35);
-$E4 = identity_matrix(4);
-change_matrix_entry($E4,[3,2],10);
-
-Context()->texStrings;
-BEGIN_TEXT
-The original matrix and its row reduced echelon form:
-\[ $A \sim $Arref. \]
-$BR
-The original matrix with rows switched, multiplied, or added together:
-\[ $Aswitch, $Amult, $Aadd. \]
-$BR
-Some elementary matrices.
-\[$E1, $E2, $E3, $E4\]
-END_TEXT
-Context()->normalStrings;
-
-
-ENDDOCUMENT();
-
-=back
-
-=head1 AUTHORS
-
-Paul Pearson, Hope College, Department of Mathematics
-
-with help from
-
-Davide Cervone, Union College, Department of Mathematics
-
-Michael Doob, University of Manitoba, Department of Mathematics
-
-=cut
-
-
-
-
-# Observation: a randomly generated 3 x 4 matrix has a very high probability
-# of having rank 3. So, trying to generate random 3 x 4 matrices until a
-# matrix of rank < 3 appears would be a bad idea. Also, there is no
-# guarantee that a randomly generated matrix will represent a consistent
-# system; however, empirical evidence suggests that the majority of the
-# time a random 3 x 4 matrix is produced, it is rank 3 and represents
-# a consistent system. Also, with randomly chosen matrices, it is
-# possible to get rows or columns of zeros, so watch out!
-
-loadMacros("MathObjects.pl","contextFraction.pl",);
-
-################################################
-# rref: input and output are MathObject matrices.
-# Should be run in Fraction context for best results.
-
-sub rref {
- my $M = shift;
- my @m = $M->value;
- my @m_reduced = rref_perl_array(@m);
- return Matrix(@m_reduced);
-}
-
-sub rcef {
- my $M = shift;
- my @m = $M->transpose->value;
- my @m_reduced = rref_perl_array(@m);
- return Matrix(@m_reduced)->transpose;
-}
-
-sub rref_perl_array {
-
- # input and output have form @A = ([1,2,3,4],[5,6,7,8]);
- my @A = @_;
- my $m = scalar(@A); # number of rows
- my $n = scalar(@{$A[0]}); # number of columns
-
- my $r = -1;
- my $i = -1;
- for my $j (0..$n-1) {
- $i = $r + 1;
- while ($i < $m and $A[$i][$j] == 0) {
- $i = $i + 1;
- }
- if ($i != $m) {
- $r = $r + 1;
- # row switch:
- @A[$i,$r] = @A[$r,$i];
- # row mult: scale row $r so that $A[$r][$j] = 1.
- my $lambda = $A[$r][$j];
- if ($lambda != 0) {
- foreach my $rowval ( @{$A[$r]} ) { $rowval /= $lambda; }
- }
- # row add:
- for my $k (0..$m-1) {
- if ($k == $r) { next; }
- my $lambda = $A[$k][$j];
- foreach my $p (0..$n-1) { $A[$k][$p] -= $lambda * $A[$r][$p]; }
- }
- }
- }
- return @A;
-}
-
-
-################################################
-# This was written by Davide Cervone.
-# http://webwork.maa.org/moodle/mod/forum/discuss.php?d=2970
-
-sub change_matrix_entry {
- my $self = shift; my $index = shift; my $x = shift;
- my $i = shift(@$index) - 1;
- if (scalar(@$index)) {change_matrix_entry($self->{data}[$i],$index,$x);}
- else {$self->{data}[$i] = Value::makeValue($x);
- }
-}
-
-################################################
-
-sub identity_matrix {
- my $n = shift;
- return Value::Matrix->I($n);
-}
-
-################################################
-
-sub elem_matrix_row_switch {
-
- # $n = number of rows (and columns) in matrix
- # $i and $j are indices of rows to be switched (index starting at 1, not 0)
- ($n,$i,$j) = @_;
- if ($i < 1 or $j < 1 or $i > $n or $j > $n) {
- warn "Index out of bounds in Elem_row_switch(). Returning identity matrix.";
- return Value::Matrix->I($n);
- }
- my $M = Value::Matrix->I($n); # construct identity matrix
- my @m = $M->value;
- @m[$i - 1, $j - 1] = @m[$j - 1, $i - 1]; # switch rows
- return Matrix(@m);
-
-}
-
-#########################################
-
-sub elem_matrix_row_mult {
-
- # $n = number of rows (and columns) in matrix
- # $i and $j are indices of rows to be switched (index starting at 1, not 0)
- ($n,$i,$s) = @_;
- if ($i < 1 or $i > $n) {
- warn "Index out of bounds in elem_row_mult(). Returning identity matrix.";
- return Value::Matrix->I($n);
- }
- if ($s == 0) {
- warn "Scaling by zero not allowed in elem_row_mult(). Returning identity matrix.";
- return Value::Matrix->I($n);
- }
- my $M = Value::Matrix->I($n); # construct identity matrix
- my @m = $M->value;
- foreach my $rowval ( @{$m[$i - 1]} ) { $rowval *= $s; }
- return Matrix(@m);
-
-}
-
-######################################
-
-sub elem_matrix_row_add {
-
- # $n = number of rows (and columns) in matrix
- # $i and $j are indices of rows to be switched (index starting at 1, not 0)
- ($n,$i,$j,$s) = @_;
- if ($i < 1 or $j < 1 or $i > $n or $j > $n) {
- warn "Index out of bounds in elem_matrix_row_add(). Returning identity matrix.";
- return Value::Matrix->I($n);
- }
- if ($s == 0) {
- warn "Scaling by zero not allowed in elem_matrix_row_add(). Returning identity matrix.";
- return Value::Matrix->I($n);
- }
- my $M = Value::Matrix->I($n); # construct identity matrix
- my @m = $M->value;
- $m[$i - 1][$j - 1] = $s;
- return Matrix(@m);
-
-}
-
-
-
-##############################################
-
-sub row_add {
-
- # put (row i) + s * (row j) into (row i)
-
- my $M = shift; # MathObject matrix
- my $i = shift; # row index
- my $j = shift; # row index
- my $s = shift; # scaling factor
-
- my ($r,$c) = $M->dimensions;
- if (($i < 1) or ($j < 1) or ($i > $r) or ($j > $r)) {
- warn "i = $i, j = $j, r = $r. Index out of bounds in row_add(). Returning original matrix.";
- return $M;
- }
- if ($s == 0 and $permissionLevel >= 10) {
- warn "Scaling a row by zero is not a valid row operation. (This warning is only shown to professors.) Returning original matrix.";
- return $M;
- }
-
- # my $E = elem_matrix_row_add($r, $i, $j, $s);
- # return $E * $M;
-
- my @m = $M->value;
- foreach my $k (0..$c-1) {
- $m[$i - 1][$k] += $s * $m[$j - 1][$k];
- }
- return Matrix(@m);
-
-}
-
-####################################
-
-sub row_switch {
-
- my $M = shift; # MathObject matrix
- my $i1 = shift; # index of row to be swapped, indexing starts at 1
- my $i2 = shift; # index of row to be swapped
- my ($r,$c) = $M->dimensions;
- if ($i1 < 1 or $i2 < 1 or $i1 > $r or $i2 > $r) {
- warn "Index out of bounds in row switch. Returning original matrix.";
- return $M;
- }
- my @m = $M->value;
- @m[$i1 - 1,$i2 - 1] = @m[$i2 - 1,$i1 - 1];
- return Matrix(@m);
-
-}
-
-#########################################
-
-sub row_mult {
-
- my $M = shift; # MathObject matrix
- my $i = shift; # index of row to be scaled
- my $s = shift; # scaling factor
- my ($r,$c) = $M->dimensions;
- if ($i < 1 or $i > $r) {
- warn "Index out of bounds in row multiplication. Returning original matrix.";
- return $M;
- }
- if ($s == 0 and $permissionLevel >= 10) { warn "Scaling a row by zero is not a valid row operation. (This warning is only shown to professors.)"; }
- my @m = $M->value;
- foreach my $rowval ( @{$m[$i - 1]} ) { $rowval *= $s; } # row multiplication
- return Matrix(@m);
-
-}
-
-####################################
-
-sub apply_fraction_to_matrix_entries {
-
- my $M = shift;
- my @m = $M->value;
- my ($r,$c) = $M->dimensions;
- foreach my $i (0..$r-1) {
- foreach my $rowval ( @{$m[$i]} ) { $rowval = Fraction("$rowval"); }
- }
- return Matrix(@m);
-
-}
-
-
-1;
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/Hope/MatrixUnits.pl b/OpenProblemLibrary/macros/Hope/MatrixUnits.pl
deleted file mode 100644
index 4de7f471bc..0000000000
--- a/OpenProblemLibrary/macros/Hope/MatrixUnits.pl
+++ /dev/null
@@ -1,310 +0,0 @@
-=pod
-
-=head1 NAME
-
-MatrixUnits.pl
-
-=head1 SYNOPSIS
-
-Generates unimodular n x n (n=2,3,4) MathObject matrices with real entries.
-
-=head1 DESCRIPTION
-
-This macro provides some routines for generating n x n (n=2,3,4)
-MathObject matrices with real entries that have determinant in the
-group of units of the integers Z (i.e., are Z-invertible). A matrix
-C<$M = GLnZ();> (for det = +1 or -1) or <$M = SLnZ();> (for det = -1)
-has all integer entries, is invertible, and its inverse has all integer entries.
-The matrix entries are intentionally chosen to be integers close to zero
-(so, if you want unimodular matrices with larger integer entries, you
-may want to copy the source code and modify it to suit your needs).
-The basic idea is to multiply several elementary matrices of
-determinant +1 or -1 together to get a unimodular matrix (although the
-code below accomplishes this by elementary row operations rather
-than by multiplication of elementary matrices).
-
-=over 12
-
-=item To produce a determinant +1 or -1 MathObject matrix C<$A>, use C<$A = GL2Z();>, C<$A = GL3Z();>, C<$A = GL4Z();>
-
-=item To produce a determinant +1 MathObject matrix C<$A>, use C<$A = SL2Z();>, C<$A = SL3Z();>, C<$A = SL4Z();>
-
-=item For determinant +1 or -1 perl arrays, use C<@a = GL2Z_perl();>, C<@a = GL3Z_perl();>, C<@a = GL4Z_perl();>
-
-=item For determinant +1 perl arrays, use C<@a = SL2Z_perl();>, C<@a = SL3Z_perl();>, C<@a = SL4Z_perl();>
-
-=back
-
-Note that the indexing on MathObject matrices starts at 1, while the indexing
-on perl arrays starts at 0, so that C<$A-element(1,1);> corresponds to
-C<$a[0][0];>. The perl arrays can be made into MathObject matrices by
-C<$A = Matrix(@a);>, and this is, in fact, what the C and C
-subroutines do for you. The perl versions C<@a = GLnZ_perl()> and
-C<@a = SLnZ_perl()> are useful if you want to have quick access to the matrix
-values (as perl reals stored in C<@a>) without having to pull them out of a
-MathObject matrix via C<@b = $A-value;> (in which case C<@b> is an
-array of MathObject reals).
-
-Note: There is overlap between MatrixUnits.pl (written after MathObject
-matrices were created) and MatrixUnimodular.pl (written before MathObject
-matrices were created). MatrixUnimodular.pl was left unchanged to provide
-legacy support for existing PG files.
-
-=head1 AUTHORS
-
-Paul Pearson, Hope College, Department of Mathematics
-
-=cut
-
-sub _MatrixUnits_init {}; # don't reload this file
-
-loadMacros("MathObjects.pl",);
-
-################################################
-#
-
-sub GL2Z {
- my @a = GL2Z_perl();
- return Matrix(@a);
-}
-
-sub GL2Z_perl {
-
- # Create an invertible 2 x 2 matrix with determinant either 1 or -1
-
- my $a11 = random(-1,1,2);
- my $a12 = non_zero_random(-3,3,1);
- my $mult = non_zero_random(-2,2,1);
- my $a21 = $mult * $a11;
- my $b1 = random(-1,1,2);
- my $a22 = $mult * $a12 + $b1;
-
- # $a_det = $a11 * $b1;
- return ([$a11,$a12],[$a21,$a22]);
-
-}
-
-###################################################
-
-sub SL2Z {
- my @a = SL2Z_perl();
- return Matrix(@a);
-}
-
-sub SL2Z_perl {
-
- # Create an invertible 2 x 2 matrix with determinant 1
-
- my $a11 = random(-1,1,2);
- my $a12 = non_zero_random(-3,3,1);
- my $mult = non_zero_random(-2,2,1);
- my $a21 = $mult * $a11;
- my $b1 = random(-1,1,2);
- my $a22 = $mult * $a12 + $b1;
-
- my $a_det = $a11 * $b1;
-
- if ($a_det == 1) {
- return ([$a11,$a12],[$a21,$a22]);
- } else { # det = -1, so swap rows to make det = 1
- return ([$a21,$a22],[$a11,$a12]);
- }
-
-}
-
-#######################################################
-
-sub GL3Z {
- my @a = GL3Z_perl();
- return Matrix(@a);
-}
-
-sub GL3Z_perl {
-
- # Create an invertible 3 x 3 matrix with determinant either 1 or -1
-
- my $a11 = random(-2,2,1);
- my $a21 = random(-1,1,2);
- my $a31 = random(-1,1,2);
-
- my $b1 = random(-1,1,2);
- my $a12 = $b1 * $a11;
- my $m = random(-1,1,2);
- my $a22 = $b1 * $a21 + $m;
- my $a32 = $b1 * $a31;
-
- my $c = random(-1,1,1);
- my $d = random(-1,1,2);
- my $n = random(-1,1,2);
- my $a13 = $c * $a11 + $d * $a12 + $n;
- my $a23 = $c * $a21 + $d * $a22;
- my $a33 = $c * $a31 + $d * $a32;
-
- # $det = - $a31 * $m * $n;
-
- return ([$a11,$a12,$a13],[$a21,$a22,$a23],[$a31,$a32,$a33]);
-
-}
-
-
-########################################################
-
-sub SL3Z {
- my @a = SL3Z_perl();
- return Matrix(@a);
-}
-
-sub SL3Z_perl {
-
- # Create an invertible 3 x 3 matrix with determinant 1
-
- my $a11 = random(-2,2,1);
- my $a21 = random(-1,1,2);
- my $a31 = random(-1,1,2);
-
- my $b1 = random(-1,1,2);
- my $a12 = $b1 * $a11;
- my $m = random(-1,1,2);
- my $a22 = $b1 * $a21 + $m;
- my $a32 = $b1 * $a31;
-
- my $c = random(-1,1,1);
- my $d = random(-1,1,2);
- my $n = random(-1,1,2);
- my $a13 = $c * $a11 + $d * $a12 + $n;
- my $a23 = $c * $a21 + $d * $a22;
- my $a33 = $c * $a31 + $d * $a32;
-
- my $det = - $a31 * $m * $n;
-
- if ($det == 1) {
- return ([$a11,$a12,$a13],[$a21,$a22,$a23],[$a31,$a32,$a33]);
- } else { # det = -1, so swap two rows so that det = +1.
- return ([$a21,$a22,$a23],[$a11,$a12,$a13],[$a31,$a32,$a33]);
- }
-
-}
-
-
-#######################################################
-
-sub GL4Z {
- my @a = GL4Z_perl();
- return Matrix(@a);
-}
-
-
-sub GL4Z_perl {
-
- # Create an invertible 4 x 4 matrix with determinant either 1 or -1
-
- my @a = ();
- $a[1][1] = random(-2,2,1);
- $a[2][1] = random(-1,1,2);
- $a[3][1] = random(-1,1,2);
- $a[4][1] = random(-1,1,1);
-
- my $b1 = random(-1,1,2);
- foreach my $i (1..4) {
- $a[$i][2] = $b1 * $a[$i][1];
- }
- my $p = random(-1,1,2);
- $a[2][2] = $a[2][2] + $p;
-
- my $c = random(-1,1,1);
- my $d = random(-1,1,2);
- my $n = random(-1,1,2);
- foreach my $i (1..4) {
- $a[$i][3] = $c * $a[$i][1] + $d * $a[$i][2];
- }
- my $n = random(-1,1,2);
- $a[1][3] = $a[1][3] + $n;
-
- my $f = random(-1,1,2);
- my $g = random(-1,1,1);
- my $h = random(-1,1,1);
- foreach my $i (1..4) {
- $a[$i][4] = $f * $a[$i][1] + $g * $a[$i][2] + $h * $a[$i][3];
- }
- my $q = random(-1,1,2);
- $a[4][4] = $a[4][4] + $q;
-
- # my $det = - $a[3][1] * $p * $n * $q;
-
- return (
- [ $a[1][1], $a[1][2], $a[1][3], $a[1][4] ],
- [ $a[2][1], $a[2][2], $a[2][3], $a[2][4] ],
- [ $a[3][1], $a[3][2], $a[3][3], $a[3][4] ],
- [ $a[4][1], $a[4][2], $a[4][3], $a[4][4] ]
- );
-
-}
-
-
-sub SL4Z {
- my @a = SL4Z_perl();
- return Matrix(@a);
-}
-
-sub SL4Z_perl {
-
- # Create an invertible 4 x 4 matrix with determinant 1
-
- my @a = ();
- $a[1][1] = random(-2,2,1);
- $a[2][1] = random(-1,1,2);
- $a[3][1] = random(-1,1,2);
- $a[4][1] = random(-1,1,1);
-
- my $b1 = random(-1,1,2);
- foreach my $i (1..4) {
- $a[$i][2] = $b1 * $a[$i][1];
- }
- my $p = random(-1,1,2);
- $a[2][2] = $a[2][2] + $p;
-
- my $c = random(-1,1,1);
- my $d = random(-1,1,2);
- my $n = random(-1,1,2);
- foreach my $i (1..4) {
- $a[$i][3] = $c * $a[$i][1] + $d * $a[$i][2];
- }
- my $n = random(-1,1,2);
- $a[1][3] = $a[1][3] + $n;
-
- my $f = random(-1,1,2);
- my $g = random(-1,1,1);
- my $h = random(-1,1,1);
- foreach my $i (1..4) {
- $a[$i][4] = $f * $a[$i][1] + $g * $a[$i][2] + $h * $a[$i][3];
- }
- my $q = random(-1,1,2);
- $a[4][4] = $a[4][4] + $q;
-
- my $det = - $a[3][1] * $p * $n * $q;
-
- if ($det == 1) {
-
- return (
- [ $a[1][1], $a[1][2], $a[1][3], $a[1][4] ],
- [ $a[2][1], $a[2][2], $a[2][3], $a[2][4] ],
- [ $a[3][1], $a[3][2], $a[3][3], $a[3][4] ],
- [ $a[4][1], $a[4][2], $a[4][3], $a[4][4] ]
- );
-
- } else { # det = -1, so swap two rows to make it have det = 1
-
- return (
- [ $a[1][1], $a[1][2], $a[1][3], $a[1][4] ],
- [ $a[3][1], $a[3][2], $a[3][3], $a[3][4] ],
- [ $a[2][1], $a[2][2], $a[2][3], $a[2][4] ],
- [ $a[4][1], $a[4][2], $a[4][3], $a[4][4] ]
- );
-
- }
-
-}
-
-##################################################
-
-1;
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/Hope/PGgraphgrid.pl b/OpenProblemLibrary/macros/Hope/PGgraphgrid.pl
deleted file mode 100644
index 674f7bcc59..0000000000
--- a/OpenProblemLibrary/macros/Hope/PGgraphgrid.pl
+++ /dev/null
@@ -1,133 +0,0 @@
-sub _PGgraphgrid_init {}; # don't reload this file
-
-=pod
-
-=head1 NAME
-
-PGgraphgrid.pl
-
-=head1 SYNOPSIS
-
-Provides subroutines plotting a parallelogram grid on a
-graph object created by PGgraphmacros.pl.
-
-=head1 DESCRIPTION
-
-Load the C macro file.
-
-=over 12
-
-=item C
-
-= back
-
-The macro C provides two different subroutines
-for graphing grids: the first one draws the grid using parallel lines
-and should be fast, and a second that draws each individual
-parallelogram and should be slow (but will suffer less from clipping):
-
-=over 12
-
-=item C
-
-=item C
-
-=back
-
-Here C<$gr> is a graph object created by C,
-C<$B> is a two by two MathObjects matrix, the integers C<$hmin> and
-C<$vmin> specify one corner of the grid, the integers C<$hmax> and
-C<$vmax> specify the opposite corner of the grid, C<$color> is a string
-that specifies the drawing color, and C<$linewidth> is a positive integer
-for the line width.
-
-=over 12
-
-=head1 AUTHORS
-
-Paul Pearson, Hope College, Department of Mathematics
-
-=cut
-
-################################################
-
-loadMacros("MathObjects.pl","PGgraphmacros.pl",);
-
-
-sub graphgrid1 {
- # inputs
- my $gr = shift; # graph object
- my $B = shift; # 2x2 basis matrix with B = (b1 | b2), with basis vectors in columns
- my $xmin = shift; my $ymin = shift; my $xmax = shift; my $ymax = shift; # (xmin,ymin) and (xmax,ymax) are two of the corners of the grid (must be integers)
- my $color = shift; # grid color
- my $linewidth = shift; # line thickness
-
- # standard coordinates for horizontal lines
- my @hx = (); # horizontal lines, x values
- my @hy = (); # horizontal lines, y values
- foreach my $y ($ymin..$ymax) {
- push(@hx, ($xmin,$xmax));
- push(@hy, ($y,$y));
- }
- my $H = Matrix([
- [@hx],
- [@hy]
- ]);
- my $BH = $B * $H;
- my @bh = $BH->value;
- # draw parallelogram grid on graph object
- # "horizontal" lines
- my $bh_ncol = ($BH->dimensions)[1];
- foreach my $i (0..$bh_ncol/2) {
- $gr->moveTo($bh[0][2*$i],$bh[1][2*$i]); $gr->lineTo($bh[0][2*$i+1],$bh[1][2*$i+1],$color,$linewidth);
- }
-
- # standard coordinates for vertical lines
- my @vx = (); # vertical lines, x values
- my @vy = (); # vertical lines, y values
- foreach my $x ($xmin..$xmax) {
- push(@vx, ($x,$x));
- push(@vy, ($ymin,$ymax));
- }
- my $V = Matrix([
- [@vx],
- [@vy]
- ]);
- my $BV = $B * $V;
- my @bv = $BV->value;
- # draw parallelogram grid on graph object
- # "vertical" lines
- my $bv_ncol = ($BV->dimensions)[1];
- foreach my $i (0..$bv_ncol/2) {
- $gr->moveTo($bv[0][2*$i],$bv[1][2*$i]); $gr->lineTo($bv[0][2*$i+1],$bv[1][2*$i+1],$color,$linewidth);
- }
-
-} # end graphgrid1
-
-
-sub graphgrid2 {
- # inputs
- my $gr = shift; # graph object
- my $B = shift; # 2x2 basis matrix with B = (b1 | b2), with basis vectors in columns
- my $xmin = shift; my $ymin = shift; my $xmax = shift; my $ymax = shift; # (xmin,ymin) and (xmax,ymax) are two of the corners of the grid (must be integers)
- my $color = shift; # grid color
- my $linewidth = shift; # line thickness
-
- foreach my $x ($xmin..$xmax) {
- foreach my $y ($ymin..$ymax) {
- my $X = Matrix([
- [$x,$x+1,$x+1,$x,$x],
- [$y,$y,$y+1,$y+1,$y]
- ]);
- my $BX = $B * $X;
- my @bx = $BX->value;
- $gr->moveTo($bx[0][0], $bx[1][0]);
- $gr->lineTo($bx[0][1], $bx[1][1], $color, $linewidth);
- $gr->lineTo($bx[0][2], $bx[1][2], $color, $linewidth);
- $gr->lineTo($bx[0][3], $bx[1][3], $color, $linewidth);
- $gr->lineTo($bx[0][4], $bx[1][4], $color, $linewidth);
- }
- }
-} # end graphgrid2
-
-1;
diff --git a/OpenProblemLibrary/macros/Hope/VectorListCheckers.pl b/OpenProblemLibrary/macros/Hope/VectorListCheckers.pl
deleted file mode 100644
index 37af04759b..0000000000
--- a/OpenProblemLibrary/macros/Hope/VectorListCheckers.pl
+++ /dev/null
@@ -1,282 +0,0 @@
-sub _VectorListCheckers_init {}; # don't reload this file
-
-=pod
-
-=head1 NAME
-
-VectorListCheckers.pl
-
-=head1 SYNOPSIS
-
-Provides subroutines for answer checking lists MathObjects
-vectors with real entries.
-
-=head1 DESCRIPTION
-
-First, load the C macro file.
-
-=over 12
-
-=item C
-
-= back
-
-For a MathObject list of MathObject vectors, the way to use the
-answer checkers is the same as using a custom answer checker
-inside of C~~&name_of_answer_checker_subroutine)>
-such as
-
-=over 12
-
-=item Ccmp( checker=~~&basis_checker_list_of_vectors ) );>
-
-=item C + s * <0,1,0> + t * <0,0,1>")-cmp( checker=~~&affine_subspace_checker_vectors ) );>
-
-=back
-
-The "list of vectors" at the end of the checker name refers to the
-fact that the student answer is a list of vectors.
-
-Here is an example of how to use these answer checkers.
-
-=over 12
-
-DOCUMENT();
-loadMacros(
-"PGstandard.pl",
-"MathObjects.pl",
-"VectorListCheckers.pl",
-"PGcourse.pl",
-);
-$showPartialCorrectAnswers = 1;
-TEXT(beginproblem());
-
-Context('Vector');
-
-$B = Matrix([[1,0,0],[0,1,0],[0,0,0]]);
-
-$answer = List(ColumnVector(1,0,0),ColumnVector(0,1,0));
-
-Context()->texStrings;
-BEGIN_TEXT
-A basis for the column space of \( B = $B \) is
-$BR
-$BR
-\{ $answer->ans_rule(60) \}
-$BR
-$BR
-Enter your answer as a comma separated list of vectors, such as
-\( \verb+<1,2,3>,<4,5,6>+ \).
-END_TEXT
-Context()->normalStrings;
-
-ANS( $answer->cmp(list_checker=>~~&basis_checker_list_of_vectors) );
-
-
-
-ENDDOCUMENT();
-
-=back
-
-The answer evaluation section of the PG file is totally standard.
-
-=over 12
-
-ANS( $multians->cmp );
-
-=back
-
-The C should be used for
-solutions to non-homogeneous systems of linear equations for
-which the solution is essentially a point plus the span of
-several linearly independent vectors. When using the parametric
-plane checker, the first vector input always serves as a point
-on the hyperplane (i.e., the first vector input is always a
-particular solution), while the remaining vectors are a basis for
-the hyperplane (i.e., they span the homogeneous solution set).
-
-=head1 AUTHORS
-
-Paul Pearson, Hope College, Department of Mathematics
-
-=cut
-
-
-
-################################################
-
-loadMacros("MathObjects.pl",);
-
-sub basis_checker_list_of_vectors {
-
- my ($correct, $student, $ansHash, $value) = @_;
- my @c = @{$correct};
- my @s = @{$student};
- my $nc = scalar(@c);
- my $ns = scalar(@s);
- my $score = 0;
- my @errors = ();
-
- return ($score,@errors) if $nc != $ns;
-
- if ($nc == 1) {
-
- if (Vector($s[0])->isParallel($c[0])) { return ($nc,@errors); }
-
- } else {
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- # put the correct vectors into the columns of a matrix $C
- my @cor = ();
- foreach my $i (0..$nc-1) {
- push(@cor, Matrix($c[$i]) );
- }
- my $C = Matrix(@cor)->transpose;
-
- # put the student vectors into the columns of a matrix $S
- my @stu = ();
- foreach my $i (0..$ns-1) {
- push(@stu, Matrix($s[$i]) );
- }
- my $S = Matrix(@stu)->transpose;
-
-
- # Put $C and $S into the local context so that
- # all of the computations that follow will also be in
- # the local context.
- $C = Matrix($context,$C);
- $S = Matrix($context,$S);
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors are linearly dependent");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- if ( $S == $C * $X ) { $score = $nc; };
-
- return ($score,@errors);
-
- }
-
-}
-
-########################################################
-
-$vector_list_column_syntax_angle_brackets = MODES(TeX=>'',HTML=>
-"Enter a column vector such as
-\\( \\left\\lbrack \\begin{array}{r} 1 \\\\ 2 \\end{array} \\right\\rbrack \\)
-using the syntax \\( \\verb+<1,2>+ \\).
-If there is more than one vector in your answer, enter
-your answer as a comma separated list of vectors, such as
-\\( \\verb+<1,2>,<3,4>+ \\)."
-);
-
-########################################################
-
-$vector_list_row_syntax_angle_brackets = MODES(TeX=>'',HTML=>
-"Enter a row vector using the syntax \\( \\verb+<1,2>+ \\).
-If there is more than one vector in your answer, enter
-your answer as a comma separated list of vectors, such as
-\\( \\verb+<1,2>,<3,4>+ \\)."
-);
-
-########################################################
-
-sub affine_subspace_checker_vectors {
-
- my ( $correct, $student, $ansHash ) = @_;
- my @s = ();
- my @c = ();
-
- # Most of the answer checking is done on integers
- # or on decimals like 0.24381729, so we will set the
- # tolerance accordingly in a local context.
- my $context = Context()->copy;
- $context->flags->set(
- tolerance => 0.001,
- tolType => "absolute",
- );
-
- # Get the variables from the context
- my @vars = $context->variables->names;
-
- # Make an array of zeros the same length as @vars
- my @zeros = ();
- foreach (@vars) { push(@zeros,0); }
-
- # Evaluate the correct and student answers on the zero vector
- my %h;
- @h{@vars} = @zeros;
- push(@c,Matrix($context,$correct->eval(%h)));
- push(@s,Matrix($context,$student->eval(%h)));
-
- # Make standard basis vectors e_i with ith entry = 1 and all other entries = 0
- # and evaluate the correct and student answers on e_i
- my @temp = ();
- foreach my $i (0..$#vars) {
- @temp = @zeros;
- $temp[$i] = 1;
- @h{@vars} = @temp;
- my $c_temp = Matrix($context,$correct->eval(%h));
- my $s_temp = Matrix($context,$student->eval(%h));
- $c_temp = $c_temp - $c[0];
- $s_temp = $s_temp - $s[0];
- push(@c,$c_temp);
- push(@s,$s_temp);
- }
-
- # Put the results into the columns of matrices
- my $C0 = Matrix($context,shift(@c))->transpose; # column vector = displacement vector
- my $C = Matrix($context,@c)->transpose; # matrix columns = vectors that span the hyperplane
- my $S0 = Matrix($context,shift(@s))->transpose; # column vector = displacement vector
- my $S = Matrix($context,@s)->transpose; # matrix columns = vectors that span the hyperplane
-
- # Theorem: A^T A is invertible if and only if A has linearly independent columns.
-
- # Check that the professor's vectors are, in fact, linearly independent.
- $CTC = ($C->transpose) * $C;
- warn "Correct answer is a linearly dependent set." if ($CTC->det == 0);
-
- # Check that the student's vectors are linearly independent
- if ( (($S->transpose) * $S)->det == 0) {
- Value->Error("Your vectors do not span a (hyper) plane of the correct dimension");
- return 0;
- }
-
- # solve (S_0 = C_0 + C A) for the column vector A of weights using
- # (S_0 - C_0) = C A
- # C^T (S_0 - C_0) = C^T C A
- # (C^T C)^{-1} C^T (S_0 - C_0) = A
- my $A = ($CTC->inverse) * ($C->transpose) * ($S0 - $C0);
- if ($S0 != $C0 + $C*$A) {
- #Value->Error("Your particular solution $S0 is incorrect");
- return 0;
- }
-
- # S = student, C = correct, X = change of basis matrix
- # Solve S = CX for X using (C^T C)^{-1} C^T S = X.
- $X = ($CTC->inverse) * (($C->transpose) * $S);
- return $S == $C * $X;
-
-}
-
-
-1;
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/LaTech/SI_property_tables.pl b/OpenProblemLibrary/macros/LaTech/SI_property_tables.pl
deleted file mode 100644
index c0d9c6f168..0000000000
--- a/OpenProblemLibrary/macros/LaTech/SI_property_tables.pl
+++ /dev/null
@@ -1,551 +0,0 @@
-# SI_property_tables.pl
-# Rename this file (with .pl extension) and place it in your course macros directory,
-
-@SI_property_tables_names = (
-"SI_water_Tsat ", "SI_water_Psat ","SI_water_vf ","SI_water_vfg ","SI_water_vg ", "SI_water_uf ", "SI_water_ufg ", "SI_water_ug ", "SI_water_hf ", "SI_water_hfg ", "SI_water_hg ", "SI_water_sf ", "SI_water_sfg ", "SI_water_sg ",
-
-"SI_air_T ", "SI_air_h ", "SI_air_Pr ", "SI_air_u ", "SI_air_vr ", "SI_air_so ",
-
-"SI_superWater_0p1MPa_T ", "SI_superWater_0p1MPa_v ", "SI_superWater_0p1MPa_u ","SI_superWater_0p1MPa_h ","SI_superWater_0p1MPa_s ",
-
-
-
-
-"SI_superWater_1p2MPa_T ", "SI_superWater_1p2MPa_v ", "SI_superWater_1p2MPa_u ","SI_superWater_1p2MPa_h ","SI_superWater_1p2MPa_s ",
-
-"SI_superWater_1p4MPa_T ", "SI_superWater_1p4MPa_v ", "SI_superWater_1p4MPa_u ","SI_superWater_1p4MPa_h ","SI_superWater_1p4MPa_s ",
-
-"SI_superWater_1p6MPa_T ", "SI_superWater_1p6MPa_v ", "SI_superWater_1p6MPa_u ","SI_superWater_1p6MPa_h ","SI_superWater_1p6MPa_s ",
-
-"SI_superWater_1p8MPa_T ", "SI_superWater_1p8MPa_v ", "SI_superWater_1p8MPa_u ","SI_superWater_1p8MPa_h ","SI_superWater_1p8MPa_s ",
-
-
-
-
-
-
-"SI_superWater_10MPa_T ", "SI_superWater_10MPa_v ", "SI_superWater_10MPa_u ","SI_superWater_10MPa_h ","SI_superWater_10MPa_s ",
-
-
-
-
-
-
-"SI_R134a_Tsat ", "SI_R134a_Psat ", "SI_R134a_vf ", "SI_R134a_vfg ", "SI_R134a_vg ", "SI_R134a_uf ", "SI_R134a_ufg ", "SI_R134a_ug ", "SI_R134a_hf ", "SI_R134a_hfg ", "SI_R134a_hg ", "SI_R134a_sf ", "SI_R134a_sfg ", "SI_R134a_sg ",
-
-
-
-
-
-
-
-"SI_superR134a_1p2MPa_T ", "SI_superR134a_1p2MPa_v ", "SI_superR134a_1p2MPa_u ", "SI_superR134a_1p2MPa_h ", "SI_superR134a_1p2MPa_s ",
-
-"SI_superR134a_1p2MPa_T ", "SI_superR134a_1p2MPa_v ", "SI_superR134a_1p2MPa_u ", "SI_superR134a_1p2MPa_h ", "SI_superR134a_1p2MPa_s ",
-
-"SI_superR134a_1p2MPa_T ", "SI_superR134a_1p2MPa_v ", "SI_superR134a_1p2MPa_u ", "SI_superR134a_1p2MPa_h ", "SI_superR134a_1p2MPa_s ",
-
-
-
-
-"SI_superR134a_1p2MPa_T ", "SI_superR134a_1p2MPa_v ", "SI_superR134a_1p2MPa_u ", "SI_superR134a_1p2MPa_h ", "SI_superR134a_1p2MPa_s "
-);
-
-#######################################################
-#######################################################
-### ###
-### below are the lists of the tabulated values ###
-### ###
-#######################################################
-#######################################################
-
-###########################
-### ###
-### saturated water ###
-### ###
-###########################
-
-@SI_water_Tsat = qw(
-0.01 5.00 6.97 10.00 13.02 15.00 17.50 20.00 21.08 24.08 25.00 28.96 30.00 32.87 35.00 40.00 40.29 45.00 45.81 50.00 53.97 55.00 60.00 60.06 65.00 69.09 70.00 75.00 75.86 80.00 81.32 85.00 90.00 91.76 95.00 99.61 105.00 105.97 110.00 111.35 115.00 116.04 120.00 120.21 123.97 125.00 127.41 130.00 133.52 135.00 136.27 138.86 140.00 141.30 143.61 145.00 147.90 150.00 151.83 155.00 155.46 158.83 160.00 161.98 165.00 167.75 170.00 170.41 172.94 175.00 177.66 180.00 184.06 185.00 187.96 190.00 191.60 195.00 198.29 200.00 205.00 205.72 210.00 212.38 215.00 218.41 220.00 223.95 225.00 230.00 235.00 240.00 242.56 245.00 250.00 255.00 260.00 263.94 265.00 270.00 275.00 275.59 280.00 285.00 285.83 290.00 295.00 300.00 303.35 305.00 310.00 311.00 315.00 318.08 320.00 324.68 325.00 330.00 330.85 335.00 336.67 340.00 342.16 345.00 347.36 350.00 352.29 355.00 356.99 360.00 361.47 365.00 365.75 369.83 370.00 373.71 373.95
-);
-
-@SI_water_Psat = qw(
-0.6117 0.8725 1.0000 1.2281 1.5000 1.7057 2.0000 2.3392 2.5000 3.0000 3.1698 4.0000 4.2469 5.0000 5.6291 7.3851 7.5000 9.5953 10.0000 12.3520 15.0000 15.7630 19.9470 20.0000 25.0430 30.0000 31.2020 38.5970 40.0000 47.4160 50.0000 57.8680 70.1830 75.0000 84.6090 100.0000 120.9000 125.0000 143.3800 150.0000 169.1800 175.0000 198.6700 200.0000 225.0000 232.2300 250.0000 270.2800 300.0000 313.2200 325.0000 350.0000 361.5300 375.0000 400.0000 415.6800 450.0000 476.1600 500.0000 543.4900 550.0000 600.0000 618.2300 650.0000 700.9300 750.0000 792.1800 800.0000 850.0000 892.6000 950.0000 1002.8000 1100.0000 1123.5000 1200.0000 1255.2000 1300.0000 1398.8000 1500.0000 1554.9000 1724.3000 1750.0000 1907.7000 2000.0000 2105.9000 2250.0000 2319.6000 2500.0000 2549.7000 2797.1000 3062.6000 3347.0000 3500.0000 3651.2000 3976.2000 4322.9000 4692.3000 5000.0000 5085.3000 5503.0000 5946.4000 6000.0000 6416.6000 6914.6000 7000.0000 7441.8000 7999.0000 8587.9000 9000.0000 9209.4000 9865.0000 10000.0000 10556.0000 11000.0000 11284.0000 12000.0000 12051.0000 12858.0000 13000.0000 13707.0000 14000.0000 14601.0000 15000.0000 15541.0000 16000.0000 16529.0000 17000.0000 17570.0000 18000.0000 18666.0000 19000.0000 19822.0000 20000.0000 21000.0000 21044.0000 22000.0000 22064.0000
-);
-
-@SI_water_vf = qw(
-0.001 0.001 0.001 0.001 0.001001 0.001001 0.001001 0.001002 0.001002 0.001003 0.001003 0.001004 0.001004 0.001005 0.001006 0.001008 0.001008 0.00101 0.00101 0.001012 0.001014 0.001015 0.001017 0.001017 0.00102 0.001022 0.001023 0.001026 0.001026 0.001029 0.00103 0.001032 0.001036 0.001037 0.00104 0.001043 0.001047 0.001048 0.001052 0.001053 0.001056 0.001057 0.00106 0.001061 0.001064 0.001065 0.001067 0.00107 0.001073 0.001075 0.001076 0.001079 0.00108 0.001081 0.001084 0.001085 0.001088 0.001091 0.001093 0.001096 0.001097 0.001101 0.001102 0.001104 0.001108 0.001111 0.001114 0.001115 0.001118 0.001121 0.001124 0.001127 0.001133 0.001134 0.001138 0.001141 0.001144 0.001149 0.001154 0.001157 0.001164 0.001166 0.001173 0.001177 0.001181 0.001187 0.00119 0.001197 0.001199 0.001209 0.001219 0.001229 0.001235 0.00124 0.001252 0.001263 0.001276 0.001286 0.001289 0.001303 0.001317 0.001319 0.001333 0.001349 0.001352 0.001366 0.001384 0.001404 0.001418 0.001425 0.001447 0.001452 0.001472 0.001488 0.001499 0.001526 0.001528 0.00156 0.001566 0.001597 0.00161 0.001638 0.001657 0.001685 0.00171 0.001741 0.00177 0.001808 0.00184 0.001895 0.001926 0.002015 0.002038 0.002207 0.002217 0.002703 0.003106
-);
-
-@SI_water_vfg = qw(
-205.999000 147.029000 129.189000 106.319000 87.962999 77.883999 66.988999 57.760998 54.240998 45.652997 43.338997 34.789996 32.877996 28.183995 25.203994 19.513992 19.231992 15.249990 14.668990 12.024988 10.018986 9.562885 7.665983 7.647083 6.192480 5.227678 5.038577 4.128074 3.992274 3.404271 3.239270 2.825068 2.358264 2.216163 1.979760 1.693057 1.417553 1.373952 1.208348 1.158347 1.034944 1.002643 0.890270 0.884719 0.792226 0.769055 0.717663 0.667010 0.604747 0.580715 0.560914 0.523141 0.507420 0.490249 0.461336 0.444915 0.412832 0.391389 0.373737 0.345384 0.341513 0.314499 0.305698 0.291496 0.271332 0.254409 0.241486 0.239235 0.225782 0.215469 0.202986 0.192713 0.176317 0.172766 0.162122 0.155219 0.150046 0.139741 0.130556 0.126053 0.113916 0.112274 0.103117 0.098410 0.093499 0.087530 0.084904 0.078755 0.077206 0.070296 0.064081 0.058478 0.055826 0.053416 0.048833 0.044678 0.040899 0.038162 0.037459 0.034319 0.031450 0.031130 0.028820 0.026407 0.026026 0.024188 0.022144 0.020255 0.019071 0.018507 0.016886 0.016576 0.015377 0.014500 0.013971 0.012738 0.012655 0.011419 0.011215 0.010251 0.009877 0.009145 0.008684 0.008087 0.007602 0.007065 0.006604 0.006064 0.005664 0.005055 0.004751 0.003994 0.003824 0.002787 0.002736 0.000941 0.000000
-);
-
-@SI_water_vg = qw(
-206 147.03 129.19 106.32 87.964 77.885 66.99 57.762 54.242 45.654 43.34 34.791 32.879 28.185 25.205 19.515 19.233 15.251 14.67 12.026 10.02 9.5639 7.667 7.6481 6.1935 5.2287 5.0396 4.1291 3.9933 3.4053 3.2403 2.8261 2.3593 2.2172 1.9808 1.6941 1.4186 1.375 1.2094 1.1594 1.036 1.0037 0.89133 0.88578 0.79329 0.77012 0.71873 0.66808 0.60582 0.58179 0.56199 0.52422 0.5085 0.49133 0.46242 0.446 0.41392 0.39248 0.37483 0.34648 0.34261 0.3156 0.3068 0.2926 0.27244 0.25552 0.2426 0.24035 0.2269 0.21659 0.20411 0.19384 0.17745 0.1739 0.16326 0.15636 0.15119 0.14089 0.13171 0.12721 0.11508 0.11344 0.10429 0.099587 0.09468 0.088717 0.086094 0.079952 0.078405 0.071505 0.0653 0.059707 0.057061 0.054656 0.050085 0.045941 0.042175 0.039448 0.038748 0.035622 0.032767 0.032449 0.030153 0.027756 0.027378 0.025554 0.023528 0.021659 0.020489 0.019932 0.018333 0.018028 0.016849 0.015988 0.01547 0.014264 0.014183 0.012979 0.012781 0.011848 0.011487 0.010783 0.010341 0.009772 0.009312 0.008806 0.008374 0.007872 0.007504 0.00695 0.006677 0.006009 0.005862 0.004994 0.004953 0.003644 0.003106
-);
-
-@SI_water_uf = qw(
-0 21.019 29.302 42.02 54.686 62.98 73.431 83.913 88.422 100.98 104.83 121.39 125.73 137.75 146.63 167.53 168.74 188.43 191.79 209.33 225.93 230.24 251.16 251.4 272.09 289.24 293.04 313.99 317.58 334.97 340.49 355.96 376.97 384.36 398 417.4 440.15 444.23 461.27 466.97 482.42 486.82 503.6 504.5 520.47 524.83 535.08 546.1 561.11 567.41 572.84 583.89 588.77 594.32 604.22 610.19 622.65 631.66 639.54 653.19 655.16 669.72 674.79 683.37 696.46 708.4 718.2 719.97 731 740.02 751.67 761.92 779.78 783.91 796.96 806 813.1 828.18 842.82 850.46 872.86 876.12 895.38 906.12 918.02 933.54 940.79 958.87 963.7 986.76 1010 1033.4 1045.4 1056.9 1080.7 1104.7 1128.8 1148.1 1153.3 1177.9 1202.9 1205.8 1228.2 1253.7 1258 1279.7 1306 1332.7 1350.9 1360 1387.7 1393.3 1416.1 1433.9 1445.1 1473 1475 1505.7 1511 1537.5 1548.4 1570.7 1585.5 1605.5 1622.6 1642.4 1660.2 1682.2 1699.1 1726.2 1740.3 1777.2 1785.8 1841.6 1844.5 1951.7 2015.7
-);
-
-@SI_water_ufg = qw(
-2374.9 2360.8 2355.2 2346.6 2338.1 2332.5 2325.5 2318.4 2315.4 2306.9 2304.3 2293.1 2290.2 2282.1 2276 2261.9 2261.1 2247.7 2245.4 2233.4 2222.1 2219.1 2204.7 2204.6 2190.3 2178.5 2175.8 2161.3 2158.8 2146.6 2142.7 2131.9 2117 2111.8 2102 2088.2 2071.8 2068.8 2056.4 2052.3 2040.9 2037.7 2025.3 2024.6 2012.7 2009.5 2001.8 1993.4 1982.1 1977.3 1973.1 1964.6 1960.9 1956.6 1948.9 1944.2 1934.5 1927.4 1921.2 1910.3 1908.8 1897.1 1893 1886.1 1875.4 1865.6 1857.5 1856.1 1846.9 1839.4 1829.6 1820.9 1805.7 1802.1 1790.9 1783 1776.8 1763.6 1750.6 1743.7 1723.5 1720.6 1702.9 1693 1681.9 1667.3 1660.5 1643.2 1638.6 1616.1 1593.2 1569.8 1557.6 1545.7 1521.1 1495.8 1469.9 1448.9 1443.2 1415.7 1387.4 1384.1 1358.2 1328.1 1323 1296.9 1264.5 1230.9 1207.6 1195.9 1159.3 1151.8 1121.1 1096.6 1080.9 1041.3 1038.5 993.5 985.5 945.5 928.7 893.8 870.3 837.7 809.4 775.9 745.1 706.4 675.9 625.7 598.9 526.4 509 391.9 385.6 140.8 0
-);
-
-@SI_water_ug = qw(
-2374.9 2381.8 2384.5 2388.7 2392.8 2395.5 2398.9 2402.3 2403.8 2407.9 2409.1 2414.5 2415.9 2419.8 2422.7 2429.4 2429.8 2436.1 2437.2 2442.7 2448 2449.3 2455.9 2456 2462.4 2467.7 2468.9 2475.3 2476.3 2481.6 2483.2 2487.8 2494 2496.1 2500.1 2505.6 2511.9 2513 2517.7 2519.2 2523.3 2524.5 2528.9 2529.1 2533.2 2534.3 2536.8 2539.5 2543.2 2544.7 2545.9 2548.5 2549.6 2550.9 2553.1 2554.4 2557.1 2559.1 2560.7 2563.5 2563.9 2566.8 2567.8 2569.4 2571.9 2574 2575.7 2576 2577.9 2579.4 2581.3 2582.8 2585.5 2586 2587.8 2589 2589.9 2591.7 2593.4 2594.2 2596.4 2596.7 2598.3 2599.1 2599.9 2600.9 2601.3 2602.1 2602.3 2602.9 2603.2 2603.1 2603 2602.7 2601.8 2600.5 2598.7 2597 2596.5 2593.7 2590.3 2589.9 2586.4 2581.8 2581 2576.5 2570.5 2563.6 2558.5 2555.8 2547.1 2545.2 2537.2 2530.4 2526 2514.3 2513.4 2499.2 2496.6 2483 2477.1 2464.5 2455.7 2443.2 2432 2418.3 2405.4 2388.6 2375 2351.9 2339.2 2303.6 2294.8 2233.5 2230.1 2092.4 2015.7
-);
-
-@SI_water_hf = qw(
-0.001 21.02 29.303 42.022 54.688 62.982 73.433 83.915 88.424 100.98 104.83 121.39 125.74 137.75 146.64 167.53 168.75 188.44 191.81 209.34 225.94 230.26 251.18 251.42 272.12 289.27 293.07 314.03 317.62 335.02 340.54 356.02 377.04 384.44 398.09 417.51 440.28 444.36 461.42 467.13 482.59 487.01 503.81 504.71 520.71 525.07 535.35 546.38 561.43 567.75 573.19 584.26 589.16 594.73 604.66 610.64 623.14 632.18 640.09 653.79 655.77 670.38 675.47 684.08 697.24 709.24 719.08 720.87 731.95 741.02 752.74 763.05 781.03 785.19 798.33 807.43 814.59 829.78 844.55 852.26 874.87 878.16 897.61 908.47 920.5 936.21 943.55 961.87 966.76 990.14 1013.7 1037.5 1049.7 1061.5 1085.7 1110.1 1134.8 1154.5 1159.8 1185.1 1210.7 1213.8 1236.7 1263.1 1267.5 1289.8 1317.1 1344.8 1363.7 1373.1 1402 1407.8 1431.6 1450.2 1462 1491.3 1493.4 1525.8 1531.4 1559.4 1571 1594.6 1610.3 1631.7 1649.9 1671.2 1690.3 1714 1732.2 1761.5 1776.8 1817.2 1826.6 1888 1891.2 2011.1 2084.3
-);
-
-@SI_water_hfg = qw(
-2500.9 2489.1 2484.4 2477.2 2470.1 2465.4 2459.5 2453.5 2451 2443.9 2441.7 2432.3 2429.8 2423 2417.9 2406 2405.3 2394 2392.1 2382 2372.3 2369.8 2357.7 2357.5 2345.4 2335.3 2333 2320.6 2318.4 2308 2304.7 2295.3 2282.5 2278 2269.6 2257.5 2243.1 2240.6 2229.7 2226 2216 2213.1 2202.1 2201.6 2191 2188.1 2181.2 2173.7 2163.5 2159.1 2155.4 2147.7 2144.3 2140.4 2133.4 2129.2 2120.3 2113.8 2108 2098 2096.6 2085.8 2082 2075.5 2065.6 2056.4 2048.8 2047.5 2038.8 2031.7 2022.4 2014.2 1999.6 1996.2 1985.4 1977.9 1971.9 1959 1946.4 1939.8 1920 1917.1 1899.7 1889.8 1878.8 1864.3 1857.4 1840.1 1835.4 1812.8 1789.5 1765.5 1753 1740.8 1715.3 1689 1661.8 1639.7 1633.7 1604.6 1574.5 1570.9 1543.2 1510.7 1505.2 1476.9 1441.6 1404.8 1379.3 1366.3 1325.9 1317.6 1283.4 1256.1 1238.5 1194.1 1191 1140.3 1131.3 1086 1067 1027.4 1000.5 963.4 931.1 892.7 857.4 812.9 777.8 720.1 689.2 605.5 585.5 450.4 443.1 161.5 0
-);
-
-@SI_water_hg = qw(
-2500.9 2510.1 2513.7 2519.2 2524.7 2528.3 2532.9 2537.4 2539.4 2544.8 2546.5 2553.7 2555.6 2560.7 2564.6 2573.5 2574 2582.4 2583.9 2591.3 2598.3 2600.1 2608.8 2608.9 2617.5 2624.6 2626.1 2634.6 2636.1 2643 2645.2 2651.4 2659.6 2662.4 2667.6 2675 2683.4 2684.9 2691.1 2693.1 2698.6 2700.2 2706 2706.3 2711.7 2713.1 2716.5 2720.1 2724.9 2726.9 2728.6 2732 2733.5 2735.1 2738.1 2739.8 2743.4 2745.9 2748.1 2751.8 2752.4 2756.2 2757.5 2759.6 2762.8 2765.7 2767.9 2768.3 2770.8 2772.7 2775.2 2777.2 2780.7 2781.4 2783.8 2785.3 2786.5 2788.8 2791 2792 2794.8 2795.2 2797.3 2798.3 2799.3 2800.5 2801 2801.9 2802.2 2802.9 2803.2 2803 2802.7 2802.2 2801 2799.1 2796.6 2794.2 2793.5 2789.7 2785.2 2784.6 2779.9 2773.7 2772.6 2766.7 2758.7 2749.6 2742.9 2739.4 2727.9 2725.5 2715 2706.3 2700.6 2685.4 2684.3 2666 2662.7 2645.4 2637.9 2622 2610.8 2595.1 2581 2563.9 2547.7 2526.9 2510 2481.6 2466 2422.7 2412.1 2338.4 2334.3 2172.6 2084.3
-);
-
-@SI_water_sf = qw(
-0 0.0763 0.1059 0.1511 0.1956 0.2245 0.2606 0.2965 0.3118 0.3543 0.3672 0.4224 0.4368 0.4762 0.5051 0.5724 0.5763 0.6386 0.6492 0.7038 0.7549 0.768 0.8313 0.832 0.8937 0.9441 0.9551 1.0158 1.0261 1.0756 1.0912 1.1346 1.1929 1.2132 1.2504 1.3028 1.3634 1.3741 1.4188 1.4337 1.4737 1.485 1.5279 1.5302 1.5706 1.5816 1.6072 1.6346 1.6717 1.6872 1.7005 1.7274 1.7392 1.7526 1.7765 1.7908 1.8205 1.8418 1.8604 1.8924 1.897 1.9308 1.9426 1.9623 1.9923 2.0195 2.0417 2.0457 2.0705 2.0906 2.1166 2.1392 2.1785 2.1875 2.2159 2.2355 2.2508 2.2831 2.3143 2.3305 2.3776 2.3844 2.4245 2.4467 2.4712 2.5029 2.5176 2.5542 2.5639 2.61 2.656 2.7018 2.7253 2.7476 2.7933 2.839 2.8847 2.9207 2.9304 2.9762 3.0221 3.0275 3.0681 3.1144 3.122 3.1608 3.2076 3.2548 3.2866 3.3024 3.3506 3.3603 3.3994 3.4299 3.4491 3.4964 3.4998 3.5516 3.5606 3.605 3.6232 3.6602 3.6848 3.7179 3.7461 3.7788 3.8082 3.8442 3.872 3.9165 3.9396 4.0004 4.0146 4.1071 4.1119 4.2942 4.407
-);
-
-@SI_water_sfg = qw(
-9.1556 8.9487 8.869 8.7488 8.6314 8.5559 8.4621 8.3696 8.3302 8.2222 8.1895 8.051 8.0152 7.9176 7.8466 7.6832 7.6738 7.5247 7.4996 7.371 7.2522 7.2218 7.0769 7.0752 6.936 6.8234 6.7989 6.6655 6.643 6.5355 6.5019 6.4089 6.2853 6.2426 6.1647 6.0562 5.9319 5.91 5.8193 5.7894 5.7092 5.6865 5.6013 5.5968 5.5171 5.4956 5.4453 5.3919 5.32 5.2901 5.2645 5.2128 5.1901 5.1645 5.1191 5.0919 5.0356 4.9953 4.9603 4.9002 4.8916 4.8285 4.8066 4.7699 4.7143 4.6642 4.6233 4.616 4.5705 4.5335 4.4862 4.4448 4.3735 4.3572 4.3058 4.2705 4.2428 4.1847 4.1287 4.0997 4.0154 4.0033 3.9318 3.8923 3.8489 3.7926 3.7664 3.7016 3.6844 3.6028 3.5216 3.4405 3.3991 3.3596 3.2788 3.1979 3.1169 3.053 3.0358 2.9542 2.8723 2.8627 2.7898 2.7066 2.6927 2.6225 2.5374 2.4511 2.3925 2.3633 2.2737 2.2556 2.1821 2.1245 2.0881 1.9975 1.9911 1.8906 1.873 1.7857 1.7497 1.6756 1.6261 1.5585 1.5005 1.4326 1.3709 1.2942 1.2343 1.1373 1.086 0.9489 0.9164 0.7005 0.689 0.2496 0
-);
-
-@SI_water_sg = qw(
-9.1556 9.0249 8.9749 8.8999 8.827 8.7803 8.7227 8.6661 8.6421 8.5765 8.5567 8.4734 8.452 8.3938 8.3517 8.2556 8.2501 8.1633 8.1488 8.0748 8.0071 7.9898 7.9082 7.9073 7.8296 7.7675 7.754 7.6812 7.6691 7.6111 7.5931 7.5435 7.4782 7.4558 7.4151 7.3589 7.2952 7.2841 7.2382 7.2231 7.1829 7.1716 7.1292 7.127 7.0877 7.0771 7.0525 7.0265 6.9917 6.9773 6.965 6.9402 6.9294 6.9171 6.8955 6.8827 6.8561 6.8371 6.8207 6.7927 6.7886 6.7593 6.7492 6.7322 6.7067 6.6837 6.665 6.6616 6.6409 6.6242 6.6027 6.5841 6.552 6.5447 6.5217 6.5059 6.4936 6.4678 6.443 6.4302 6.393 6.3877 6.3563 6.339 6.32 6.2954 6.284 6.2558 6.2483 6.2128 6.1775 6.1424 6.1244 6.1072 6.0721 6.0369 6.0017 5.9737 5.9662 5.9305 5.8944 5.8902 5.8579 5.821 5.8148 5.7834 5.745 5.7059 5.6791 5.6657 5.6243 5.6159 5.5816 5.5544 5.5372 5.4939 5.4908 5.4422 5.4336 5.3907 5.3728 5.3358 5.3108 5.2765 5.2466 5.2114 5.1791 5.1384 5.1064 5.0537 5.0256 4.9493 4.931 4.8076 4.8009 4.5439 4.407
-);
-
-
-###############
-### ###
-### air ###
-### ###
-###############
-
-
-@SI_air_T = qw(
-200 210 220 230 240 250 260 270 280 285 290 295 298 300 305 310 315 320 325 330 340 350 360 370 380 390 400 410 420 430 440 450 460 470 480 490 500 510 520 530 540 550 560 570 580 590 600 610 620 630 640 650 660 670 680 690 700 710 720 730 740 750 760 780 800 820 840 860 880 900 920 940 960 980 1000 1020 1040 1060 1080 1100 1120 1140 1160 1180 1200 1220 1240 1260 1280 1300 1320 1340 1360 1380 1400 1420 1440 1460 1480 1500 1520 1540 1560 1580 1600 1620 1640 1660 1680 1700 1750 1800 1850 1900 1950 2000 2050 2100 2150 2200 2250
-);
-
-@SI_air_h = qw(
-199.97 209.97 219.97 230.02 240.02 250.05 260.09 270.11 280.13 285.14 290.16 295.17 298.18 300.19 305.22 310.24 315.27 320.29 325.31 330.34 340.42 350.49 360.58 370.67 380.77 390.88 400.98 411.12 421.26 431.43 441.61 451.8 462.02 472.24 482.49 492.74 503.02 513.32 523.63 533.98 544.35 555.74 565.17 575.59 586.04 596.52 607.02 617.53 628.07 638.63 649.22 659.84 670.47 681.14 691.82 702.52 713.27 724.04 734.82 745.62 756.44 767.29 778.18 800.03 821.95 843.98 866.08 888.27 910.56 932.93 955.38 977.92 1000.55 1023.25 1046.04 1068.89 1091.85 1114.86 1137.89 1161.07 1184.28 1207.57 1230.92 1254.34 1277.79 1301.31 1324.93 1348.55 1372.24 1395.97 1419.76 1443.6 1467.49 1491.44 1515.42 1539.44 1563.51 1587.63 1611.79 1635.97 1660.23 1684.51 1708.82 1733.17 1757.57 1782 1806.46 1830.96 1855.5 1880.1 1941.6 2003.3 2065.3 2127.4 2189.7 2252.1 2314.6 2377.7 2440.3 2503.2 2566.4
-);
-
-@SI_air_Pr = qw(
-0.3363 0.3987 0.469 0.5477 0.6355 0.7329 0.8405 0.959 1.0889 1.1584 1.2311 1.3068 1.3543 1.386 1.4686 1.5546 1.6442 1.7375 1.8345 1.9352 2.149 2.379 2.626 2.892 3.176 3.481 3.806 4.153 4.522 4.915 5.332 5.775 6.245 6.742 7.268 7.824 8.411 9.031 9.684 10.37 11.1 11.86 12.66 13.5 14.38 15.31 16.28 17.3 18.36 19.84 20.64 21.86 23.13 24.46 25.85 27.29 28.8 30.38 32.02 33.72 35.5 37.35 39.27 43.35 47.75 52.59 57.6 63.09 68.98 75.29 82.05 89.28 97 105.2 114 123.4 133.3 143.9 155.2 167.1 179.7 193.1 207.2 222.2 238 254.7 272.3 290.8 310.4 330.9 352.5 375.3 399.1 424.2 450.5 478 506.9 537.1 568.8 601.9 636.5 672.8 710.5 750 791.2 834.1 878.9 925.6 974.2 1025 1161 1310 1475 1655 1852 2068 2303 2559 2837 3138 3464
-);
-
-@SI_air_u = qw(
-142.56 149.69 156.82 164 171.13 178.28 185.45 192.6 199.75 203.33 206.91 210.49 212.64 214.07 217.67 221.25 224.85 228.42 232.02 235.61 242.82 250.02 257.24 264.46 271.69 278.93 286.16 293.43 300.69 307.99 315.3 322.62 329.97 337.32 344.7 352.08 359.49 366.92 374.36 381.84 389.34 396.86 404.42 411.97 419.55 427.15 434.78 442.42 450.09 457.78 465.5 473.25 481.01 488.81 496.62 504.45 512.33 520.23 528.14 536.07 544.02 551.99 560.01 576.12 592.3 608.59 624.95 641.4 657.95 674.58 691.28 708.08 725.02 741.98 758.94 776.1 793.36 810.62 827.88 845.33 862.79 880.35 897.91 915.57 933.33 951.09 968.95 986.9 1004.76 1022.82 1040.88 1058.94 1077.1 1095.26 1113.52 1131.77 1150.13 1168.49 1186.95 1205.41 1223.87 1242.43 1260.99 1279.65 1298.3 1316.96 1335.72 1354.48 1373.24 1392.7 1439.8 1487.2 1534.9 1582.6 1630.6 1678.7 1726.8 1775.3 1823.8 1872.4 1921.3
-);
-
-@SI_air_vr = qw(
-1707 1512 1346 1205 1084 979 887.8 808 738 706.1 676.1 647.9 631.9 621.2 596 572.3 549.8 528.6 508.4 489.4 454.1 422.2 393.4 367.2 343.4 321.5 301.6 283.3 266.6 251.1 236.8 223.6 211.4 200.1 189.5 179.7 170.6 162.1 154.1 146.7 139.7 133.1 127 121.2 115.7 110.6 105.8 101.2 96.92 92.84 88.99 85.34 81.89 78.61 75.5 72.56 69.76 67.07 64.53 62.13 59.82 57.63 55.54 51.64 48.08 44.84 41.85 39.12 36.61 34.31 32.18 30.22 28.4 26.73 25.17 23.72 23.29 21.14 19.98 18.896 17.886 16.946 16.064 15.241 14.47 13.747 13.069 12.435 11.835 11.275 10.747 10.247 9.78 9.337 8.919 8.526 8.153 7.801 7.468 7.152 6.854 6.569 6.301 6.046 5.804 5.574 5.355 5.147 4.949 4.761 4.328 3.994 3.601 3.295 3.022 2.776 2.555 2.356 2.175 2.012 1.864
-);
-
-@SI_air_so = qw(
-1.29559 1.34444 1.39105 1.43557 1.47824 1.51917 1.55848 1.59634 1.63279 1.65055 1.66802 1.68515 1.69528 1.70203 1.71865 1.73498 1.75106 1.7669 1.78249 1.79783 1.8279 1.85708 1.88543 1.91313 1.94001 1.96633 1.99194 2.01699 2.04142 2.06533 2.0887 2.11161 2.13407 2.15604 2.1776 2.19876 2.21952 2.23993 2.25997 2.27967 2.29906 2.31809 2.33685 2.35531 2.37348 2.3914 2.40902 2.42644 2.44356 2.46048 2.47716 2.49364 2.50985 2.52589 2.54175 2.55731 2.57277 2.5881 2.60319 2.61803 2.6328 2.64737 2.66176 2.69013 2.71787 2.74504 2.7717 2.79783 2.82344 2.84856 2.87324 2.89748 2.92128 2.94468 2.9677 2.99034 3.0126 3.03449 3.05608 3.07732 3.09825 3.11883 3.13916 3.15916 3.17888 3.19834 3.21751 3.23638 3.2551 3.27345 3.2916 3.30959 3.32724 3.34474 3.362 3.37901 3.39586 3.41247 3.42892 3.44516 3.4612 3.47712 3.49276 3.50829 3.52364 3.53879 3.55381 3.56867 3.58335 3.5979 3.6336 3.6684 3.7023 3.7354 3.7677 3.7994 3.8303 3.8605 3.8901 3.9191 3.9474
-);
-
-#############################
-### ###
-### superheated water ###
-### ###
-#############################
-
-
-#### ####
-#### 0.1 MPa ####
-#### ####
-
-@SI_superWater_0p1MPa_T = qw(
-99.61 100 150 200 250 300 400 500 600 700 800 900 1000 1100 1200 1300
-);
-
-@SI_superWater_0p1MPa_v = qw(
-1.6941 1.6959 1.9367 2.1724 2.4062 2.6389 3.1027 3.5655 4.0279 4.49 4.9519 5.4137 5.8755 6.3372 6.7988 7.2605
-);
-
-@SI_superWater_0p1MPa_u = qw(
-2505.6 2506.2 2582.9 2658.2 2733.9 2810.7 2968.3 3132.2 3302.8 3480.4 3665 3856.7 4055 4259.8 4470.7 4687.2
-);
-
-@SI_superWater_0p1MPa_h = qw(
-2675 2675.8 2776.6 2875.5 2974.5 3074.5 3278.6 3488.7 3705.6 3929.4 4160.2 4398 4642.6 4893.6 5150.6 5413.3
-);
-
-@SI_superWater_0p1MPa_s = qw(
-7.3589 7.3611 7.6148 7.8356 8.0346 8.2172 8.5452 8.8362 9.0999 9.3424 9.5682 9.78 9.98 10.1698 10.3504 10.5229
-);
-
-
-
-
-
-
-
-
-
-
-
-#### ####
-#### 1.2 MPa ####
-#### ####
-
-@SI_superWater_1p2MPa_T = qw(
-179.88 200 250 300 350 400 500 600 700 800 900 1000 1100 1200 1300
-);
-
-@SI_superWater_1p2MPa_v = qw(
-0.16326 0.16934 0.19241 0.21386 0.23455 0.25482 0.29464 0.33395 0.37297 0.41184 0.45059 0.48928 0.52792 0.56652 0.60509
-);
-
-@SI_superWater_1p2MPa_u = qw(
-2587.8 2612.9 2704.7 2789.7 2872.7 2955.5 3123.4 3296.3 3475.3 3661 3853.3 4052.2 4257.5 4468.7 4685.5
-);
-
-@SI_superWater_1p2MPa_h = qw(
-2783.8 2816.1 2935.6 3046.3 3154.2 3261.3 3477 3697 3922.9 4155.2 4394 4639.4 4891 5148.5 5411.6
-);
-
-@SI_superWater_1p2MPa_s = qw(
-6.5217 6.5909 6.8313 7.0335 7.2139 7.3793 7.6779 7.9456 8.1904 8.4176 8.6303 8.831 9.0212 9.2022 9.375
-);
-
-#### ####
-#### 1.4 MPa ####
-#### ####
-
-@SI_superWater_1p4MPa_T = qw(
-195.04 200 250 300 350 400 500 600 700 800 900 1000 1100 1200 1300
-);
-
-@SI_superWater_1p4MPa_v = qw(
-0.14078 0.14303 0.16356 0.18233 0.20029 0.21782 0.25216 0.28597 0.31951 0.35288 0.38614 0.41933 0.45247 0.48558 0.51866
-);
-
-@SI_superWater_1p4MPa_u = qw(
-2591.8 2602.7 2698.9 2785.7 2869.7 2953.1 3121.8 3295.1 3474.4 3660.3 3852.7 4051.7 4257 4468.3 4685.1
-);
-
-@SI_superWater_1p4MPa_h = qw(
-2788.9 2803 2927.9 3040.9 3150.1 3258.1 3474.8 3695.5 3921.7 4154.3 4393.3 4638.8 4890.5 5148.1 5411.3
-);
-
-@SI_superWater_1p4MPa_s = qw(
-6.4675 6.4975 6.7488 6.9553 7.1379 7.3046 7.6047 7.873 8.1183 8.3458 8.5587 8.7595 8.9497 9.1308 9.3036
-);
-
-#### ####
-#### 1.6 MPa ####
-#### ####
-
-@SI_superWater_1p6MPa_T = qw(
-201.37 225 250 300 350 400 500 600 700 800 900 1000 1100 1200 1300
-);
-
-@SI_superWater_1p6MPa_v = qw(
-0.12374 0.13293 0.1419 0.15866 0.17459 0.19007 0.22029 0.24999 0.27941 0.30865 0.3378 0.36687 0.39589 0.42488 0.45383
-);
-
-@SI_superWater_1p6MPa_u = qw(
-2594.8 2645.1 2692.9 2781.6 2866.6 2950.8 3120.1 3293.9 3473.5 3659.5 3852.1 4051.2 4256.6 4467.9 4684.8
-);
-
-@SI_superWater_1p6MPa_h = qw(
-2792.8 2857.8 2919.9 3035.4 3146 3254.9 3472.6 3693.9 3920.5 4153.4 4392.6 4638.2 4890 5147.7 5410.9
-);
-
-@SI_superWater_1p6MPa_s = qw(
-6.42 6.5537 6.6753 6.8864 7.0713 7.2394 7.541 7.8101 8.0558 8.2834 8.4965 8.6974 8.8878 9.0689 9.2418
-);
-
-#### ####
-#### 1.8 MPa ####
-#### ####
-
-@SI_superWater_1p8MPa_T = qw(
-207.11 225 250 300 350 400 500 600 700 800 900 1000 1100 1200 1300
-);
-
-@SI_superWater_1p8MPa_v = qw(
-0.11037 0.11678 0.12502 0.14025 0.1546 0.16849 0.19551 0.222 0.24822 0.27426 0.3002 0.32606 0.35188 0.37766 0.40341
-);
-
-@SI_superWater_1p8MPa_u = qw(
-2597.3 2637 2686.7 2777.4 2863.6 2948.3 3118.5 3292.7 3472.6 3658.8 3851.5 4050.7 4256.2 4467.6 4684.5
-);
-
-@SI_superWater_1p8MPa_h = qw(
-2795.9 2847.2 2911.7 3029.9 3141.9 3251.6 3470.4 3692.3 3919.4 4152.4 4391.9 4637.6 4889.6 5147.3 5410.6
-);
-
-@SI_superWater_1p8MPa_s = qw(
-6.3775 6.4825 6.6088 6.8246 7.012 7.1814 7.4845 7.7543 8.0005 8.2284 8.4417 8.6427 8.8331 9.0143 9.1872
-);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-#### ####
-#### 10 MPa ####
-#### ####
-
-@SI_superWater_10MPa_T = qw(
-311 325 350 400 450 500 550 600 650 700 800 900 1000 1100 1200 1300
-);
-
-@SI_superWater_10MPa_v = qw(
-.018028 0.019877 0.02244 0.026436 0.029782 0.032811 0.035655 0.038378 0.041018 0.043597 0.048629 0.053547 0.058391 0.063183 0.067938 0.072667
-);
-
-@SI_superWater_10MPa_u = qw(
-2545.2 2611.6 2699.6 2833.1 2944.5 3047 3145.4 3242 3338 3434 3628.2 3826.5 4029.9 4238.5 4452.4 4671.3
-);
-
-@SI_superWater_10MPa_h = qw(
-2725.5 2810.3 2924 3097.5 3242.4 3375.1 3502 3625.8 3748.1 3870 4114.5 4362 4613.8 4870.3 5131.7 5398
-);
-
-@SI_superWater_10MPa_s = qw(
-5.6159 5.7596 5.946 6.2141 6.4219 6.5995 6.7585 6.9045 7.0408 7.1693 7.4085 7.629 7.8349 8.0289 8.2126 8.3874
-);
-
-
-
-
-
-############################
-### ###
-### saturated R-134a ###
-### ###
-############################
-
-
-
-
-
-@SI_R134a_Tsat = qw(
--40.00 -38.00 -36.95 -36.00 -34.00 -33.87 -32.00 -31.13 -30.00 -28.65 -28.00 -26.37 -26.00 -24.00 -22.32 -22.00 -20.00 -18.77 -18.00 -16.00 -15.60 -14.00 -12.73 -12.00 -10.09 -10.00 -8.00 -6.00 -5.38 -4.00 -2.00 -1.25 0.00 2.00 2.46 4.00 5.82 6.00 8.00 8.91 10.00 12.00 12.46 14.00 15.71 16.00 18.00 18.73 20.00 21.55 22.00 24.00 24.20 26.00 26.69 28.00 29.06 30.00 31.31 32.00 33.45 34.00 35.51 36.00 37.48 38.00 39.37 40.00 42.00 44.00 46.00 46.29 48.00 52.00 52.40 56.00 57.88 60.00 62.87 65.00 67.45 70.00 75.00 77.54 80.00 85.00 86.16 90.00 95.00 100.00
-);
-
-@SI_R134a_Psat = qw(
-51.250 56.860 60.00 62.950 69.560 70.00 76.710 80.00 84.430 90.00 92.760 100.00 101.730 111.370 120.00 121.720 132.820 140.00 144.690 157.380 160.00 170.930 180.00 185.370 200.00 200.740 217.080 234.440 240.00 252.850 272.360 280.00 293.010 314.840 320.00 337.900 360.00 362.230 387.880 400.00 414.890 443.310 450.00 473.190 500.00 504.580 537.520 550.00 572.070 600.00 608.270 646.180 650.00 685.840 700.00 727.310 750.00 770.640 800.00 815.890 850.00 863.110 900.00 912.350 950.00 963.680 1000.00 1017.100 1072.800 1130.700 1191.000 1200.00 1253.600 1386.200 1400.00 1529.100 1600.00 1682.800 1800.00 1891.000 2000.00 2118.200 2365.800 2500.00 2635.300 2928.200 3000.00 3246.900 3594.100 3975.100
-);
-
-@SI_R134a_vf = qw(
-0.0007054 0.0007083 0.0007098 0.0007112 0.0007142 0.0007144 0.0007172 0.0007185 0.0007203 0.0007223 0.0007234 0.0007259 0.0007265 0.0007297 0.0007324 0.0007329 0.0007362 0.0007383 0.0007396 0.000743 0.0007437 0.0007464 0.0007487 0.0007499 0.0007533 0.0007535 0.0007571 0.0007608 0.000762 0.0007646 0.0007684 0.0007699 0.0007723 0.0007763 0.0007772 0.0007804 0.0007841 0.0007845 0.0007887 0.0007907 0.000793 0.0007975 0.0007985 0.000802 0.0008059 0.0008066 0.0008113 0.000813 0.0008161 0.0008199 0.000821 0.0008261 0.0008266 0.0008313 0.0008331 0.0008366 0.0008395 0.0008421 0.0008458 0.0008478 0.000852 0.0008536 0.000858 0.0008595 0.0008641 0.0008657 0.00087 0.000872 0.0008786 0.0008854 0.0008924 0.0008934 0.0008996 0.000915 0.0009166 0.0009317 0.00094 0.0009498 0.0009639 0.000975 0.0009886 0.0010037 0.0010372 0.0010566 0.0010772 0.001127 0.0011406 0.0011932 0.0012933 0.0015269
-);
-
-@SI_R134a_vfg = qw(
-0.360105 0.326612 0.310500 0.296799 0.270186 0.268576 0.246393 0.236812 0.225080 0.211908 0.205937 0.191814 0.188734 0.173220 0.161388 0.159217 0.146554 0.139402 0.135090 0.124677 0.122736 0.115224 0.109661 0.106610 0.099114 0.098763 0.091595 0.085041 0.083135 0.079039 0.073536 0.071582 0.068483 0.063836 0.062827 0.059558 0.055954 0.055614 0.051973 0.050410 0.048610 0.045498 0.044821 0.042615 0.040312 0.039941 0.037460 0.036595 0.035153 0.033475 0.033007 0.031008 0.030819 0.029145 0.028528 0.027405 0.026532 0.025780 0.024775 0.024260 0.023217 0.022837 0.021825 0.021505 0.020574 0.020253 0.019443 0.019080 0.017976 0.016939 0.015961 0.015822 0.015039 0.013350 0.013190 0.011839 0.011183 0.010484 0.009595 0.008975 0.008299 0.007638 0.006443 0.005879 0.005359 0.004359 0.004134 0.003406 0.002433 0.001103
-);
-
-@SI_R134a_vg = qw(
-0.36081 0.32732 0.31121 0.29751 0.2709 0.26929 0.24711 0.23753 0.2258 0.21263 0.20666 0.19254 0.18946 0.17395 0.16212 0.15995 0.14729 0.14014 0.13583 0.12542 0.12348 0.11597 0.11041 0.10736 0.099867 0.099516 0.092352 0.085802 0.083897 0.079804 0.074304 0.072352 0.069255 0.064612 0.063604 0.060338 0.056738 0.056398 0.052762 0.051201 0.049403 0.046295 0.045619 0.043417 0.041118 0.040748 0.038271 0.037408 0.035969 0.034295 0.033828 0.031834 0.031646 0.029976 0.029361 0.028242 0.027371 0.026622 0.025621 0.025108 0.024069 0.023691 0.022683 0.022364 0.021438 0.021119 0.020313 0.019952 0.018855 0.017824 0.016853 0.016715 0.015939 0.014265 0.014107 0.012771 0.012123 0.011434 0.010559 0.00995 0.009288 0.008642 0.00748 0.006936 0.006436 0.005486 0.005275 0.004599 0.003726 0.00263
-);
-
-@SI_R134a_uf = qw(
--0.036 2.475 3.798 4.992 7.517 7.68 10.05 11.15 12.59 14.31 15.13 17.21 17.69 20.25 22.4 22.82 25.39 26.98 27.98 30.57 31.09 33.17 34.83 35.78 38.28 38.4 41.03 43.66 44.48 46.31 48.96 49.97 51.63 54.3 54.92 56.99 59.44 59.68 62.39 63.62 65.1 67.83 68.45 70.57 72.93 73.32 76.08 77.1 78.86 81.02 81.64 84.44 84.72 87.26 88.24 90.09 91.59 92.93 94.79 95.79 97.87 98.66 100.83 101.55 103.69 104.45 106.45 107.38 110.32 113.28 116.26 116.7 119.26 125.33 125.94 131.49 134.43 137.76 142.33 145.77 149.78 154.01 162.53 166.99 171.4 180.77 183.04 190.89 202.4 218.72
-);
-
-@SI_R134a_ufg = qw(
-207.4 206.04 205.32 204.67 203.29 203.2 201.91 201.3 200.52 199.57 199.12 197.98 197.72 196.3 195.11 194.88 193.45 192.57 192.01 190.56 190.27 189.09 188.16 187.62 186.21 186.14 184.64 183.13 182.67 181.61 180.08 179.5 178.53 176.97 176.61 175.39 173.94 173.8 172.19 171.45 170.56 168.92 168.54 167.26 165.82 165.58 163.88 163.25 162.16 160.81 160.42 158.65 158.48 156.87 156.24 155.05 154.08 153.22 152 151.35 149.98 149.46 148.01 147.54 146.1 145.58 144.23 143.6 141.58 139.52 137.42 137.11 135.29 130.88 130.43 126.28 124.04 121.46 117.83 115.05 111.73 108.14 100.6 96.47 92.23 82.67 80.22 71.29 56.47 29.19
-);
-
-@SI_R134a_ug = qw(
-207.37 208.51 209.12 209.66 210.81 210.88 211.96 212.46 213.11 213.88 214.25 215.19 215.4 216.55 217.51 217.7 218.84 219.54 219.98 221.13 221.35 222.27 222.99 223.4 224.48 224.54 225.67 226.8 227.14 227.92 229.04 229.46 230.16 231.27 231.52 232.38 233.38 233.48 234.58 235.07 235.67 236.75 237 237.83 238.75 238.9 239.96 240.35 241.02 241.83 242.06 243.1 243.2 244.12 244.48 245.14 245.67 246.14 246.79 247.14 247.85 248.12 248.85 249.08 249.79 250.04 250.68 250.97 251.89 252.8 253.68 253.81 254.55 256.21 256.37 257.77 258.47 259.22 260.17 260.82 261.51 262.15 263.13 263.45 263.63 263.44 263.26 262.18 258.87 247.91
-);
-
-@SI_R134a_hf = qw(
-0 2.515 3.841 5.037 7.566 7.73 10.1 11.21 12.65 14.37 15.2 17.28 17.76 20.33 22.49 22.91 25.49 27.08 28.09 30.69 31.21 33.3 34.97 35.92 38.43 38.55 41.19 43.84 44.66 46.5 49.17 50.18 51.86 54.55 55.16 57.25 59.72 59.97 62.69 63.94 65.43 68.18 68.81 70.95 73.33 73.73 76.52 77.54 79.32 81.51 82.14 84.98 85.26 87.83 88.82 90.69 92.22 93.58 95.47 96.48 98.6 99.4 101.61 102.33 104.51 105.29 107.32 108.26 111.26 114.28 117.32 117.77 120.39 126.59 127.22 132.91 135.93 139.36 144.07 147.62 151.76 156.13 164.98 169.63 174.24 184.07 186.46 194.76 207.05 224.79
-);
-
-@SI_R134a_hfg = qw(
-225.86 224.61 223.95 223.35 222.09 222 220.81 220.25 219.52 218.65 218.22 217.16 216.92 215.59 214.48 214.26 212.91 212.08 211.55 210.18 209.9 208.79 207.9 207.38 206.03 205.96 204.52 203.07 202.62 201.6 200.11 199.54 198.6 197.07 196.71 195.51 194.08 193.94 192.35 191.62 190.73 189.09 188.71 187.42 185.98 185.73 184.01 183.38 182.27 180.9 180.49 178.69 178.51 176.85 176.21 174.99 173.98 173.08 171.82 171.14 169.71 169.17 167.66 167.16 165.64 165.1 163.67 163 160.86 158.67 156.43 156.1 154.14 149.39 148.9 144.38 141.93 139.1 135.11 132.02 128.33 124.32 115.85 111.16 106.35 95.44 92.63 82.35 65.21 33.58
-);
-
-@SI_R134a_hg = qw(
-225.86 227.12 227.79 228.39 229.65 229.73 230.91 231.46 232.17 233.02 233.43 234.44 234.68 235.92 236.97 237.17 238.41 239.16 239.64 240.87 241.11 242.09 242.86 243.3 244.46 244.51 245.72 246.91 247.28 248.1 249.28 249.72 250.45 251.61 251.88 252.77 253.81 253.91 255.04 255.55 256.16 257.27 257.53 258.37 259.3 259.46 260.53 260.92 261.59 262.4 262.64 263.67 263.77 264.68 265.03 265.68 266.2 266.66 267.29 267.62 268.31 268.57 269.26 269.49 270.15 270.39 270.99 271.27 272.12 272.95 273.75 273.87 274.53 275.98 276.12 277.3 277.86 278.46 279.17 279.64 280.09 280.46 280.82 280.79 280.59 279.51 279.09 277.11 272.26 258.37
-);
-
-@SI_R134a_sf = qw(
-0 0.01072 0.01634 0.02138 0.03199 0.03267 0.04253 0.04711 0.05301 0.06008 0.06344 0.07188 0.07382 0.08414 0.09275 0.09441 0.10463 0.11087 0.11481 0.12493 0.12693 0.13501 0.14139 0.14504 0.15457 0.15504 0.16498 0.17489 0.17794 0.18476 0.19459 0.19829 0.20439 0.21415 0.21637 0.22387 0.2327 0.23356 0.24323 0.24761 0.25286 0.26246 0.26465 0.27204 0.28023 0.28159 0.29112 0.29461 0.30063 0.30799 0.31011 0.31958 0.32051 0.32903 0.3323 0.33846 0.34345 0.34789 0.35404 0.3573 0.36413 0.3667 0.37377 0.37609 0.38301 0.38548 0.39189 0.39486 0.40425 0.41363 0.42302 0.42441 0.43242 0.45126 0.45315 0.47018 0.47911 0.4892 0.50294 0.5132 0.52509 0.53755 0.56241 0.57531 0.588 0.61473 0.62118 0.64336 0.67578 0.72217
-);
-
-@SI_R134a_sfg = qw(
-0.96866 0.95511 0.94807 0.94176 0.92859 0.92775 0.9156 0.90999 0.90278 0.89419 0.89012 0.87995 0.87762 0.86527 0.85503 0.85307 0.84101 0.83368 0.82908 0.81729 0.81496 0.80561 0.79826 0.79406 0.78316 0.78263 0.7713 0.76008 0.75664 0.74896 0.73794 0.73381 0.72701 0.71616 0.71369 0.7054 0.69566 0.69471 0.6841 0.67929 0.67356 0.66308 0.66069 0.65266 0.64377 0.6423 0.63198 0.62821 0.62172 0.61378 0.61149 0.6013 0.6003 0.59115 0.58763 0.58102 0.57567 0.57091 0.56431 0.56082 0.55349 0.55074 0.54315 0.54066 0.53323 0.53058 0.52368 0.52049 0.51039 0.50027 0.49012 0.48863 0.47993 0.45941 0.45734 0.43863 0.42873 0.41749 0.40204 0.39039 0.37675 0.36227 0.33272 0.31695 0.30111 0.26644 0.25776 0.22674 0.17711 0.08999
-);
-
-@SI_R134a_sg = qw(
-0.96866 0.96584 0.96441 0.96315 0.96058 0.96042 0.95813 0.9571 0.95579 0.95427 0.95356 0.95183 0.95144 0.94941 0.94779 0.94748 0.94564 0.94456 0.94389 0.94222 0.9419 0.94063 0.93965 0.93911 0.93773 0.93766 0.93629 0.93497 0.93458 0.93372 0.93253 0.9321 0.93139 0.93031 0.93006 0.92927 0.92836 0.92828 0.92733 0.92691 0.92641 0.92554 0.92535 0.9247 0.924 0.92389 0.9231 0.92282 0.92234 0.92177 0.9216 0.92088 0.92081 0.92018 0.91994 0.91948 0.91912 0.91879 0.91835 0.91811 0.91762 0.91743 0.91692 0.91675 0.91624 0.91606 0.91558 0.91536 0.91464 0.91391 0.91315 0.91303 0.91236 0.91067 0.9105 0.9088 0.90784 0.90669 0.90498 0.90359 0.90184 0.89982 0.89512 0.89226 0.88912 0.88117 0.87894 0.8701 0.85289 0.81215
-);
-
-
-
-
-
-
-
-
-##############################
-### ###
-### superheated R-134a ###
-### ###
-##############################
-
-
-
-
-
-#### ####
-#### 0.7 MPa ####
-#### ####
-
-@SI_superR134a_0p7MPa_T = qw(
-26.69 30 40 50 60 70 80 90 100 110 120 130 140 150 160
-);
-
-@SI_superR134a_0p7MPa_v = qw(
-0.029361 0.029966 0.031696 0.033322 0.034875 0.036373 0.037829 0.03925 0.040642 0.04201 0.043358 0.044688 0.046004 0.047306 0.048597
-);
-
-@SI_superR134a_0p7MPa_u = qw(
-244.48 247.48 256.39 265.2 274.01 282.87 291.8 300.82 309.95 319.19 328.55 338.04 347.66 357.41 367.29
-);
-
-@SI_superR134a_0p7MPa_h = qw(
-265.03 268.45 278.57 288.53 298.42 308.33 318.28 328.29 338.4 348.6 358.9 369.32 379.86 390.52 401.31
-);
-
-@SI_superR134a_0p7MPa_s = qw(
-0.9199 0.9313 0.9641 0.9954 1.0256 1.0549 1.0835 1.1114 1.1389 1.1658 1.1924 1.2186 1.2444 1.2699 1.2951
-);
-
-#### ####
-#### 0.8 MPa ####
-#### ####
-
-@SI_superR134a_0p8MPa_T = qw(
-31.31 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180
-);
-
-@SI_superR134a_0p8MPa_v = qw(
-0.025621 0.027035 0.028547 0.029973 0.03134 0.032659 0.033941 0.035193 0.03642 0.037625 0.038813 0.039985 0.041143 0.04229 0.043427 0.044554
-);
-
-@SI_superR134a_0p8MPa_u = qw(
-246.79 254.82 263.86 272.83 281.81 290.84 299.95 309.15 318.45 327.87 337.4 347.06 356.85 366.76 376.81 386.99
-);
-
-@SI_superR134a_0p8MPa_h = qw(
-267.29 276.45 286.69 296.81 306.88 316.97 327.1 337.3 347.59 357.97 368.45 379.05 389.76 400.59 411.55 422.64
-);
-
-@SI_superR134a_0p8MPa_s = qw(
-0.9183 0.948 0.9802 1.011 1.0408 1.0698 1.0981 1.1258 1.153 1.1798 1.2061 1.2321 1.2577 1.283 1.308 1.3327
-);
-
-#### ####
-#### 0.9 MPa ####
-#### ####
-
-@SI_superR134a_0p9MPa_T = qw(
-35.51 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180
-);
-
-@SI_superR134a_0p9MPa_v = qw(
-0.022683 0.023375 0.024809 0.026146 0.027413 0.02863 0.029806 0.030951 0.032068 0.033164 0.034241 0.035302 0.036349 0.037384 0.038408 0.039423
-);
-
-@SI_superR134a_0p9MPa_u = qw(
-248.85 253.13 262.44 271.6 280.72 289.86 299.06 308.34 317.7 327.18 336.76 346.46 356.28 366.23 376.31 386.52
-);
-
-@SI_superR134a_0p9MPa_h = qw(
-269.26 274.17 284.77 295.13 305.39 315.63 325.89 336.19 346.56 357.02 367.58 378.23 389 399.88 410.88 422
-);
-
-@SI_superR134a_0p9MPa_s = qw(
-0.9169 0.9327 0.966 0.9976 1.028 1.0574 1.086 1.114 1.1414 1.1684 1.1949 1.221 1.2467 1.2721 1.2972 1.3221
-);
-
-
-
-
-
-
-
-
-#### ####
-#### 1.2 MPa ####
-#### ####
-
-@SI_superR134a_1p2MPa_T = qw(
-46.29 50 60 70 80 90 100 110 120 130 140 150 160 170 180
-);
-
-@SI_superR134a_1p2MPa_v = qw(
-0.016715 0.017201 0.018404 0.019502 0.020529 0.021506 0.022442 0.023348 0.024228 0.025086 0.025927 0.026753 0.027566 0.028367 0.029158
-);
-
-@SI_superR134a_1p2MPa_u = qw(
-253.81 257.63 267.56 277.21 286.75 296.26 305.8 315.38 325.03 334.77 344.61 354.56 364.61 374.78 385.08
-);
-
-@SI_superR134a_1p2MPa_h = qw(
-273.87 278.27 289.64 300.61 311.39 322.07 332.73 343.4 354.11 364.88 375.72 386.66 397.69 408.82 420.07
-);
-
-@SI_superR134a_1p2MPa_s = qw(
-0.913 0.9267 0.9614 0.9938 1.0248 1.0546 1.0836 1.1118 1.1394 1.1664 1.193 1.2192 1.2449 1.2703 1.2954
-);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1; #required at end of file - a perl thing
\ No newline at end of file
diff --git a/OpenProblemLibrary/macros/LaTech/interpMacros.pl b/OpenProblemLibrary/macros/LaTech/interpMacros.pl
deleted file mode 100644
index 36214df2ee..0000000000
--- a/OpenProblemLibrary/macros/LaTech/interpMacros.pl
+++ /dev/null
@@ -1,34 +0,0 @@
-# interpMacros.pl
-# Rename this file (with .pl extension) and place it in your course macros directory,
-
-sub interpVals {
- $arrayLength = ($#_ )/2;
- @A_ARRAY = @_[0..($arrayLength-1)];
- @B_ARRAY = @_[$arrayLength .. ($#_-1)];
- $A_VAL = @_[$#_];
- $arrayLength2 = $#A_ARRAY;
-
-
- for ($i = 1; $i < ($#A_ARRAY+1); $i++) {
- if($A_VAL == $A_ARRAY[$i-1]) {
- $B_VAL = $B_ARRAY[$i-1];
- last;
- } elsif ($A_ARRAY[$i-1] < $A_VAL && $A_VAL < $A_ARRAY[$i]) {
- $AL = $A_ARRAY[$i-1];
- $AR = $A_ARRAY[$i];
- $BL = $B_ARRAY[$i-1];
- $BR = $B_ARRAY[$i];
- $B_VAL = (($A_VAL-$AL)/($AR - $AL)*($BR-$BL))+$BL;
- last;
- } elsif($A_VAL == $A_ARRAY[$i]) {
- $B_VAL = $B_ARRAY[$i];
- last;
- } else {
- $B_VAL = $B_ARRAY[0];
- }
- }
-
- return $B_VAL;
-}
-
-1; #required at end of file - a perl thing
diff --git a/OpenProblemLibrary/macros/MC/draggableProof.pl b/OpenProblemLibrary/macros/MC/draggableProof.pl
deleted file mode 100644
index 0b866be90d..0000000000
--- a/OpenProblemLibrary/macros/MC/draggableProof.pl
+++ /dev/null
@@ -1,291 +0,0 @@
-# Done: show possible choices in TeX mode
-# To do: display student answers and correct answers in TeX mode properly.
-# To do: put jquery.nestable.js in a universal spot on every webwork server.
-
-loadMacros("PGchoicemacros.pl");
-
-sub _draggableProof_init {
- PG_restricted_eval("sub DraggableProof {new draggableProof(\@_)}");
-
- $courseHtmlUrl = $envir{htmlURL};
-
-# if (-e "${wwHtmlDir}js/vendor/jquery/modules/jquery.nestable.js") {
-# $scriptPath = $wwHtmlUrl.'js/vendor/jquery/modules/';
-# } else {
-# $scriptPath = $courseHtmlUrl.'js/';
-# }
-
- # post global javascript
- main::POST_HEADER_TEXT(main::MODES(TeX=>"", HTML=><<" END_SCRIPTS"));
-
-
-
-
- END_SCRIPTS
-}
-
-package draggableProof;
-
-my $n = 0; # number of nestable lists so far
-
-sub new {
- $n++;
- my $self = shift; my $class = ref($self) || $self;
- my $proof = shift || []; my $extra = shift || [];
- my %options = (
- SourceLabel => "Choose from these sentences:",
- TargetLabel => "Your Proof:",
- id => "P$n",
- @_
- );
- my $lines = [@$proof,@$extra];
- my $numNeeded = scalar(@$proof);
- my $numProvided = scalar(@$lines);
- my @order = main::shuffle($numProvided);
- my @unorder = main::invert(@order);
- $self = bless {
- lines => $lines,
- numNeeded => $numNeeded, numProvided => $numProvided,
- order => \@order, unordered => \@unorder,
- proof => "$options{id}-".join(",$options{id}-",@unorder[0..$numNeeded-1]),
- %options
- }, $class;
- $self->AnswerRule;
- $self->ScriptAndStyles;
- $self->GetAnswer;
- return $self;
-}
-
-sub lines {my $self = shift; return @{$self->{lines}}}
-sub numNeeded {(shift)->{numNeeded}}
-sub numProvided {(shift)->{numProvided}}
-sub order {my $self = shift; return @{$self->{order}}}
-sub unorder {my $self = shift; return @{$self->{unorder}}}
-
-# In principle, the styles (for example, color and size of the tiles)
-# could be customized for each draggableProof instance. This is why
-# each instance receives its own CSS container class.
-
-sub ScriptAndStyles {
- my $self = shift; my $id = $self->{id};
-
- main::POST_HEADER_TEXT(main::MODES(TeX=>"", HTML=><<" SCRIPT_AND_STYLE"));
-
-
-
- SCRIPT_AND_STYLE
-}
-
-sub AnswerRule {
- my $self = shift;
- my $rule = main::ans_rule(1);
- $self->{tgtAns} = ""; $self->{tgtAns} = $1 if $rule =~ m/id="(.*?)"/;
- $self->{srcAns} = $self->{tgtAns}."-src";
- main::RECORD_FORM_LABEL($self->{srcAns}); # use this for release 2.13 and comment out for develop
- #$main::PG->store_persistent_data; # uncomment this for develop and releases beyond 2.13
- my $ext = main::NAMED_ANS_RULE_EXTENSION($self->{srcAns},1,answer_group_name=>$self->{srcAns}.'-src');
- main::TEXT( main::MODES(TeX=>"", HTML=>'
'.$rule.$ext.'
'));
-}
-
-sub GetAnswer {
- my $self = shift; my $previous;
-
- # Retrieve the previous state of the right column.
- $previous = $main::inputs_ref->{$self->{tgtAns}} || "";
- $previous =~ s/$self->{id}-//g; $self->{previousTarget} = [split(/,/,$previous)];
-
- # Calculate the complement of the right column.
- my %prevTarget = map {$_ => 1} @{$self->{previousTarget}};
- my @diff = grep {not $prevTarget{$_}} (0..$self->{numProvided}-1);
-
- # If the previous state of the left column has been saved, use it. (This ensures that the tiles
- # in the left column are kept in the same order that the user had arranged them). If it has not
- # been saved, use the complement of the right column.
- $previous = $main::inputs_ref->{$self->{srcAns}} || "$self->{id}-".join(",$self->{id}-",@diff);
- $previous =~ s/$self->{id}-//g; $self->{previousSource} = [split(/,/,$previous)];
-}
-
-sub Print {
- my $self = shift;
-
- if ($main::displayMode ne "TeX") { # HTML mode
-
- return join("\n",
- '
',
- $self->Source,
- $self->Target,
- ' ',
- '
',
- );
-
- } else { # TeX mode
-
- return join("\n",
- $self->Source,
- $self->Target,
- );
-
- }
-
-}
-
-sub Source {
- my $self = shift;
- return $self->Bucket("source",$self->{srcAns},$self->{SourceLabel},$self->{previousSource});
-}
-
-sub Target {
- my $self = shift;
- return $self->Bucket("target",$self->{tgtAns},$self->{TargetLabel},$self->{previousTarget});
-}
-
-sub Bucket {
- my $self = shift; my $id = $self->{id};
- my ($name,$ans,$label,$previous) = @_;
-
- if ($main::displayMode ne "TeX") { # HTML mode
-
- my @lines = ();
- push(@lines, '
\n",
- );
- $out;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/courseHeaders.pl b/OpenProblemLibrary/macros/Union/courseHeaders.pl
deleted file mode 100755
index dbd34ed6e4..0000000000
--- a/OpenProblemLibrary/macros/Union/courseHeaders.pl
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/local/bin/perl
-
-sub _courseHeaders_init {
-#
-# This is the hint to display in screen headers. You can change this
-# in the specific header .pg file for a problem set, provided you do so
-# after the call to loadMacros that loads this file.
-#
-
-$HINT =
- "Give 4 or 5 significant digits when entering decimal numbers. ".
- "For most problems, you can enter elementary expressions such as ".
- "${BTT}2^3${ETT} instead of ${BTT}8${ETT}, ${BTT}sin(3pi/2)${ETT} ".
- "instead of ${BTT}-1${ETT}, ${BTT}e^(ln(2))${ETT} instead of ${BTT}2${ETT}, ".
- "${BTT}(2+tan(3))*(4-sin(5))^6-7/8${ETT} instead of ${BTT}27620.3413${ETT}, ".
- "etc. Consult WeBWorK's ".
- htmlLink('http://webwork.math.rochester.edu/webwork_system_html/docs/docs/pglanguage/availablefunctions.html','list of functions').
- " or review the problems in the orientation homework set for more ".
- "information on the functions and values that WeBWorK understands.";
-
-};
-
-######################################################################
-#
-# This file implements a standard format for the screen and paper
-# headers. The same file works for both, so there is no need to
-# make duplicate files. See courseHeader() below for details.
-#
-
-loadMacros(
- "PG.pl",
- "PGbasicmacros.pl",
- "PGunion.pl"
-);
-
-#
-# Get the course name from the course ID
-#
-$course = $courseName;
-$course =~ s/\d\d(FA|WI|SP|SU)-//; # Union-sepcific
-$course =~ s/-.*//; # Union-specific
-$course = protect_underbar($course); # just in case
-
-#
-# Set some variables to use in headers
-#
-$dateTime = $formatedDueDate;
-$sectionNumber = protect_underbar($sectionNumber);
-$setNumber = protect_underbar($setNumber);
-
-#
-# Evaluate the string as in PG, then trim white space from the ends
-#
-sub EV_trim {
- my $string = EV2(@_);
- $string =~ s/(^\s+|\s+$)//g;
- return $string;
-}
-
-#
-# Get a number sign in all modes
-#
-$NUMBER = MODES(TeX => '\#', HTML => '#');
-
-#
-# couseHeader creates the header based on values passed to it.
-# It works for both screen and paper headers, so you only need
-# one header file. The options you can pass it are:
-#
-# topic => '...' a short string to be used in
-# "this is an assignment on ..."
-#
-# preposition => 'on'
-# what word to use before the topic
-#
-# bookinfo => '...' the section of the book to refer to for more
-# information.
-#
-# bookprobs => ['...','...',]
-# a list of strings giving problems from
-# various sections of the book. As many
-# strings can be supplied as you want.
-# They will be placed on separate lines in
-# the screen header, but on one line in the PDF
-# file. If left empty, the word "none" will be
-# supplied automatically. If set to undef,
-# no book problems will be given.
-#
-# moreprobs => ['...','...',]
-# a list of strings giving problems from
-# various sections of the book. (See bookprobs
-# for details of how this works.)
-#
-# text => '...' This is additional text to be inserted
-# after the book assignment. It can explain
-# more about the problems, give hints, etc.
-#
-# showhint => 0 or 1 Indicates whether the message about typing
-# webwork answers should be shown in the screen
-# header. It defaults to 1 (yes).
-# You can change the variable $HINT to be
-# a different hint, if you want. Be sure
-# to do this AFTER the loadMacros call.
-#
-#
-sub courseHeader {
- my %ops = (
- topic => "",
- preposition => "on",
- bookinfo => "",
- bookprobs => [],
- moreprobs => undef,
- text => "",
- showhint => 1,
-
- topic_text => 'This is a collection of WeBWorK problems ',
- bookinfo_text => 'Relevant information can be found in %s of your text.',
- bookprobs_text => 'Book problems to do as part of this assignment:',
- moreprobs_text => 'Additional problems to do with this assignment:',
- @_
- );
-
- if ($displayMode =~ m/^HTML/ || $displayMode eq "Latex2HTML") {
-# TEXT($BBLOCKQUOTE);
- TEXT(EV_trim($ops{topic_text}.$ops{preposition}.' '.$ops{topic}).".\n") if $ops{topic};
- TEXT(sprintf($ops{bookinfo_text},$ops{bookinfo})) if $ops{bookinfo};
- TEXT($BR,$PAR,"\n\n");
- if (ref($ops{bookprobs}) eq "ARRAY") {
- TEXT($ops{bookprobs_text}."\n");
- if (scalar(@{$ops{bookprobs}}) == 0) {TEXT("none.\n\n")} else {
- TEXT(
- $BBLOCKQUOTE,
- EV_trim(join($BR."\n",@{$ops{bookprobs}})),
- $EBLOCKQUOTE,"\n"
- );
- }
- TEXT($PAR,"\n\n");
- }
- if (ref($ops{moreprobs}) eq "ARRAY") {
- TEXT($ops{moreprobs_text}."\n");
- if (scalar(@{$ops{moreprobs}}) == 0) {TEXT("none.\n\n")} else {
- TEXT(
- $BBLOCKQUOTE,
- EV_trim(join($BR."\n",@{$ops{moreprobs}})),
- $EBLOCKQUOTE,"\n"
- );
- }
- }
- TEXT($HR,$PAR,EV_trim($ops{text})) if $ops{text};
- TEXT($HR,$PAR."\n\n",$BSMALL.$HINT.$ESMALL."\n\n",$PAR)
- if ($ops{showhint});
-# TEXT($EBLOCKQUOTE);
- } elsif ($displayMode eq "TeX") {
- TEXT(
- $BEGIN_ONE_COLUMN,
- '{\parindent=0pt \parskip=4pt',"\n",
- '{\large\bf '.$studentName.'\hfill '.$course.' '.$sectionNumber.'}',
- '\break\null\hfill '.
- "WeBWorK assignment $setNumber due $dateTime".'\par'."\n",
- );
- TEXT(EV_trim($ops{topic_text}.$ops{preposition}.' '.$ops{topic}).".\n") if $ops{topic};
- TEXT(sprintf($ops{bookinfo_text},$ops{bookinfo})) if $ops{bookinfo};
- TEXT('\par',"\n\n");
- if (ref($ops{bookprobs}) eq "ARRAY") {
- TEXT($ops{bookprobs_text}.' ');
- if (scalar(@{$ops{bookprobs}}) == 0) {TEXT("none.\\par\n\n")} else {
- TEXT(
- EV_trim(join("; ",@{$ops{bookprobs}})).
- '.\par'."\n\n"
- );
- }
- }
- if (ref($ops{moreprobs}) eq "ARRAY") {
- TEXT($ops{moreprobs_text}.' ');
- if (scalar(@{$ops{moreprobs}}) == 0) {TEXT("none.\\par\n\n")} else {
- TEXT(
- EV_trim(join("; ",@{$ops{moreprobs}})).
- '.\par'."\n\n"
- );
- }
- }
- TEXT(EV_trim($ops{text}).'\par'."\n\n") if $ops{text};
- TEXT('\par}',$END_ONE_COLUMN);
- } else {
- warn "courseHeader: Unknown display mode: $displayMode"
- }
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/imageChoice.pl b/OpenProblemLibrary/macros/Union/imageChoice.pl
deleted file mode 100755
index 178f473e16..0000000000
--- a/OpenProblemLibrary/macros/Union/imageChoice.pl
+++ /dev/null
@@ -1,91 +0,0 @@
-loadMacros(
- 'PGchoicemacros.pl',
- 'unionUtils.pl',
- 'choiceUtils.pl',
-);
-
-sub _imageChoice_init {}; # don't reload this file
-
-######################################################################
-#
-# Create a match list where the answers are images
-#
-# Usage: $ml = new_image_match_list(options);
-#
-# where options are those that can be supplied to image_print_a below.
-# The answers should be an image name or reference to to a plot object
-# (or a reference to a pair of either of these), and they are passed
-# to the Image function for processing. See unionUtils.pl for more
-# information on how these are handled.
-#
-sub new_image_match_list {
- my $ml = new Match(random(1,2000,1), \&alt_print_q, \&img_print_a);
- $ml->{ImageOptions} = [@_];
- $ml;
-}
-
-######################################################################
-#
-# A print routine for image matching. This is designed to display
-# four graphs per row. More can be included by setting the ImageOptions
-# variable in the match list. For example:
-#
-# $ml->{ImageOptions} = [size => [100,100]]
-#
-# You can include the following options:
-#
-# size => [w,h] the width and height of the images
-# width => n the width of the images (obsolete)
-# height => n the height of the images (obsolete)
-# tex_size => n the size for the TeX version of the image
-# separation => n the spacing between the images in a row
-# vseparation => n the spacing between the images and captions
-# link => 0 or 1 1 to make a link to the original image
-# columns => n the number of images in each row (defaults to 4)
-# border => n the width of the image border
-#
-
-sub img_print_a {
- my $self = shift;
- $self->{ImageOptions} = [] unless defined($self->{ImageOptions});
- my %options = (
- width => 150, height => 150, tex_size => 200, columns => 4,
- separation => 15, vseparation => 5, link => 0, @{$self->{ImageOptions}});
- my ($w,$h,$m) = ($options{width},$options{height},$options{columns});
- ($w,$h) = @{$options{size}} if defined($options{size});
- my ($sep,$vsep) = ($options{separation},$options{vseparation});
- my ($tsize,$link) = ($options{tex_size},$options{link});
- my $border = $options{border}; $border = ($link?2:1) unless defined($border);
- my $HTML; my @images = (); my @labels = (); my $i = 0;
- my $out;
-
- $out = BeginTable(tex_spacing => "5pt", tex_border => "5pt");
- while ($image = shift) {
- push(@images,Image(
- $image, size => [$w,$h], tex_size => $tsize,
- link => $link, border => $border
- ));
- push(@labels,MODES(
- TeX => "\\hfil \\textbf{$main::ALPHABET[$i]}",
- Latex2HTML=>$bHTML."
$main::ALPHABET[$i]
".$eHTML,
- HTML => "
$main::ALPHABET[$i]
"
- ));
- if ((++$i % $m) == 0) {
- $out .= TableSpace(2*$vsep,6) if ($i > $m);
- $out .= Row([@images], separation => $sep).
- TableSpace($vsep,0).
- Row([@labels], separation => $sep);
- @images = (); @labels = ();
- }
- }
- if (scalar(@images) > 0) {
- $out .= TableSpace(2*$vsep) if ($i > $m && $displayMode ne "TeX");
- $out .= Row([@images], separation => $sep).
- TableSpace($vsep,0).
- Row([@labels], separation => $sep);
- }
- $out .= EndTable(tex_border => "5pt");
- $out;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/altPlotMacros.pl b/OpenProblemLibrary/macros/Union/obsolete/altPlotMacros.pl
deleted file mode 100755
index ae47655386..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/altPlotMacros.pl
+++ /dev/null
@@ -1,108 +0,0 @@
-sub _altPlotMacros_int {}; # don't reload this file
-
-#
-# An alternative to plot_functions that allows any perl
-# expression as the function (it doesn't get parsed by
-# the PG function parser, so you can do fancier
-# expressions; in particular, things like f(x,y))
-#
-# This is just a hack, as it doesn't really parse the
-# expression, so might not translate everything properly.
-# It will be obsolete when I finish my new expression
-# parser, but I needed it to handle traces of multivariable
-# functions easier. --- DPVC
-#
-
-sub alt_plot_functions {
- my $graph = shift;
- my @function_list = @_;
- my $error = "";
- $error .= "The first argument to plot_functions must be a graph object" unless ref($graph) =~/WWPlot/;
- my $fn;
- my @functions=();
- foreach $fn (@function_list) {
-
- # model: "2.5-x^2 for x in <-1,0> using color:red and weight:2"
- if ($fn =~ /^(.+)for\s*(\w+)\s*in\s*([\(\[\<])\s*([\d\.\-]+)\s*,\s*([\d\.\-]+)\s*([\)\]\>])\s*using\s*(.*)$/ ) {
- my ($rule,$var, $left_br, $left_end, $right_end, $right_br, $options) =
- ($1, $2, $3, $4, $5, $6, $7);
- my %options = split( /\s*and\s*|\s*:\s*|\s*,\s*|\s*=\s*|\s+/,$options);
- my ($color, $weight);
- if ( defined($options{'color'}) ){
- $color = $options{'color'}; #set pen color
- } else {
- $color = 'default_color';
- }
- if ( defined($options{'weight'}) ) {
- $weight = $options{'weight'}; # set pen weight (width in pixels)
- } else {
- $weight = 2;
- }
-
- my $subRef = alt_string_to_sub($rule,$var);
- my $funRef = new Fun($subRef,$graph);
- $funRef->color($color);
- $funRef->weight($weight);
- $funRef->domain($left_end , $right_end);
- push(@functions,$funRef);
- # place open (1,3) or closed (1,3) circle at the endpoints or do nothing <1,3>
- if ($left_br eq '[' ) {
- $graph->stamps(closed_circle($left_end,&$subRef($left_end),$color) );
- } elsif ($left_br eq '(' ) {
- $graph->stamps(open_circle($left_end, &$subRef($left_end), $color) );
- }
- if ($right_br eq ']' ) {
- $graph->stamps(closed_circle($right_end,&$subRef($right_end),$color) );
- } elsif ($right_br eq ')' ) {
- $graph->stamps(open_circle($right_end, &$subRef($right_end), $color) );
- }
-
- } else {
- $error .= "Error in parsing: $fn";
- }
-
- }
- die ("Error in plot_functions:\n\t $error") if $error;
- @functions; # return function references unless there is an error.
-}
-
-#
-# A cheap way to convert a string to a perl function
-# that returns the value of the expression given in the
-# string. Since no special parsing is done, you need
-# to make sure your function is essentially in perl
-# form.
-#
-sub alt_string_to_sub {
- my $expr = my_math_constants(shift);
- my $x = shift;
- #
- # Give the variable a $ and rename it with an leading underscore
- #
- $expr =~ s/(\b|\d)$x\b/$1(\$_x)/g;
- #
- # Fix up the expression
- #
- $expr =~ s!\\frac\{([^\}]*)\}\s*\{([^\}]*)\}!($1)/($2)!g; # fractions
- $expr =~ s/\{([^\}]*)\}/($1)/g; # TeX parameters
- $expr =~ s/\\//g; # TeX slashes
- $expr =~ s/\^/**/g; # change ^ to **
- #
- # Do implied multiplication
- #
- $expr =~ s/\)\s*\(/\)*\(/g;
- $expr =~ s/\)\s*([a-zA-Z0-9.])/\)*$1/g;
- $expr =~ s/([\d.])(\s\d)/$1*$2/g;
- $expr =~ s/([\d.])\s*([a-zA-Z\(])/$1*$2/g;
- #
- # Fix +-, -+, ++ and --
- #
- $expr =~ s/\+\s*([\+-])/$1/g;
- $expr =~ s/-\s*\+/-/g; $expr =~ s/-\s*-/+/g;
- #
- # Make the function
- #
- PG_restricted_eval "sub {my \$_x = shift; return $expr}";
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/compositionAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/compositionAnswer.pl
deleted file mode 100755
index 1fad973813..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/compositionAnswer.pl
+++ /dev/null
@@ -1,154 +0,0 @@
-loadMacros('answerUtils.pl');
-
-sub _compositionAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# An answer checker that determines if two functions compose
-# to form a given function. (For use in problems where you ask
-# a student to break a given function into a composition of two
-# simpler functions, neither of which is allowed to be the identity
-# function.)
-#
-
-######################################################################
-#
-# An answer checked to see if f composed with g matches a given function.
-#
-# Usage: COMPOSITION_ANS(f,g,options)
-#
-# where f and g are one possible decomposition of the target function
-# (these are used to display the "correct" answer, and the composition
-# is computed from them) and options are any of the options allowed
-# by composition_ans_list below.
-#
-# This function actually supplies TWO answer checkers, for the two
-# previous answer blanks. So be sure to call it immediately after
-# the answer blanks have been supplied. (It may be best to use the
-# NAMED_COMPOSITION_ANS checker below, which specifies the answer
-# blanks explicitly.)
-#
-# Example:
-#
-# BEGIN_TEXT
-# \(f\circ g = (1+x)^2\) when
-# \(f(x)\) = \{ans_rule(20)\} and \(g(x)\) = \{ans_rule(20)\}
-# END_TEXT
-# COMPOSITION_ANS("x^2","1+x");
-#
-#
-sub COMPOSITION_ANS {
- my $f = shift; my $g = shift;
- my $fID = ANS_NUM_TO_NAME($main::ans_rule_count-1);
- my $gID = ANS_NUM_TO_NAME($main::ans_rule_count);
- my %ans = composition_ans_list($fID=>$f,$gID=>$g,@_);
- ANS(values(%ans));
-}
-
-
-######################################################################
-#
-# An answer checked to see if f composed with g matches a given function.
-#
-# Usage: NAMED_COMPOSITION_ANS(fID=>f,gID->g,options)
-#
-# where fID and gID are the names of the answer rules for the functions
-# f and g, and f and g are the answers for the functions. Options are
-# any of the options allowed by composition_ans_list below.
-#
-# This routine allows you to put the f and g answer blanks at any
-# location in the problem, and in any order.
-#
-# Example:
-#
-# BEGIN_TEXT
-# \(g\circ f = (1+x)^2\) when
-# \(f(x)\) = \{NAMED_ANS('f',20)\} and \(g(x)\) = \{NAMED_ANS('g',20)\}
-# END_TEXT
-# NAMED_COMPOSITION_ANS(f => "x^2", g => "1+x");
-
-sub NAMED_COMPOSITION_ANS {NAMED_ANS(composition_ans_list(@_))}
-
-
-######################################################################
-#
-# This is an internal routine that returns the named answer checkers
-# used by COMPOSITION_ANS and NAMED_COMPOSITION_ANS above.
-#
-# Usage: composition_ans_list(fID=>f,gID=>g,options)
-#
-# where fID and gID are the names of the answer rules for the functions
-# and f and g are the answers for these functions. Options are from
-# among:
-#
-# var => 'x' the name of the variable to use (both
-# functions use the same variable -- this
-# should probably be improved).
-#
-# or any parameters that can be passed to fun_cmp.
-#
-sub composition_ans_list {
- my ($fID,$f,$gID,$g,%params) = @_;
- my ($i,$ident,$comp,$eval,$field,$fog,$student_ans);
- my @IDs = ($fID,$gID);
- my @cmp = (composition_cmp($f),composition_cmp($g));
- my @ans = ($fID => $cmp[0], $gID => $cmp[1]);
- my $error = 0;
- my $var = "x"; $var = $params{'var'} if (defined($params{'var'}));
-
- #
- # Check that the answers exist (otherwise it's our first time through)
- #
- foreach $i (@IDs) {return(@ans) if (!defined($inputs_ref->{$i}))}
-
- $ident = fun_cmp($var,%params);
- foreach $i (0,1) {
- $eval = evaluateAnswer($ident,$inputs_ref->{$IDs[$i]});
- if ($eval->{ans_message} ne "") {$error = 1}
- elsif ($eval->{score} == 1) {
- $eval->{ans_message} = "The identity function is not allowed";
- $error = 1; $eval->{score} = 0;
- }
- foreach $field ('ans_message','error_message','preview_latex_string',
- 'preview_text_string','student_ans') {
- $cmp[$i]->rh_ans->{$field} = $eval->{$field}; $eval->{$field} = "";
- }
- }
-
- if (!$error) {
- $fog = $f; $fog =~ s/$var/($g)/g;
- $student_ans = $inputs_ref->{$fID};
- $student_ans =~ s/$var/($inputs_ref->{$gID})/g;
- if (isCorrectAnswer(fun_cmp($fog,%params),$student_ans)) {
- $cmp[0]->rh_ans->{score} = $cmp[1]->rh_ans->{score} = 1;
- }
- }
- return (@ans);
-}
-
-
-######################################################################
-#
-# Evaluator that always returns correct or always returns incorrect,
-# depending on the parameter passed to it. Used by COMPOSITION_ANS
-# to produce "dummy" answer checkers for the two parts of the
-# composition.
-#
-sub composition_cmp {
- my $score = shift;
- my %params = @_;
- $params{debug} = 0 unless defined($params{debug});
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(type => "composition", correct_ans => $score);
- $answerEvaluator->install_evaluator(\&composition_cmp_check,%params);
- return $answerEvaluator;
-}
-
-sub composition_cmp_check {
- my $ans = shift;
- my %params = @_;
- return($ans);
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/diffquotientAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/diffquotientAnswer.pl
deleted file mode 100755
index 21d246d8dd..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/diffquotientAnswer.pl
+++ /dev/null
@@ -1,119 +0,0 @@
-loadMacros('answerUtils.pl');
-
-sub _diffquotientAnswer_init {}; # don't reload this file
-
-#########################################################################
-##
-## An answer checker for handling difference quotients. It requires
-## that the student simplify the equation (at least far enough to
-## cancel the dx in the bottom).
-##
-
-
-#########################################################################
-#
-# Usage: diff_quotient_cmp(ans,options)
-#
-# where ans is the correct difference quotient, and options are
-# from among:
-#
-# var => 'x' specifies the variable for the difference quotient
-#
-# limits => [a,b] gives the lower and upper limits of the domain
-# to use for checking the student's response.
-#
-# or any of the parameters that can be passed to fun_cmp().
-#
-# This checker checks that the student answer is the correct difference
-# and that it doesn't contain dx in the denominator (i.e., they will
-# have had to simplify it at least far enough to cancel the dx).
-#
-# The checker accepts 'dx' or 'H' as the difference in the x variable.
-# (This is a bit of a hack, and there is a chance that the student could
-# receive odd error messages because it it.)
-#
-# Example:
-#
-# BEGIN_TEXT
-# Find the simplified difference quotient for \(f(x)=x^2\):
-# \{ans_rule(30)\}.
-# END_TEXT
-#
-# ANS(diff_quotient_cmp("2x+dx"));
-#
-#
-
-sub diff_quotient_cmp {
- my $answer = shift || '';
- my %params = (
- debug => 0,
- var => 'x',
- limits => [$functLLimitDefault,$functULimitDefault],
- @_
- );
- #
- # Get the variable and limits
- #
- my $x = $params{var}; delete $params{var};
- my ($ll,$ul) = @{$params{limits}};
- $params{vars} = [$x,'H'];
- $params{limits} = [[$ll,$ul],[$functLLimitDefault,$functULimitDefault]];
- #
- # Convert dx to H
- #
- my $answer_h = $answer; $answer_h =~ s/d$x/H/g;
- #
- # The answer checker that tests for division by zero
- #
- my $zero = fun_cmp($answer_h,%params);
- $zero->{rh_ans}{evaluation_points} = [[($ul+$ll)/2,0]];
-
- my $ans = new AnswerEvaluator;
- $ans->{debug} = $params{debug};
- $ans->ans_hash(
- type => "difference quotient",
- correct_ans => $answer,
- cmp => fun_cmp($answer_h,%params),
- zero_cmp => $zero,
- var => $x,
- );
- $ans->install_evaluator(\&diff_quotient_cmp_check,%params);
- return $ans;
-}
-
-#
-# The guts of the checker
-#
-sub diff_quotient_cmp_check {
- my $ans = shift;
- my $x = $ans->{var};
- my $answer = $ans->{student_ans}; $answer =~ s/d$x/H/g;
-
- #
- # Check the answer, and copy the score and messages
- #
- my $hash = evaluateAnswer($ans->{cmp},$answer);
- foreach my $id ('score','student_ans','ans_message','error_message',
- 'error_flags','preview_text_string','preview_latex_string') {
- $ans->{$id} = $hash->{$id};
- $ans->{$id} =~ s/H/d$x/g if defined($ans->{$id});
- }
-
- #
- # If the function matches, check that it is simplified
- # (no division by zero when dx = 0). Otherwise, give an
- # appropriate error message.
- #
- if ($hash->{score} == 1) {
- $hash = evaluateAnswer($ans->{zero_cmp},$answer);
- if ($hash->{ans_message} =~ m/division by zero/) {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} =
- "It looks like you didn't finish simplifying your answer\n";
- }
- }
-
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/infiniteAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/infiniteAnswer.pl
deleted file mode 100755
index 2625b8557e..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/infiniteAnswer.pl
+++ /dev/null
@@ -1,131 +0,0 @@
-loadMacros('unionUtils.pl','answerUtils.pl');
-
-sub _infiniteAnswer_init {
-
- #$INFINITY_WORD = "INF";
- $INFINITY_WORD = "infinity" unless defined($INFINITY_WORD);
-
- #
- # A message that can be inclued (within BEGIN_TEXT and END_TEXT)
- # to tell the student how to enter infinity and minus infinity
- #
- $INFINITY_MESSAGE =
- $BITALIC.$BSMALL.
- "Use ${LQ}$INFINITY_WORD${RQ} for $LQ\\(\\infty\\)$RQ ".
- "and ${LQ}-$INFINITY_WORD${RQ} for $LQ\\(-\\infty\\)$RQ." .
- $ESMALL.$EITALIC;
-
- $DNE_MESSAGE =
- $BITALIC.$BSMALL.
- "Use ${LQ}DNE${RQ} for ${LQ}Does not exist${RQ}.".
- $ESMALL.$EITALIC;
-
- $INFINITY_MESSAGE = "" if $displayMode eq 'TeX';
- $DNE_MESSAGE = "" if $displayMode eq 'TeX';
-
-};
-
-##########################################################################
-#
-# Check for a number or "-INF", "INF", "DNE" or several synonyms.
-#
-# WeBWorK's std_num_str_cmp doesn't allow for strings like "-INF", so it
-# uses the unsatisfying "MINF" instead. This answer checker provides
-# for both MINF and -INF to mean negative infinity, and INF or NaN for
-# positive infinity, and similarly INFINITY or -INFINITY. It also
-# allows for DNE as an answer. The strings can be entered in upper-
-# or lower-case and still be recognized.
-#
-# Usage: infinite_num_cmp(number, options)
-#
-# where number is a number or one of the words for infinity, and options
-# are chosen from
-#
-# allowDNE => 0 or 1 whether to accept DNE as a valid entry
-# (default is 0)
-#
-# DNEisINF => 0 or 1 whether to treat DNE as INF or as a
-# separate word (default is 0)
-#
-#
-sub infinite_num_cmp {
- my $infPattern = '^(INF|INFINITY|\+INF|\+INFINITY|NaN)$';
- my $neginfPattern = '^(-INF|-INFINITY|MINF)$';
- my $num = shift;
- my %params = (allowDNE => 0, DNEisINF => 0,
- infPattern => $infPattern,
- neginfPattern => $neginfPattern, @_);
- my %numops = @_;
- delete($numops{allowDNE}) if (defined($numops{allowDNE}));
- delete($numops{DNEisINF}) if (defined($numops{DNEisINF}));
- $params{debug} = 0 unless defined($params{debug});
- $num = "-$INFINITY_WORD" if ($num =~ m/$neginfPattern/i);
- $num = $INFINITY_WORD if ($num =~ m/$infPattern/i);
- if ($params{allowDNE}) {
- $params{strings} = ["INF","-INF","+INF","+INFINITY","INFINITY","-INFINITY","DNE"];
- $params{num_cmp} = num_cmp($num,
- strings => ["INF","-INF","+INF","MINF","NaN","INFINITY","-INFINITY","+INFINITY","DNE"],
- %numops);
- } else {
- $params{strings} = ["INF","-INF","+INF","INFINITY","-INFINITY","+INFINITY"];
- $params{num_cmp} = num_cmp($num,
- strings => ["INF","-INF","+INF","MINF","NaN","INFINITY","-INFINITY","+INFINITY"],
- %numops);
- }
- $params{num_cmp}->install_post_filter('reset'); # to prevent NUM_CMP from putting
- # error messages in student_ans
- $params{isString} = 0;
- foreach my $string (@{$params{strings}}) {
- if (uc($string) eq uc($num)) {$params{isString} = 1; last}
- }
-
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(correct_ans => $num, type => "infinite number");
- $answerEvaluator->install_evaluator(\&infinite_num_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the checker
-#
-sub infinite_num_check {
- my $ans = shift;
- my %params = @_;
- $ans->{student_ans} = trimString($ans->{student_ans});
- my $answer = $ans->{student_ans};
- my $realAnswer = $ans->{correct_ans};
- my $isString = 0;
- $realAnswer = "DNE"
- if (uc($answer) eq "DNE" && $params{DNEisINF} &&
- $realAnswer =~ m/$params{infPattern}/i);
- $answer = "-$INFINITY_WORD" if ($answer =~ m/$params{neginfPattern}/i);
- $answer = $INFINITY_WORD if ($answer =~ m/$params{infPattern}/i);
- if ($params{isString} && uc($answer) eq uc($realAnswer)) {
- $ans->score(1); $isString = 1
- } else {
- foreach my $string (@{$params{strings}}) {
- if (uc($answer) eq uc($string)) {$ans->score(0); $isString = 1}
- }
- }
- if ($isString) {
- $ans->{student_ans} = $answer;
- $ans->{preview_text_string} = $answer;
- $ans->{preview_latex_string} = $answer;
- return $ans;
- }
- #
- # transfer the NUM_CMP error message to the answer message
- # so we can report it correctly in other checkers
- #
- my $hash = evaluateAnswer($params{num_cmp},$ans->{student_ans});
- $hash->{ans_message} = trimString($hash->{error_message})
- if ($hash->{ans_message} eq '');
- $hash->{ans_message} =
- "Your answer does not seem to be a number or infinity"
- if ($hash->{ans_message} =~ m/recognized answer/);
- $hash->clear_error('EVAL'); # in case one was left over from std_num_cmp
- return $hash;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/integerAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/integerAnswer.pl
deleted file mode 100755
index 8148f01cc5..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/integerAnswer.pl
+++ /dev/null
@@ -1,52 +0,0 @@
-sub _integerAnswer_init {
- $INTEGER_TOLERANCE = 1E-14;
-};
-
-######################################################################
-#
-# Integer answer checker.
-#
-# integer_cmp(ans,options)
-#
-# where options are those allowed by num_cmp().
-#
-# This provided an answer checker that compares against an integer.
-# it is really just a shell around num_cmp() that sets the tolerance to
-# an absolute tolerance of .5 (so that only the correct integer
-# would be correct). It also adds a post-filter to check that
-# the student answer actually IS an integer.
-#
-# Note, the checker is only good to about 12 digits.
-#
-
-sub integer_cmp {
- my $cmp = num_cmp(@_,tol => .5);
- $cmp->install_post_filter(\&check_integer_answer);
- my $x = $cmp->{rh_ans}{correct_ans};
- warn "Professor's answer is too large for integer comparison"
- if (abs($x) > (1/$INTEGER_TOLERANCE)/100);
- if (abs($x - int($x+$x*$INTEGER_TOLERANCE)) > $x*$INTEGER_TOLERANCE) {
- warn "Professor's answer is not an integer";
- } else {
- $cmp->{rh_ans}{original_correct_ans} =
- $cmp->{rh_ans}{correct_ans} = sprintf("%.0f",$x);
- }
- return $cmp;
-}
-
-sub check_integer_answer {
- my $ans = shift;
- if ($ans->{ans_message} eq "" && $ans->{error_message} eq "") {
- my $x = $ans->{student_ans};
- if (abs($x - int($x+$x*$INTEGER_TOLERANCE)) > $x*$INTEGER_TOLERANCE) {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} =
- "Your answer is not an integer";
- } else {
- $ans->{student_ans} = sprintf("%.0f",$x);
- }
- }
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/intervalAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/intervalAnswer.pl
deleted file mode 100755
index 352b02a1a9..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/intervalAnswer.pl
+++ /dev/null
@@ -1,258 +0,0 @@
-loadMacros('infiniteAnswer.pl');
-
-sub _intervalAnswer_init {}; # don't reload this file
-
-######################################################################
-##
-## Interval answer checkers.
-##
-## num_interval_cmp() intervals with numeric or infinite endpoints
-## fun_interval_cmp() intervals with functions as endpoints
-##
-## interval_cmp() provide your own endpoint checkers
-##
-
-######################################################################
-#
-# num_interval_cmp(answer,options)
-#
-# where options are from among:
-#
-# cmp_params => [list] parameters to be passed to infinite_num_cmp
-# for each coordinate
-#
-# or any of the options to interval_cmp (see below).
-#
-# This provided an answer checker that compares against an interval
-# with numeric or infinite endpoints.
-#
-# e.g. num_point_cmp("(1,10)");
-# num_point_cmp("(-INF,10)");
-#
-
-sub num_interval_cmp {
- my $ans = shift;
- std_interval_cmp($ans, cmp => \&infinite_num_cmp, @_);
-}
-
-
-######################################################################
-#
-# num_interval_cmp(answer,options)
-#
-# where options are from among:
-#
-# cmp_params => [list] parameters to be passed to infinite_num_cmp
-# for each coordinate
-#
-# vars => [list] the variables for the formulas
-#
-# or any of the options to interval_cmp (see below).
-#
-# This provided an answer checker that compares against an interval
-# with numeric or infinite endpoints.
-#
-# e.g. fun_point_cmp("(x,2x)");
-# fun_point_cmp("(-t,t+2)", vars => 't');
-#
-
-sub fun_interval_cmp {
- my $ans = shift;
- my %params = (cmp_params => [], @_);
- if (defined($params{vars})) {
- $params{cmp_params} = [vars => $params{vars}, @{$params{cmp_params}}];
- delete $params{vars};
- }
- std_interval_cmp($ans, cmp => \&fun_cmp, %params);
-}
-
-
-######################################################################
-#
-# std_interval_cmp(ans,options)
-#
-# where ans is the correct answer as a string (e.g. "(1,INF)"), and
-# options are from among the following:
-#
-# cmp => \&cmp a reference to the answer checker to use for each
-# endpoint (e.g., \&std_num_cmp, or ~~&std_num_cmp
-# in a .pg file)
-#
-# cmp_params => [...] is a reference to a list of parameters for the
-# answer checker (e.g., [vars => 'x'])
-#
-# or any of the options allowed by interval_cmp (see below).
-#
-# This returns an answer checker that compares the interval using the
-# given answer checker on each endpoint.
-#
-# e.g. std_interval_cmp("(1,INF)",cmp => ~~&infinite_num_cmp);
-#
-
-sub std_interval_cmp {
- my $ans = shift;
- my %params = (
- cmp => \&infinite_num_cmp,
- cmp_params => [],
- debug => 0,
- @_
- );
- my ($cmp,$cmp_params) = ($params{cmp},$params{cmp_params});
- delete $params{cmp}; delete $params{cmp_params};
- die "The correct answer doesn't look like an interval"
- if ($ans !~ m/^(\[|\()([^,]*),([^,]*)(\]|\))$/);
- my ($left,$a,$b,$right) = ($1,$2,$3,$4);
- interval_cmp(&{$cmp}($a,@{$cmp_params}),&{$cmp}($b,@{$cmp_params}),
- ends => "$left$right", %params);
-}
-
-
-##########################################################################
-#
-# Check if an answer is an interval
-#
-# Format:
-#
-# interval_cmp(left_evaluator,right_evaluator, options)
-#
-# where "left_evaluator" is an answer checker for the left endpoint
-# and "right_evaluator" is an answer checker for the right endpoint,
-#
-# Options can be taken from:
-#
-# ends => string indicates the type of interval, where
-# "string" is one of '()', '(]', '[)', or '[]'.
-#
-# showHints => 0 or 1 indicates whether to show hints about
-# the correctness of the endpoints
-# (default is 1).
-#
-# showOrderHints => 0 or 1
-# indicates whether to show hints about
-# the order of the endpoints
-# (default is $showHints).
-#
-# Example:
-#
-# interval_cmp(std_num_cmp(0),std_num_cmp(1), ends=>'[)');
-#
-sub interval_cmp {
- my $lendpnt = shift;
- my $rendpnt = shift;
- my %params = @_;
- set_default_options(\%params,
- ends => '()',
- showHints => 1,
- showOrderHints => undef,
- debug => 0
- );
- $params{lendpnt} = $lendpnt;
- $params{rendpnt} = $rendpnt;
-
- my $ends = $params{ends};
- my ($ltype,$rtype) = (substr($ends,0,1),substr($ends,-1));
- my ($lhash,$rhash) = (hashFor($lendpnt),hashFor($rendpnt));
- #
- # Needed to get preview to work properly
- #
- my $type = "interval";
- $type .= " (number)"
- if ($lhash->{type} =~ m/number/ || $rhash->{type} =~ m/number/);
-
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => $ltype . $lhash->{correct_ans} . "," .
- $rhash->{correct_ans} . $rtype,
- type => $type
- );
- $answerEvaluator->install_evaluator(\&interval_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the checker
-#
-sub interval_check {
- my $ans = shift;
- my %params = @_;
- my ($lendpnt,$rendpnt) = ($params{lendpnt},$params{rendpnt});
- my $ends = $params{ends};
-
- my $showHints = defined($params{showHints})?
- $params{showHints} : $showPartialCorrectAnswers;
- my $showOrderHints = defined($params{showOrderHints})?
- $params{showOrderHints} : $showPartialCorrectAnswers;
- $showHints = $showOrderHints = 0 if (isPreviewMode());
-
- $ans->{student_ans} = trimString($ans->{student_ans});
- my $answer = $ans->{student_ans};
- my ($sl,$sa,$sb,$sr) = ($answer =~ m/^(\[|\()([^,]*),([^,]*)(\]|\))$/);
- my @errors = (); my $score = 1;
-
- if (!defined($sl)) {
- push(@errors,"Your answer doesn't look like an interval.");
- } else {
- my ($lhash,$rhash) =
- (evaluateAnswer($lendpnt,$sa),evaluateAnswer($rendpnt,$sb));
- #
- # (Second check is a hack since std_num_cmp with strings
- # doesn't always set the error message when an error
- # occurs. Grrr!)
- #
- if ($lhash->{ans_message} ne "" ||
- $lhash->{student_ans} =~ m/ Your answer/) {
- push(@errors,"Error evaluating left endpoint: ");
- push(@errors,IndentError($lhash->{student_ans}));
- push(@errors,IndentError($lhash->{ans_message}));
- } else {
- $sa = $lhash->{student_ans};
- if ($lhash->{score} != 1) {
- push(@errors,"The left endpoint is incorrect") if ($showHints);
- $score = 0;
- }
- }
- if ($rhash->{ans_message} ne "" ||
- $rhash->{student_ans} =~ m/ Your answer/) {
- push(@errors,"Error evaluating right endpoint:");
- push(@errors,IndentError($rhash->{student_ans}));
- push(@errors,IndentError($rhash->{ans_message}));
- } else {
- $sb = $rhash->{student_ans};
- if ($rhash->{score} != 1) {
- push(@errors,"The right endpoint is incorrect") if ($showHints);
- $score = 0;
- }
- }
- $ans->setKeys(student_ans => $sl.$sa.",".$sb.$sr);
- my ($la,$ra) = ($lhash->{student_ans},$rhash->{student_ans});
- push(@errors,"Note: The left endpoint is greater than ".
- "the right endpoint (empty interval)")
- if ($showOrderHints && isNumber($la) && isNumber($ra) && $la > $ra);
- if ($sl.$sr ne $ends) {
- push(@errors,"The type of interval is incorrect") if ($showHints);
- $score = 0;
- }
- $ans->setKeys(
- preview_text_string =>
- $sl . StringOrBlank($lhash->{preview_text_string},$sa) . "," .
- StringOrBlank($rhash->{preview_text_string},$sb) . $sr,
- preview_latex_string =>
- $sl . StringOrBlank($lhash->{preview_latex_string},$sa) . "," .
- StringOrBlank($rhash->{preview_latex_string},$sb) . $sr
- );
- clearEvaluator($lendpnt);
- clearEvaluator($rendpnt);
- }
-
- if (scalar(@errors) == 0) {
- $ans->score($score);
- $ans->{ans_message} = $ans->{error_message} = '';
- } else {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} = join("\n",@errors);
- }
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/lineAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/lineAnswer.pl
deleted file mode 100755
index a17348e4d0..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/lineAnswer.pl
+++ /dev/null
@@ -1,73 +0,0 @@
-loadMacros('vectorAnswer.pl');
-
-sub _lineAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# Compare a parametric formula to a given line
-# (allows any parallel vector, and any point on the line).
-#
-# Usage: parametric_line_cmp(ans,options)
-#
-# where ans is the answer in vector parametric form (e.g., "<1+3t,2-t>")
-# or as a Vector object, and options are those that are allowed by
-# point_cmp. The variable is assumed to be 't', but that can be changed
-# using the cmp_params option.
-#
-
-sub parametric_line_cmp {
- my $answer = shift;
- my $ans = fun_point_cmp($answer,
- post_process => \&checkParametricLine,
- showHints => 0, showLengthHints => 1,
- cmp_params => [vars => 't'],
- @_
- );
- foreach my $cmp (@{$ans->{rh_ans}->{components}}) {
- #
- # We evaluate the functions at t=0 and t=1 to get
- # p = L(0) and v = L(1)-L(0).
- #
- $cmp->{rh_ans}->{evaluation_points} = [[0],[1]];
- }
- return $ans;
-}
-
-#
-# The guts of the checker (called as a post-processor by
-# the point checker).
-#
-sub checkParametricLine {
- my $ans = shift;
- my (@p,@cp,@v,@cv);
- #
- # Get the P and V for each line
- # (we arranged above to evaluate at t=0 and t=1).
- #
- foreach my $cmp (@{$ans->{components}}) {
- push(@cp,$cmp->{rh_ans}->{ra_instructor_values}->[0]);
- push(@cv,$cmp->{rh_ans}->{ra_instructor_values}->[1]);
- push(@p,$cmp->{rh_ans}->{ra_student_values}->[0]);
- push(@v,$cmp->{rh_ans}->{ra_student_values}->[1]);
- }
- #
- # Get the vector (v = L(1)-L(0)).
- #
- $v = vDiff(Point(@v),Point(@p)); $cv = vDiff(Point(@cv),Point(@cp));
- #
- # The vectors must be parallel to be equal.
- #
- return 0 if (!areParallel($v,$cv));
- #
- # If the points are equal, the lines are.
- #
- my $w = vDiff(Point(@cp),Point(@p));
- return 1 if (isCorrectAnswer(std_num_cmp(0),Norm($w)));
- #
- # Otherwise, if the vector between the two points is
- # parallel to the direction vectors, the lines are equal.
- #
- return (areParallel($v,$w));
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/listAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/listAnswer.pl
deleted file mode 100755
index cbaf9079b1..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/listAnswer.pl
+++ /dev/null
@@ -1,580 +0,0 @@
-sub _listAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# This file implements a general list answer checker, which allows
-# you to specify how the answer is to be split up, whether
-# the entries must appear in the same order as the correct answer,
-# whether informational messages are to be produced for incorrect
-# entries, and what answer checker to call on each entry.
-#
-# The list_cmp() and std_list_cmp() functions are very general, and
-# could be used to implement a variety of special cases of lists.
-# A number of these are given below, including:
-#
-# num_list_cmp() a list of numeric values
-# infinite_num_list_cmp() a list of numeric values or infinities
-# fun_list_cmp() a list of formulas
-# num_interval_list_cmp() a list of intervals with numeric endpoints
-# fun_interval_list_cmp() a list of intervals with endpoint equations
-# num_union_list_cmp() a list of unions of numeric intervals
-# fun_union_list_cmp() a list of unions of variable intervals
-# num_point_list_cmp() a list of numeric points
-# fun_point_list_cmp() a list of formulaic points
-# num_vector_list_cmp() a list of numeric vectors
-# fun_vector_list_cmp() a list of formulaic vectors
-#
-# Some of these require that you load the .pl file for the
-# associated answer checker as well. For example, to use
-# num_point_list_cmp(), you must include
-#
-# loadMacros("pointAnswer.pl");
-#
-# in your .pg file.
-#
-# Partial credit is given for getting some entries correct, unless
-# $showParialCorrectAnswers is set to 0. A system level change to
-# displayMacros.pl is required to make the system indicate this in
-# a meaningful way. You can prevent partial credit by using the
-# partialCredit => 0 option to any of the *_cmp() routines.
-#
-
-######################################################################
-
-
-loadMacros(
- "unionUtils.pl",
- "answerUtils.pl",
-);
-
-######################################################################
-#
-# Usage: num_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "10, -3, 5")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_list_cmp {std_list_cmp(@_)}
-
-
-######################################################################
-#
-# Usage: infinite_num_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "10, -INF, 5")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub infinite_num_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&infinite_num_cmp,
- type => "infinite number", @_);
-}
-
-
-######################################################################
-#
-# Usage: fun_list_cmp(ans,options)
-#
-# where ans is the string indicating the correct list and options are
-# any of those that can be passed to std_list_cmp.
-#
-# Options can also include:
-#
-# vars => [list] the variables for the function checker
-#
-# or any of the options allowed by list_cmp (see below).
-#
-
-sub fun_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_cmp,
- entry_type => 'equation',
- fun_var_params(@_));
-}
-
-#
-# Put the function's 'vars' option into the 'cmp_params' option.
-#
-sub fun_var_params {
- my %params = (cmp_defaults => [], @_);
- if (defined($params{vars})) {
- $params{cmp_defaults} = [vars => $params{vars}, @{$params{cmp_defaults}}];
- delete $params{vars}
- }
- return %params;
-}
-
-
-######################################################################
-#
-# Usage: num_interval_list_cmp(ans,options)
-# fun_interval_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "[1,3), (-inf,-5)")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_interval_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_interval_cmp,
- type => "number interval",
- entry_type => 'interval',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_interval_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_interval_cmp,
- type => "function interval",
- entry_type => 'interval',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-
-######################################################################
-#
-# Usage: num_union_list_cmp(ans,options)
-# fun_union_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g.,
-# "[1,3) U (-inf,-5), [10,11]") and options are any of those that can
-# be passed to std_list_cmp.
-#
-
-sub num_union_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_union_cmp,
- type => "number union",
- entry_type => 'interval or union',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0, showLengthHints => 0],
- @_);
-}
-
-sub fun_union_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_union_cmp,
- type => "fun union",
- entry_type => 'interval or union',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => "(0,1]",
- fun_var_params(
- cmp_defaults => [showHints => 0, showLengthHints => 0],
- @_
- ));
-}
-
-
-######################################################################
-#
-# Usage: num_point_list_cmp(ans,options)
-# fun_point_list_cmp(ans,options)
-# num_vector_list_cmp(ans,options)
-# fun_vector_list_cmp(ans,options)
-#
-# where ans is the string indicating the list (e.g., "(1,2,3), (3,-2,4)")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_point_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_point_cmp,
- type => "number point",
- entry_type => 'point',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => undef,
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_point_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_point_cmp,
- type => "function point",
- entry_type => 'point',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [separator => ','],
- cmp_ans => undef,
- fun_var_params(cmp_defaults => [showHints => 0],@_));
-}
-
-sub num_vector_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_vector_cmp,
- type => "number vector",
- entry_type => 'vector',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [
- separator => ',',
- open => '[(<',
- close => '])>',
- ],
- cmp_ans => undef,
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_vector_list_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_vector_cmp,
- type => "function vector",
- entry_type => 'vector',
- separator => ' , ',
- split => \&paren_split,
- split_defaults => [
- separator => ',',
- open => '[(<',
- close => '])>',
- ],
- cmp_ans => undef,
- fun_var_params(cmp_defaults => [showHints => 0],@_));
-}
-
-
-######################################################################
-#
-# std_list_cmp(ans,options)
-#
-# where ans is the correct answer as a string (e.g. "10, -5"), and
-# options are from among the following:
-#
-# cmp => \&cmp a reference to the answer checker to use for each
-# list element (eg, \&std_num_cmp or \&fun_cmp)
-#
-# cmp_params => [...] a reference to a list of parameters for the
-# answer checker (e.g., cmp_params => [vars => 'x'])
-#
-# or any of the options allowed by list_cmp (see below).
-#
-# This returns an answer checker that compares the list using the
-# given answer checker on each element in the list.
-#
-# e.g. std_list_cmp("10, -5",cmp => ~~&std_num_cmp);
-#
-
-sub std_list_cmp {
- my $ans = shift;
- my %params = (
- cmp => \&std_num_cmp,
- cmp_ans => "0",
- cmp_params => [],
- cmp_defaults => [],
- split => \&std_split,
- split_params => [],
- split_defaults => [separator => ','],
- debug => 0,
- @_
- );
- my $cmp = $params{cmp};
- my @cmp_params = (@{$params{cmp_defaults}},@{$params{cmp_params}});
- my $split = $params{split};
- my @split_params = (@{$params{split_defaults}},@{$params{split_params}});
- my $ans_ref = &{$split}($ans,@split_params);
- warn "Error in professor's answer: $ans_ref" if (ref($ans_ref) ne "ARRAY");
- my @list = ();
- foreach my $element (@{$ans_ref}) {
- $element = trimString($element);
- push(@list,&{$cmp}($element,@cmp_params));
- }
- $params{cmp_ans} = hashFor($list[0])->{correct_ans}
- if (!defined($params{cmp_ans}) && scalar(@list));
- list_cmp([@list],%params);
-}
-
-
-######################################################################
-#
-# Usage: list_cmp([list],options)
-#
-# where list is the array of checkers for the elements in the list
-# and options are among:
-#
-# showHints => 0 or 1 indicates whether to show messages about
-# which elements are correct.
-#
-# showLengthHints => 0 or 1
-# indicates whether to show messages about
-# having too many entries in the list
-#
-# ordered => 0 or 1 specifies if the order of the student's
-# answers must match thos of the professor.
-# If 0, they can be in any order, if 1, they
-# must be in the same order. Defaut: 0.
-#
-# partialCredit => 0 or 1 indicates if scores other than 0 and 1 are
-# to be used (to provide for partial credit
-# when some of the answers are correct).
-#
-# cmp => \&cmp reference to a comparison
-# for doing syntax checking on the
-# elements given by the student.
-#
-# cmp_params => [...] parameters to pass to the answer checker
-# for syntax checking.
-#
-# cmp_defaults => [...] default parameters for the syntax answer check
-#
-# cmp_ans => "..." a string to use for the answer when checking
-# for syntax errors in the entries that aren't
-# correct.
-#
-# split => \&split a reference to a routine to split the
-# answer string into elements (by default, it
-# uses the standard perl split() funciton
-# splitting at commas)
-#
-# split_params => [...] a reference to a list of parameters for the
-# split routine (e.g.,
-# split_params => [separator => ','])
-#
-# split_defaults => [...] a reference to a list of defaults for the
-# split_params list above.
-#
-# separator => ', ' the formatted specifier for use when
-# creating the string to display (it can
-# contain spaces, whereas the separator
-# in split_defaults or split_params
-# should not). Note that split_defaults
-# usually includes the separator used
-# for the actual splitting.
-#
-
-sub list_cmp {
- my $elements = shift;
- $elements = [$elements] unless ref($elements) eq 'ARRAY';
- my %params = @_;
- set_default_options(\%params,
- cmp => \&std_num_cmp,
- cmp_params => [],
- cmp_defaults => [],
- cmp_ans => "0",
- split => \&std_split,
- split_params => [],
- split_defaults => [separator => ','],
- separator => ', ',
- debug => 0,
- type => "number",
- entry_type => "number",
- list_type => "list",
- showHints => undef,
- showLengthHints => undef,
- ordered => undef,
- );
- my $type = "list ($params{type})";
- my @list = ();
- foreach my $cmp (@{$elements}) {push(@list,hashFor($cmp)->{correct_ans})}
-
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => join($params{separator},@list),
- elements => $elements,
- type => $type,
- );
- $answerEvaluator->install_evaluator(\&list_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the list checker.
-#
-sub list_check {
- my $ans = shift;
- my %params = @_;
- my $value = $params{entry_type}; my $ltype = $params{list_type};
- my $cmp = $params{cmp}; my $cmp_ans = $params{cmp_ans};
- my @cmp_params = (@{$params{cmp_defaults}},@{$params{cmp_params}});
- my $split = $params{split};
- my @split_params = (@{$params{split_defaults}},@{$params{split_params}});
- my @cmp = @{$ans->{elements}};
- my (@errors,@list,@text,@latex);
- my $ordered = $params{ordered};
- my $showHints = defined($params{showHints})?
- $params{showHints} : $showPartialCorrectAnswers;
- my $showLengthHints = defined($params{showLengthHints})?
- $params{showLengthHints} : $showPartialCorrectAnswers;
- my $partialCredit = defined($params{partialCredit})?
- $params{partialCredit} : $showPartialCorrectAnswers;
- $showHints = $showLengthHints = 0 if (isPreviewMode());
-
- my $list_ref = &{$split}($ans->{student_ans},@split_params);
- if (ref($list_ref) ne "ARRAY") {
- $ans->score(0); $ans->{error} = 1;
- $ans->{error_message} = $ans->{ans_message} = $list_ref;
- return $ans;
- }
-
- my $maxscore = scalar(@cmp);
- my $m = scalar(@{$list_ref});
- $maxscore = $m if ($m > $maxscore);
- my $i = 0; my $score = 0; my $hash;
- my $indent = ($m > 1)? 4: 0;
-
- ELEMENT: foreach my $element (@{$list_ref}) {
- $element = trimString($element); $i++;
- if ($element eq '') {
- push(@errors,"Your ".NameForNumber($i)." $value is blank");
- push(@list,''); push(@text,''); push(@latex,'');
- next ELEMENT;
- }
- if ($ordered) {
- $hash = evaluateAnswer(shift(@cmp),$element);
- if ($hash && $hash->{score} == 1) {
- push(@list,$hash->{student_ans});
- push(@text,StringOrBlank($hash->{preview_text_string}));
- push(@latex,StringOrBlank($hash->{preview_latex_string}));
- $score++; next ELEMENT;
- }
- } else {
- foreach my $k (0..$#cmp) {
- $hash = evaluateAnswer($cmp[$k],$element);
- if ($hash && $hash->{score} == 1) {
- splice(@cmp,$k,1);
- push(@list,$hash->{student_ans});
- push(@text,StringOrBlank($hash->{preview_text_string}));
- push(@latex,StringOrBlank($hash->{preview_latex_string}));
- $score++; next ELEMENT;
- }
- }
- }
- $hash = evaluateAnswer(&{$cmp}($cmp_ans,@cmp_params),$element)
- if (!$ordered || !$hash);
- if ($hash->{ans_message} ne '') {
- push(@errors,"Error evaluating the ".NameForNumber($i)." $value:")
- if ($m > 1);
- push(@errors,IndentError($hash->{student_ans},$indent))
- if ($m > 1 || $hash->{student_ans} =~ m/error/i);
- push(@errors,IndentError($hash->{ans_message},$indent));
- push(@list,$element);
- } else {
- push(@list,$hash->{student_ans});
- push(@errors,"Your ".NameForNumber($i)." $value is incorrect")
- if $showHints && $m > 1;
- }
- push(@text,StringOrBlank($hash->{preview_text_string}));
- push(@latex,StringOrBlank($hash->{preview_latex_string}));
- }
-
- if ($showLengthHints) {
- $value =~ s/ or /s or /; # fix "interval or union"
- push(@errors,"There should be more ${value}s in your $ltype")
- if ($score == $m && scalar(@cmp) > 0);
- push(@errors,"There should be fewer ${value}s in your $ltype")
- if ($score < $maxscore && $score == scalar(@{$ans->{elements}}));
- }
-
- $ans->{student_ans} = join($params{separator},@list);
- $ans->{preview_text_string} = join($params{separator},@text);
- $ans->{preview_latex_string} = join($params{separator},@latex);
-
- $score = 0 if ($score != $maxscore && !$partialCredit);
- $ans->score($score/$maxscore);
- $ans->{error_message} = $ans->{ans_message} = join("\n",@errors);
-
- return $ans;
-}
-
-
-######################################################################
-#
-# Do a split at a specific character
-# (routine should return a reference to the split list of
-# answers, or a string that is an error message indicating
-# a syntax error in the string).
-#
-
-sub std_split {
- my $s = shift;
- my %params = (separator => ',', @_);
- return [split($params{separator},$s)];
-}
-
-
-######################################################################
-#
-# Split at commas between intervals or points.
-# (Try to match parentheses, and only split when not within an
-# open set of parentheses).
-#
-# Paremeters can include:
-#
-# separator => ',' the character to split at (you can use
-# a regexp like '[,;]' to allow several
-# characters). Default: ','
-#
-# open => '...' the characters that count as open
-# parentheses. Default: '[('
-#
-# close => '...' the characters that count as close
-# parentheses. Default: '])'
-#
-# spaceSeparates => 0 or 1
-# indicates whether a space can be used to
-# separate entries in the list (when the regular
-# separator is not already there). This will
-# only occur at spaces between unnested close
-# and open parens (with nothing but spaces in
-# between). Default: 1
-#
-
-sub paren_split {
- my $s = shift;
- my %params = @_;
- set_default_options(\%params,
- separator => ',',
- open => '[(',
- close => '])',
- spaceSeparates => 1,
- );
- my $separator = $params{separator};
- my ($open,$close) = ($params{open},$params{close});
- $open =~ s/\]/\\\]/g; $close =~ s/\]/\\\]/g;
- my $spaceSeparates = $params{spaceSeparates};
- my $parens = 0; my $c;
- my @list; my $element; my $space = 0;
-
- foreach $c (split('',$s)) {
- if ($c =~ m/[$open]/) {
- if ($spaceSeparates && $space == 2) {push(@list,$element); $element = ''}
- $parens++; $space = 0;
- }
- elsif ($c =~ m/[$close]/) {
- $parens-- if $parens;
- $space = ($parens == 0);
- }
- elsif ($c =~ m/$separator/) {
- $space = 0;
- if ($parens == 0) {push(@list,$element); $element = ''; next}
- }
- elsif ($c eq ' ' && $space) {$space = 2}
- elsif ($c ne ' ') {$space = 0}
- $element .= $c;
- }
- push (@list,$element);
- return [@list];
-}
-
-######################################################################
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/parallelAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/parallelAnswer.pl
deleted file mode 100755
index 704864c253..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/parallelAnswer.pl
+++ /dev/null
@@ -1,47 +0,0 @@
-loadMacros("vectorAnswer.pl");
-
-sub _parallelAnswer_init {}; # don't reload this file
-
-######################################################################
-#
-# Check if the student's vector is parallel to the answer vector.
-#
-# Usage: parallel_vector_cmp(ans,options)
-#
-# Where ans is the vector to compare against (e.g., "<1,2,3>" or a
-# Vector object), and options are any of the options allowed
-# by point_cmp. The vector must be a constant, not a formula.
-# One additional option is allowed:
-#
-# same_direction => 0 or 1 indicates if the two vectors must
-# also point in the same (not
-# opposite) direction. Default: 0.
-#
-
-sub parallel_vector_cmp {
- my $answer = shift;
- my %params = (same_direction => 0, @_);
- my $sameDirection = $params{same_direction};
- delete $params{same_direction};
- my $cmp = num_point_cmp($answer,
- post_process => \&checkParallel,
- showHints => 0,
- %params
- );
- $cmp->{rh_ans}{same_direction} = $sameDirection;
- return $cmp;
-}
-
-#
-# The parallel check, as a post-processor to point_cmp
-#
-sub checkParallel {
- my $ans = shift;
- areParallel(
- Point(@{$ans->{correct_point}}),
- Point(@{$ans->{answer_point}}),
- $ans->{same_direction}
- );
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/planeAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/planeAnswer.pl
deleted file mode 100755
index 2efeccd883..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/planeAnswer.pl
+++ /dev/null
@@ -1,147 +0,0 @@
-loadMacros(
- 'unionAnswer.pl',
- 'unionMacros.pl',
- 'unionVectors.pl',
- 'vectorUtils.pl',
-);
-
-sub _planeAnswer_init {}; # don't reload this file
-
-#
-# Check that a formula represents a given plane implicitly
-#
-# Usage: implicit_plane_cmp(N,P);
-#
-# where N is a normal vector to the plane and P is a point on the
-# plane. Ex: plane_cmp(Vector(1,2,3),Point(0,0,0)); or
-# plane_cmp([1,2,3],[0,0,0]);
-#
-# The student enter's an answer in the form "a x + b y + c z = d",
-# or anything equivalent to that. This answer checking will properly
-# recognize the plane even if it is given as a different multiple of
-# the equation, or if it is reorganized, or has computations within it.
-# E.g., the student could enter "0 = 20 -(x + 3y + z)".
-#
-# The answer checker will produce the string used for displaying the
-# correct answer for you automatically, properly handling zero coefficients.
-#
-
-sub implicit_plane_cmp {
- my $N = Vector(shift); my $P = Point(shift);
- my %params = @_;
- set_default_options(\%params,
- showHints => 1,
- debug => 0,
- );
- my $answer = Plane($N,$P);
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => $answer,
- type => "implicit plane",
- N => $N, P => $P,
- );
- $answerEvaluator->install_evaluator(\&implicit_plane_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the implicit plane checker
-#
-sub implicit_plane_check {
- my $ans = shift;
- my %params = @_;
- my @errors = (); my $score = 0;
- my $showHints = $params{showHints};
- $showHints = 0 if ($showPartialCorrectAnswers == 0 || isPreviewMode());
- my ($text,$latex);
- my ($a,$b,$c,$d);
- my ($N,$P) = ($ans->{N}->data,$ans->{P}->data);
-
- my $student_ans = trimString($ans->{student_ans});
- #
- # Find the left- and right-hand sides
- #
- if ($student_ans !~ m/^(.*)=(.*)$/) {
- push(@errors,"Your answer is not of the form 'ax + by + cz = d'")
- if ($showHints);
- } else {
- my ($lhs,$rhs) = (trimString($1),trimString($2));
- push(@errors,"The left-hand side is blank") if $lhs eq '';
- push(@errors,"The right-hand side is blank") if $rhs eq '';
- if (scalar(@errors) == 0) {
- #
- # Do a syntax check on the two sides
- #
- my $cmp = fun_cmp("0",vars=>['x','y','z']);
- my $hash = evaluateAnswer($cmp,$lhs,1);
- if ($hash->{ans_message} eq "") {
- $lhs = $hash->{student_ans};
- $text = $hash->{preview_text_string};
- $latex = $hash->{preview_latex_string};
- } else {
- push(@errors,"Error evaluating left-hand side:");
- push(@errors,IndentError($hash->{student_ans}));
- push(@errors,IndentError($hash->{ans_message}));
- }
- clearEvaluator($cmp);
- $hash = evaluateAnswer($cmp,$rhs,1);
- if ($hash->{ans_message} eq "") {
- $rhs = $hash->{student_ans};
- $text .= " = ".$hash->{preview_text_string};
- $latex .= " = ".$hash->{preview_latex_string};
- } else {
- push(@errors,"Error evaluating right-hand side:");
- push(@errors,IndentError($hash->{student_ans}));
- push(@errors,IndentError($hash->{ans_message}));
- }
- clearEvaluator($cmp);
-
- if (scalar(@errors) == 0) {
- #
- # Use $cmp to evaluate student function to obtain coefficients
- #
- $cmp->{rh_ans}{evaluation_points} = [[0,0,0],[1,0,0],[0,1,0],[0,0,1]];
- $hash = evaluateAnswer($cmp,"($lhs)-($rhs)");
- # check for errors here, too?
- $d = $hash->{ra_student_values}->[0];
- $a = $hash->{ra_student_values}->[1] - $d;
- $b = $hash->{ra_student_values}->[2] - $d;
- $c = $hash->{ra_student_values}->[3] - $d;
- #
- # Check that the student function really IS a plane
- #
- $cmp = fun_cmp("$a x + $b y + $c z + $d",vars => ['x','y','z']);
- if (isCorrectAnswer($cmp,"($lhs)-($rhs)")) {
- #
- # Check that is is the RIGHT plane
- #
- $score = (areParallel($N,Point($a,$b,$c)) &&
- isCorrectAnswer(std_num_cmp(-$d),vDot($P,Point($a,$b,$c))));
- } else {
- push(@errors,
- "Your answer does not seem to be of the form 'ax + by + cz = d'")
- if ($showHints);
- }
- }
- $ans->setKeys(
- student_ans => $lhs." = ".$rhs,
- preview_text_string => $text,
- preview_latex_string => $latex,
- );
- }
- }
- if (scalar(@errors) == 0) {
- $ans->score($score);
- $ans->{ans_message} = $ans->{error_message} = '';
- $ans->{error} = 0;
- } else {
- $ans->score(0);
- $ans->{error_message} = join("\n",@errors);
- $ans->{ans_message} = join("\n",@errors);
- $ans->{error} = 1;
- }
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/pointAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/pointAnswer.pl
deleted file mode 100755
index f441598abd..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/pointAnswer.pl
+++ /dev/null
@@ -1,300 +0,0 @@
-loadMacros(
- "unionMacros.pl",
- "unionUtils.pl",
- "unionVectors.pl",
- "answerUtils.pl",
-);
-
-sub _pointAnswer_init {}; # don't reload this file
-
-######################################################################
-##
-## Point (and Vector) answer checkers
-##
-## num_point_cmp() check for a point with numeric coordinates
-## fun_point_cmp() check for a point with coordinate functions
-##
-## std_point_cmp() provide your own coordinate checker
-## point_cmp() provide array of coordiante checkers
-
-
-######################################################################
-#
-# num_point_cmp(answer,options)
-#
-# where options are from among:
-#
-# extra_cmp => cmp an answer checker to use for extra coordinates
-# supplied by the student (for syntax checking)
-#
-# cmp_params => [list] parameters to be passed to std_num_cmp
-# for each coordinate
-#
-# format => string an sprintf format string used to format
-# the answer (for display purposes only).
-# Default: "%.6g"
-#
-# or any of the options to point_cmp (see below).
-#
-# This provides an answer checker that compares against a point
-# or vector with numeric coordinates.
-#
-# e.g. num_point_cmp("(1,0,0)")
-#
-
-sub num_point_cmp {
- my $ans = shift;
- std_point_cmp($ans,cmp => \&std_num_cmp, format => '%.6g', @_);
-}
-
-
-######################################################################
-#
-# fun_point_cmp(answer,options)
-#
-# where options are from among:
-#
-# extra_cmp => cmp an answer checker to use for extra coordinates
-# supplied by the student (for syntax checking)
-#
-# cmp_params => [list] parameters to be passed to fun_cmp
-# for each coordinate
-#
-# vars => [list] the variables used in the functions
-#
-# or any of the options to point_cmp (see below).
-#
-# This provides an answer checker that compares against a point
-# or vector with functional coordinates.
-#
-# e.g. fun_point_cmp("(t,t^2,t^3)", vars => 't');
-#
-
-sub fun_point_cmp {
- my $ans = shift;
- my %params = (cmp_params => [], @_);
- if (defined($params{vars})) {
- $params{cmp_params} = [vars => $params{vars}, @{$params{cmp_params}}];
- delete $params{vars};
- }
- std_point_cmp($ans, cmp => \&fun_cmp, %params);
-}
-
-
-######################################################################
-#
-# std_point_cmp(ans,options)
-#
-# where ans is the correct answer as a string (e.g. "(1,0,0)") and
-# options are taken from among the following:
-#
-# cmp => \&cmp a reference to the answer checker to use for each
-# endpoint (e.g., \&std_num_cmp, or ~~&std_num_cmp
-# in a .pg file)
-#
-# cmp_params => [...] is a reference to a list of parameters for the
-# answer checker (e.g., [vars => 'x'])
-#
-# default => ans is the answer to use for any extra coordinates
-# supplied by the student (for syntax checking only)
-#
-# or any of the options allowed by point_cmp (see below)
-#
-# This returns an answer checker that compares the point using the
-# given answer checker on each coordinate.
-#
-# e.g. std_point_cmp("(1,0,0)",cmp => ~~&strict_num_cmp, default => 0);
-#
-sub std_point_cmp {
- my $ans = shift; $ans = $ans->answer if isVector($ans);
- my %params = (
- cmp => \&std_num_cmp,
- cmp_params => [],
- default => 0,
- @_
- );
- my ($cmp,$cmp_params) = ($params{cmp},$params{cmp_params});
- delete $params{cmp}; delete $params{cmp_params};
- my $default = $params{default}; delete $params{default};
- $params{extra_cmp} = &{$cmp}($default,@{$cmp_params})
- unless $params{extra_cmp};
- if ($ans =~ s/^(\[|\(|<)(.*)(>|\]|\))$/$2/)
- {$params{left} = $1; $params{right} = $3}
- my @answers = (); my $answer;
- foreach $answer (split(',',$ans))
- {push(@answers,&{$cmp}($answer,@{$cmp_params}))}
- point_cmp([@answers],%params);
-}
-
-
-######################################################################
-#
-# point_cmp(cmps,options)
-#
-# where
-#
-# cmps is a reference to an array of answer checkers, one
-# for each component of the answer
-#
-# and options are taken from:
-#
-# showHints => 0 or 1 determines if coordinate-by-coordinate
-# hints are given (tells whether each
-# coordinate is correct or not).
-# (default: 1)
-#
-# showLengthHints => 0 or 1 determines if messages about incorrect
-# number of components should be issued
-# (default: 1)
-#
-# extra_cmp => cmp an answer checker to use for any extra
-# coordinates supplied by the student
-# (for syntax checking purposes)
-#
-# format => string sprintf format for the coordinates
-#
-# post_process => code routine to determine the score once
-# the point passes the syntax checking
-# of the individual components. This
-# can be used to change the score
-# after the fact (e.g., to check for
-# parallel vectors, etc.)
-#
-sub point_cmp {
- my $compref = shift;
- my %params = @_;
- set_default_options(\%params,
- showHints => 1,
- showLengthHints => 1,
- extra_cmp => undef,
- post_process => undef,
- format => undef,
- debug => 0,
- left => '(',
- right => ')',
- );
- $params{components} = $compref;
- $params{pattern} = "\\$params{left}(.*)\\$params{right}"
- unless defined($params{pattern});
-
- #
- # Needed to get preview to work properly
- #
- my $type = "point"; my $hash;
- foreach $hash (@{$compref}) {
- if ((hashFor($hash))->{type} =~ m/number/) {
- $type .= " (number)";
- last;
- }
- }
-
- my @ans = (); my @ans_point = ();
- my $format = $params{format}; my $correct_ans;
- foreach $hash (@{$compref}) {
- $correct_ans = (hashFor($hash))->{correct_ans};
- push(@ans_point,$correct_ans);
- $correct_ans = sprintf($format,$correct_ans) if ($format);
- push(@ans,$correct_ans);
- }
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- correct_ans => $params{left}.' '.join(", ",@ans).' '.$params{right},
- correct_point => [@ans_point],
- components => $compref,
- type => $type,
- );
- $answerEvaluator->install_evaluator(\&point_check,%params);
- return $answerEvaluator;
-}
-
-######################################################################
-#
-# The guts of the point checker
-#
-sub point_check {
- my $ans = shift;
- my %params = @_;
- my @errors = (); my $score = 1;
- my $showHints = defined($params{showHints})?
- $params{showHints} : $showPartialCorrectAnswers;
- my $showLengthHints = defined($params{showLengthHints})?
- $params{showLengthHints} : $showPartialCorrectAnswers;
- $showHints = $showLengthHints = 0 if isPreviewMode();
-
- my $extra_cmp = $params{extra_cmp};
- $extra_comp = std_num_cmp(0) unless $extra_cmp;
- my ($lp,$rp) = ($params{left},$params{right});
- my ($addparens) = 1;
- my $format = $params{format};
- my (@new_ans,@new_ans_point);
-
- my $student_ans = trimString($ans->{student_ans});
- if ($student_ans !~ s/^$params{pattern}$/$1/) {
- my %parens = ('(' => "parentheses",
- '<' => "angle brackets",
- '[' => "square brackets");
- $parens{$lp} = "the proper characters" unless defined($parens{$lp});
- push(@errors,
- showHTML("Your answer is not enclosed in $parens{$lp}: $lp and $rp"));
- $score = 0;
- } else {
- my $i = 0; my @answers = split(',',$student_ans);
- my ($answer, $answer_full, $correct_cmp, @text, @latex);
-
- foreach $answer (@answers) {
- $correct_cmp = (@{$ans->{components}})[$i++] || $extra_cmp;
- $hash = evaluateAnswer($correct_cmp,$answer);
- $answer_full = $answer;
- if ($hash->{ans_message} eq "") {
- $answer_full = $answer = $hash->{student_ans};
- $answer = sprintf($format,$answer) if ($format);
- } else {$hash->{score} = 0}
- push(@new_ans,$answer); push(@new_ans_point,$answer_full);
- push(@text,StringOrBlank($hash->{preview_text_string},$answer));
- push(@latex,StringOrBlank($hash->{preview_latex_string},$answer));
- if ($hash->{score} != 1 || $correct_cmp == $extra_cmp) {
- $score = 0;
- if ($hash->{ans_message} ne "") {
- push(@errors,"Error evaluating the ".NameForNumber($i).
- " coordinate:");
- push(@errors,IndentError($answer));
- push(@errors,IndentError($hash->{ans_message}));
- } else {
- push(@errors,"The ".NameForNumber($i)." coordinate is incorrect.")
- if ($showHints);
- }
- }
- clearEvaluator($correct_cmp);
- }
-
- if (scalar(@answers) != scalar(@{$ans->{components}})) {
- push(@errors,"The number of coordinates is not correct.")
- if ($showLengthHints);
- $score = 0;
- }
- $ans->setKeys(student_ans => $lp . join(', ',@new_ans) . $rp)
- if (scalar(@new_ans) > 0);
- $ans->setKeys(
- preview_text_string => $lp . join(', ',@text) . $rp,
- preview_latex_string => $lp . join(', ',@latex) . $rp,
- );
- }
-
- # make sure vectors aren't interpretted as HTML tags
- $ans->setKeys(student_ans => showHTML($ans->{student_ans}));
-
- if (scalar(@errors) == 0) {
- $ans->score($score);
- $ans->{ans_message} = $ans->{error_message} = '';
- $ans->{answer_point} = [@new_ans_point];
- if ($params{post_process}) {$ans->score(&{$params{post_process}}($ans))}
- } else {
- $ans->score(0);
- $ans->{ans_message} = $ans->{error_message} = join("\n",@errors);
- }
-
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/unionAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/unionAnswer.pl
deleted file mode 100755
index 3b3f1a6a0e..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/unionAnswer.pl
+++ /dev/null
@@ -1,56 +0,0 @@
-######################################################################
-#
-# Implements answer checkers for unions of intervals
-#
-
-loadMacros(
- "intervalAnswer.pl",
- "listAnswer.pl"
-);
-
-sub _unionAnswer_init {
- $INFINITY_UNION_MESSAGE =
- "$BBOLD Note: $EBOLD ".
- "If the answer includes more than one interval, write the intervals ".
- "separated by the ${LQ}union$RQ symbol, ${BITALIC}U${EITALIC}. If needed, enter ".
- "\\(\\infty\\) as ${BITALIC}$INFINITY_WORD${EITALIC} and \\(-\\infty\\) as ".
- "${BITALIC}-$INFINITY_WORD${EITALIC}.";
-
- $INFINITY_UNION_MESSAGE = "" if $displayMode eq 'TeX';
-};
-
-######################################################################
-#
-# Usage: num_union_cmp(ans,options)
-# fun_union_cmp(ans,options)
-#
-# where ans is the string indicating the union (e.g., "[1,3) U (-inf,-5)")
-# and options are any of those that can be passed to std_list_cmp.
-#
-
-sub num_union_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&num_interval_cmp,
- type => "number interval union",
- entry_type => 'interval',
- list_type => 'union',
- separator => ' U ',
- split_defaults => [separator => 'U'],
- cmp_ans => "(0,1]",
- cmp_defaults => [showHints => 0],
- @_);
-}
-
-sub fun_union_cmp {
- my $ans = shift;
- std_list_cmp($ans, cmp => \&fun_interval_cmp,
- type => "function interval union",
- entry_type => 'interval',
- list_type => 'union',
- separator => ' U ',
- split_defaults => [separator => 'U'],
- cmp_ans => "(0,1]",
- fun_var_params(cmp_defaults => [showHints => 0],@_));
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/unionVectors.pl b/OpenProblemLibrary/macros/Union/obsolete/unionVectors.pl
deleted file mode 100755
index 3f3fb89ee6..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/unionVectors.pl
+++ /dev/null
@@ -1,486 +0,0 @@
-sub _unionVectors_init {}; # don't reload this file
-
-######################################################################
-#
-# A class that implements Vector and Point objects. It allows you
-# to create them, perform arithmatic on them, and display them in
-# various formats.
-#
-# This is just a temprary hack until I finish the complete
-# multi-variable parser that is in the works. -- DPVC
-#
-# Usage:
-#
-# Point(x1,...,xn) creates a point object with n coordinates
-# Vector(x1,...,xn) creates a vector object with n coordinates
-#
-# Norm(x) computes the length of a vector
-# Unit(x) computes a unit vector in the same direction as x
-#
-# areParallel(x,y) returns 1 if the vectors are parallel
-#
-# vSum(x,y) adds two points or vectors
-# vDiff(x,y) computes x - y
-# vProd(a,x) computes the scalar product ax for a point
-# or vector x and scalar a
-# vDiv(x,a) divides point or vector x by a
-# vDot(x,y) computes the dot product x.y
-# vCross(x,y) comptes the cross product of two vectors
-# vNeg(x) computes -x
-# vEqual(x,y) true when x and y are equal vectors
-# vCmp(x,y) does a comparison of two points or vectors
-# in lexicographic order (like <=> for vectors).
-# when not of the same length, the shorter one
-# is considered to be smaller.
-#
-# These operations can be performed much easier by using the overload
-# package to overload the operators to work with point and vector
-# objects. However, to do this in WeBWorK requires making this a
-# module and adding it to the PG_module_list.pl file (a system-level
-# change). I'm working on a more complete multi-variable package
-# that will supersede this, and so wanted to keep it a local change
-# for now.
-#
-# The Point and Vector routines can accept a variety of input
-# formats, for example, Point([1,2,3]) also produces the same result
-# as Point(1,2,3). So you could do $x = [1,2,3], $y = Point($x), or
-# $x = vDiff([1,2,3],[4,5,6]) to obtain the point (-3,-3,-3).
-#
-# You can also pass Point and Vector objects themselves, which
-# provides a means of converting one type to the other. For example:
-#
-# $x = Point(1,2,3); $y = Point(4,5,6);
-# $v = Vector(vDiff($y,$x));
-#
-# produces the vector from $x to $y (without the Vector call, the
-# result of vDiff would be a Point).
-#
-# The various vector-based answer checkers all accept Vector or Point
-# objects as their inputs (and usually also accept strings like
-# "(1,2,3)", or arrays like [1,2,3]).
-#
-# Once you have a Point or Vector object, $x, you can get a printable
-# version of the object using $x->string, $x->TeX or $x->answer.
-# Answer and string both produce text strings suitable for display as
-# the correct answer, while TeX produces a string for use within
-# \( \) in the problem itself. For example:
-#
-# $P = Point(1,2,3);
-# BEGIN_TEXT
-# Consider the point \(P = \{$P->TeX\}\).
-# END_TEXT
-#
-
-##################################################
-#
-# Can't seem to get Exporter to work, so doing it by hand -- DPVC
-# (If you turn this into a .pm file, you need to make these
-# subroutines in PG_priv::, e.g., sub PG_priv::Point ...)
-#
-
-sub Point {unionVectors::Point(@_)}
-sub Vector {unionVectors::Vector(@_)}
-
-sub isVector {unionVectors::isVector(@_)}
-
-sub Norm {unionVectors::norm(@_)}
-sub Unit {unionVectors::unit(@_)}
-sub areParallel {unionVectors::areParallel(@_)}
-
-#
-# Can't use 'use overload' from loadMacros, so doing
-# explicit calls. (If the file is made a .pm file and added
-# to PG_module_list.pl, then things can work much nicer.)
-#
-sub vSum {unionVectors::add(@_)}
-sub vDiff {unionVectors::sub(@_)}
-sub vProd {unionVectors::mult($_[1],$_[0])}
-sub vDiv {unionVectors::div(@_)}
-sub vDot {unionVectors::dot(@_)}
-sub vCross {unionVectors::cross(@_)}
-sub vNeg {unionVectors::neg(@_)}
-sub vCmp {unionVectors::compare(@_)}
-sub vEqual {unionVectors::compare(@_) == 0}
-
-##################################################
-
-package unionVectors;
-my $pkg = 'unionVectors';
-
-#use strict;
-#use vars qw(%parens);
-
-#use overload
-# '+' => \&add,
-# '-' => \&sub,
-# '*' => \&mult,
-# '/' => \&div,
-# '**' => \&power,
-# '.' => \&dot,
-# 'x' => \&cross,
-# '<=>' => \&compare,
-# 'cmp' => \&compare,
-# 'neg' => sub {$_[0]->neg},
-# 'abs' => sub {$_[0]->abs},
-# '""' => \&string,
-# 'nomethod' => \&nomethod;
-
-#
-# Usually we don't want to see the full precision, so
-# use this for display purposes (computation still at
-# full precision)
-#
-my $numberFormat = '%.6g'; # could be '%s' for full precision
-
-#
-# What a number looks like
-#
-my $numPattern = '-?(\d+(\.\d*)?|\.\d+)(E[-+]?\d+)?';
-
-#
-# What parentheses to use for points and vectors
-#
-%parens = (
- 'Point' => {open => '(', close => ')'},
- 'Vector' => {open => '<', close => '>'},
-);
-
-##################################################
-
-#
-# Create an object of the required type
-#
-sub Point {$pkg->new('Point',@_)}
-sub Vector {$pkg->new('Vector',@_)}
-
-#
-# Create a new object of the requested type using the given data
-#
-# Check that the type is valid
-# Get the data into an array if there is more than one coordinate given
-# If the input is already a point or vector, use its data otherwise
-# Make it an array if it isn't already
-# Check that there is at least one coordinate
-# Check that each coordinate is a number or string
-# Return the new object
-#
-sub new {
- my $self = shift; my $class = ref($self) || $self;
- my $type = shift;
- die "Unknown multivariable type '$type'" unless defined($parens{$type});
- my $p = shift; $p = [$p,@_] if (scalar(@_) > 0);
- if (isVector($p)) {$p = [$p->value]} else {
- $p = [$p] if (defined($p) && ref($p) ne 'ARRAY');
- die $type."s must have at least one coordinate"
- unless defined($p) && scalar(@{$p}) > 0;
- foreach my $x (@{$p}) {die "Can't use ".showType($x)." as a coordinate"
- if ref($x)}
- }
- bless {type => $type, data => $p}, $class;
-}
-
-#
-# Create a new object from data that is known to be good
-# (faster -- for use within the methods below)
-#
-sub make {
- my $self = shift; my $class = ref($self) || $self;
- my $type = $self->type;
- bless {type => $type, data => [@_]}, $class;
-}
-
-#
-# Get the object's data or type
-#
-sub value {@{(shift)->{data}}}
-sub data {(shift)->{data}}
-sub type {(shift)->{type}}
-
-##################################################
-
-#
-# Check if an item is of the required type
-#
-sub isNumber {my $n = shift; $n =~ m/^$numPattern$/oi}
-sub isVector {ref(shift) eq $pkg}
-
-#
-# Show an item's type for error messages
-#
-sub showType {
- my $value = shift;
- return "'".$value."'" unless ref($value);
- my $type = ref($value); $type = $value->type if ($type eq $pkg);
- return 'an '.$type if substr($type,0,1) =~ m/[aeio]/i;
- return 'a '.$type;
-}
-
-#
-# Return the object if it is a Point or Vector already,
-# otherwise make it into a Point. (This guarantees that
-# we have a Point or Vector as a result.)
-#
-sub promote {
- my $x = shift;
- $x = [$x,@_] if scalar(@_) > 0 || isNumber($x);
- return $pkg->new('Point',$x) if ref($x) eq 'ARRAY';
- return $x if ref($x) eq $pkg;
- die "Can't convert ".showType($x)." to a Point";
-}
-
-#
-# Returns the object of highest precedence (where Vectors are
-# considered higher precedence than Points).
-#
-sub highestType {
- my ($l,$r) = @_;
- return $r if (isVector($r) && $r->type eq 'Vector');
- return $l;
-}
-
-##################################################
-#
-# Implement the vector operations. These are set up to be used
-# with the overload package, and the $flag argument is part of
-# that mechanism (it tells if the order of the operands has been
-# reversed).
-#
-
-#
-# A catch-all for operations that aren't defined
-# (when overloading is in effect).
-#
-sub nomethod {
- my ($l,$r,$flag,$op) = @_;
- die "Can't use '$op' with ".$l->type."-valued operands"
-}
-
-#
-# Add the vectors of they are of the same length.
-#
-sub add {
- my ($l,$r,$flag) = @_; my $self = highestType($l,$r);
- ($l,$r) = (promote($l)->data,promote($r)->data);
- die $self->type." addition with different number of coordiantes"
- unless scalar(@{$l}) == scalar(@{$r});
- my @s = ();
- foreach my $i (0..scalar(@{$l})-1) {push(@s,$l->[$i] + $r->[$i])}
- return $self->make(@s);
-}
-
-#
-# Subtract the vectors, if they are of the same length
-#
-sub sub {
- my ($l,$r,$flag) = @_; my $self = highestType($l,$r);
- ($l,$r) = (promote($l)->data,promote($r)->data);
- die $self->type." subtraction with different number of coordiantes"
- unless scalar(@{$l}) == scalar(@{$r});
- if ($flag) {my $tmp = $l; $l = $r; $r = $tmp};
- my @s = ();
- foreach my $i (0..scalar(@{$l})-1) {push(@s,$l->[$i] - $r->[$i])}
- return $self->make(@s);
-}
-
-#
-# Multiply a vector by a scalar. (Adding 0 seems to avoid some funny
-# things like -0 as the result. Don't know why.)
-#
-sub mult {
- my ($l,$r,$flag) = @_; my $self = $l;
- die $l->type."s can only be multiplied by numbers" unless isNumber($r);
- my @coords = ();
- foreach my $x ($l->value) {push(@coords,$x*$r+0)}
- return $self->make(@coords);
-}
-
-#
-# Divide a vector by a non-zer scalar
-#
-sub div {
- my ($l,$r,$flag) = @_; my $self = $l;
- die "Can't divide by a ".$self->type if $flag;
- die $self->type."s can only be divided by numbers" unless isNumber($r);
- die "Division by zero" if $r == 0;
- my @coords = ();
- foreach my $x ($l->value) {push(@coords,$x/$r+0)}
- return $self->make(@coords);
-}
-
-#
-# Warn that powers don't make sense for vectors
-# (when overloading is in effect)
-#
-sub power {
- my ($l,$r,$flag) = @_; my $self = $l;
- die "Can't raise ".$self->type."s to powers" unless $flag;
- die "Can't use ".$self->type."s in exponents";
-}
-
-#
-# Dot two vectors together
-#
-sub dot {
- my ($l,$r,$flag) = @_; my $self = $l;
- ($l,$r) = (promote($l)->data,promote($r)->data);
- die "Dot product with different number of coordiantes"
- unless scalar(@{$l}) == scalar(@{$r});
- my $s = 0;
- foreach my $i (0..scalar(@{$l})-1) {$s += $l->[$i] * $r->[$i]}
- return $s;
-}
-
-#
-# Take the cross product of two vectors in 3D
-#
-sub cross {
- my ($l,$r,$flag) = @_; my $self = $l; $self->{type} = "Vector";
- ($l,$r) = (promote($l)->data,promote($r)->data);
- die $self->type."s must be in 3-space for cross product"
- unless scalar(@{$l}) == 3 && scalar(@{$r}) == 3;
- $self->make($l->[1]*$r->[2] - $l->[2]*$r->[1],
- -($l->[0]*$r->[2] - $l->[2]*$r->[0]),
- $l->[0]*$r->[1] - $l->[1]*$r->[0]);
-}
-
-#
-# Do a lexicographic comparison of two vectors
-#
-sub compare {
- my ($l,$r,$flag) = @_;
- ($l,$r) = (promote($l)->data,promote($r)->data);
- return scalar(@{$l}) <=> scalar(@{$r}) unless scalar(@{$l}) == scalar(@{$r});
- if ($flag) {my $tmp = $l; $l = $r; $r = $tmp};
- my $cmp = 0;
- foreach my $i (0..scalar(@{$l})-1)
- {$cmp = $l->[$i] <=> $r->[$i]; last if $cmp}
- return $cmp;
-}
-
-#
-# Negate a vector
-#
-sub neg {
- my $self = shift; $self = promote(@_) unless isVector($self);
- my @coords = ();
- foreach my $x ($self->value) {push(@coords,-$x)}
- return $self->make(@coords);
-}
-
-#
-# Get the length of a vector
-#
-sub abs {(shift)->norm}
-sub norm {
- my $self = shift; $self = promote($self,@_) unless isVector($self);
- my $s = 0;
- foreach my $x ($self->value) {$s += $x*$x}
- return CORE::sqrt($s);
-}
-
-#
-# Produce a unit vector in the same direction as the given
-# vector (or return the zero vector if the original is the zero
-# vector).
-#
-sub unit {
- my $self = shift; $self = promote($self,@_) unless isVector($self);
- my $s = $self->norm; $s = 1/$s unless $s == 0;
- return $self->mult($s);
-}
-
-#
-# Check if two vectors are parallel
-#
-sub areParallel {
- my $sameDirection = $_[2];
- my @u = (promote($_[0]))->value;
- my @v = (promote($_[1]))->value;
- if (scalar(@u) != scalar(@v)) {return 0}
- my $epsilon = 1E-6; # tolerance for equal to zero
- my $k = ''; # scaling factor for u = k v
- foreach $i (0..$#u) {
- if ($k ne '') {
- return 0 if (CORE::abs($v[$i] - $k*$u[$i]) >= $epsilon);
- } else {
- #
- # if one is zero and the other isn't then not parallel
- # otherwise use the ratio of the two as k
- #
- if (CORE::abs($u[$i]) < $epsilon) {
- return 0 if (CORE::abs($v[$i]) >= $epsilon);
- } else {
- return 0 if (CORE::abs($v[$i]) < $epsilon);
- $k = $v[$i]/$u[$i];
- return 0 if $k < 0 && $sameDirection;
- }
- }
- }
- #
- # Note: it will return 1 if both are zero vectors. This is a
- # feature, since one is provided by the problem writer, and he
- # should only supply the zero vector if he means it. One could
- # return ($k ne '') to return 0 if both are zero.
- #
- return 1;
-}
-
-##################################################
-#
-# Produce the various output formats
-#
-# ->string gets a printable string (for output)
-# ->answer gets a sting for the answer checkers
-# (currently just calls string)
-# ->TeX produces TeX commands suitable for use within \( \).
-# ->ijk produces TeX version of vector using i,j, and k
-# vectors (must include the vectorUtils.pl file
-# in order to use this, or define $i, $j and $k
-# to be the TeX values you want to use for these).
-#
-
-sub string {
- my $self = shift; my $paren = $parens{$self->type};
- my @p = ();
- foreach my $x ($self->value) {
- if (isNumber($x)) {push(@p,sprintf($numberFormat,$x))} else {push(@p,$x)}
- }
- $paren->{open}.join(',',@p).$paren->{close};
-}
-
-sub answer {(shift)->string(@_)}
-
-sub TeX {
- my $self = shift; my $paren = $parens{$self->type};
- my $open = $paren->{TeX_open} || '\left'.$paren->{open};
- my $close = $paren->{TeX_close} || '\right'.$paren->{close};
- my @p = ();
- foreach my $x ($self->value) {
- if (isNumber($x)) {push(@p,sprintf($numberFormat,$x))} else {push(@p,$x)}
- }
- $open.join(',',@p).$close
-}
-
-sub ijk {
- my $self = shift; my @p = ();
- foreach my $x ($self->value) {
- if (isNumber($x)) {push(@p,sprintf($numberFormat,$x))}
- else {push(@p,'('.$x.')')}
- }
- "$p[0]$main::i + $p[1]$main::j + $p[2]$main::k";
-}
-
-##################################################
-
-#
-# Set the number output format to the given sprintf string.
-# E.g., '%s' would give the full precision of the number.
-#
-# Default: '%.6g'
-#
-sub numberFormat {shift; $numberFormat = shift}
-
-###########################################################################
-###########################################################################
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/variableAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/variableAnswer.pl
deleted file mode 100755
index 88f68bd8bc..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/variableAnswer.pl
+++ /dev/null
@@ -1,94 +0,0 @@
-sub _variableAnswer_init {}; # don't reload this file
-
-##################################################
-#
-# A match on a collection of comma- or space-separated
-# strings, optionally enclosed in parentheses.
-# The match can be case insensitive, and order insensitive.
-#
-# Usage: variable_cmp(ans,options)
-#
-# where ans is the correct answer string (or an array of the answers,
-# which will be made into a comma-separated string), and options
-# are taken from:
-#
-# ignore_case => 0 or 1 determines wether upper- and
-# lower-case are to be distinguished or not
-# (Default: 0)
-#
-# ignore_order => 0 or 1 determines whether the order of the
-# answers matters or not
-# (Default: 0)
-#
-# allow_parens => 0 or 1 determines whether parens are stripped
-# from around the answer automatically
-# (Default: 1)
-#
-# force_parens => 0 or 1 determines whether parens are
-# required in the student's answer
-# (Default: 0)
-
-sub variable_cmp {
- my $answer = shift || '';
- $answer = join(',',@{$answer}) if ref($answer) eq 'ARRAY';
- $answer = trimString($answer);
- my %params = @_;
- set_default_options(\%params,
- ignore_case => 0,
- ignore_order => 0,
- allow_parens => 1,
- force_parens => 0,
- );
- $answer = '('.$answer.')' if $params{force_parens} && $answer !~ m/^\(.*\)$/;
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug} || 0;
- $answerEvaluator->ans_hash(type => "variable", correct_ans => $answer);
- $answerEvaluator->install_evaluator(\&variable_cmp_check,%params);
- return $answerEvaluator;
-}
-
-#
-# The guts of the checker
-#
-sub variable_cmp_check {
- my $ans = shift;
- my %option = @_;
- my $student_ans = $ans->{student_ans};
- my $correct_ans = $ans->{correct_ans};
- $student_ans = trimString($student_ans);
- $ans->setKeys(
- student_ans => $student_ans,
- original_student_ans => $student_ans,
- preview_text_string => $student_ans,
- preview_latex_string => $student_ans,
- ans_message => ''
- );
- if ($option{force_parens}) {
- if ($student_ans !~ m/^\(.*\)$/) {
- $ans->{ans_message} = "Your answer isn't enclosed in parentheses";
- $ans->{error} = 1; $ans->score(0); return $ans;
- }
- $option{allow_parens} = 1;
- }
- if ($option{allow_parens}) {
- $student_ans =~ s/^\((.*)\)$/$1/; $correct_ans =~ s/^\((.*)\)$/$1/;
- if ($student_ans =~ m/^\(|\)$/) {
- $ans->{ans_message} = "Incorrect parentheses";
- $ans->{error} = 1; $ans->score(0); return $ans;
- }
- }
- $student_ans =~ s/,/ /g; $correct_ans =~ s/,/ /g;
- $student_ans =~ s/\s+/ /g; $correct_ans =~ s/\s+/ /g;
- if ($option{ignore_case}) {
- $student_ans = lc($student_ans);
- $correct_ans = lc($correct_ans);
- }
- if ($option{ignore_order}) {
- $student_ans = join(' ',lex_sort(split(' ',$student_ans)));
- $correct_ans = join(' ',lex_sort(split(' ',$correct_ans)));
- }
- $ans->score($student_ans eq $correct_ans);
- return $ans;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/vectorAnswer.pl b/OpenProblemLibrary/macros/Union/obsolete/vectorAnswer.pl
deleted file mode 100755
index f08a9dec80..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/vectorAnswer.pl
+++ /dev/null
@@ -1,11 +0,0 @@
-loadMacros("pointAnswer.pl","vectorUtils.pl");
-
-#
-# Just a renaming of the point comparisons.
-#
-sub num_vector_cmp {num_point_cmp(@_)}
-sub fun_vector_cmp {fun_point_cmp(@_)}
-sub std_vector_cmp {std_point_cmp(@_)}
-sub vector_cmp {point_cmp(@_)}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/obsolete/vectorUtils.pl b/OpenProblemLibrary/macros/Union/obsolete/vectorUtils.pl
deleted file mode 100755
index f537c5bca4..0000000000
--- a/OpenProblemLibrary/macros/Union/obsolete/vectorUtils.pl
+++ /dev/null
@@ -1,121 +0,0 @@
-#####################################################################
-#
-# Some utility routines that are useful in vector problems
-#
-
-sub _vectorUtils_init {}; # don't reload this file
-
-##################################################
-
-#
-# formats a vector name (should be used in math mode)
-#
-# Vectors will be in bold italics in HTML modes, and
-# will be overlined in TeX modes. (Bold italic could also work in
-# TeX modes, but the low resolution on screen made it less easy
-# to distinguish the difference between bold and regular letters.)
-#
-sub Overline {
- my $v = shift;
- my $HTML = ''.$v.'';
- MODES(
- TeX => "\\overline{$v}",
- HTML => $HTML,
- HTML_tth => '\begin{rawhtml}'.$HTML.'\end{rawhtml}',
- HTML_dpng => "\\overline{$v}",
- );
-}
-
-#
-# This gets a bold letter in TeX as well as HTML modes.
-# Although \boldsymbol{} works fine on screen in latex2html mode,
-# the PDF file produces non-bold letters. I haven't been able to
-# track this down, so used \mathbf{} in TeX mode, which produces
-# roman bold, not math-italic bold.
-#
-sub BoldMath {
- my $v = shift;
- my $HTML = ''.$v.'';
- MODES(
- TeX => "\\boldsymbol{$v}", # doesn't seem to work in TeX mode
-# TeX => "\\mathbf{$v}", # gives non-italic bold in TeX mode
- Latex2HTML => "\\boldsymbol{$v}",
- HTML => $HTML,
- HTML_tth => '\begin{rawhtml}'.$HTML.'\end{rawhtml}',
- HTML_dpng => "\\boldsymbol{$v}",
- );
-}
-
-#
-# The coordinate unit vectors
-#
-#if ($main::displayMode eq "TeX") {
- $i = BoldMath('i');
- $j = BoldMath('j');
- $k = BoldMath('k');
-#} else {
-# $i = Overline(MODES(TeX=>'\imath',HTML=>'i'));
-# $j = Overline(MODES(TeX=>'\jmath',HTML=>'j'));
-# $k = Overline('k');
-#}
-
-#
-# Grad sumbol
-#
-$GRAD = '\nabla ';
-
-#
-# Create a non-zero point with the given number of coordinates
-# with the given random range (which defaults to (-5,5,1)).
-#
-# non_zero_point(n,a,b,c)
-#
-sub non_zero_point {
- my $n = shift; my $k = $n; my @v = ();
- my $a = shift || -5; my $b = shift || $a + 10; my $c = shift || 1;
- while ($k--) {push(@v,random($a,$b,$c))}
- if (Norm(@v) == 0) {$v[random(0,$n-1,1)] = non_zero_random($a,$b,$c)}
- return Point(@v);
-}
-sub non_zero_point2D {non_zero_point(2,@_)}
-sub non_zero_point3D {non_zero_point(3,@_)}
-
-#
-# Same but for Vectors
-#
-sub non_zero_vector {Vector(non_zero_point(@_))}
-sub non_zero_vector2D {non_zero_vector(2,@_)}
-sub non_zero_vector3D {non_zero_vector(3,@_)}
-
-#
-# Form the string for a line given its point and vector
-#
-# Usage: line(P,V); or line(P,V,'t');
-#
-# where P is the point and V the direction vector for the line, and
-# t is the variable to use (default is 't').
-#
-# Ex: Line([1,-3],[2,1]) produces Vectir("1+2t","-3+t").
-# Ex: Line(Point(1,-3),Vector(2,1)) produces Vector("1+2t","-3+t").
-#
-sub Line {
- my @p = Point(shift)->value; my @v = Vector(shift)->value;
- my $t = shift; $t = 't' unless $t;
- my @coords = ();
- if ($#p != $#v) {die "Dimensions of point and vector don't match"}
- foreach my $i (0..$#p) {push(@coords,FPOLY("$p[$i]+$v[$i]$t",$t))}
- return Vector(@coords);
-}
-
-#
-# Creates a displayable string for a plane given its
-# normal vector and a point on the plane.
-#
-# Usage: plane(N,P);
-#
-sub Plane {
- my $N = Vector(shift); my $P = Point(shift); my @N = $N->value;
- FPOLY("$N[0] x + $N[1] y + $N[2] z = ".vDot($N,$P));
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/piecewiseFunctions.pl b/OpenProblemLibrary/macros/Union/piecewiseFunctions.pl
deleted file mode 100755
index 3a903640d0..0000000000
--- a/OpenProblemLibrary/macros/Union/piecewiseFunctions.pl
+++ /dev/null
@@ -1,97 +0,0 @@
-#! /usr/local/bin/perl
-
-sub _piecewiseFunctions_init {}; # don't reload this file
-
-#
-# Implements a method of producing piecewise-defined functions that
-# works in all modes (TeX, Latex2HTML and HTML).
-#
-
-##################################################
-#
-# piecewiseFunction(name, [part1, part1-x, ...], options)
-#
-# Here, "name" is a string like "f(x)" that is the name of the
-# function,
-#
-# "part1" is the function's definition for piece one, e.g. "x+4".
-# (It is put in math mode automatically.)
-#
-# "part1-x" is the function's domain description, e.g., "if \(x $LTS 3\)".
-# (It is NOT in math mode automatically.)
-#
-# You can supply as many partN,partN-x pairs as needed.
-#
-# The options are:
-#
-# bracesize => n specifies height of braces for HTML modes
-# spacing => n gives row spacing for HTML
-#
-sub piecewiseFunction {
- my $f = shift;
- my $arrayref = shift; my @array = @{$arrayref};
- my %options = @_;
- set_default_options(\%options, bracesize => 0, spacing => 5);
- my ($size,$sep) = ($options{bracesize},$options{spacing});
- my ($output,$fx,$ifx) = ('','','');
-
- if ($displayMode eq 'HTML' || $displayMode eq 'HTML_tth') {
- #
- # A
hack to handle piecewise functions in HTML
- #
- $output =
- '
";
- } elsif ($displayMode =~ m/^HTML/ ||
- $displayMode eq "Latex2HTML" || $displayMode eq "TeX") {
- $output = '\[' . $f . '= \begin{cases}';
- while (@array) {
- $fx = shift(@array); $ifx = shift(@array);
- $ifx =~ s/\\\(/\}/g; $ifx =~ s/\\\)/\\text\{/g;
- $output .= $fx . '&\text{' . $ifx . '}\\\\' . "\n";
- }
- $output =~ s/\\text\{\}//g; $output =~ s/\\\\$//;
- $output .= '\end{cases}\]';
- } else {
- warn "piecewiseFunction: Unknown display mode: $displayMode"
- }
- return($output);
-}
-
-#
-# Characters that make up the brace in the symbol font
-#
-($brt,$brm,$brb,$brc) = ('','','','');
-
-#
-# Braces of different sizes (an alternative would be to
-# add $brc characters to extend the vertical parts).
-# If you want additional sizes, you can push more onto the end
-# of the array from within the .pg file, or add them here.
-#
-#
-@braceHTML = (
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb},
- qq{$brt $brm $brb}
-);
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unionImage.pl b/OpenProblemLibrary/macros/Union/unionImage.pl
deleted file mode 100755
index 54dbb63c4f..0000000000
--- a/OpenProblemLibrary/macros/Union/unionImage.pl
+++ /dev/null
@@ -1,88 +0,0 @@
-loadMacros("unionMacros.pl");
-
-sub _unionImage_init {}; # don't reload this file
-
-######################################################################
-#
-# A routine to make including images easier to control
-#
-# Usage: Image(name,options)
-#
-# where name is the name of an image file or a reference to a
-# graphics object (or a reference to a pair of one of these),
-# and options are taken from among the following:
-#
-# size => [w,h] the size of the image in the HTML page
-# (default is [150,150])
-#
-# tex_size => r the size to use in TeX mode (as a percentage
-# of the line width times 10). E.g., 500 is
-# half the width, etc. (default is 200.)
-#
-# link => 0 or 1 whether to include a link to the original
-# image (default is 0, unless there are
-# two images given)
-#
-# border => 0 or 1 size of image border in HTML mode
-# (defaults to 2 or 1 depending on whether
-# there is a link or not)
-#
-# align => placement vertical alignment for image in HTML mode
-# (default is "BOTTOM")
-#
-# tex_center => 0 or 1 whether to center the image horizontally
-# in TeX mode (default is 0)
-#
-# The image name can be one of a number of different things. It can be
-# the name of an image file, or an alias to one produce by the alias()
-# command. It can be a graphics object reference created by init_graph().
-# Or it can be a pair of these (in square brackets). The first is the
-# image for the HTML file, and the second is the image that it will be
-# linked to.
-#
-# Examples: Image("graph.gif", size => [200,200]);
-# Image(["graph.gif","graph-large.gif"]);
-#
-# The alias() and insertGraph() functions will be called automatically
-# when needed.
-#
-sub Image {
- my $image = shift; my $ilink;
- return unless defined $image;
- my %options = (
- size => [150,150], tex_size => 200,
- link => 0, align => "BOTTOM", tex_center => 0, @_);
- my ($w,$h) = @{$options{size}};
- my ($ratio,$link) = ($options{tex_size}*(.001),$options{link});
- my ($border,$align) = ($options{border},$options{align});
- my ($tcenter) = $options{tex_center};
- my $HTML; my $TeX;
- ($image,$ilink) = @{$image} if (ref($image) eq "ARRAY");
- $ilink = $ilink//'';
- $image = alias(insertGraph($image)) if (ref($image) eq "WWPlot");
- $image = alias($image) unless ($image =~ m!^(/|https?:)!i); # see note
- if ($ilink) {
- $ilink = alias(insertGraph($ilink)) if (ref($ilink) eq "WWPlot");
- $ilink = alias($ilink) unless ($ilink =~ m!^(/|https?:)!i); # see note
- } else {$ilink = $image}
- #
- # Note: These cases were added to handle the examples where the
- # $image tag has a full url -- in practice this arises when using lighttpd
- # to server images from a different port
- # e.g. http://hosted2.webwork.rochester.edu:8000/webwork2_course_files/....
- # A smarter implementation of alias might make this check unnecessary
- #
- $border = (($link || $ilink ne $image)? 2: 1) unless defined($border);
- $HTML = '';
- $HTML = ''.$HTML.'' if $link or $ilink ne $image;
- $TeX = '\includegraphics[width='.$ratio.'\linewidth]{'.$image.'}';
- $TeX = '\centerline{'.$TeX.'}' if $tcenter;
- MODES(
- TeX => $TeX."\n",
- Latex2HTML => $bHTML.$HTML.$eHTML,
- HTML => $HTML
- );
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unionInclude.pl b/OpenProblemLibrary/macros/Union/unionInclude.pl
deleted file mode 100755
index 2ed83f0779..0000000000
--- a/OpenProblemLibrary/macros/Union/unionInclude.pl
+++ /dev/null
@@ -1,93 +0,0 @@
-######################################################################
-#
-# Routines to make it easier to include additional PG files within
-# a given one. These files don't have to be in the courseScripts
-# directory; rather, they are assumed to be relative to the directory
-# containing the calling PG file.
-#
-
-sub _unionInclude_init {}; # don't reload this file
-
-######################################################################
-#
-# Usage: includePGfile(name)
-#
-# where name is the name of a PG file (relative to the directory
-# of the file containing this call).
-#
-sub includePGfile {
- my $name = shift;
- my $PGfile = $main::envir{'fileName'};
- $PGfile =~ s![^/]+$!!; $PGfile .= $name;
- while ($PGfile =~ s![^/]*/../!!) {}
- $PGfile =~ s!^tmpEdit/!!;
-# warn("file is $PGfile, directory is $main::templateDirectory");
- my $problem = read_whole_problem_file($main::templateDirectory.$PGfile);
-
- my ($oldpname,$oldname) =
- ($main::envir{'probFileName'},$main::envir{'fileName'});
- $main::envir{'probFileName'} = $PGfile;
- $main::envir{'fileName'} = $PGfile;
- includePGtext($problem,%main::envir);
- ($main::envir{'probFileName'},$main::envir{'fileName'}) =
- ($oldpname,$oldname);
-}
-
-######################################################################
-#
-#
-# Usage: includeRandomProblem(file1,file2,...,fileN);
-#
-# where the fileNs are the names of the files from which
-# to choose (relative to the directory of the file containing
-# this call).
-#
-# To use this, make one PG file that include the call to this
-# random routine, and then include it the set definition file
-# as many times as you want (up to N times). A different problem
-# will be included for each instance in the set definition file.
-#
-sub includeRandomProblem {
- my @flist = @_;
- my @shuffle = _NchooseK(scalar(@flist),scalar(@flist));
- my $start = $initialProblemNumber; $start = 1 unless defined $start;
- WARN_MESSAGE("There is an error in initializing this random problem. initialProblemNumber $start is greater than the current problem number $probNum")
- if $probNum-$start < 0 ;
- my $n = (@shuffle)[$probNum-$start];
- includePGfile($flist[$n]);
- #$main::problemPostamble->{HTML} = ""; # Hack to prevent ENDDOCUMENT from adding it again
- # commenting this out is another hack which prevents nesting on quizzes -- go figure
-}
-
-#
-# Legacy code no longer needed. The included file can contain
-# BEGIN_INCLUSION(); and END_INCLUSION(); in place of DOCUMENT()
-# and ENDDOCUMENT(); calls.
-#
-sub BEGIN_INCLUSION {}
-sub END_INCLUSION {}
-
-######################################################################
-#
-# This is a service routine for includeRandomProblem() above.
-# It an array of k numbers chosen from 0 to n-1, but preserves the
-# random seed so that the included problem won't be affected by
-# this function, and replaces it by the psvn, so that the list
-# produced will be the same each time it is called.
-#
-sub _NchooseK {
- my ($n,$k)=@_;
- my @array = 0..($n-1);
- my @out = ();
- my $seed = ($main::psvn || 23)*101 + ($initialProblemNumber || 1);
- my $oldseed = $main::PG_random_generator->{seed};
- $main::PG_random_generator->srand($seed);
- while (@out<$k) {
- push(@out,
- splice(@array,$main::PG_random_generator->random(0,$#array,1),1));
- }
- $main::PG_random_generator->srand($oldseed);
- return @out;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unionMacros.pl b/OpenProblemLibrary/macros/Union/unionMacros.pl
deleted file mode 100755
index 9bdf44a38b..0000000000
--- a/OpenProblemLibrary/macros/Union/unionMacros.pl
+++ /dev/null
@@ -1,162 +0,0 @@
-######################################################################
-#
-# Some macros that add to the ones like $PAR, $BR, etc.
-#
-
-sub _unionMacros_init {}; # don't reload this file
-
-#
-# Shorthand for WeBWorK
-#
-$WW = "WeBWorK";
-
-#
-# Shorthands for entering and leaving rawhtml mode in
-# LaTeX2HTML (since they are so commonly used).
-#
-$bHTML = '\begin{rawhtml}';
-$eHTML = '\end{rawhtml}';
-
-
-#
-# HTML(htmlcode)
-# HTML(htmlcode,texcode)
-#
-# Insert $html in HTML mode or \begin{rawhtml}$html\end{rawhtml} in
-# Latex2HTML mode. In TeX mode, insert nothing for the first form, and
-# $tex for the second form.
-#
-sub HTML {
- my ($html,$tex) = @_;
- return('') unless (defined($html) && $html ne '');
- $tex = '' unless (defined($tex));
- MODES(TeX => $tex, Latex2HTML => $bHTML.$html.$eHTML, HTML => $html);
-}
-
-
-#
-# Begin and end indented text
-#
-
-$BBLOCKQUOTE = HTML('
','\par\bgroup\advance\leftskip by 2em ');
-$EBLOCKQUOTE = HTML('
','\end{center}');
-
-
-#
-# Begin and end mode
-#
-$BTT = HTML('','\texttt{');
-$ETT = HTML('','}');
-
-#
-# Begin and end mode
-#
-$BSMALL = HTML('','{\small ');
-$ESMALL = HTML('','}');
-
-#
-# Remove extra space in bold in latex2html mode
-#
-$BBOLD = HTML('','{\bf ');
-$EBOLD = HTML('','}');
-
-#
-# tth doesn't seem to understand \colon
-#
-$COLON = MODES(TeX=>'\colon ',HTML=>':', HTML_dpng => '\colon ');
-
-#
-# Alternatives to the standard WW versions of these
-#
-$LT = $LTS;
-$GT = $GTS;
-
-$LE = $LTE;
-$GE = $GTE;
-
-#
-# Common math sets
-#
-$R = MODES(TeX => '{\bf R}', HTML_tth => '{\bf R}', HTML => 'R');
-$Z = MODES(TeX => '{\bf Z}', HTML_tth => '{\bf Z}', HTML => 'Z');
-$N = MODES(TeX => '{\bf N}', HTML_tth => '{\bf N}', HTML => 'N');
-$Q = MODES(TeX => '{\bf Q}', HTML_tth => '{\bf Q}', HTML => 'Q');
-$C = MODES(TeX => '{\bf C}', HTML_tth => '{\bf C}', HTML => 'C');
-
-#
-# Superscripts and subscript (mostly for if you want answer
-# rules in these positions).
-#
-$BSUP = HTML('','$^{');
-$ESUP = HTML('','}$');
-
-$BSUB = HTML('','$_{');
-$ESUB = HTML('','}$');
-
-#
-# Browser-only BR
-#
-$BBR = HTML(' ');
-
-#
-# Broser-only \displaystyle
-#
-$DISPLAY = MODES(TeX => '', Latex2HTML => '\displaystyle ',
- HTML_tth => '\displaystyle ', HTML => '');
-
-#
-# Provides a title to the problem
-#
-sub Title {
- my $title = shift;
-
- TEXT(MODES(
- TeX => "\\par\\begin{centering}{\\bf $title}\\par\\end{centering}\\nobreak\n",
- Latex2HTML => $bHTML.'
'.$title.'
'.$eHTML,
- HTML => '
'.$title.'
'
- ));
-}
-
-
-#
-# A warning that we are using javaScript
-#
-sub JAVASCRIPT_PROBLEM {
- TEXT(HTML(
- ''
- ));
-}
-
-
-#
-# Modify a polynomial to remove coeficients of 1, -1 and 0
-# The polynomial can be a multivariable one. The parameters
-# following the formula itself are the names of the variables
-# for the formula. Any number can be provided, and the default
-# is x, y, and z. Variable names must be one character long,
-# and the formula really should be a polynomial, as the algorithm
-# for removing coefficients of 0 relies on that in an important way.
-#
-sub FPOLY {
- my $poly = shift; $poly = FEQ($poly);
- @_ = ('x','y','z') unless scalar(@_) > 0;
- my $x = '['.join('',@_).']';
- $poly =~ s/(^|[^\d.])1\s*(\*\s*)?($x)/$1$3/g;
- $poly =~ s/-1\s*($x)/-$1/g;
- $poly =~ s/(^|\+|\-)\s*0(\s*(\*\s*)?$x((\^|\*\*)\d+(\.\d*)?)?)+//g;
- $poly =~ s/(^|\+|\-)\s*0+\s*([-+]|$)/$2/;
- $poly =~ s/^\s*\+\s*//;
- $poly = "0" if ($poly eq "");
- return $poly;
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unionMessages.pl b/OpenProblemLibrary/macros/Union/unionMessages.pl
deleted file mode 100755
index c594b3423f..0000000000
--- a/OpenProblemLibrary/macros/Union/unionMessages.pl
+++ /dev/null
@@ -1,72 +0,0 @@
-sub _unionMessages_init {};
-
-loadMacros("unionMacros.pl");
-
-######################################################################
-#
-# How to say "infinity"
-#
-
-$INFINITY_WORD = $$Value::context->flag('infiniteWord') unless defined($INFINITY_WORD);
-
-######################################################################
-#
-# A message that can be included (within BEGIN_TEXT and END_TEXT)
-# to tell the student how to enter infinity and minus infinity.
-#
-$INFINITY_MESSAGE =
- $BITALIC.$BSMALL.
- "Use ${LQ}$INFINITY_WORD${RQ} for $LQ\\(\\infty\\)$RQ ".
- "and ${LQ}-$INFINITY_WORD${RQ} for $LQ\\(-\\infty\\)$RQ." .
- $ESMALL.$EITALIC;
-
-$INFINITY_MESSAGE = "" if $displayMode eq 'TeX';
-
-######################################################################
-#
-# A message to tell students how to enter "Does not exist".
-#
-$DNE_MESSAGE =
- $BITALIC.$BSMALL.
- "Use ${LQ}DNE${RQ} for ${LQ}Does not exist${RQ}.".
- $ESMALL.$EITALIC;
-
-$DNE_MESSAGE = "" if $displayMode eq 'TeX';
-
-######################################################################
-#
-# A message to tell students how to enter unions and infinities
-#
-$INFINITY_UNION_MESSAGE =
- "${BSMALL}${BBOLD}Note:${EBOLD} ".
- "If the answer includes more than one interval, write the intervals ".
- "separated by the ${LQ}union$RQ symbol, ${BITALIC}U${EITALIC}. If needed, enter ".
- "\\(\\infty\\) as ${BITALIC}$INFINITY_WORD${EITALIC} and \\(-\\infty\\) as ".
- "${BITALIC}-$INFINITY_WORD${EITALIC}.${ESMALL}";
-
-$INFINITY_UNION_MESSAGE = "" if $displayMode eq 'TeX';
-
-######################################################################
-#
-# A message to tell students how to enter lists of intervals
-#
-$INTERVAL_LIST_MESSAGE =
- $BSMALL.$BBOLD."Note:".$EBOLD.
- "Your answer should be a list of one or more intervals separated by commas. ".
- "Enter ${BITALIC}NONE${EITALIC} if there are no intervals.";
-
-$INTERVAL_LIST_MESSAGE = "" if $displayMode eq 'TeX';
-
-######################################################################
-#
-# A message for lists of unions
-#
-$UNION_LIST_MESSAGE =
- $BSMALL.$BBOLD."Note:".$EBOLD.
- "Your answer should be a list of one or more intervals or unions of intervals. ".
- "Separate the entries in your list by commas. ".
- "Enter ${BITALIC}NONE${EITALIC} if there are no intervals or unions.";
-
-$UNION_LIST_MESSAGE = "" if $displayMode eq 'TeX';
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unionProblem.pl b/OpenProblemLibrary/macros/Union/unionProblem.pl
deleted file mode 100755
index 08479d3fbd..0000000000
--- a/OpenProblemLibrary/macros/Union/unionProblem.pl
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/local/bin/perl
-
-sub _unionProblem_init {};
-
-##################################################
-#
-# No longer needed since WW can output the grey
-# box automatically by changes in global.conf
-#
-sub BEGIN_PROBLEM {}
-sub END_PROBLEM {}
-
-sub problem_NoTable {}
-
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unionUtils.pl b/OpenProblemLibrary/macros/Union/unionUtils.pl
deleted file mode 100755
index 6a8a93da67..0000000000
--- a/OpenProblemLibrary/macros/Union/unionUtils.pl
+++ /dev/null
@@ -1,131 +0,0 @@
-######################################################################
-##
-## These are some miscellaneous routines that may be useful.
-##
-
-sub _unionUtils_init {}; # don't reload this file
-
-#
-# Remove leading and trailing spaces
-#
-sub trimString {
- my $s = shift;
- $s =~ s/^\s+|\s+$//g;
- return $s;
-}
-
-#
-# Check if a string is a number
-#
-sub isNumber {
- my $n = shift;
- $n = ($n =~ m/^[+-]?(\d+(\.\d*)?|\.\d+)([Ee][-+]?\d+)?$/);
- return $n;
-}
-
-#
-# names for numbers
-#
-sub NameForNumber {
- my $n = shift;
- my $name = ('zeroth','first','second','third','fourth','fifth',
- 'sixth','seventh','eighth','ninth','tenth')[$n];
- $name = "$n-th" if ($n > 10);
- return $name;
-}
-
-
-#
-# A debugging routine that allows the "warn" function to print a variable that
-# contains HTML code properly
-#
-sub showHTML {
- my $string = shift;
- $string =~ s/&/\&/g;
- $string =~ s/\</g;
- $string =~ s/>/\>/g;
- $string;
-}
-
-#
-# Make a named subroutine that returns the value of a function. If
-# no parameters are passed to the function, the function's string
-# is returned. (This will be obsolete when I finish the
-# new expression parser -- DPVC.)
-#
-sub perlFunction {
- my $def = shift; my $debug = shift;
- if ($def !~ m/^\s*(\w+)\s*\(\s*((\w+\s*,?\s*)+)\s*\)\s*:?=\s*(.*)$/) {
- warn "perlFunction: can't parse '$def'";
- return
- }
- my ($name,$vars,$expr) = ($1,$2,$4);
- my $f = $expr;
- my @X; my $x; $vars =~ s/\s//g;
- foreach $x (split(',',$vars)) {
- push(@X,"\$$x");
- $expr =~ s/(\b|\d)$x\b/$1(\$$x)/g;
- }
- #
- # Fix up the expression
- #
- $expr =~ s/\bpi\b/(4*atan2(1,1))/g;
- $expr =~ s/\be\b/(exp(1))/g;
- $expr =~ s!\\frac\{([^\}]*)\}\s*\{([^\}]*)\}!($1)/($2)!g; # fractions
- $expr =~ s/\{([^\}]*)\}/($1)/g; # TeX parameters
- $expr =~ s/\\//g; # TeX slashes
- $expr =~ s/\^/**/g; # change ^ to **
- #
- # Do implied multiplication
- #
- $expr =~ s/\)\s*\(/\)*\(/g;
- $expr =~ s/\)\s*([a-zA-Z0-9.])/\)*$1/g;
- $expr =~ s/([\d.])(\s\d)/$1*$2/g;
- $expr =~ s/([\d.])\s*([a-zA-Z\(])/$1*$2/g;
- #
- # Fix +-, -+, ++ and --
- #
- $expr =~ s/\+\s*([\+-])/$1/g;
- $expr =~ s/-\s*\+/-/g; $expr =~ s/-\s*-/+/g;
- #
- # Create the named function
- #
- PG_restricted_eval("sub $name { return('$f') unless (\@_);
- my (".join(',',@X).") = \@_; $expr}");
- warn("sub $name { my (".join(',',@X).") = \@_; $expr}") if $debug;
-}
-
-#
-# A hack to pick display mode in HTML modes, but plain math mode
-# in TeX modes. This makes fractions appear better in HTML mode,
-# without making it worse in TeX modes. This is for use with
-# AlignedList objects.
-#
-sub DMATH {
- my $math = shift;
- #
- # HTML_tth puts an unwanted at the beginning,
- # and uses a centered table. So here we remove the
- # and re-align the table to the right.
- #
- if ($displayMode eq "HTML_tth") {
- $math = trimString(EV2('\['.$math.'\]'));
- $math =~ s! !!;
- $math =~ s!table align="center"!table align="right"!;
- $math =~ s!(table [^>]*) width="100%"!$1!;
- } elsif ($displayMode eq "HTML") {
- $math = '\('.$math.'\)'
- } elsif ($displayMode =~ m/^HTML/) {
- $math = '\(\displaystyle '.$math.'\)'
- }
-
- MODES(
- TeX => '\(\displaystyle '.$math.'\)',
- Latex2HTML => '\(\displaystyle '.$math.'\)',
- HTML => $math,
- HTML_tth => $math,
- HTML_dpng => $math,
- );
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/unorderedAnswer.pl b/OpenProblemLibrary/macros/Union/unorderedAnswer.pl
deleted file mode 100755
index d174b8f6fd..0000000000
--- a/OpenProblemLibrary/macros/Union/unorderedAnswer.pl
+++ /dev/null
@@ -1,163 +0,0 @@
-##########################################################################
-##########################################################################
-##
-## Routines for groups of answer blanks where the user can enter
-## answers in any order in the blanks.
-##
-
-loadMacros("answerUtils.pl");
-
-sub _unorderedAnswer_init {}; # don't reload this file
-
-##########################################################################
-#
-# Collect a group of answer checkers for use with answers that can be given
-# in any order. If N answer checkers are given, then the last N answer
-# rules will be used. It is beter to use named rules and UNORDERED_NAMED_ANS
-# below. Otherwise, be sure to use UNORDERED_ANS right after the answer
-# rules for the answers you want to compare.
-#
-# Format:
-#
-# UNORDERED_ANS(checker1, checker2, ...);
-#
-# Example:
-#
-# BEGIN_TEXT
-# The function \(f(x) = \frac{1}{x^2-$a}\) is defined except
-# for \(x =\) \{ans_rule(10)\} and \(x =\) \{ans_rule(10)\}.
-# END_TEXT
-#
-# UNORDERED_ANS(std_num_cmp(sqrt($a)), std_num_cmp(-sqrt($a)));
-#
-# (the student can enter the solutions in either order.)
-#
-sub UNORDERED_ANS {
- my @cmp = @_; my @params = (); my $i; my $n = scalar(@cmp);
- #
- # The best thing would be to use the size of @PG_ANSWERS in place of
- # $main::ans_rule_count, but we don't have access to that
- #
- my $num_of_answers = (keys %{$PG->{PG_ANSWERS_HASH}} );
- foreach $i (1..$n)
- {push(@params,ANS_NUM_TO_NAME($i+$num_of_answers -$n),$cmp[$i-1])}
- my @results = unordered_answer_list(@params);
- while (scalar(@results) > 0) {shift(@results), ANS(shift(@results))}
-}
-
-##########################################################################
-#
-# Collect a group of answer checkers for use with named answers that
-# can be given in any order.
-#
-# Format:
-#
-# UNORDERED_NAMED_ANS(name1 => checker1, name2 => checker2, ...);
-#
-# Example:
-#
-# BEGIN_TEXT
-# The function \(f(x) = \frac{1}{x^2-$a}\) is defined except
-# for \(x =\) \{NAMED_ANS_RULE(A1,10)\}
-# and \(x =\) \{NAMED_ANS_RULE(A2,10)\}.
-# END_TEXT
-#
-# UNORDERED_NAMED_ANS(
-# A1 => std_num_cmp(sqrt($a)),
-# A2 => std_num_cmp(-sqrt($a))
-# );
-#
-# (the student can enter the solutions in either blank.)
-#
-sub UNORDERED_NAMED_ANS {
- NAMED_ANS(unordered_answer_list(@_));
-}
-
-##########################################################################
-#
-# Low-level routine for handling unordered collections of answer checkers
-#
-sub unordered_answer_list {
- my %params = @_; my @args = @_;
- my (@cmp,@ids);
- while (scalar(@_) > 0) {push(@ids,shift); push(@cmp,shift)}
- #
- # Setup
- #
- my ($i,$j,$k);
- my $n = scalar(@cmp);
- my @cmpi = (0..$n-1);
- my @skipped = ();
- #
- # Check that the answers exist (otherwise it's our first time through)
- #
- foreach $i (@ids) {return(@args) if (!defined($inputs_ref->{$i}))}
- #
- # Check each answer against the available answer checkers.
- # Keep track of the ones that match and that don't.
- #
- ANSWER: foreach $i (0..$n-1) {
- $k = 0;
- foreach $j (@cmpi) {
- if (isCorrectAnswer($cmp[$j],$inputs_ref->{$ids[$i]}))
- {$ans[$i] = $j; splice(@cmpi,$k,1); next ANSWER}
- $k++;
- }
- push(@skipped,$i);
- }
- #
- # Check if the unmatched checkers are all blank checkers.
- # If so, let them report blanks as correct answers.
- #
- my $blankOK = 1;
- foreach $i (@cmpi) {
- if (ref($cmp[$i]) ne "AnswerEvaluator" ||
- ($cmp[$i]->rh_ans)->{type} ne "blank") {$blankOK = 0; last}
- }
- if ($blankOK) {foreach $i (@cmpi) {($cmp[$i]->rh_ans)->{blankOK} = 1}}
- #
- # Assign the unmatching answers to umatched checkers
- #
- foreach $i (0..scalar(@skipped)-1) {$ans[$skipped[$i]] = $cmpi[$i]}
- #
- # Make the final list of answer checkers in their proper order
- #
- my (@list) = ();
- foreach $i (0..$n-1)
- {clearEvaluator($cmp[$ans[$i]]); push(@list,$ids[$i],$cmp[$ans[$i]])}
- return (@list);
-}
-
-##################################################
-#
-# AnswerChecker that allows a blank answer in a collection of unordered
-# answer checkers. It will return "correct" for a blank answer only if
-# all the other answers are correct. (The blankOK value is set by
-# unordered_answer_list when this is true.) This lets you ask a question
-# where the number of answers is not known (by the student) ahead of time.
-#
-sub blank_cmp {
- my %params = @_;
- $params{debug} = 0 unless defined($params{debug});
- my $answerEvaluator = new AnswerEvaluator;
- $answerEvaluator->{debug} = $params{debug};
- $answerEvaluator->ans_hash(
- type => "blank", blankOK => 0,
- correct_ans => '', weight => 0
- );
- $answerEvaluator->install_pre_filter('reset'); # remove the blank filter
- $answerEvaluator->install_evaluator(\&blank_cmp_check,%params);
- $answerEvaluator->install_post_filter('reset'); # remove the blank filter
- return $answerEvaluator;
-}
-
-sub blank_cmp_check {
- my $ans = shift;
- my %params = @_;
- $ans->{student_ans} = trimString($ans->{student_ans});
- if ($ans->{student_ans} eq "") {$ans->score($ans->{blankOK})}
- else {$ans->score(0)}
- return($ans);
-}
-
-1;
diff --git a/OpenProblemLibrary/macros/Union/weightedGrader.pl b/OpenProblemLibrary/macros/Union/weightedGrader.pl
deleted file mode 100755
index e294444051..0000000000
--- a/OpenProblemLibrary/macros/Union/weightedGrader.pl
+++ /dev/null
@@ -1,331 +0,0 @@
-loadMacros('unionUtils.pl');
-
-sub _weightedGrader_init {}; # don't reload this file
-
-######################################################################
-#
-# A weighted grader that allows you to assign arbitrary percentages
-# to the various answers in a problem. It also allows you to indicate
-# that answering one part correctly will give you credit for some
-# other part(s). This way, if there are several parts leading up to
-# a "goal" answer, and the student produces the goal answer by
-# some other means, he can be given full credit for the problem anyway.
-#
-#
-# WEIGHTED ANSWERS:
-#
-# Each problem is assigned a weight (the default is 1). The
-# student's score is then the sum of the weights for his correct
-# answers divided by the total of the weights for all answers. (To
-# assign weights as percentages, use integers that add up to 100, eg,
-# use 40 and 60 for the weights for two answers.)
-#
-# There are two ways to assign weights. The first is to use the
-# WEIGHTED_ANS() routine (in place of ANS) to give an answer checker
-# plus a weight.
-#
-# Example:
-#
-# WEIGHTED_ANS(std_num_cmp($ans1),2);
-#
-# This assigns a weight of 2 to the corresponding numeric answer.
-#
-# As with ANS(), WEIGHTED_ANS() can take more than one answer checker and
-# weight.
-#
-# Example:
-#
-# WEIGHTED_ANS(
-# std_num_cmp($ans1), 40,
-# std_num_cmp($ans2), 60
-# );
-#
-# This assigns 40% to the first answer and 60% to the second answer.
-#
-# The second way of assigning a weight is through the weight_ans()
-# function. This takes a single answer checker and weight and returns
-# a new answer checker of the same type that has the desired weight.
-# Thus
-#
-# ANS(weight_ans(std_num_cmp($ans1),2));
-#
-# is equivalent to the first example above.
-#
-# The main purpose for weighted_ans() is so that weights can be used
-# with UNORDERED_ANS(), or in other places where you want to use the
-# weighted answer checker directly. For example:
-#
-# UNORDERED_ANS(
-# weight_ans(std_num_cmp($ans1),40),
-# weight_ans(std_num_cmp($ans2),60),
-# );
-#
-# produces two answers whose order doesn't matter, but the student
-# will get 40% for getting $ans1 and 60% for getting $ans2 (no matter
-# what order they appear in).
-#
-# Note that the blank_cmp() answer checker has a weight of 0 by
-# default. You can override this using weight_ans(); for example,
-# weight_ans(blank_cmp(),1) makes the blank count the same as all
-# the other answers. (If there are two or more non-blank answers,
-# then having the blanks with weight 0 will allow the observant
-# student to deduce the number of blank answers from the percentage
-# for a single correct answer, provided all the non-blank answers are
-# equally weighted).
-#
-# Once you have given weights to the answers, you also need to
-# install the weighted grader. Do this using the command
-#
-# install_weighted_grader();
-#
-#
-# HAVING ONE ANSWER PROVIDE CREDIT FOR ANOTHER:
-#
-# You may want to have a correct answer for one problem automatically
-# give credit for one or more other parts of the problem. For example
-# If several parts are used to lead up to the "real" answer to the
-# problem, and the student produces that final answer without doing
-# the intermediate parts (perhaps using some other method), then you
-# may want to give the student full credit for the problem anyway.
-# You can do so in the following way.
-#
-# First, let us call the final answer the "goal" answer, and the
-# answer that it would give automatic credit for the "optional" answer.
-#
-# The optional answer blank must be a named answer, e.g.,
-#
-# BEGIN_TEXT
-# You get credit for this answer: \{NAMED_ANS_RULE('optional',10)\}
-# When you answer this one: \{ans_rule(10)\}
-# END_TEXT
-# NAMED_ANS('optional',std_num_cmp(5));
-#
-# Then for the goal answer, in place of ANS, use CREDIT_ANS, listing the
-# optional answer as the second argument:
-#
-# CREDIT_ANS(std_num_cmp(10),'optional');
-#
-# You could also use NAMED_WEIGHTED_ANS for the optional answer, and
-# supply a third argument for CREDIT_ANS, which is the weight for the
-# goal answer. For example:
-#
-# NAMED_WEIGHTED_ANS('optional',std_num_cmp(5),20);
-# CREDIT_ANS(std_num_cmp(10),'optional',80);
-#
-# This way, if the student gets the optional part right (but not the
-# goal), he gets 20%, and if he gets the goal right, he gets 100%.
-#
-# One can use CREDIT_ANS to give credit for several other (named)
-# answers at once by passing a list of names rather than a single one,
-# as in:
-#
-# CREDIT_ANS(std_num_cmp(10),['optional1','optional2'],80);
-#
-# The weight_ans() routine, described in the section above, also can
-# be used to give credit to another answer. In addition to the
-# answer-checker and the weight, you can pass an answer name (or
-# list of names) that should get credit when this one is right.
-# For example
-#
-# ANS(weight_ans(std_num_cmp(10),80,'optional'));
-#
-# is equivalent to
-#
-# CREDIT_ANS(std_num_cmp(10),'optional',80);
-#
-# One caveat to keep in mind is that credit is given to the optional
-# answer ONLY if the answer is left blank (or is actually correct).
-# Credit will NOT be given if the answer is incorrect, even if the
-# goal answer IS correct.
-#
-# When credit IS given, the blank answer is still marked as incorrect
-# in the grey answer report at the top of the page, but the student
-# gets awarded the points for that answer anyway (with no other
-# indication). It is possible to cause the blank to be marked as
-# correct, but this seemed confusing to the students.
-#
-# Once you have issued the various ANS calls, you also need to
-# install the weighted grader. Do this using the command
-#
-# install_weighted_grader();
-#
-
-##################################################
-#
-# Issue ANS() calls for the weighted checkers
-#
-sub WEIGHTED_ANS {
- my ($checker,$weight);
- while (@_) {
- $checker = shift; $weight = shift;
- ANS(weight_ans($checker,$weight));
- }
-}
-
-##################################################
-#
-# Issue NAMED_ANS() calls for the weighted checkers
-#
-sub NAMED_WEIGHTED_ANS {
- my ($name,$checker,$weight);
- while (@_) {
- $name = shift; $checker = shift; $weight = shift;
- NAMED_ANS($name,weight_ans($checker,$weight));
- }
-}
-
-##################################################
-#
-# Issue an ANS() call for the checker, giving
-# credit to the given answers.
-#
-sub CREDIT_ANS {
- my $checker = shift;
- my $credit = shift;
- $credit = [$credit] if defined($credit) && ref($credit) ne "ARRAY";
- my $weight = shift;
- ANS(weight_ans($checker,$weight,$credit));
-}
-
-
-##################################################
-#
-# Either add a weight to an AnswerEvaluator, or return a
-# new checker that adds the weight to its result. Also,
-# add the "credit" field, if supplied.
-#
-sub weight_ans {
- my $checker = shift; my $weight = shift;
- my $credit = shift;
- $credit = [$credit] if defined($credit) && ref($credit) ne "ARRAY";
- if (ref($checker) eq "AnswerEvaluator") {
- $checker->{rh_ans}->{weight} = $weight;
- $checker->{rh_ans}->{credit} = $credit if defined($credit);
- return $checker;
- } else {
- my $newChecker = sub {
- my $hash = &{$checker}(@_);
- $hash->{weight} = $weight;
- $checker->{rh_ans}->{credit} = $credit if defined($credit);
- return $hash;
- };
- return $newChecker;
- }
-}
-
-
-##################################################
-#
-# This is the weighted grader. It uses an extra field added to the
-# AnswerHash (named "weight") to tell how much weight to give each
-# problem. The grader adds up the total weights for the correct
-# answers. For partially correct ones, it uses the score for that
-# answer to give a portion of that weight. For example, if the
-# weight is 40 and the score for the answer is .5, then 20 is added
-# to the total for the problem. (Note that most answer checkers only
-# return 1 or 0, but they are allowed to return partial credit as
-# well.)
-#
-# When the student's total is computed, it is divided by the sum of
-# all the weights in order to determine the final score.
-#
-# It also uses a special field called "credit" that determines
-# what other (named) answers are given full credit if the given
-# answer is correct. This can be used to make "optional" answers,
-# where getting the "final" answer right gives credit for the other parts.
-#
-
-sub weighted_grader {
- my $rh_evaluated_answers = shift;
- my $rh_problem_state = shift;
- my %form_options = @_;
- my %answers = %{$rh_evaluated_answers};
- my %problem_state = %{$rh_problem_state};
-
- my %problem_result = (
- score => 0,
- errors => '',
- type => 'weighted_grader',
- msg => '',
- );
-
- if (scalar(keys(%answers)) == 0) {
- $problem_result{msg} = "This problem did not ask any questions.";
- return(\%problem_result,\%problem_state);
- }
-
- return(\%problem_result,\%problem_state)
- if (!$form_options{answers_submitted});
-
- my ($score,$total) = (0,0);
- my ($weight,$ans_name,$credit_name);
- my (%credit);
-
- #
- # Get the score for each answer
- # (error if can't recognize the answer format).
- #
- foreach $ans_name (keys %answers) {
- if (ref($answers{$ans_name}) =~ m/^(HASH|AnswerHash)$/) {
- $credit{$ans_name} = $answers{$ans_name}->{score};
- } else {
- die "Error at file ",__FILE__,"line ", __LINE__,": Answer |$ans_name| " .
- "is not a hash reference\n" . $answers{$ans_name} .
- "\nThis probably means that the answer evaluator for ".
- "this answer is not working correctly.";
- $problem_result{error} =
- "Error: Answer $ans_name is not a hash: $answers{$ans_name}";
- }
- }
-
- #
- # Mark any optional answers as correct, if the goal answers
- # are right and the optional ones are blank.
- #
- foreach $ans_name (keys %answers) {
- if ($credit{$ans_name} == 1 &&
- defined($answers{$ans_name}->{credit})) {
- foreach $credit_name (@{$answers{$ans_name}->{credit}}) {
- $credit{$credit_name} = 1
- if (trimString($answers{$credit_name}->{student_ans}) eq "");
- }
- }
- }
-
- #
- # Add up the weighted scores
- #
- foreach $ans_name (keys %answers) {
- $weight = $answers{$ans_name}->{weight};
- $weight = 1 unless (defined($weight));
- $total += $weight;
- $score += $weight * $credit{$ans_name};
- }
-
- $problem_result{score} = $score/$total if $total;
-
- # This gets rid of non-numeric scores
- $problem_state{recorded_score} = 0
- unless (defined($problem_state{recorded_score}) &&
- isNumber($problem_state{recorded_score}));
-
- $problem_state{recorded_score} = $problem_result{score}
- if ($problem_result{score} > $problem_state{recorded_score});
-
- $problem_state{num_of_correct_ans}++ if ($score == $total);
- $problem_state{num_of_incorrect_ans}++ if ($score < $total);
- warn "Error in grading this problem: ".
- "the score is larger than the total ($score > $total)"
- if $score > $total;
-
- (\%problem_result, \%problem_state);
-}
-
-
-##################################################
-#
-# Syntactic sugar to avoid ugly ~~& construct in PG.
-#
-sub install_weighted_grader {install_problem_grader(\&weighted_grader)}
-
-1;
diff --git a/OpenProblemLibrary/macros/WHFreeman/freemanMacros.pl b/OpenProblemLibrary/macros/WHFreeman/freemanMacros.pl
deleted file mode 100755
index 9cd1443b1d..0000000000
--- a/OpenProblemLibrary/macros/WHFreeman/freemanMacros.pl
+++ /dev/null
@@ -1,540 +0,0 @@
-sub textbook_ref {
- my ($text, $sec, $ex) = @_;
-return "";
- return "$text section $sec, exercise $ex";
-}
-
-sub textbook_ref_corr {
-return "";
- return "Similar to " . textbook_ref(@_) . ".";
-}
-
-sub textbook_ref_exact {
-return "";
- return "From " . textbook_ref(@_) . ".";
-}
-
-sub list_random_multi_uniq($@) {
- my ($n, @list) = @_;
- my @result;
- while (@result < $n) {
- my $i = random(0,$#list,1);
- if ($i==0) {
- push @result, shift @list;
- } elsif ($i==$#list) {
- push @result, pop @list;
- } else {
- push @result, $list[$i];
- $list[$i] = pop @list;
- }
- }
- return @result;
-}
-
-sub IINT {
- return '\int\!\!\int';
-}
-
-sub IIINT {
- return '\int\!\!\int\!\!\int';
-}
-
-$IINT = IINT();
-$IIINT = IIINT();
-
-sub VUSAGE {
- return $BBOLD . ' Usage: ' . $EBOLD . 'To enter a vector, for example \(\langle x,y,z\rangle\), type '.$LQ . '\('. $LTS .'\) x, y, z \(' . $GTS . '\)' . $RQ;
-}
-
-$VUSAGE = VUSAGE();
-
-sub PUSAGE {
- return $BBOLD . ' Usage: ' . $EBOLD . 'To enter a point, for example \( (x,y,z) \), type "(x, y, z)".';
-}
-
-$PUSAGE = PUSAGE();
-
-#sam# copied from bkellMacros.pl -- no reason to maintain two macro files.
-#sam# FIXME -- these should probably lose their "bkell_" prefixes.
-
-# bkellMacros.pl
-# Brian Kell
-# Last updated 3:24 CDT, 24 Jun 2007
-
-###############################################################################
-# bkell_linear_simplify($a, $b)
-#
-# Returns a string representing $a*x+$b in simplified form, where "simplified"
-# means something along the lines of the following:
-#
-# a b output
-# --- --- ------
-# 0 0 0
-# 1 1 x+1
-# -1 -1 -x-1
-# -1 5 5-x
-# 2 0 2x
-# -4 3 3-4x
-# -4 -3 -4x-3
-#
-sub bkell_linear_simplify
-{
- my ($a, $b) = @_;
-
- if ($a == 0) {
- return "$b";
- } elsif ($b == 0) {
- if ($a == -1) {
- return "-x";
- } elsif ($a == 1) {
- return "x";
- } else {
- return "${a}x";
- }
- } elsif ($a < 0 && $b > 0) {
- if ($a == -1) {
- return "$b-x";
- } else {
- return "$b-".(abs $a)."x";
- }
- } elsif ($a == 1) {
- return "x".sprintf("%+d", $b);
- } elsif ($a == -1) {
- return "-x".sprintf("%+d", $b);
- } else {
- return "${a}x".sprintf("%+d", $b);
- }
-}
-
-###############################################################################
-# bkell_simplify_fraction($num, $denom)
-#
-# Simplifies the fraction $num/$denom; returns the list ($num, $denom).
-#
-sub bkell_simplify_fraction
-{
- my ($num, $denom) = @_;
-
- if ($num == 0) { return (0, 1); }
-
- my $sign = +1;
- if ($num < 0) { $sign *= -1; $num *= -1; }
- if ($denom < 0) { $sign *= -1; $denom *= -1; }
-
- for ($i = 2; $i <= $num && $i <= $denom; ++$i) {
- while ($num % $i == 0 && $denom % $i == 0) {
- $num /= $i;
- $denom /= $i;
- }
- }
-
- return ($sign*$num, $denom);
-}
-
-###############################################################################
-# bkell_simplify_fraction_string($num, $denom [, $flags])
-#
-# Returns a string like "$num/$denom" in simplified form. If the string $flags
-# contains "+", then a leading "+" is included if the fraction is non-negative.
-# If $flags contains "0", then a fraction with a value of 0 will cause the
-# empty string to be returned. If $flags contains "1", then a fraction with a
-# value of 1 or -1 will cause only the sign to be returned (or the empty
-# string, if the fraction is non-negative and $flags does not contain "+"). If
-# $flags contains "(", then parentheses will be placed around "$num/$denom"
-# (the sign, if it exists, will be outside the parentheses); if $flags contains
-# "[", then parentheses will be used only if a sign is used and the denominator
-# is other than 1. A flag of "(" overrides "]". If $flags contains "f", then
-# the string returned will be in the form "{$num \over $denom}" instead of the
-# normal slashed version.
-#
-sub bkell_simplify_fraction_string
-{
- my ($num, $denom, $flags) = @_;
- if (!defined $flags) { $flags = ""; }
-
- ($num, $denom) = bkell_simplify_fraction($num, $denom);
-
- my $sign = ($num >= 0 ? ($flags =~ /\+/ ? "+" : "") : "-");
- $num = abs $num;
-
- my ($pre, $post);
- if ($flags =~ /\(/ || ($flags =~ /\[/ && $sign ne "" && $denom != 1)) {
- ($pre, $post) = ("(", ")");
- } else {
- ($pre, $post) = ("", "");
- }
-
- if ($num == 0 && $flags =~ /0/) { return ""; }
- if ($denom == 1) {
- if ($num == 1 && $flags =~ /1/) { return "$sign"; }
- return "$sign$pre$num$post";
- }
- if ($flags =~ /f/) { return "$sign$pre {$num \\over $denom}$post"; }
- return "$sign$pre$num/$denom$post";
-}
-
-###############################################################################
-# bkell_poly_term($coeff_num, $coeff_denom, $var [, "+"])
-#
-# Produces and simplifies a term of a polynomial of the general form
-# "($coeff_num/$coeff_denom)$var". Handles special cases (such as $num==0,
-# $denom==1, etc.). If the fourth argument is "+", then a leading "+" is
-# included if the term is positive.
-#
-sub bkell_poly_term
-{
- my ($coeff_num, $coeff_denom, $var, $plus) = @_;
- if (!defined $plus) { $plus = ""; }
-
- if ($coeff_num == 0) { return ""; }
-
- my $sign = +1;
- if ($coeff_num < 0) { $sign *= -1; $coeff_num *= -1; }
- if ($coeff_denom < 0) { $sign *= -1; $coeff_denom *= -1; }
- $sign = ($sign > 0 ? ($plus eq "+" ? "+" : "") : "-");
-
- my ($num, $denom) = bkell_simplify_fraction($coeff_num, $coeff_denom);
-
- if ($denom == 1) {
- if ($num == 1) {
- return "$sign$var";
- } else {
- return "$sign$num$var";
- }
- }
-
- return "$sign($num/$denom)$var";
-}
-
-###############################################################################
-# bkell_gcd($x, $y)
-#
-# Returns the greatest common divisor of $x and $y.
-#
-sub bkell_gcd {
- my ($x, $y) = @_;
- $x = abs $x;
- $y = abs $y;
- if ($x > $y) { ($x, $y) = ($y, $x); }
- if ($x == 0) { return $y; }
- my $r = $y % $x;
- if ($r == 0) { return $x; }
- return bkell_gcd($x, $r);
-}
-
-###############################################################################
-# bkell_poly_eval($x, $a_n, ..., $a_0)
-#
-# Evaluates the polynomial a_n*x^n + ... + a_1*x + a_0 at the given value of x.
-#
-sub bkell_poly_eval
-{
- my $x = shift;
- my $value = shift;
- while (@_) { $value *= $x; $value += shift; }
- return $value;
-}
-
-###############################################################################
-# bkell_real_zeros_finder($a_n, ..., $a_0)
-#
-# Returns a list of numerical approximations of the zeros of the polynomial
-# a_n*x^n + ... + a_1*x + a_0, in order from least to greatest.
-#
-# The possibility of overflow or underflow is ignored. Overflow is likely to be
-# a bigger problem than underflow.
-#
-# Do not use this code to guide missiles or control nuclear power plants.
-#
-sub bkell_real_zeros_finder
-{
- my @coeffs = @_;
-
- while (@coeffs && $coeffs[0] == 0) { shift @coeffs; }
- my $deg = $#coeffs;
-
- if ($deg == -1) {
- return ("x"); # zero polynomial is zero everywhere
- } elsif ($deg == 0) {
- return (); # constant nonzero polynomial has no zeros
- } elsif ($deg == 1) {
- return (-$coeffs[1]/$coeffs[0]); # linear polynomial has one zero
- }
-
- # find critical points
- my @derivative = @coeffs;
- pop @derivative;
- for (my $i = 0; $i < $#derivative; ++$i) {
- $derivative[$i] *= @derivative - $i;
- }
- my @cp = bkell_real_zeros_finder(@derivative);
-
- # if no critical points, we have a monotone function
- if (!@cp) {
- my ($lb, $rb) = (-1, 1);
- my $y1 = bkell_poly_eval($lb, @coeffs);
- my $y2 = bkell_poly_eval($rb, @coeffs);
- my $sign = ($y1 < $y2 ? +1 : -1);
- while ($sign * $y1 > 0) {
- $lb *= 2;
- $y1 = bkell_poly_eval($lb, @coeffs);
- }
- while ($sign * $y2 < 0) {
- $rb *= 2;
- $y2 = bkell_poly_eval($rb, @coeffs);
- }
- my $guess_x = ($lb + $rb) / 2;
- while ($lb < $guess_x && $guess_x < $rb &&
- (my $guess_y = bkell_poly_eval($guess_x, @coeffs)) != 0)
- {
- if ( ($y1 < 0 && $guess_y < 0) || ($y1 > 0 && $guess_y > 0) ) {
- $lb = $guess_x;
- } else {
- $rb = $guess_x;
- }
- $guess_x = ($lb + $rb) / 2;
- }
- return ($guess_x);
- }
-
- my @zeros = ();
-
- # search for a zero to the left of the first critical point
- {
- my $y = bkell_poly_eval($cp[0], @coeffs);
- # we catch this case when we check between critical points:
- last if $y == 0;
- # not really the limit, but only the sign matters:
- my $lim = $coeffs[0] * ($deg % 2 ? -1 : +1);
- if ( ($y > 0 && $lim < 0) || ($y < 0 && $lim > 0) ) {
- my ($lb, $rb) = (undef, $cp[0]);
- my $guess_x = $rb - 10;
- if ($guess_x >= 0) { $guess_x = -10; }
- while ((!defined $lb || $lb < $guess_x) && $guess_x < $rb &&
- (my $guess_y = bkell_poly_eval($guess_x, @coeffs)) != 0)
- {
- if ( ($y > 0 && $guess_y > 0) || ($y < 0 && $guess_y < 0) ) {
- $rb = $guess_x;
- if (defined $lb) {
- $guess_x = ($lb + $guess_x) / 2;
- } else {
- $guess_x *= 2;
- }
- } else {
- $lb = $guess_x;
- $guess_x = ($guess_x + $rb) / 2;
- }
- }
- push @zeros, $guess_x;
- }
- }
-
- # search for zeros between critical points
- for (my $i = 0; $i < $#cp; ++$i) {
- my $y1 = bkell_poly_eval($cp[$i], @coeffs);
- if ($y1 == 0) {
- push @zeros, $cp[$i];
- next;
- }
- my $y2 = bkell_poly_eval($cp[$i+1], @coeffs);
- if ($y2 == 0) {
- push @zeros, $cp[$i+1];
- ++$i;
- next;
- }
- next if ($y1 > 0 && $y2 > 0) || ($y1 < 0 && $y2 < 0);
- my ($lb, $rb) = ($cp[$i], $cp[$i+1]);
- my $guess_x = ($lb + $rb) / 2;
- while ($lb < $guess_x && $guess_x < $rb &&
- (my $guess_y = bkell_poly_eval($guess_x, @coeffs)) != 0)
- {
- if ( ($y1 > 0 && $guess_y > 0) || ($y1 < 0 && $guess_y < 0) ) {
- $lb = $guess_x;
- } else {
- $rb = $guess_x;
- }
- $guess_x = ($lb + $rb) / 2;
- }
- push @zeros, $guess_x unless @zeros && $zeros[-1] == $guess_x;
- }
-
- # search for a zero to the right of the last critical point
- {
- my $y = bkell_poly_eval($cp[-1], @coeffs);
- if ($y == 0 && $zeros[-1] != $cp[-1]) {
- push @zeros, $cp[-1];
- last;
- }
- if ( ($y > 0 && $coeffs[0] < 0) || ($y < 0 && $coeffs[0] > 0) ) {
- my ($lb, $rb) = ($cp[-1], undef);
- my $guess_x = $lb + 10;
- if ($guess_x <= 0) { $guess_x = 10; }
- while ($lb < $guess_x && (!defined $rb || $guess_x < $rb) &&
- (my $guess_y = bkell_poly_eval($guess_x, @coeffs)) != 0)
- {
- if ( ($y > 0 && $guess_y > 0) || ($y < 0 && $guess_y < 0) ) {
- $lb = $guess_x;
- if (defined $rb) {
- $guess_x = ($guess_x + $rb) / 2;
- } else {
- $guess_x *= 2;
- }
- } else {
- $rb = $guess_x;
- $guess_x = ($lb + $guess_x) / 2;
- }
- }
- push @zeros, $guess_x unless @zeros && $zeros[-1] == $guess_x;
- }
- }
-
- return @zeros;
-}
-
-###############################################################################
-# bkell_floor($x)
-#
-# Returns the floor of $x. Normally this would be done with POSIX::floor, but
-# WeBWorK doesn't allow you to use standard modules like POSIX.
-#
-sub bkell_floor
-{
- my $x = shift;
- my $floor = int $x;
- if ($x < 0 && $x != $floor) { $floor -= 1; }
- return $floor;
-}
-
-###############################################################################
-# bkell_ceil($x)
-#
-# Returns the ceiling of $x.
-#
-sub bkell_ceil
-{
- return -bkell_floor(-shift);
-}
-
-###############################################################################
-# bkell_sigfigs($x, $n)
-#
-# Returns a string containing $x rounded to $n significant figures.
-#
-sub bkell_sigfigs
-{
- my ($x, $n) = @_;
-
- if ($x == 0) { return "0".($n > 1 ? "." : "").("0" x ($n-1)); }
-
- my $minus = "";
- if ($x < 0) {
- $minus = "-";
- $x = -$x;
- }
-
- my $floor_log = bkell_floor(log($x)/log(10));
-
- if ($floor_log+1 >= $n) {
- my $sf = 10**($floor_log-$n+1);
- return $minus.(sprintf("%.0f", $x/$sf)*$sf);
- } else {
- my $digits = $n-$floor_log-1;
- return $minus.sprintf("%.${digits}f", $x);
- }
-}
-
-###############################################################################
-# bkell_125($x)
-#
-# Returns the value logarithmically nearest $x in the sequence
-# ..., -1000, -500, -200, -100, -50, -20, -10, -5, -2, -1, -0.5, -0.2,
-# -0.1, -0.05, -0.02, -0.01, ..., 0, ..., 0.01, 0.02, 0.05, 0.1,
-# 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, ... .
-#
-sub bkell_125
-{
- my $x = shift;
-
- if ($x == 0) { return 0; }
-
- my $sign = +1;
- if ($x < 0) { $sign = -1; $x = -$x; }
-
- my $log = log($x)/log(10);
- my $characteristic = bkell_floor($log);
- my $mantissa = $log - $characteristic;
-
- my $log2 = log(2)/log(10);
- my $log5 = log(5)/log(10);
- my $m;
- if ($mantissa < $log2 / 2) {
- $m = 0;
- } elsif ($mantissa < ($log2 + $log5) / 2) {
- $m = $log2;
- } elsif ($mantissa < ($log5 + 1) / 2) {
- $m = $log5;
- } else {
- $m = 1;
- }
-
- return $sign * (10 ** ($characteristic + $m));
-}
-
-###############################################################################
-# bkell_list_random_selection($n, @list)
-#
-# Returns a selection of $n distinct elements of @list. This is like
-# list_random_multi_uniq in freemanMacros.pl, except that this function will
-# always return the elements in the same order as they appear in @list.
-#
-sub bkell_list_random_selection
-{
- my $n = int abs shift; # so strange $n won't cause infinite loop
- my @list = @_;
-
- my $needed = $n;
- my @result = ();
- while ($needed && @list) {
- if (random(1, scalar @list) <= $needed) {
- push @result, shift @list;
- --$needed;
- } else {
- shift @list;
- }
- }
-
- return @result;
-}
-
-###############################################################################
-# bkell_graph_axis($a, $b)
-#
-# Returns a list ($min, $max, $step), where $min <= $a, $max >= $b, $step is a
-# power of 10, $min and $max are multiples of $step, abs($min) <= 9*$step, and
-# abs($max) <= 9*$step. Useful for deciding bounds for the axis of a graph. For
-# example, to make a graph axis that can handle values between $a and $b, call
-# bkell_graph_axis, and then set the minimum value of the axis to $min and the
-# maximum to $max, and put tick marks every $step units.
-#
-sub bkell_graph_axis
-{
- my ($a, $b) = @_;
-
- if ($a > $b) { ($a, $b) = ($b, $a); }
-
- my $s1 = 0;
- my $s2 = 0;
-
- if ($a != 0) { $s1 = bkell_floor(log(abs $a)/log(10)); }
- if ($b != 0) { $s2 = bkell_floor(log(abs $b)/log(10)); }
-
- my $s = ($s1 > $s2 ? $s1 : $s2);
-
- $step = 10**$s;
- $min = $step * bkell_floor($a/$step);
- $max = $step * bkell_ceil($b/$step);
-
- return ($min, $max, $step);
-}
-
-####################################################################### EOF ###
diff --git a/OpenProblemLibrary/macros/Wiley/littleneck.pl b/OpenProblemLibrary/macros/Wiley/littleneck.pl
deleted file mode 100644
index 8eb3cd8e46..0000000000
--- a/OpenProblemLibrary/macros/Wiley/littleneck.pl
+++ /dev/null
@@ -1,227 +0,0 @@
-#*****************************
-# Question mode variables
-#*****************************
-$PRACTICE_MODE = 0;
-loadMacros("problemRandomize.pl");
-#********************************************
-# Set up a "generate new problem" button
-#********************************************
-sub rand_button
-{
- if ($PRACTICE_MODE == 1)
- {
- ProblemRandomize(when=>"Always",onlyAfterDue=>0,style=>"Input");
- }
- elsif ($PRACTICE_MODE == 2)
- {
- ProblemRandomize(when=>"Always",onlyAfterDue=>0,label=>"Generate New Problem");
- }
-}
-#**********************************************************
-# Subroutine to reduce fractions
-# Input : Num, Denom
-# Output: Num, Denom, Wholenum (if != 0, = $num/$denom)
-#
-# 22Jul09 - Returned Wholenum < 0 if num or denom < 0
-#**********************************************************
-sub reduce_fraction
-{
- $n = $_[0];
- $d = $_[1];
- $wholenum = 0;
-#
-# **********************
-# Remove negatives
-# **********************
- if ($n < 0)
- {
- $num = -$n;
- }
- else
- {
- $num = $n;
- }
- if ($d < 0)
- {
- $denom = -$d;
- }
- else
- {
- $denom = $d;
- }
-# ******************************
-# Check for a whole number
-# ******************************
- if ($num/$denom == int($num/$denom))
- {
- $wholenum = $n/$d;
- }
-# ***************
-# Find gcf
-# ***************
- else
- {
- if ($num > $denom)
- {
- $gcf = $denom;
- }
- else
- {
- $gcf = $num;
- }
- $found = 0;
- while ( ($found == 0) && ($gcf > 1) )
- {
- if ( ($num/$gcf == int($num/$gcf)) && ($denom/$gcf == int($denom/$gcf)) )
- {
- $found = 1;
- }
- else
- {
- $gcf--;
- }
- }
-# ********************************
-# If a GCF was found, reduce
-# ********************************
- if ($found == 1)
- {
- $num = $num/$gcf;
- $denom = $denom/$gcf;
- }
- }
-# ***********************
-# Restore negatives
-# ***********************
- if ($n < 0)
- {
- $num = -1*$num;
- }
- if ($d < 0)
- {
- $denom = -1*$denom;
- }
- return($num, $denom, $wholenum);
-}
-#
-#**********************************************************
-# Subroutine to produce reduced display fraction
-# Input : Num($n), Denom($d)
-# Output: Num($n), Denom($d), Wholenum($w),Display($display)
-# calls reduce_fraction to get,
-# Output: Num($n), Denom($d), Wholenum($w),
-#(if Wholenum > 0,$display = $w
-# else $Display=\(\frac{$n}{$d}\)
-#**********************************************************
-sub display_fraction_long
-{ $n = $_[0];
- $d = $_[1];
- $w=0;
- $display=0;
-#call reduce_fraction
-($n,$d,$w)=reduce_fraction($n,$d,$w);
-#Decide on display format
-if ($w>0){
- $display=$wholenumber;
- }
-else{
- $display="\\frac{$num}{$denom}";
- }
-return($n, $d, $w,$display);
-}
-#
-#
-#
-#
-#**********************************************************
-# Subroutine to produce reduced display fraction
-# Input : Num($n), Denom($d)
-# Output: Display($display)
-# calls reduce_fraction to get,
-# Output: Num($n), Denom($d), Wholenum($w),
-#(if Wholenum > 0,$display = $w
-# else $Display=\(\frac{$n}{$d}\)
-#**********************************************************
-sub display_fraction
-{ $n = $_[0];
- $d = $_[1];
- $w=0;
- $display=0;
-#call reduce_fraction
-($n,$d,$w)=reduce_fraction($n,$d,$w);
-#Decide on display format
-if ($w>0){
- $display=$wholenumber;
- }
- else{
- $display="\\frac{$num}{$denom}";
- }
-return($display);
-}
-#*******************************************************************************
-# sqrt_simplify(Num,Natnum,Radnum,Texstr,Error)
-#
-# Description: Given a natural number, will find the greatest perfect square
-# that is a factor and use this to simplify the expression:
-# sqrt(number).
-# Input :
-# Num = Number whose sqrt is being taken
-#
-# Output:
-# Natnum => Natural number portion of solution (= 1 if no perfect square
-# divides evenly)
-# Radnum => The value still inside the radical
-# Texstr => A LaTex string of the form "Natnum \sqrt{$Radnum}" to be used
-# for displaying the solution.
-# Error => If == 1, then the number entered was bad (ie, negative, nonint)
-# (If necessary, this code can be made specific for the error)
-#*******************************************************************************
-sub sqrt_simplify
-{
- $number = $_[0];
- ($Natnum,$Radnum) = (1,1);
- $Error = 0;
-
- #***********************************
- # Check the number for validity
- #***********************************
- if ( ($number == int($number)) && ($number > 0) )
- {
- $perfsqr = 1;
- #*************************************************************************************
- # Check all perfect squares up to the max and store the hightest one that divides
- #*************************************************************************************
- for ($i = 2; $i*$i <= $number; $i++)
- {
- $sqr = $i*$i;
- if ( int($number/$sqr) == $number/$sqr )
- {
- $perfsqr = $i;
- }
- }
- $Natnum = $perfsqr;
- $Radnum = $number/($Natnum*$Natnum);
- #************************************************************
- # If radnum = 1, the original number is a perfect square
- # If natnum = 1, it cannot be simplified
- #************************************************************
- if ($Radnum == 1)
- {
- $Texstr = "$Natnum";
- }
- elsif ($Natnum == 1)
- {
- $Texstr = "\\sqrt{$number}";
- }
- else
- {
- $Texstr = "$Natnum \\sqrt{$Radnum}";
- }
- }
- else
- {
- ($Natnum,$Radnum,$Error) = 1;
- $Texstr = "1";
- }
- return($Num,$Natnum,$Radnum,$Texstr,$Error);
-}