% \iffalse
%<*copyright>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% dljsLib.sty package,             2002-2-9            %%
%% Copyright (C) 2001-2002  D. P. Story                 %%
%%   dpstory@uakron.edu                                 %%
%%                                                      %%
%% This program can redistributed and/or modified under %%
%% the terms of the LaTeX Projet Public License         %%
%% Distributed from CTAN archives in directory          %%
%% macros/latex/base/lppl.txt; either version 1 of the  %%
%% License, or (at your option) any later version.      %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%</copyright>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{dljslib}
%<package> [2007/02/05 v1.6 Manage a Library of Document Level JavaScripts (dps)]
%<*driver>
\documentclass{ltxdoc}
\usepackage[dviwindo,colorlinks,hyperindex]{hyperref}
\pdfstringdefDisableCommands{\let\\\textbackslash}%
\EnableCrossrefs \CodelineIndex
\begin{document}
  \GetFileInfo{dljslib.sty}
  \title{The \texttt{dljsLib} Package}
  \author{D. P. Story\\
    Email: \texttt{dpstory@uakron.edu}}
  \date{processed \today}
  \maketitle
  \tableofcontents
  \let\Email\texttt
  \DocInput{dljslib.dtx}
  \PrintIndex
\end{document}
%</driver>
% \fi
% \changes{v1.3}{2005/08/27}{. Added new user contributed routines for unordered,
%        interval, point and factored responses. Added a feature whereby you
%        can create a file called libcusopt.opt to declare your own options
%        for this package, but these should be a combination of existing
%        options.}
%
%\section{Introduction}
% This is a companion package to the \texttt{insdljs} package. \texttt{Insdljs} gives the
% document author the ability to write document level JavaScripts to the PDF docuement, when
% it is finally built.  I personally will be writing a number of general routines to
% handle situations that arise, and I would hope that other enthusiasts of \texttt{insdljs} will
% do the same. Therefore, it is desirable to gather together some general purpose routines into
% a single library, and have a way of selecting the desired function or functions to be used.
%
% This package is meant for document authors, not for package developers. This package can only be used
% once per document, perhaps called from the preamble of a document.
%
%\section{The Library Procedures}
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
% Define some convenience commands, \cs{dljsRegister} and \cs{DeclareAndRegister}, see comments that follow.
%    \begin{macrocode}
\newcommand\dljsRegister[2][n]
    {\expandafter\let\csname checkout@#2\endcsname=#1}
\newcommand\DeclareAndRegister[1]
    {\DeclareOption{#1}{\dljsRegister[y]{#1}}\dljsRegister{#1}}
%    \end{macrocode}
% Here we ``register'' the functions contained in the library. \cs{dljsRegister} defines a
% control sequence that records the name of the function (actually, the option name). This
% control is set to `n'. When a package user chooses a particular function for inclusion, the
% control is set to `y'.
%    \begin{macrocode}
\dljsRegister[y]{dljslib}
%    \end{macrocode}
% \subsection{Library Card Catalog}
% The arguments of the \cs{DeclareAndRegister} command are the options of this package, and
% their names represent JavaScript functions in the library.
%    \begin{macrocode}
\DeclareAndRegister{equations}
\DeclareAndRegister{vectors}
\DeclareAndRegister{indefIntegral}
\DeclareAndRegister{ImplMulti}
\DeclareAndRegister{nodec}
\DeclareAndRegister{noBinFac}
\DeclareAndRegister{limitArith}
\DeclareAndRegister{combinatorics}
\DeclareAndRegister{setSupport}
\DeclareAndRegister{unordered}
\DeclareAndRegister{factors}
\DeclareAndRegister{point}
\DeclareAndRegister{intervals}
\InputIfFileExists{libcusopt.opt}{}{}
%    \end{macrocode}
%    \begin{macrocode}
\ProcessOptions
%    \end{macrocode}
% \subsection{Requirements for a Library Card}
%
% In order to check a function out of this library, you must have
% the \texttt{insdljs} Package. The \texttt{insdljs} package itself
% has software requirements: (1) the \texttt{verbatim} and
% \texttt{hyperref} packages; (2) One of the fillowing,
% \textsf{Distiller~5.0} or greater, \textsf{pdftex}, or
% \textsf{dvipdfm}.
%
%    \begin{macrocode}
\RequirePackage{insdljs}
%    \end{macrocode}
%
% \subsection{Checkout Procedure}
%
% Functions can be checkout of the library by using the \texttt{dljslib} package
% in the usual way. For example:
%\begin{verbatim}
%\documentclass{article}
%\usepackage{amsmath}
%\usepackage[pdftex,designi]{web}
%\usepackage{exerquiz}
%\usepackage[indefIntegral]{dljslib}  % <- check out `indefIntegral'
%\end{verbatim}
% Here, we first use \texttt{exerquiz}, which has \texttt{insdljs} as a required package.
% The use of this package is not limited to users of \texttt{exerquiz}, for example, we can
% say
%\begin{verbatim}
%\documentclass{article}
%\def\mydriver{dvipdfm}
%\usepackage[\mydriver]{color}
%\usepackage[\mydriver,colorlinks,pdfpagemode=None]{hyperref}
%\usepackage[\mydriver]{insdljs}
%\usepackage[indefIntegral]{dljslib}  % <- check out `indefIntegral'
%\end{verbatim}
% However, at the time of the release of v1.0 of this package, the only functions in this
% library are ones used by \texttt{exerquiz}.
%
% \subsection{Exiting the Library with your Checkouts}
%
% This package has an output stream, \cs{dljslib@verbatim@out},
% that is used to write all the functions that are to be included.
% We use a control sequence \cs{js@verbatim@out} defined in
% \texttt{insdljs}. We also use a verbatim write from
% \texttt{insdljs} as well, the \cs{js@verbatimwrite} environment.
% \cs{js@verbatimwrite} writes to the output stream pointed to
% \cs{js@verbatim@out}.
%    \begin{macrocode}
\newwrite\dljslib@verbatim@out
%    \end{macrocode}
% This package generates only one auxiliary file,
% \texttt{dljslib.ljs}, which can be deleted after the document is
% latexed. The file \texttt{dljslib.ljs} (\texttt{ljs} means
% ``library javascripts'') and contains the functions that are
% specified in the package options.  At the end of this package,
% the file \texttt{dljslib.ljs} is input back into the calling
% document where the package \texttt{insdljs} takes over.
%    \begin{macrocode}
\immediate\openout\dljslib@verbatim@out=dljslib.ljs
%    \end{macrocode}
% \subsection{The Catalog and Checkout Mechanism}
%    \begin{macro}{library@holding}
% This is a simple environment, it reads its parameter, and if that option was specified by the
% user, it writes the function verbatim to the \texttt{dljslib.ljs}, otherwise, it comments out
% that function using the \texttt{comment} environment from the \texttt{verbatim} package.
% This environment uses, \texttt{js@verbatimwrite}, an environment
% defined in the \texttt{insdljs} package.
%    \begin{macrocode}
\newenvironment{library@holding}[1]
{%
    \expandafter\ifx\csname checkout@#1\endcsname y%
    \let\js@verbatim@out=\dljslib@verbatim@out
    \let\dljs@verbatim=\js@verbatimwrite
    \let\enddljs@verbatim=\endjs@verbatimwrite\else
    \let\dljs@verbatim=\comment
    \let\enddljs@verbatim=\endcomment\fi\dljs@verbatim
}{\enddljs@verbatim}
%    \end{macrocode}
%    \end{macro}
%\section{The DLJS Library}
% We finaly reach the ``stacks'', the location of the actual library holdings.
%
%   \medskip\noindent This item must always accompany the collection of functions that are to be
% checked out. This is the beginning of the \texttt{insDLJS} environment. To continue this library analogy,
% this of this as the ``front wrapper'' or ``front cover'' of your library selections. It contains the
% ``name'' of the library from which you checked out your selections.
%    \begin{macrocode}
\begin{library@holding}{dljslib}
\begin{insDLJS*}[dljslib]{dljslib}
\begin{newsegment}{dljslib: AcroTeX DLJS Library}
/*
        The Document Level JavaScript Library
        D. P. Story copyright 2001-\the\year
*/
var dljslib = true;
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%\subsection{The Stacks}
% Now we reach of the beginning of the stacks. There are several sections of the library, currently,
% \nameref{s:respfunctions} and \nameref{s:compfunctions}.
%
% \subsection{Response Functions}\label{s:respfunctions}
%
% \textbf{Used by Exerquiz.} In this section we catalog response functions. A response function is the one that
% \cs{RespBoxMath} calls to process the user's response to a math fill-in question. See the sample file
% \texttt{jqzspec.tex} for a detailed explanation of this type of function.
%
% \subsubsection{\texttt{equations}}\label{equations}
%    \begin{macro}{equations}
% These routines process questions for which an equation is the expected answer.
%    \begin{macrocode}
\begin{library@holding}{equations}
\begin{newsegment}{dljslib: Equation Handling}
function ProcRespEq(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
    if (!ProcessIt) return null;
    ok2Continue = true;
    var success;
    var fieldname = event.target.name;
    var UserAns = event.value;
%    \end{macrocode}
% Implement an "undefined" answer. Due to Ross-Griffin
%    \begin{macrocode}
%    if (UserAns == "undefined") {
%        success = (CorrAns == UserAns);
%        return notifyField(success, flag, fieldname);
%    }
%-    var Expressions = CorrAns.split("=");
%-    var zCorrAns = "("+Expressions[0]+")-("+Expressions[1] +")";
%-    Expressions = UserAns.split("=");
%-    if (Expressions.length != 2)
%-    {
    var CorrExpressions = CorrAns.split("=");
    var zCorrAns = "("+CorrExpressions[0]+")-("+CorrExpressions[1] +")";
    UserAns = stripWhiteSpace (UserAns);
    if(!ok2Continue ) return null;
    if (!/[=]/.test(UserAns)) {
            app.alert("An equation is expected", 3);
            return null;
    }
%-    var zUserAns = "("+Expressions[0]+")-("+Expressions[1] +")";
    var UserExpressions = UserAns.split("=");
    var zUserAns = "("+UserExpressions[0]+")-("+UserExpressions[1] +")";

%    \end{macrocode}
% If \texttt{oComp} is an object, then see if it has a \texttt{comp} property
%    \begin{macrocode}
    var comp = ( typeof oComp == "object" ) ?
       (typeof oComp.comp == "undefined" ) ? diffCompare : oComp.comp : oComp;
%    \end{macrocode}
% The \texttt{comp} parameter, which has been changed to \texttt{oComp} can now be
% an object. One property of this object is \texttt{comp}, handled above. Another
% property is \texttt{priorParse}, this is a function that returns \texttt{null}
% or \texttt{true}. This \texttt{priorParse} function allows for additional
% filtering of the \texttt{zUserAns} before parsing. If it returns \texttt{true},
% we are ok to continue, if \texttt{null}, we don't like something the user has entered,
% and ask him/her to change it.
%    \begin{macrocode}
    if ( typeof oComp == "object" && typeof oComp.priorParse != "undefined" )
    {
%    \end{macrocode}
% Let's go ahead and allow \texttt{oComp.priorParse} be an array of functions.
%    \begin{macrocode}
        if ( typeof oComp.priorParse == "object" )
        {
            for ( var i=0; i < oComp.priorParse.length; i++)
            {
                var retn = oComp.priorParse[i](zUserAns);
                if ( retn == null ) return null;
            }
        } else {
            var retn = oComp.priorParse(zUserAns);
            if ( retn == null ) return null;
        }
    }
    zCorrAns = ParseInput(zCorrAns);
    if (!ok2Continue) {
        app.alert("Syntax error in author's answer! Check console.", 3);
        console.println("Syntax Error: " + CorrAns);
        return null;
    }
    zUserAns = ParseInput(zUserAns);
    if (!ok2Continue) return null;
    indepVar = TypeParameters(indepVar); // convert vars to  new format, if needed
    var lambda = getNonZeroRatio (a, indepVar, zCorrAns, zUserAns);
    if ( lambda == null ) { app.alert(\eqSyntaxErrorUndefVar,3); return null; };
    if ( !ok2Continue ) return notifyField(false, flag, fieldname);
    zCorrAns  = lambda + "*(" + zCorrAns + ")";
\db console.println("zCorrAns = " + zCorrAns);\db%
    success=randomPointCompare (n,a,indepVar,epsilon,zCorrAns,zUserAns,comp)
\db console.println("success = " + success );\db%
    if ( success == null ) { app.alert(\eqSyntaxErrorUndefVar,3); return null; }
    return notifyField(success, flag, fieldname);
}
function getNonZeroRatio (_a, _v, _F, _G)
{
    var _i, _j;
    var aXY = new Array();
%    var nV = _v.length;
    _a = _a.replace(/[\[\]\s]/g, "");
    var _V = _v.split(",");  // e.g. _V[0] = "i:x"
    var _n = _V.length;
    var aIntervals = _a.split("&");
    var aInterval = aIntervals[0].split("x");
    var endpoints = aInterval[0].split(",");
%    with (Math)
%    {
        for (_j=0; _j < 4; _j++)
        {
            for (_i = 0; _i < _n; _i++)
            {
                var endpoints = aInterval[_i].split(",");
                aXY[_i] = endpoints[0]-0+(endpoints[1]-endpoints[0])*random();
\db             console.println("aXY["+_i+"] = " + aXY[_i]);\db%
            }
            for (var _i = 0; _i< _n; _i++)
            {
                if (_V[_i].charAt(0) == "r" )
                    eval ( "var "+ _V[_i].charAt(2) + " = " + aXY[_i] + ";");
                else // assume type "i"
                    eval ( "var "+ _V[_i].charAt(2) + " = " + ceil(aXY[_i]) + ";");
%                    eval ( "var "+_v[_i] + " = " + aXY[_i] + ";");
            }
            _F = eval(_F);
            if ( app.viewerVersion >= 5)
            {
                var rtnCode = 0;
                eval("try { if(isNaN(_G = eval(_G))) rtnCode=-1; } catch (e) { rtnCode=1; }");
                switch(rtnCode)
                {
                    case  0: break;
                    case  1: return null;
                    case -1: ok2Continue=false;
                             return -1;
                }
            }
            else
                if(isNaN(_G = eval(_G))) { ok2Continue=false; return -1; }
            if ( _F != 0 && _G != 0 ) return _G/_F;
        }
%    }
    console.println( "Can't find a non zero scalar");
    return null;
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \end{macro}
% \subsubsection{\texttt{vectors}}\label{vectors}
%    \begin{macro}{vectors}
% This function attempts to process questions that have vectors
% as answers. Note the name of the function is \texttt{ProcVec}, this is the name used to call it.
%\begin{verbatim}
%$\vec a + \vec b = \RespBoxMath{<4, 4, 4>}{1}{.0001}{[2,4]}*{ProcVec}$
%\end{verbatim}
%See also the file \texttt{jqzspec.tex} for more details.
%    \begin{macrocode}
\begin{library@holding}{vectors}
\begin{newsegment}{dljslib: Vector Handling}
function ProcVec (flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
% This function attempts to process questions that have vectors
% as answers.
    if (!ProcessIt) return null;
    ok2Continue = true;
%-    var i, success, truthCnt=0;
    var i, success, truthCnt=1;
    var aScalar, scalar = 1;
    var fieldname = event.target.name;
    var UserAns = event.value;
%    \end{macrocode}
% Implement an "undefined" answer. Due to Ross-Griffin
%    \begin{macrocode}
    if (UserAns == "undefined") {
        success = (CorrAns == UserAns);
        return notifyField(success, flag, fieldname);
    }
    CorrAns = stripWhiteSpace (CorrAns);
    UserAns = stripWhiteSpace (UserAns); // sets ok2Continue
    if ( !ok2Continue ) return null;
    if (!/[<>]/.test(UserAns)) {
        app.alert("I'm looking for a vector. You need to use proper vector notation.", 3);
        return null;
    }
    if (!CkBalP(UserAns,"<",">")) {
        app.alert("Angle brackets are not balanced.", 3);
        return null;
    }
    // see if there is a scalar multiple to the left of '<'
    aScalar = UserAns.match(/(.*)(\*)(\s*<)/);
    if (aScalar != null) {
        scalar = aScalar[1];
        UserAns = UserAns.slice(aScalar.index + aScalar[0].length-1)
    }
%    \end{macrocode}
% If \texttt{oComp} is an object, then see if it has a \texttt{comp} property
%    \begin{macrocode}
    var comp = ( typeof oComp == "object" ) ?
       (typeof oComp.comp == "undefined" ) ? diffCompare : oComp.comp : oComp;
%    \end{macrocode}
%    \begin{macrocode}
    CorrAns = CorrAns.replace(/[<>]/g, ""); // strip of < and >
    UserAns = UserAns.replace(/[<>]/g, "");
%    \end{macrocode}
% The \texttt{comp} parameter, which has been changed to \texttt{oComp} can now be
% an object. One property of this object is \texttt{comp}, handled above. Another
% property is \texttt{priorParse}, this is a function that returns \texttt{null}
% or \texttt{true}. This \texttt{priorParse} function allows for additional
% filtering of the \texttt{UserAns} before parsing. If it returns \texttt{true},
% we are ok to continue, if \texttt{null}, we don't like something the user has entered,
% and ask him/her to change it.
%    \begin{macrocode}
    if ( typeof oComp == "object" && typeof oComp.priorParse != "undefined" )
    {
%    \end{macrocode}
% Let's go ahead and allow \texttt{oComp.priorParse} be an array of functions.
%    \begin{macrocode}
        if ( typeof oComp.priorParse == "object" )
        {
            for ( var i=0; i < oComp.priorParse.length; i++)
            {
                var retn = oComp.priorParse[i](UserAns);
                if ( retn == null ) return null;
            }
        } else {
            var retn = oComp.priorParse(UserAns);
            if ( retn == null ) return null;
        }
    }
%    \end{macrocode}
% Not convert each to an array
%    \begin{macrocode}
    aUserAns = UserAns.split(",");
    aCorrAns = CorrAns.split(",");
    if (scalar != 1)
        for (i=0; i<aUserAns.length; i++)
            aUserAns[i]=""+scalar+"*"+aUserAns[i];
    if (aCorrAns.length != aUserAns.length) {
        app.alert("Incorrect number of components. The answer requires "
            + aCorrAns.length+" components.",3);
        return null;
    }
    indepVar = TypeParameters(indepVar); // convert to new format, if needed
    for (i=0; i<aCorrAns.length; i++) {
        aCorrAns[i] = ParseInput(aCorrAns[i]);
        if (!ok2Continue) {
            app.alert("Author Syntax error!", 3);
            return null;
        }
        aUserAns[i] = ParseInput(aUserAns[i]);
        if (!ok2Continue) return null;
        success=randomPointCompare (n,a,indepVar,epsilon,aCorrAns[i],aUserAns[i],comp)
        if ( success == null ) { app.alert(\eqSyntaxErrorUndefVar,3); return null; }
        truthCnt *= (success) ? 1 : 0;
%-        if (success) truthCnt +=1;
    }
%    return notifyField((truthCnt == 3), flag, fieldname);
    return notifyField(!!truthCnt, flag, fieldname);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \end{macro}
% \subsubsection{\texttt{setSupport}}
%    \begin{macro}{setSupport}
% We introduce two JavaScript functions \texttt{ProcRespSetNum} and
% \texttt{ProcRespSetSym}, for handling a set of answers or a comma
% delimited list of answers. The first function is for
% numerical answers, the second for simple symbolic answers.  The
% demo file for these two response functions is
% \texttt{set\_test.tex}; the examples below were taken from that file.
%    \end{macro}
%    \begin{macrocode}
\begin{library@holding}{setSupport}
\begin{newsegment}{dljslib: Support for Sets}
%    \end{macrocode}
% This function can handle (math fill-in) questions whose answers are a set of numbers or a
% comma delimited list of numbers.
%\begin{flushleft}
% Sample usage:
%\begin{verbatim}
% $(x+1)(2x-1)(x-2)^3 = 0$, $x = \RespBoxMath[\rectW{.75in}\textSize{0}]
%    {-1, 1/2, 2, 2, 2}{1}{.0001}{[0,1]}*{ProcRespSetNum}$
%\end{verbatim}
%\end{flushleft}
%    \begin{macrocode}
function ProcRespSetNum(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
    ok2Continue = true;
    if (!ProcessIt) return null;
    var fieldname = event.target.name;
    var UserAns = event.value;
    UserAns = stripWhiteSpace(UserAns);
    if (!ok2Continue) return null;
    // make sure all of UserAns are numbers
    var aUserAns = UserAns.split(",");
    for ( var i=0; i < aUserAns.length; i++) {
        try {
            if (isNaN(eval(aUserAns[i]))) return syntaxError(), null;
        } catch(e) { return syntaxError(), null; }
    }
    var aUserAns = aUserAns.sort( function(a,b) { return eval(a) - eval(b);} );
    var aCorrAns = CorrAns.split(",").sort( function(a,b) { return  eval(a) - eval(b);} );
    var numCorrect = 0;
    if ( aUserAns.length != aCorrAns.length ) return notifyField(false, flag, fieldname);
    for ( var i=0; i< aCorrAns.length; i++) {
        var retn = _ProcResp(flag,aCorrAns[i],aUserAns[i],n,epsilon,a,indepVar,oComp);
        if ( retn == null ) return syntaxError(), null;
        numCorrect += (retn) ? 1 : 0;
    }
    var success = (numCorrect == aCorrAns.length) ? true : false;
    if ( success == null ) return syntaxError(), null;
    return notifyField(success, flag, fieldname);
}
%    \end{macrocode}
% This function can handle simple symbolic answers. The variable list, \texttt{inderVar}, should
% be the ``universal set'' of the problem.
% \begin{flushleft}
% Sample usage:
%\begin{verbatim}
% \def\U{a,b,c,d,e,f,g} % define a universal set
% $A \cap B = \RespBoxMath[\AA{\AAKeystroke{\AAKqRespBoxMath}\AAFormat{\setAsFormat}}
%     \rectW{.75in}\textSize{0}]{c,d}(\U){1}{.0001}{[0,1]}*{ProcRespSetSym}$
%\end{verbatim}
% \end{flushleft}
%    \begin{macrocode}
function ProcRespSetSym(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
    ok2Continue = true;
    if (!ProcessIt) return null;
    var fieldname = event.target.name;
    var UserAns = event.value;
    UserAns = stripWhiteSpace(UserAns);
    if (!ok2Continue) return null;
    // make sure all of UserAns are numbers
    var aUserAns = UserAns.split(",");
    var _V = indepVar.split(",");
    for ( var _i=0; _i < _V.length; _i++) {
         eval ( "var "+ _V[_i] + " = \"" + _i + "\";");
    }
    for ( var _i=0; _i < aUserAns.length; _i++) {
        try {
            if (isNaN(eval(aUserAns[_i]))) return syntaxError(), null;
            aUserAns[_i] = eval(aUserAns[_i]);
        } catch(e) { return syntaxError(), null; }
    }
    var aCorrAns = CorrAns.split(",");
    for ( var _i=0; _i < aCorrAns.length; _i++) {
        try {
            if (isNaN(eval(aCorrAns[_i]))) return app.alert("Author error, recheck your code",3), null;
            aCorrAns[_i] = eval(aCorrAns[_i]);
        } catch(e) { return app.alert("Author error, recheck your code",3), null; }
    }
    var aUserAns = aUserAns.sort( function(a,b) { return eval(a) - eval(b);} );
    var aCorrAns = aCorrAns.sort( function(a,b) { return  eval(a) - eval(b);} );
    var numCorrect = 0;
    if ( aUserAns.length != aCorrAns.length ) return notifyField(false, flag, fieldname);
    for ( var _i=0; _i< aCorrAns.length; _i++) {
        var retn = _ProcResp(flag,aCorrAns[_i],aUserAns[_i],n,epsilon,"[0,1]","i:_x",oComp);
        if ( retn == null ) return syntaxError(), null;
        numCorrect += (retn) ? 1 : 0;
    }
    console.println( aUserAns.toSource() );
    var success = (numCorrect == aCorrAns.length) ? true : false;
    if ( success == null ) return syntaxError(), null;
    return notifyField(success, flag, fieldname);
}
%    \end{macrocode}
% The function \texttt{ProcRespListFormula} can be used to process a comma-delimited
% \emph{ordered} list of expressions.
%    \begin{macrocode}
function ProcRespListFormula(flag,CorrAns,n,epsilon,a,indepVar,oComp) {
     ok2Continue = true;
     if (!ProcessIt) return null;
     var fieldname = event.target.name;
     var UserAns = event.value;
     UserAns = stripWhiteSpace(UserAns);
     if (!ok2Continue) return null;
     var aUserAns = UserAns.split(",");
     var aCorrAns = CorrAns.split(",");
     var numCorrect = 0;
     if ( aUserAns.length != aCorrAns.length ) return notifyField(false, flag, fieldname);
     for ( var i=0; i< aCorrAns.length; i++) {
         var retn =_ProcResp(flag,aCorrAns[i],aUserAns[i],n,epsilon,a,indepVar,oComp);
         if ( retn == null ) return syntaxError(), null;
         numCorrect += (retn) ? 1 : 0;
     }
     var success = (numCorrect == aCorrAns.length) ? true : false;
     if ( success == null ) return syntaxError(), null;
     return notifyField(success, flag, fieldname);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%
% \subsection{Compare Functions}\label{s:compfunctions}
%
% \textbf{Used by Exerquiz.}   A compare function is a JavaScript that compares the author's answer
% with the user's answer. There may be a need for compare functions other than the default one provided
% by \texttt{exerquiz}.
%
% \subsubsection{\texttt{indefIntegral}}\label{indefIntegral}
%    \begin{macro}{indefIntegral}
% The answer to an indefinite integral is nonunique; however all answers differ by a constant.
% This compare function is used with indefinite integrals. See \texttt{jqzspec.tex} for an
% example of the use of this function. Note the name of the function is \texttt{indefCompare}, this
% is the name you use to call the function. An example of usage of this function can be found in
% the sample file \texttt{jslib\_ex.tex} that comes with the Acro\TeX{} Bundle; from that file we
% have:
%\begin{verbatim}
%$\displaystyle\int\sin(x)\,dx =
%    \RespBoxMath{-cos(x)}[intSin]{4}{.0001}{[0,1]}[indefCompare]$
%\end{verbatim}
% See also the file \texttt{jqzspec.tex} for more details.
%    \begin{macrocode}
\begin{library@holding}{indefIntegral}
\begin{newsegment}{dljslib: Indefinite Integral Handling}
function indefCompare(_a,_c,_v,_F,_G) {
    var eqC;
    var aAB = _a.split(",");
    var aXY = _c.split(",");
    var _V = _v.split(",");  // e.g. _V[0] = "i:x"
    var _n = aXY.length
%    with(Math) {                   // dps/change 02/23/07
        for (var _i=0; _i< _n; _i++)
        {
            if (_V[_i].charAt(0) == "r" )
                eval ( "var "+ _V[_i].charAt(2) + " = " + aAB[2*_i] + ";");
%            eval ( "var "+_v[i] + " = " + aAB[2*i] + ";" );
            else // assume type "i"
                eval ( "var "+ _V[_i].charAt(2) + " = " + ceil(aAB[2*_i]) + ";");
        }
% var C = 0 is used to designate an arbitrary constant
        var C = 0;
        if ( app.viewerVersion >= 5)
        {
            var rtnCode = 0;
            eval("try { if (isNaN(eqC = eval(_F)-eval(_G))) rtnCode=-1; } catch (e) { rtnCode=1; }");
            switch(rtnCode)
            {
                case  0: break;
                case  1: return null;
                case -1: return -1;
            }
        }
        else
            if (isNaN(eqC = eval(_F)-eval(_G))) return -1;
        for (var _i=0; _i< _n; _i++)
        {
            if (_V[_i].charAt(0) == "r" )
                eval ( "var "+ _V[_i].charAt(2) + " = " + aXY[_i] + ";");
            else // assume type "i"
                eval ( "var "+ _V[_i].charAt(2) + " = " + ceil(aXY[_i]) + ";");
        }
%            eval ( "var "+_v[i] + " = " + aXY[i] + ";" );
        _F = eval(_F);
        if ( app.viewerVersion >= 5)
        {
            var rtnCode = 0;
            eval("try { if(isNaN(_G = eval(_G))) rtnCode=-1; } catch (e) { rtnCode=1; }");
            switch(rtnCode)
            {
                case  0: break;
                case  1: return null;
                case -1: return -1;
            }
        }
        else
            if(isNaN(_G = eval(_G))) return -1;
        return Math.abs( _F - _G - eqC );
%    }      dps/change 02/23/07
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \end{macro}
% \subsection{Filter User's Responses}
% The following two function were contributed by Ross Moore and Frances Griffin, and were taken
% from their \href{http://rutherglen.ics.mq.edu.au/~macqtex/}{MacQ\TeX} online testing system. See the sample file \texttt{integer\_tst.tex} for sample usage.
% These two functions take \texttt{UserAns} as a parameter and return \texttt{null} or \texttt{true} to signal
% the user expression is not an acceptable response, or that it's ok for processing, respectively.
%    \begin{macrocode}
\begin{library@holding}{nodec}
%    \end{macrocode}
% \subsubsection{\texttt{nodec}}
% Do not allow the use of decimal numbers. (Just searches of ``.''.)
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - No Decimals}
function nodec(UserAns)
{
    var dot = /\./;
    if (dot.test(UserAns)) {
        app.alert("A decimal answer is not acceptable here."
            + " Please express your answer using fractions, square roots, "
            + "e, log, etc.");
        return null;
    } else return true;
}
\end{newsegment}
\end{library@holding}
\begin{library@holding}{noBinFac}
%    \end{macrocode}
% \subsubsection{\texttt{noBinFac}}
% Disallow binomial coefficients and factorials in math fill-ins.
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - No Binomial Coefficients Allowed}
function noBinFac(UserAns)
{
    var bad = /(C\()/;
    if (bad.test(UserAns)) {
        app.alert("You may not use this notation here. "
            + "Please evaluate the binomial coefficient. "
            +  "You may present your answer as a product rather than calculating a very large number.",3);
        return null;
    }
    var bad = /(P\()/;
    if (bad.test(UserAns)) {
        app.alert("You may not use this notation here. "
            + "Please evaluate the permutation. "
            + "You may present your answer as a product rather than calculating a very large number.",3);
        return null;
    }
    bad = /(fact)/;
    if (bad.test(UserAns)) {
    app.alert("You may not use this notation here. "
        + "Please evaluate the factorial."
        + "You may present your answer as a product rather than calculating a very large number.",3);
        return null;
    }
    return true
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \begin{macrocode}
\begin{library@holding}{limitArith}
%    \end{macrocode}
% \subsubsection{\texttt{Limit Arithmetic Operations \& Built-in Functions}}
% A collection of functions to limit the use of the arithmetic operations and to limit
% the use of the trig functions. These functions are called through an optional parameter
% of \cs{RespBoxMath}, as illustrated below and in the demo document \texttt{limarith.tex}.
%    \begin{macrocode}
\begin{newsegment}{dljslib: Limit Arithmetic and Built in Functions}
%    \end{macrocode}
% The \texttt{DecimalsOnly} is a function that takes only numbers, either integer or decimal.
% Usage
%\begin{verbatim}
% $ 2.3 + 4.5 = \RespBoxMath[\rectW{.75in}\textSize{0}]{6.8}{1}{.0001}{[0,1]}
%    [{priorParse: DecimalsOnly }]\CorrAnsButton{6.8}$
%\end{verbatim}
%    \begin{macrocode}
function DecimalsOnly(UserAns)
{
    var errorStr = "Enter only an integer, e.g., 17, or a decimal number, e.g. 12.4. "
        + "Using arithmetic operations or built in function is not acceptable for this problem."
    UserAns  = stripWhiteSpace(UserAns);
    if ( !ok2Continue ) return null;
    if( !isFinite( UserAns ) ) {
        app.alert(errorStr);
        return null;
    }
    return true;
}
%    \end{macrocode}
% The function \texttt{NoProducts} requires that \texttt{ImplMulti} be taken.
% An example of usage is
%\begin{verbatim}
%$ 3/4 = \RespBoxMath[\rectW{.75in}\textSize{0}]{.75}{1}{.0001}{[0,1]}
%    [{priorParse: new Array(NoDivision, NoProducts) }]\CorrAnsButton{.75}$
%\end{verbatim}
% In the above example, we first call \texttt{NoDivision} then \texttt{NoProducts}. This is
% the way you can chain these filtering functions together.
%    \begin{macrocode}
function NoProducts (UserAns)
{
    // Requires the ImplMulti option of dljslib
    UserAns  = stripWhiteSpace(UserAns);
    if ( !ok2Continue ) return null;
    UserAns = Ck4Products(UserAns);
    if ( /\*/.test( UserAns ) ) {
        app.alert( "Multiplication is not allowed for this problem.");
        return null;
    }
    return true;
}
function NoDivision (UserAns)
{
    if ( /\//.test( UserAns) ) {
        app.alert( "Division is not allowed for this problem.");
        return null;
    }
    return true;
}
%    \end{macrocode}
% This function, as the name implies, denies the use of both addition and subtraction.
% The algorithm I use here is that if a plus or minus follows anything but a left parenthesis,
% we assume it is a binary operation of addition or subtraction, respectively.
%\begin{verbatim}
%$ 5.1 - 3.2 = \RespBoxMath[\rectW{.75in}\textSize{0}]{1.9}{1}{.0001}{[0,1]}
%       [{priorParse: NoAddOrSub }]\CorrAnsButton{1.9}$
%\end{verbatim}
%    \begin{macrocode}
function NoAddOrSub (UserAns)
{
    UserAns  = stripWhiteSpace(UserAns);
    if ( !ok2Continue ) return null;
    UserAns = UserAns.replace(/\[|\{/g, "\(");
    UserAns = UserAns.replace(/\]|\}/g, "\)");
    var result;
    var re = /.[+-]/g;
    re.lastIndex = 0;
    while ( (result = re.exec( UserAns )) != null ) {
        if ( result[0].charAt(0) != "\(" ) {
            app.alert( "Neither addition nor subtraction is not allowed for this problem.");
            return null;
        }
    }
    return true;
}
%    \end{macrocode}
% Deny user the use of all arithmetic functions, including exponents.
%    \begin{macrocode}
function NoArithAllowed (UserAns)
{
    var aNoArithmetic = new Array ( NoAddOrSub, NoProducts, NoDivision, NoExpAllowed );
    for ( var i = 0; i < aNoArithmetic.length; i++ )
        if ( (retn = aNoArithmetic[i](UserAns)) == null ) return null;
    return true;
}
%    \end{macrocode}
% Deny user the use of exponents.
%    \begin{macrocode}
function NoExpAllowed (UserAns)
{
    // Requires the ImplMulti option of dljslib
    UserAns  = stripWhiteSpace(UserAns);
    if ( !ok2Continue ) return null;
    if ( /\^/.test( UserAns ) || /pow/.test( UserAns ) ) {
        app.alert( "The use of exponents is not allowed for this problem.");
        return null;
    }
    return true;
}
%    \end{macrocode}
% Deny user the use all trig functions, as well as the constants \texttt{PI} and \texttt{pi},
% which are aliases for $\pi$. Example:
%\begin{verbatim}
%$ \sin(\pi/4) = \RespBoxMath[\rectW{.75in}\textSize{0}]{sqrt(2)/2}{1}{.0001}{[0,1]}
%    [{priorParse: NoTrigAllowed }]\CorrAnsButton{sqrt(2)/2}$
%\end{verbatim}
%You can obviously build similar function to deny the use of logs or square roots, for example.
%\changes{v1.5}{2007/02/05}
%{
% Removed \texttt{"pi"} and \texttt{"PI}" from the \texttt{aTrigFuncs array}, and added
% \texttt{"arcsin"}, \texttt{"arccos"}, "\texttt{arctan"}.
%}
%    \begin{macrocode}
function NoTrigAllowed (UserAns)
{
    UserAns  = stripWhiteSpace(UserAns);
    if ( !ok2Continue ) return null;
    var aTrigfuncs = new Array
    ( "acos","asin","atan","cos", "sin", "tan","sec","csc","cot",
      "arcsin", "arccos", "arctan"
    );
    var re, regexp;
    re = /[a-zA-Z]{2,}/g;
    aF = UserAns.match(re);
    if (  aF != null ) {
        for (var i=0; i < aF.length; i++)
        {
            for(var j=0; j < aTrigfuncs.length; j++) {
                if ( aF[i].indexOf(aTrigfuncs[j]) != -1 ) {
                    app.alert("The use of trig functions in this problem is not allowed.");
                    return null
                }
            }
        }
    }
    return true;
}
function NoTrigLogAllowed (UserAns)
{
    UserAns  = stripWhiteSpace(UserAns);
    if ( !ok2Continue ) return null;
    var aTrigfuncs = new Array
    ( "acos","asin","atan","cos", "sin",
      "tan","sec","csc","cot", "arcsin", "arccos", "arctan",
      "logc","log", "ln"
    );
    var re, regexp;
    re = /[a-zA-Z]{2,}/g;
    aF = UserAns.match(re);
    if (  aF != null ) {
        for (var i=0; i < aF.length; i++)
        {
            for(var j=0; j < aTrigfuncs.length; j++) {
                if ( aF[i].indexOf(aTrigfuncs[j]) != -1 ) {
                    app.alert("The use of trig and log functions is not allowed in this problem.");
                    return null
                }
            }
        }
    }
    return true;
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
% \subsection{\texttt{ParseInput} Extensions}\label{s:parseinput}
% The default behavior for processing a math fill-in question is to
% require the student to insert `\texttt*' for multiplication and to
% enclose any function being raised to a power in parentheses, e.g.
% \verb+x*(sin(x))^2+. This becomes quite tiresome if the expression to be entered
% is complicated. The following two functions enable the student to use
% `implied multiplication' and simplified exponentiation.
%    \begin{macro}{ImplMulti}
% The \texttt{ImplMulti} option loads two JavaScript functions, \texttt{Ck4Products()}
% and \texttt{Ck4Exponents()}.  The latter implements the notation, \verb+sin^2(x)+
% for $\sin^2(x)$, equivalent to $(\sin(x))^2$. The exponent can be complex and enclosed
% in parentheses, for example \verb-ln^(x+1)(x)-. The former function, \texttt{Ck4Products()},
% inserts the multiplication symbol, `\texttt{*}', wherever implied. For example,
% \verb+xysin(xy)+ becomes \verb+x*y*sin(x*y)+.
% \begin{flushleft}
% \textcolor{red}{Important:} If loaded, \texttt{Exerquiz} will automatically use these two functions.
% \end{flushleft}
%    \begin{macrocode}
\begin{library@holding}{ImplMulti}
%    \end{macrocode}
% \subsubsection{ImplMulti}
%    \begin{macrocode}
\begin{newsegment}{dljslib: Implied Multiplication}
%    \end{macrocode}
% The JavaScript function \texttt{Ck4Products()} takes the user input and tries to
% insert the multiplication symbol, `\texttt*', wherever implied.
%    \begin{macrocode}
function Ck4Products(UserInput)
{
    var re, aR;
%    var aRegExp = new Array(/([\d\)])([A-Za-z\(\\])/g, /(\))(\d)/g, /([A-Za-z])([\d\(\\])/g, /(@)([A-Za-z\d])/g );
%    \end{macrocode}
% Search through for matches with known functions
%    \begin{macrocode}
    for (var i=0; i<JSf.length; i++)
    {
%    \end{macrocode}
% Here we mark the beginning of the left parenthesis for a
% that follows one of the  known functions. This way we can
% distinguish between the built in JavaScript functions and
% other sequences of letters that may represent products.
% \begin{flushleft}
% \textbf{Note:} In the regular
% expression below, and elsewhere, when our search includes unbalanced parentheses
% we need to triple escape them, i.e., instead of `\verb+\\(+' we write
% `\verb+\\\(+'. See comments in \texttt{insdlis.dtx}.
% \end{flushleft}
%    \begin{macrocode}
        re = new RegExp("("+JSf[i]+")(\\\()","g");
        UserInput = UserInput.replace(re, "\\$1@$2");
%    \end{macrocode}
% If a known function has a letter or an right parenthesis to the left of it,
% the user must want multiplication, make it so!
%    \begin{macrocode}
        re = new RegExp("([\\w\\\)])(\\"+JSf[i]+")(@\\\()","g");
        UserInput = UserInput.replace(re, "$1*$2$3");
    }
%    \end{macrocode}
% Now do the same type thing for known constants.
%    \begin{macrocode}
    for (var i=0; i<JSc.length; i++)
    {
%    \end{macrocode}
% We mark the beginning and end of a known predefined constant
% \changes{v1.6}{2007/02/23}
%{
%    If we match up with "E", we do nothing. This is support of
%    using "E" for scientific notation.
%}
%    \begin{macrocode}
        re = new RegExp("("+JSc[i]+")","g");
        if ( JSc[i] != "E" ) {
            UserInput = UserInput.replace(re, "\\$1@");
%    \end{macrocode}
% If a known constant has a letter or an right parenthesis to the left of it,
% the user must want multiplication, make it so!
%    \begin{macrocode}
            re = new RegExp("([\\w\\\)])(\\"+JSc[i]+")(@)","g");
        }
    }
%    \end{macrocode}
% Search for a number or right paren followed by a letter or right paren
% and insert *.
%\changes{v1.6}{2007/02/23}
%{
%    dps/change 02/23/07. In the search below, we exclude the search
%   for the letter "E", because it is used for scientific notation (called exponential)
%}
% notation in JavaScript).
%    \begin{macrocode}
%    for (var i=0; i<aRegExp.length; i++)
%        UserInput = UserInput.replace(aRegExp[i], "$1*$2");
%    re = /([\d\)])([A-Za-z\(\\])/g;
%    UserInput = UserInput.replace(/([\d\)])([A-Za-z\(\\])/g, "$1*$2");
    UserInput = UserInput.replace(/([\d\)])([A-DF-Za-z\(\\])/g, "$1*$2");
%    \end{macrocode}
% Search for a right paren followed by a number.
%    \begin{macrocode}
%    re = /(\))(\d)/g;
    UserInput = UserInput.replace(/(\))(\d)/g, "$1*$2");
%    \end{macrocode}
% Search for a letter followed by a number of right paren, and insert *
%    \begin{macrocode}
%    re = /([A-Za-z])([\d\(\\])/g;
    UserInput = UserInput.replace(/([A-Za-z])([\d\(\\])/g, "$1*$2");
%    \end{macrocode}
% If a predefined constant, such as \texttt{PI}, is begin multiplied on the
% right by a factor, there will be a \texttt{@} followed by a letter or decimal.
%    \begin{macrocode}
%    re = /(@)([A-Za-z\d])/g;
    UserInput = UserInput.replace(/(@)([A-Za-z\d])/g, "$1*$2");
%    \end{macrocode}
% Now strip off the markers
%    \begin{macrocode}
    UserInput = UserInput.replace(/(\\)([A-Za-z]{1,})(@)/g, "$2"); % dps MacQTeX change
%    UserInput = UserInput.replace(/(\\)([A-Za-z]{2,})(@)/g, "$2");
%    re = /(\\)([A-Za-z]{2,})(@)/g;
%    UserInput = UserInput.replace(re, "$2");
%    \end{macrocode}
%  Search through list of known functions for a match.
%    \begin{macrocode}
%    re = /[A-Za-z]{2,}/g;
    re = /[A-Za-z]{1,}/g;    % MacQTeX change   dps/change 02/23/07
    while ( (aR = re.exec(UserInput)) != null)
    {
        for (var i=0; i<JSf.length; i++) if ( aR[0] == JSf[i]) break;
        if ( i < JSf.length ) continue;
        for (var i=0; i<JSc.length; i++) if ( aR[0] == JSc[i]) break;
        if ( i < JSc.length ) continue;
%    \end{macrocode}
% If there is no match with known functions or constants, then we need to assume
% this word is a series of products, and separate them on their non-word
% boundaries by a multiplication operator *. We will not be able to identify
% mistyped functions, for example, if the user enters \texttt{cis(x)} instead of
% \texttt{cos(x)}, this will end up as \texttt{c*i*s*(x)}. Ultimately,
% the user will get a message that there is an error in the expression, but not
% hints as to what the error is will not be given.
%    \begin{macrocode}
        aR[0] = aR[0].replace(/([A-Za-z])\B/g,"$1*");
        UserInput = UserInput.substring(0,aR.index)+aR[0]+UserInput.substring(re.lastIndex);
    }
    return UserInput;
}
%    \end{macrocode}
% The function \texttt{Ck4Exponents()} attempts to convert the notation \verb+sin^2(x)+
% into standard JavaScript format of \texttt{pow(sin(x),2)}.
%    \begin{macrocode}
function Ck4Exponents(UserInput)
{
    var re, regexp, aP, RightP;
    for (var i=0; (i<JSf.length) && (ok2Continue); i++)
    {
        re = new RegExp(JSf[i]+"\\^");
        while ( re.test(UserInput) && (ok2Continue) )
        {
%    \end{macrocode}
% Here we seek to match an expression of the form: \verb+cos^(exp)(arg)+
%    \begin{macrocode}
            regexp = new RegExp(JSf[i]+"\\^\\\(", "g");
            if ( (aP = regexp.exec(UserInput)) != null )
            {
                RightP=FindBalP(UserInput,regexp.lastIndex-1,1); // forward search
                var offsetExp = RightP-regexp.lastIndex;
                regexp = new RegExp(JSf[i]+"\\^\\(.{"+offsetExp+"}\\)\\\(", "g");
                regexp.lastIndex=0;
                if ( (aP = regexp.exec(UserInput)) != null )
                {
                    RightP=FindBalP(UserInput,regexp.lastIndex-1,1); // forward search
                    var offsetArg = RightP - regexp.lastIndex;
                    regexp = new RegExp("("+JSf[i]+")\\^\\((.{"+offsetExp+"})\\)\\((.{"+offsetArg+"})\\)");
                    regexp.lastIndex=0;
                    if (regexp.test(UserInput)) UserInput=UserInput.replace(regexp,"pow($1($3),$2)");
                    else ok2Continue=false;
                    continue;
                }
            }
%    \end{macrocode}
% Here we seek to match an expression of the form: \verb+cos^\pmNum.Num(arg)+
%    \begin{macrocode}
            regexp = new RegExp(JSf[i]+"\\^([a-zA-Z]|[+-]?\\d+\\.?\\d*|[+-]?\\d*\\.?\\d+)\\\(","g");
            if ( (aP = regexp.exec(UserInput)) != null )
            {
                RightP=FindBalP(UserInput,regexp.lastIndex-1,1); // forward search
                regexp = new RegExp("("+JSf[i]+")\\^([a-zA-Z]|[+-]?\\d+\\.?\\d*|[+-]?\\d*\\.?\\d+)\\((.{"
                    +eval(RightP-regexp.lastIndex)+"})\\)");
                regexp.lastIndex=0;
                if (regexp.test(UserInput)) UserInput=UserInput.replace(regexp,"pow($1($3),$2)");
                else ok2Continue=false;
            }
            else ok2Continue=false;
        }
    }
%    \end{macrocode}
% Now we do the same thing for declared constants.
%    \begin{macrocode}
    for (var i=0; (i < JSc.length) && (ok2Continue); i++)
    {
        re = new RegExp(JSc[i]+"\\^", "g");
        while ( re.test(UserInput) && (ok2Continue) )
        {
            re.lastIndex = 0;
            aR = re.exec(UserInput);
            if (UserInput.charAt(re.lastIndex)=='\(')
            {
                RightP=FindBalP(UserInput,re.lastIndex,1); // forward search
                var offsetExp = RightP - re.lastIndex - 1;
                re.lastIndex=0;
                regexp = new RegExp("("+JSc[i]+")\\^\\((.{"+offsetExp+"})\\)");
                if ( regexp.test(UserInput) )
                    UserInput = UserInput.replace(regexp, "pow($1,$2)");
                else ok2Continue = false;
            }
            else
            {
                re.lastIndex=0;
                regexp = new RegExp("("+JSc[i]+")\\^([a-zA-Z]|[+-]?\\d+\\.?\\d*|[+-]?\\d*\\.?\\d+)");
                if (regexp.test(UserInput))
                    UserInput = UserInput.replace(regexp, "pow($1,$2)");
                else ok2Continue = false;
            }
        }
    }
    return UserInput;
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \end{macro}
% \subsection{User Contributions}
% The following are contributions by Ross Moore and Frances Griffin, from their work
% on \href{http://rutherglen.ics.mq.edu.au/~macqtex/}{MacQ\TeX}. These define function of an integer variable: combinations, permutations and factorials.
% These can be used for math fill-ins.
%    \begin{macrocode}
\begin{library@holding}{combinatorics}
%    \end{macrocode}
% \subsubsection{\texttt{combinatorics}}
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - Combinatorial Functions}
function ch(n,r)
{
    if ((n==r)||(r==0)) return(1);
    if ((n==(r+1))||(r==1)) return(n);
    if (r > (n-r))
        var coeff = factorialCancel(expandFactorial(r+1,n),expandFactorial(1,n-r));
    else
        var coeff = factorialCancel(expandFactorial(n-r+1,n),expandFactorial(1,r));
    return (eval(coeff));
}
function perm(n,r)
{
    if (r==0) return(1);
    else
        var coeff = factorialCancel(expandFactorial(n-r+1,n),expandFactorial(1,n-r));
    return (eval(coeff));
}
%%% factorialCancel and expandFactorial are needed by binomialCoeff
function expandFactorial(lo,hi)
{
    var f = lo;
    for (var i=lo+1;i<=hi;i++) f = i+"*"+f;
    return f;
}
% factorialCancel cancels common factors in num and denom using strings produced
% by expandFactorial. It expects tails of factorials to have already been cancelled.
function factorialCancel(top,bot)
{
    var num = top.split("*");
    var denom = bot.split("*");
    var len = denom.length;
    var temp = 0;
    var i, j;
    for (i=0;i<=len-1;i++) {
        for (j=0;j<=len-1;j++) {
            temp = num[i]/denom[j];
            if ((temp - Math.round(temp)) == 0) {
                num[i] = temp;
                denom[j] = 1;
            }
        }
    }
    var t = denom.join("");
    var reg = /[^1]/;
    if (reg.test(t)) {
        temp = factorialCancel(denom.join("*"),num.join("*"));
    } else {
        temp = num.join("*");
    }
    return (temp);
}
function fact(num)
{
    var tot = 1;
    for (var r=1; r <= num; r++) tot *= r;
    return(tot);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
% The following functions, which are \texttt{ProcResp}-types, were written for an online
% grading system being developed by Drs.\ Bruce Wagner and David Arnold, and Mr.
% Jacob Miles-Prystowsky.  The descriptions given below were provided by the authors.
%    \begin{macrocode}
\begin{library@holding}{unordered}
%    \end{macrocode}
% \subsubsection{\texttt{unordered}}
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - Processing Unordered Responses}
%    \end{macrocode}
%  The JS function \texttt{ProcRespSetFormula} will grade an
%  unordered list of formulas, such as
%  \texttt{x}, \verb!x^2!, \verb!x^3!. The code is a modification of
%  \texttt{ProcRespListFormula}. The idea is to split the user and correct
%  answers and then compare the first correct answer with each of the
%  user answers in turn. If there is a match, swap that user answer
%  with the first user answer. Then compare the second correct answer
%  with the rest of the user answers, and continue in that way.
%\begin{flushleft}
% Usage:
%\begin{verbatim}
%\def\formulabox#1#2#3{\RespBoxMath{#1}(#2){4}{1.0E-15}{#3}}
%Some question requiring an unordered list of responses.
%\formulasetbox{x,x^2,x^3}{x}{[1,2]}
%\end{verbatim}
%\end{flushleft}
%    \begin{macrocode}
function ProcRespSetFormula(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
    ok2Continue = true;
    if (!ProcessIt) return null;
    var fieldname = event.target.name;
    var UserAns = event.value;
    UserAns = stripWhiteSpace(UserAns);
    if (!ok2Continue) return null;
    var aUserAns = UserAns.split(",");
    var aCorrAns = CorrAns.split(",");
    var numCorrect = 0;
    var match = 0;
    if ( aUserAns.length != aCorrAns.length ) return notifyField(false, flag, fieldname);
    for ( var i=0; i< aCorrAns.length; i++) {
        match = 0;
        for ( var j=i; j< aUserAns.length; j++) {
            var retn = _ProcResp(flag,aCorrAns[i],aUserAns[j],n,epsilon,a,indepVar,oComp);
            if ( retn == null ) return syntaxError(), null;
            if (retn==1) {
               var temp=aUserAns[j];
               aUserAns[j]=aUserAns[i];
               aUserAns[i]=temp;
               match = match + 1;
            }
        }
        numCorrect += (match) ? 1 : 0;
    }
    var success = (numCorrect == aCorrAns.length) ? true : false;
    if ( success == null ) return syntaxError(), null;
    return notifyField(success, flag, fieldname);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \begin{macrocode}
\begin{library@holding}{factors}
%    \end{macrocode}
% \subsubsection{\texttt{factors}}
%  \texttt{ProcRespFactors} is for grading polynomial factoring
%  questions. For example, if a polynomial factors as
%  \verb!-5x^2(x-4)(x+2)!, then the answer is only unique up to the order of
%  factors and a change of sign on an even number of factors. For
%  example, it could also be written as \verb!-5x^2(x+2)(x-4)! or
%  \verb!5x^2(-x+4)(x+2)! or \verb!-5(x-4)(x+2)x^2!, etc. This script
%  should grade all of these correctly. (However, it will not allow
%  something like \verb!-(x-4)(x+2)5x^2!. The leading coefficient, if
%  there is one, must be placed at the beginning, which conforms to
%  our usual conventions.)
%\begin{flushleft}
% Usage:
%\begin{verbatim}
%\def\factorsbox#1#2#3{\RespBoxMath{#1}(#2){4}{1.0E-15}{#3}*{ProcRespFactors}}
%Some question requiring a factored response
%\factorsbox{3x(x^2+1)(2x-1)^3}{x}{[0,1]}
%\end{verbatim}
%\end{flushleft}
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - Processing Factors as Responses}
function ProcRespFactors(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
    ok2Continue = true;
    if (!ProcessIt) return null;
    var fieldname = event.target.name;
    var UserAns = event.value;
    UserAns = stripWhiteSpace(UserAns);
    if (!ok2Continue) return null;
    var retn = _ProcResp(flag,CorrAns,UserAns,n,epsilon,a,indepVar,oComp);
    if ( retn == null ) return syntaxError(), null;
    if ( retn == 0 ) {
        var initialsuccess = false;
        return notifyField(initialsuccess, flag, fieldname);
    }
    UserAns = UserAns.replace(/\*/g, "");
    UserAns = UserAns.replace(/([A-Za-z]\^\d+)\(/g, "($1)(");
    UserAns = UserAns.replace(/\)([A-Za-z]\^\d+)/g, ")($1)");
    UserAns = UserAns.replace(/([A-Za-z])\(/g, "($1)(");
    UserAns = UserAns.replace(/\)([A-Za-z])/g, ")($1)");
    UserAns = UserAns.replace(/\)\(/g, "),(");
    UserAns = UserAns.replace(/(\w)\(/g, "$1,(");
    UserAns = UserAns.replace(/\)(\w)/g, "),$1");
    CorrAns = CorrAns.replace(/\*/g, "");
    CorrAns = CorrAns.replace(/([A-Za-z]\^\d+)\(/g, "($1)(");
    CorrAns = CorrAns.replace(/\)([A-Za-z]\^\d+)/g, ")($1)");
    CorrAns = CorrAns.replace(/([A-Za-z])\(/g, "($1)(");
    CorrAns = CorrAns.replace(/\)([A-Za-z])/g, ")($1)");
    CorrAns = CorrAns.replace(/\)\(/g, "),(");
    CorrAns = CorrAns.replace(/(\w)\(/g, "$1,(");
    CorrAns = CorrAns.replace(/\)(\w)/g, "),$1");
    var NegCorrAns = CorrAns;
    var aUserAns = UserAns.split(",");
    var aCorrAns = CorrAns.split(",");
    var aNegCorrAns = NegCorrAns.split(",");
    for ( var i=0; i< aNegCorrAns.length; i++) {aNegCorrAns[i] = "-" + "(" + aNegCorrAns[i] + ")"}
    var numCorrect = 0;
    var match = 0;
    var signflag=0;
    if ( aUserAns.length != aCorrAns.length ) return notifyField(false, flag, fieldname);
    for ( var i=0; i< aCorrAns.length; i++) {
        match = 0;
        for ( var j=i; j< aUserAns.length; j++) {
            var retn = _ProcResp(flag,aCorrAns[i],aUserAns[j],n,epsilon,a,indepVar,oComp);
            if ( retn == null ) return syntaxError(), null;
            if (retn==1) {
                var temp=aUserAns[j];
                aUserAns[j]=aUserAns[i];
                aUserAns[i]=temp;
                match = match + 1;
            }
            else {
                var retn = _ProcResp(flag,aNegCorrAns[i],aUserAns[j],n,epsilon,a,indepVar,oComp);
                if ( retn == null ) return syntaxError(), null;
                if (retn==1) {
                    var temp=aUserAns[j];
                    aUserAns[j]=aUserAns[i];
                    aUserAns[i]=temp;
                    match = match + 1;
                    signflag = signflag + 1;
                }
            }
        }
        numCorrect += (match) ? 1 : 0;
    }
    var success = ((numCorrect == aCorrAns.length) && (signflag\%2 == 0)) ? true : false;
    if ( success == null ) return syntaxError(), null;
    return notifyField(success, flag, fieldname);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \begin{macrocode}
\begin{library@holding}{point}
%    \end{macrocode}
% \subsubsection{\texttt{point}}
%  The JS function \texttt{ProcPoint} is an almost exact copy of your
%  \texttt{ProcVec}, but uses parentheses instead of angle brackets as
%  delimiters. This is for questions that have a point $(x,y)$ as the
%  answer.
%\begin{flushleft}
% Usage:
%\begin{verbatim}
%\def\formulapointbox#1#2#3{\RespBoxMath{#1}(#2){4}{1.0E-15}{#3}*{ProcPoint}}
%Some question requiring a point (ordered pair) response
%\formulapointbox{(e^t,te^t)}{t}{[0,1]}
%\end{verbatim}
%\end{flushleft}
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - Processing a Point Response}
function ProcPoint(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
    if (!ProcessIt) return null;
    ok2Continue = true;
%   var i, success, truthCnt=0;
    var i, success, truthCnt=1;
    var aScalar, scalar = 1;
    var fieldname = event.target.name;
    var UserAns = event.value;
% Implement an "undefined" answer. Due to Ross-Griffin
    if (UserAns == "undefined") {
        success = (CorrAns == UserAns);
        return notifyField(success, flag, fieldname);
    }
    CorrAns = stripWhiteSpace (CorrAns);
    UserAns = stripWhiteSpace (UserAns); // sets ok2Continue
    if ( !ok2Continue ) return null;
    if (!/[()]/.test(UserAns)) {
        app.alert("I'm looking for a point. You need to use proper point notation.", 3);
        return null;
    }
    if (!CkBalP(UserAns,"(",")")) {
        app.alert("Parentheses are not balanced.", 3);
        return null;
    }
%    \end{macrocode}
% If \texttt{oComp} is an object, then see if it has a \texttt{comp} property
%    \begin{macrocode}
    var comp = ( typeof oComp == "object" ) ?
       (typeof oComp.comp == "undefined" ) ? diffCompare : oComp.comp : oComp;
    CorrAns = CorrAns.replace(/[()]/g, ""); // strip off ( and )
    UserAns = UserAns.replace(/[()]/g, "");
%    \end{macrocode}
% The \texttt{comp} parameter, which has been changed to \texttt{oComp} can now be
% an object. One property of this object is \texttt{comp}, handled above. Another
% property is \texttt{priorParse}, this is a function that returns \texttt{null}
% or \texttt{true}. This \texttt{priorParse} function allows for additional
% filtering of the \texttt{UserAns} before parsing. If it returns \texttt{true},
% we are ok to continue, if \texttt{null}, we don't like something the user has entered,
% and ask him/her to change it.
%    \begin{macrocode}
    if ( typeof oComp == "object" && typeof oComp.priorParse != "undefined" )
    {
%    \end{macrocode}
% Let's go ahead and allow \texttt{oComp.priorParse} be an array of functions.
%    \begin{macrocode}
        if ( typeof oComp.priorParse == "object" )
        {
            for ( var i=0; i < oComp.priorParse.length; i++)
            {
                var retn = oComp.priorParse[i](UserAns);
                if ( retn == null ) return null;
            }
        } else {
            var retn = oComp.priorParse(UserAns);
            if ( retn == null ) return null;
        }
    }
% Not convert each to an array
    aUserAns = UserAns.split(",");
    aCorrAns = CorrAns.split(",");
    if (scalar != 1)
        for (i=0; i<aUserAns.length; i++)
            aUserAns[i]=""+scalar+"*"+aUserAns[i];
    if (aCorrAns.length != aUserAns.length) {
        app.alert("Incorrect number of components. The answer requires "
            + aCorrAns.length+" components.",3);
        return null;
    }
    indepVar = TypeParameters(indepVar); // convert to new format, if needed
    for (i=0; i<aCorrAns.length; i++) {
        aCorrAns[i] = ParseInput(aCorrAns[i]);
        if (!ok2Continue) {
            app.alert("Author Syntax error!", 3);
            return null;
        }
        aUserAns[i] = ParseInput(aUserAns[i]);
        if (!ok2Continue) return null;
        success=randomPointCompare (n,a,indepVar,epsilon,aCorrAns[i],aUserAns[i],comp)
        if ( success == null ) { app.alert(\eqSyntaxErrorUndefVar,3); return null; }
        truthCnt *= (success) ? 1 : 0;
%-        if (success) truthCnt +=1;
    }
%    return notifyField((truthCnt == 3), flag, fieldname);
    return notifyField(!!truthCnt, flag, fieldname);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
%    \begin{macrocode}
\begin{library@holding}{intervals}
%    \end{macrocode}
% \subsubsection{\texttt{intervals}}
%  \texttt{ProcRespIntervals} is for grading questions that have an
%  interval or union of intervals as the answer. Example answers
%  include:
%\begin{verbatim}
%(2,3)
%[2,3]
%(-inf,4)
%(-inf,4]
%(6,inf)
%[6,inf)
%(2,3)U[8,9)
%(-inf,6)U(9,inf)
%(-inf,6]U[7,8)U(9,inf)
%\end{verbatim}
%  Here I've used "inf" for infinity and the capital letter "U" for
%  the union symbol. Note also that intervals in a union can appear
%  in any order.
%\begin{flushleft}
%The \texttt{ProcRespIntervals} function has been modified by Robert Marik
%to allow intervals with end points \texttt{ln(2)}, \texttt{exp(4)} or \texttt{sqrt(3)}.
%Thus, intervals of the form
%\verb!(ln(2),ln(3)]U(exp(10),inf)! are recognized by this procedure.
%\medskip\noindent
% Usage:
%\begin{verbatim}
%\def\intervalbox#1{\RespBoxMath{#1}(infU){10}
%    {1.0E-4}{[0,1]x[0,1]x[0,1]x[0,1]}*{ProcRespIntervals}}
%Some question requiring an interval or union of intervals
%\intervalbox{(-inf,4]U[5,inf)}
%\end{verbatim}
% To avoid problems with unbalanced parentheses, as in this example,
%\verb!\intervalbox{(-inf,4)U[5,inf)}!.
% Here there is only one right parenthesis and two left parentheses. As a
% workaround, escape the odd
% parenthesis, like so
%\verb!\intervalbox{(-inf,4)U[5,inf\eqbs)}!,
% where \cs{eqbs} is defined in the \textsf{insdljs} package.
%\end{flushleft}
%    \begin{macrocode}
\begin{newsegment}{dljslib: Contrib - Processing Interval Responses}
function ProcRespIntervals(flag,CorrAns,n,epsilon,a,indepVar,oComp)
{
     ok2Continue = true;
     if (!ProcessIt) return null;
     var fieldname = event.target.name;
     var UserAns = event.value;
     UserAns = stripWhiteSpace(UserAns);
     CorrAns = stripWhiteSpace(CorrAns);
     if (!ok2Continue) return null;
     UserAns = UserAns.replace(/inf/g, "x");
     CorrAns = CorrAns.replace(/inf/g, "x");
     indepVar = "x";
     a="[0,1]";
     var aUserAns = UserAns.split("U");
     var aCorrAns = CorrAns.split("U");
     var numCorrect = 0;
     var match = 0;
     var matchparts = 0;
     if ( aUserAns.length != aCorrAns.length ) return notifyField(false,flag, fieldname);
     for ( var i=0; i< aCorrAns.length; i++) {
         match = 0;
         for ( var j=i; j< aUserAns.length; j++) {
             CorrInt=aCorrAns[i];
             UserInt=aUserAns[j];
             var levaUser = UserInt.charAt(0);
             var pravaUser = UserInt.charAt(UserInt.length-1);
             var stredUser = UserInt.substring(1,UserInt.length-1);
             UserInt = levaUser+","+stredUser+","+pravaUser;
             var levaCorr = CorrInt.charAt(0);
             var pravaCorr = CorrInt.charAt(CorrInt.length-1);
             var stredCorr = CorrInt.substring(1,CorrInt.length-1);
             CorrInt = levaCorr+","+stredCorr+","+pravaCorr;
             var aCorrInt = CorrInt.split(",");
             var aUserInt = UserInt.split(",");
             if ( aUserInt.length != 4 ) return notifyField(false, flag, fieldname);
             matchparts = 0;
             if (aCorrInt[0] == aUserInt[0]) matchparts+=1;
             if (aCorrInt[3] == aUserInt[3]) matchparts+=1;
             var retn1 = _ProcResp(flag,aCorrInt[1],aUserInt[1],n,epsilon,a,indepVar,oComp);
             if (retn1 == null) return syntaxError(), null;
             if (retn1 == 1) matchparts+=1;
             var retn2 = _ProcResp(flag,aCorrInt[2],aUserInt[2],n,epsilon,a,indepVar,oComp);
             if (retn2 == null) return syntaxError(), null;
             if (retn2 == 1) matchparts+=1;
             if (matchparts == 4) {
                 var temp=aUserAns[j];
                 aUserAns[j]=aUserAns[i];
                 aUserAns[i]=temp;
                 match = match + 1;
             }
         }
         numCorrect += (match) ? 1 : 0;
     }
     var success = (numCorrect == aCorrAns.length) ? true : false;
     if (success == null) return syntaxError(), null;
     return notifyField(success, flag, fieldname);
}
\end{newsegment}
\end{library@holding}
%    \end{macrocode}
% Finally, we have the ``back wrapper'' or ``back cover'' of the selected materials. We close the
% \texttt{insDLJS} environment
%    \begin{macrocode}
\begin{library@holding}{dljslib}
\end{insDLJS*}
\end{library@holding}
%    \end{macrocode}
% \section{Out the Door and Close it behind you}
%    \begin{macrocode}
\immediate\closeout\dljslib@verbatim@out
%    \end{macrocode}
% \section{Back Home with your Selections}
%    \begin{macrocode}
\input{dljslib.ljs}
%</package>
%    \end{macrocode}
\endinput
