summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/ran_toks/ran_toks.dtx
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-01-26 03:01:06 +0000
committerNorbert Preining <norbert@preining.info>2021-01-26 03:01:06 +0000
commit94ac70b92400e4b95d43d570ad53a713c036118b (patch)
treef312a316fd2dc7070b7550ece5dbb3d25be5f480 /macros/latex/contrib/ran_toks/ran_toks.dtx
parent31152d888efa58265aef8521042ad58c300f9576 (diff)
CTAN sync 202101260301
Diffstat (limited to 'macros/latex/contrib/ran_toks/ran_toks.dtx')
-rw-r--r--macros/latex/contrib/ran_toks/ran_toks.dtx470
1 files changed, 400 insertions, 70 deletions
diff --git a/macros/latex/contrib/ran_toks/ran_toks.dtx b/macros/latex/contrib/ran_toks/ran_toks.dtx
index 89aafdc826..5549bbc01c 100644
--- a/macros/latex/contrib/ran_toks/ran_toks.dtx
+++ b/macros/latex/contrib/ran_toks/ran_toks.dtx
@@ -4,7 +4,7 @@
%<*copyright>
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% ran_toks package, %%
-%% Copyright (C) 1999-2019 D. P. Story %%
+%% Copyright (C) 1999-2021 D. P. Story %%
%% dpstory@uakron.edu, dpstory@acrotex.net %%
%% %%
%% This program can redistributed and/or modified under %%
@@ -16,10 +16,11 @@
%</copyright>
%<package>\NeedsTeXFormat{LaTeX2e}[1997/12/01]
%<package>\ProvidesPackage{ran_toks}
-%<package> [2019/12/28 v1.2 Randomizing tokens (dps)]
+%<package> [2021/01/19 v1.3.1 Randomizing tokens (dps)]
%<*driver>
\documentclass{ltxdoc}
\usepackage[colorlinks,hyperindex=false]{hyperref}
+\usepackage{fancyvrb}
%\def\texorpdfstring#1#2{#1}
%\pdfstringdefDisableCommands{\let\\\textbackslash}
\OnlyDescription % comment out for implementation details
@@ -37,6 +38,9 @@
\def\meta#1{\textsl{\texttt{#1}}}
\def\SUB#1{\ensuremath{{}_{\mbox{\scriptsize\ttfamily#1}}}}
\def\cs#1{\texttt{\bslash#1}}
+\makeatletter
+\let\@latex@warning@no@line\@gobble
+\makeatother
\InputIfFileExists{aebdocfmt.def}{\PackageInfo{ran_toks}{Inputting aebdocfmt.def}}
{\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax
\PackageInfo{ran_toks}{aebdocfmt.def cannot be found}}
@@ -72,39 +76,42 @@
% \paragraph*{Description.}
% This short package randomizes a list of tokens. The command, \cs{ranToks},
% takes one argument, which is a list of tokens:
-%\begin{quote}\ttfamily
-% \string\ranToks\darg{\ameta{name}}\\
-% \darg{\\\null
-% \qquad\darg{\ameta{tok\SUB1}}\darg{\ameta{tok\SUB2}}...\darg{\ameta{tok\SUB{n}}}\\
-% }
-%\end{quote}
+%\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small,
+%commandchars={!()},codes={\catcode`\%=9}]
+%\ranToks{!ameta(name)}{!%
+%!quad{!ameta(tok!SUB1)}{!ameta(tok!SUB2)}...{!ameta(tok!SUB(n))}
+%}
+%\end{Verbatim}
% The command defines a series of $n$ internal commands, one for each of the tokens.
% The definitions are essentially randomized. The randomized tokens are accessed through
-% the command \cs{useRanTok}. For example
-%\begin{quote}\ttfamily
-%\cs{useRanTok\darg{1}}, \cs{useRanTok\darg{2}},..., \cs{useRanTok\darg{n}}
-%\end{quote}
+% the command \cs{useRanTok}. For example,
+%\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small,
+%commandchars={!()},codes={\catcode`\%=9}]
+%\useRanTok{1}, \useRanTok{2},..., \useRanTok{n}
+%\end{Verbatim}
% gives a random listing of the $n$ tokens. These can be arranged on the page
% as desired.
%
% There is a second construct, designed for more elaborate randomization.
-%\begin{quote}\ttfamily
-%\string\bRTVToks\darg{\ameta{name}}\\
-%\string\begin\darg{rtVW}\\
-%\null\qquad\ameta{some content}\\
-%\string\end\darg{rtVW}\\
-%...\\
-%...\\
-%\string\begin\darg{rtVW}\\
-%\null\qquad\ameta{some content}\\
-%\string\end\darg{rtVW}\\
-%\string\eRTVToks
-%\end{quote}
+%\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small,
+%commandchars={!()},codes={\catcode`\%=9}]
+%\bRTVToks{!ameta(name)}
+%\begin{rtVW}
+%!quad!ameta(some content)
+%\end{rtVW}
+%...
+%...
+%\begin{rtVW}
+%!quad!ameta(some content)
+%\end{rtVW}
+%\eRTVToks
+%\end{Verbatim}
% The contents of each of the \texttt{rtVW} environments are written to the computers hard drive, then input
% back in random order, using \cs{useRanTok}, eg,
-%\begin{quote}\ttfamily
-%\cs{useRanTok\darg{1}}, \cs{useRanTok\darg{2}},..., \cs{useRanTok\darg{n}}
-%\end{quote}
+%\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small,
+%commandchars={!()},codes={\catcode`\%=9}]
+%\useRanTok{1}, \useRanTok{2},..., \useRanTok{n}
+%\end{Verbatim}
% Other details are left to the readers' imagination.
%
% \paragraph{Requirements.} As of this writing, we require only the \texttt{verbatim} package
@@ -158,11 +165,28 @@
\newif\ifrtdebug \rtdebugfalse
\newif\ifwerandomize \werandomizetrue
\newif\ifsaveseed\saveseedtrue
+\newif\ifrt@InputUsedIDs\rt@InputUsedIDsfalse
\newwrite\rt@Verb@write
% \end{macrocode}
+% Convenience commands.
% \begin{macrocode}
+\def\rtcsarg#1#2{\expandafter#1\csname#2\endcsname}
\def\rt@nameedef#1{\expandafter\edef\csname #1\endcsname}
% \end{macrocode}
+% \leavevmode\IndexOpt{usedbapp}^^A
+% The code to support a DB application has grown, so much so, it desirves
+% a option so as to include the code only if needed.
+% \changes{v1.3}{2021/01/14}{Added \string\opt{usedbapp} option}
+% \begin{macrocode}
+\DeclareOption{usedbapp}{\let\rtPkgInpt\rt@PkgInpt}
+\def\rt@PkgInpt{\InputIfFileExists{rt-dbapp.def}
+ {\PackageInfo{ran_toks}{Inputting rt-dbapp.def}}
+ {\PackageInfo{ran_toks}{Cannot find rt-dbapp.def}}
+}
+\let\rtPkgInpt\relax
+\AtEndOfPackage{\rtPkgInpt}
+\ProcessOptions\relax
+% \end{macrocode}
% \begin{macrocode}
%</package>
%<*altpkgname>
@@ -272,7 +296,7 @@
\edef\rt@listInHold{\the\rt@listIn\noexpand\\{\the\rt@nCnt}}%
\rt@listIn=\expandafter{\rt@listInHold}}}
% \end{macrocode}
-% \DescribeMacro{\rt@RandomizeList}\hskip-\marginparsep\thinspace|{|\ameta{n}|}|
+% \DescribeMacro{\rt@RandomizeList}\hskip-\marginparsep\thinspace\texttt{\darg{\ameta{n}}}
% is the command that gets the process of randomizing
% the input list going. The argument is the number \ameta{n} of tokens. If
% \cs{werandomize} is false, it just returns the input list; otherwise, it
@@ -361,7 +385,7 @@
instead will use\MessageBreak
\string\useRanTok{\rt@mod}, obtained from modular
arithmetic.\MessageBreak
- You might want to fix this}
+ You might want to fix this}%
}
\def\rt@badTokName#1{%
\PackageWarningNoLine{ran_toks}
@@ -414,14 +438,14 @@
% \cs{r@nVToks}.
% \begin{macrocode}
\newcommand{\eRTVToks}{\global
- \rt@nameedef{\rt@BaseName Cnt}{\the\rt@nCnt}%
- \expandafter\r@nVToks\expandafter{\rt@BaseName}}
+ \rt@nameedef{\rt@BaseName Cnt}{\the\rt@nCnt}\expandafter
+ \r@nVToks\expandafter{\rt@BaseName}}
% \end{macrocode}
% \end{macro}
% \begin{environment}{rtVW}
% \cs{rtVW} is a verbatim write environment. It saves its contents to the file
-% \verb!\jobname_\rt@BaseName\the\rt@nCnt.cut!. The file is later input back into
-% the source file in a random way.
+% \verb!\jobname_\rt@BaseName-\the\rt@nCnt.cut!. The file is later input back into
+% the source file in a random way. % J14
% \begin{macrocode}
\def\reVerbEnd{\ifhmode\unskip\fi}
% \end{macrocode}
@@ -432,11 +456,21 @@
\def\rtVWHook#1{\def\@rgi{#1}\ifx\@rgi\@empty
\let\RTVWHook\relax\else\def\RTVWHook{#1}\fi}
\rtVWHook{}
+\newwrite\wrtprobids
+\newif\ifviewIDs\viewIDsfalse
+\newif\ifxDBUnique\xDBUniquefalse
+\def\wrtProbIds#1{\immediate\write\wrtprobids{\string
+ \rtcsarg\string\gdef{#1}{used}}}
+\def\rtVWId#1{\ifviewIDs\noindent#1\fi
+ \ifxDBUnique\ifrt@InputUsedIDs\wrtProbIds{#1}\fi\fi
+}
\newenvironment{rtVW}{\global\advance\rt@nCnt\@ne
\immediate\openout\rt@Verb@write
- \jobname_\rt@BaseName\the\rt@nCnt.cut
+ \jobname_\rt@BaseName-\the\rt@nCnt.cut
\let\verbatim@out\rt@Verb@write
\rt@IWVO{\string\RTVWHook}%
+ \rt@IWVO{\string
+ \rtVWId{\rt@BaseName-\the\rt@nCnt}\string\relax}%
\verbatimwrite
}{%
\endverbatimwrite
@@ -454,11 +488,22 @@
\rt@listIn={}\rt@nCnt=0\relax\let\rt@listInHold\@empty
\@whilenum\rt@nCnt<\rt@nMax\do{\advance\rt@nCnt\@ne
\edef\rt@listInHold{%
- \the\rt@listIn{\noexpand\rt@inputVerb{#1\the\rt@nCnt}}}%
+ \the\rt@listIn{\noexpand\rt@inputVerb{#1-\the\rt@nCnt}}}% J14
\rt@listIn=\expandafter{\rt@listInHold}}\ifrtdebug
\typeout{\string\r@nVToks: \the\rt@listIn}\fi
\expandafter\r@nToks\expandafter{\the\rt@listIn}}
-\def\rt@inputVerb#1{\input{\jobname_#1.cut}}
+% \end{macrocode}
+% \DescribeMacro\rt@inputVerb\hskip-\marginparsep\texttt{\darg{\ameta{db-name}-\ameta{num}}} This
+% is the command that inputs a DB Test problem, it inputs it from the file named
+% \cs{jobname\_\darg{\ameta{db-name}-\ameta{num}}}. As we input, we make a record of the
+% problem we input by expanding \cs{rt@recordAsUsed\darg{\ameta{db-name}-\ameta{num}}}, which
+% itself expands to \cs{rtcsarg\string\gdef\darg{\ameta{db-name}-\ameta{num}}\darg{used}}. This is necessary when we are
+% choosing more than one item from a given DB Test file; it must be recorded immediately so that later
+% it cannot be used again, if possible.
+% \begin{macrocode}
+\def\rt@inputVerb#1{\rt@recordAsUsed{#1}\input{\jobname_#1.cut}}
+%\def\rt@recordAsUsed#1{\ifxDBUnique\rtcsarg\gdef{#1}{used}\fi}
+\def\rt@recordAsUsed#1{\rtcsarg\gdef{#1}{used}}
% \end{macrocode}
% \DescribeMacro{\r@ndToks} is main looping command for \cs{ranToks}
% and \cs{eRTVToks} (through \cs{r@nVToks}). If the ending token \cs{rt@NIL} is detected, we
@@ -524,16 +569,18 @@
% Use this command to copy \ameta{name1} to \ameta{name2}. This gives
% a randomization of the same list, without affecting the original order of \ameta{name1}.
% \begin{macrocode}
-\newcommand\copyRanToks[2]{\begingroup\expandafter
+\newcommand\copyRanToks[2]{\begingroup
+ \expandafter
\ifx\csname nMax4#1\endcsname\relax
% \end{macrocode}
% Source list is not defined
% \begin{macrocode}
- \rt@badTokName{#1}%
- \else\expandafter
+ \rt@badTokName{#1}%
+ \else
% \end{macrocode}
% Source list is defined
% \begin{macrocode}
+ \expandafter
\ifx\csname nMax4#2\endcsname\relax
% \end{macrocode}
% Destination list is not defined, which is good in this instance. This is
@@ -545,14 +592,17 @@
\@whilenum\rt@nCnt>\z@\do{\global
\rt@nameedef{rtTok\the\rt@nCnt#2}%
{\noexpand\@nameuse{rtTok\the\rt@nCnt#1}}%
- \advance\rt@nCnt\m@ne}%
- \rt@performRanDefns{\@nameuse{nMax4#2}}\else
+ \advance\rt@nCnt\m@ne
+ }\rt@performRanDefns{\@nameuse{nMax4#2}}%
+ \else
% \end{macrocode}
% Destination list is defined already, warn the user.
% \begin{macrocode}
- \rt@warnTokName{#2}\fi
+ \rt@warnTokName{#2}%
+ \fi
\fi
-\endgroup}
+ \endgroup
+}
% \end{macrocode}
% \end{macro}
%\DescribeMacro{\rt@ssign}\hskip-\marginparsep\texttt{\darg{\ameta{name}}} makes the assignments that are expanded by \cs{useRanTok}.
@@ -570,7 +620,8 @@
\newcommand{\nToksFor}[1]{\expandafter
\ifx\csname nMax4#1\endcsname\relax
\textbf{??}\rt@badTokName{#1}\else
- \@nameuse{nMax4#1}\fi}
+ \@nameuse{nMax4#1}\fi
+}
% \end{macrocode}
% \DescribeMacro{\rtTokByNum}\hskip-\marginparsep\texttt{[\ameta{name}]\darg{\ameta{num}}} is an internal macro, but it can be used publicly.
% The argument of it is an integer, eg, \verb!\rtTokByNum{3}! is the third token, as listed in the order
@@ -579,23 +630,66 @@
\newcommand{\rtTokByNum}[2][\rt@BaseName]{\expandafter
\ifx\csname nMax4#1\endcsname\relax
\textbf{??}\rt@badTokName{#1}\else
- \@nameuse{rtTok#2#1}\expandafter\ignorespaces\fi}
+ \@nameuse{rtTok#2#1}\expandafter\ignorespaces
+ \fi
+}
% \end{macrocode}
%\DescribeMacro{\useRanTok}\hskip-\marginparsep\texttt{[\ameta{name}]\darg{\ameta{num}}}
% After \cs{ranToks} has been executed, the user has access to the
% randomized tokens through \cs{useRanTok}. The argument \ameta{num} is an integer 1 through max.
% \begin{macrocode}
-\newcommand{\useRanTok}[2][\rt@BaseName]{\bgroup
- \expandafter\ifx\csname nMax4#1\endcsname\relax
- \rt@badTokName{#1}\else
- \ifnum#2>\nToksFor{#1}\rt@modarith{#2}{\nToksFor{#1}}%
% \end{macrocode}
-% If index (\texttt{\#2}) is greater than array length, use modular arithmetic to resolve
-% the issue, and send a warning to the user.
-% \changes{v1.1}{2017/05/04}{Add modular arithmetic to resolve case where index is greater than length}
+% We provide two commands to control the feature of try to select unique
+% choices across multiple renditions of the same source file.
+% \DescribeMacro\uniqueXDBChoicesOn\cs{uniqueXDBChoicesOn}, turns on this feature;
+% the default is \DescribeMacro\uniqueXDBChoicesOff\cs{uniqueXDBChoicesOff} make
+% no changes to how \cs{useRanTok} operates. One other command we define here is
+% \DescribeMacro\makeInfoAWarning\cs{makeInfoAWarning}; this command applies only
+% when \cs{uniqueXDBChoicesOn} is expanded. In the macro \cs{xdb@unique} which is
+% expanded when \cs{uniqueXDBChoicesOn} is expanded first, there is one line that
+% reports information to the log as \cs{PackageInfo}. By expanding \cs{makeInfoAWarning}
+% we change \cs{PackageInfo} to \cs{PackageWarning}, which gives it greater
+% visibility in the log and the log report.
+% \changes{v1.3.1}{2021/01/19}{Added \string\cs{ifrt@recording}}
+% \begin{macrocode}
+\newcommand{\uniqueXDBChoicesOn}{\xDBUniquefalse
+ \PackageWarning{ran_toks}
+ {The \string\uniqueXDBChoicesOn\space requires the\MessageBreak
+ \texttt{usedbapp} option}}
+\newcommand{\uniqueXDBChoicesOff}{\let\xdbunique\relax\xDBUniquefalse}
+\let\xdbunique\relax
+\newcommand{\makeInfoAWarning}{\def\pkgNotifType{\PackageWarning}}
+\def\pkgNotifType{\PackageInfo}
+\newif\ifrt@recording \rt@recordingtrue % dps
+% \end{macrocode}
+% Now for the definition of \cs{useRanTok}.
% \begin{macrocode}
- \rt@badIndex{#2}{#1}\@nameuse{rtRanTok\rt@mod#1}\else
- \@nameuse{rtRanTok#2#1}\fi\fi\egroup}
+\newcommand{\useRanTok}[2][\rt@BaseName]{\bgroup\expandafter
+ \ifx\csname nMax4#1\endcsname\relax
+ \rt@badTokName{#1}\global\let\rt@next\relax
+ \else
+ \ifnum#2>\@nameuse{nMax4#1}%
+ \rt@modarith{#2}{\@nameuse{nMax4#1}}%
+ \rt@badIndex{#2}{#1}\edef\Indx{\rt@mod}%
+ \else
+ \edef\Indx{#2}%
+ \fi
+ \xdef\rt@orig@Indx{\Indx}%
+% \end{macrocode}
+% If \cs{xdbunique} is \cs{relax}, \cs{useRanTok} executes as it did in the past
+% (no change in behavior); otherwise, we expand \cs{xdb@unique} which attempts
+% to avoid duplicate choices based on the DBs input by \cs{useProbDBs}.
+% \begin{macrocode}
+ \ifx\xdbunique\relax
+ \ifrt@recording\rt@recordAsUsed{#1-\Indx}\fi
+ \xdef\rt@next{\noexpand\@nameuse{rtRanTok\Indx#1}}%
+ \else
+ \xdb@unique{#1}%
+ \fi
+ \fi
+ \egroup
+ \rt@next
+}
% \end{macrocode}
% \DescribeMacro{\displayListRandomly}\hskip-\marginparsep\texttt{[\ameta{prior}][\ameta{post}]\darg{\ameta{name}}}
% lists all items in the list as passed
@@ -606,12 +700,14 @@
%\changes{v1.0e}{2016/02/06}{Added optional argument to \string\cs{displayListRandomly}}
%\changes{v1.1}{2017/05/04}{Added second optional argument to \string\cs{displayListRandomly}}
% \begin{macrocode}
-\newcommand{\displayListRandomly}[1][]{\bgroup\def\rt@prior{#1}%
- \displ@yListRandomly}
-\newcommand{\displ@yListRandomly}[2][]{\rt@nCnt\z@
- \expandafter\ifx\csname nMax4#2\endcsname\relax
+\newcommand{\displayListRandomly}[1][]{\bgroup
+ \def\rt@prior{#1}\displ@yListRandomly
+}
+\newcommand{\displ@yListRandomly}[2][]{\rt@nCnt\z@\expandafter
+ \ifx\csname nMax4#2\endcsname\relax
\rt@rgi\space\textbf{??}\rt@badTokName{#2}#1%
\else
+ \rt@recordingfalse
% \end{macrocode}
% Within the optional arguments, we define \DescribeMacro{\i}\cs{i},
% \DescribeMacro{\first}\cs{first}, \DescribeMacro{\last}\cs{last}, and
@@ -620,28 +716,75 @@
% \cs{displayListRandomly}.
% \begin{macrocode}
\def\rt@post{#1}\useRTName{#2}\let\i\rt@nCnt
- \def\first{1}\edef\last{\@nameuse{nMax4#2}}%
- \@tempcnta\last \advance\@tempcnta\m@ne
- \edef\lessone{\the\@tempcnta}%
- \@whilenum\rt@nCnt<\last\advance\rt@nCnt\@ne
- \do{\rt@prior\useRanTok{\the\rt@nCnt}\rt@post}%
- \fi
-\egroup}
+ \def\first{1}\edef\last{\@nameuse{nMax4#2}}\@tempcnta\last
+ \advance\@tempcnta\m@ne
+ \edef\lessone{\the\@tempcnta}\@whilenum\rt@nCnt<\last
+ \advance\rt@nCnt\@ne
+ \do{\rt@prior\useRanTok{\the\rt@nCnt}\rt@post
+ }\fi
+ \egroup
+}
+%</package>
+%<*dbapp>
+% \end{macrocode}
+% \section{A DB application}
+% This (optional) section supports an application of \pkg{ran\_toks} to the \pkg{eqexam} package; though,
+% conceptually, the commands of this section may be applied in other settings. In this application,
+% the document author has a series of DB test files (TEX files), each file contains \cs{bRTVToks}/\allowbreak
+% \cs{eRTVToks} constructs, which contain a series of \env{rtVW} environments of verbatim content. In this application,
+% the verbatim content are \env{problem}/\env{problem*} environments of \pkg{eqexam}.
+%
+% The following verbatim listing is taken from the preamble of \texttt{mc-db.tex}, which illustrates the layout
+% of how to apply the commands of this section.
+%\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small,
+%commandchars={!()},codes={\catcode`\%=9}]
+%\examNum{1}
+%\numVersions{4}
+%\forVersion{a}
+%!%!textsf( initial seeds for each of the four versions of this document)
+%\vA{\useThisSeed{54356}}
+%\vB{\useThisSeed{577867}}
+%\vC{\useThisSeed{6746788}}
+%\vD{\useThisSeed{856785}}
+%
+%\uniqueXDBChoicesOn !%!textsf( Try to avoid duplicate questions in multi-version doc)
+%\InputUsedIDs !%!textsf( Input history of previous versions to current version)
+%\viewIDstrue !%!textsf( To view the IDs of problems used)
+%...
+%\useTheseDBs{db1,db2,db3,db4}
+%\end{Verbatim}
+% \changes{v1.3}{2021/01/14}{Added several commands and macro to continue to support
+% a DB application.}
+% If \cs{ifxDBUnique} is true and if \pkg{eqexam} is loaded, we
+% open \cs{wrtprobids} which is used to write the problem IDs of the problems
+% already chosen in earlier version of this source file. The name of this file
+% is \cs{jobname-ver\string\selVersion.cut}; eg, \texttt{mc-db-verA.cut},
+% \texttt{mc-db-verB.cut}, etc.
+% \begin{macrocode}
+\def\rt@OpenProbIds{\@ifpackageloaded{eqexam}
+ {\immediate\openout\wrtprobids\jobname-ver\selVersion.cut}{}}
+% \end{macrocode}
+% We open the file \cs{jobname-ver\cs{selVersion}.cut} when \cs{InputUsedIDs} is
+% expanded in the preamble.
+% \begin{macrocode}
+%\def\rt@ABD{\ifxDBUnique\expandafter\rt@OpenProbIds\fi}
+\def\rt@ABD{\@ifundefined{eq@nVersions}{}
+ {\ifnum\eq@nVersions>\@ne\expandafter\rt@OpenProbIds\fi}}
% \end{macrocode}
-% \section{Commands that support a DB application}
% We begin with some utility commands to help parse the argument of \cs{useProbDBs}.
% \begin{macrocode}
\def\rt@gettonil#1\@nil{\def\to@nilarg{#1}}
\def\rt@ifspc{\ifx\@let@token\@sptoken
\let\rt@next\rt@xifspc\else
- \let\rt@next\rt@gettonil\fi\rt@next}
+ \let\rt@next\rt@gettonil\fi\rt@next
+}
\begingroup
-\def\:{\rt@xifspc}
-\expandafter\gdef\: {\futurelet\@let@token\rt@ifspc}
+\def\:{\rt@xifspc}\expandafter
+\gdef\: {\futurelet\@let@token\rt@ifspc}
\endgroup
\def\rt@strpspcs{\futurelet\@let@token\rt@ifspc}
% \end{macrocode}
-% \begin{macro}{\useTheseDBs}\hskip-\marginparsep\thinspace|{|\ameta{list}|}|
+% \begin{macro}{\useTheseDBs}\hskip-\marginparsep\thinspace\texttt{\darg{\ameta{list}}}
% Inputs any files included in the comma-delimited list. The base names need only be listed,
% as the extension is assumed to be \texttt{.tex}. The command \cs{useProbDBs} can only be used
% in the preamble. Refer to the demo file \texttt{mc\_db.tex} for an illustration of its intended use.
@@ -662,10 +805,197 @@
\toks@=\expandafter{\rt@nextDB}%
\edef\rt@DB@List{\the\toks\tw@\space\the\toks@}\fi
}\expandafter\rt@DB@List\fi}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\useProbDBs}\hskip-\marginparsep\thinspace\texttt{\darg{\ameta{list}}} Is an alias of
+% \cs{useTheseDBs}.
+% \begin{macrocode}
\let\useProbDBs\useTheseDBs
% \end{macrocode}
% \end{macro}
+% \begin{macro}{\viewDB}\hskip-\marginparsep\thinspace\texttt{\darg{\ameta{name}}}
+% Typeset the entire contents of a DB Test file. The argument \ameta{name} is the name
+% of the DB Test file (as in |\bRTVToks{DB1}|, here \texttt{DB1} is the \ameta{name}.
+% The DB test files should be input using \cs{useProbDBs}.
+% \begin{macrocode}
+\def\viewDB#1{\useRTName{#1}\rt@nCnt\z@
+ \edef\nSTOP{\@nameuse{nMax4\rt@BaseName}}%
+ \loop\advance\rt@nCnt\@ne
+ \rtTokByNum{\the\rt@nCnt}%
+ \ifnum\rt@nCnt<\nSTOP\repeat
+}
+% \end{macrocode}
+% \end{macro}
+% The macro \DescribeMacro\getR@nIndx\cs{getR@nIndx} executes with each
+% entry of |\@nameuse{#1-List}|.
+% For an index value of \cs{Indx}, the macro goes through the
+% arguments to the \cs{Indx}'th argument and reads
+% the value of the argument at that point. It
+% returns the argument of the \cs{Indx}'th as \cs{ranIndx};
+% eg, if |\Indx=1|, then |\ranIndx=3|, for the above example.
+% \begin{macrocode}
+%% uses \@tempcnta and \Indx
+\def\getR@nIndx#1{\def\argi{#1}%
+ \ifx\argi\rt@STOP
+ % no match, something is wrong
+ \edef\ranIndex{-1}\else
+ \advance\@tempcnta\@ne
+ \ifnum\Indx=\@tempcnta
+ \def\ranIndx{#1}\fi
+ \fi
+}
+% \end{macrocode}
+% \DescribeMacro\xdb@unique\hskip-\marginparsep\texttt{\darg{\ameta{name}}}
+% An add-on command to \cs{useRanTok}. The command attempts
+% to create a unique choice of a problem over several versions of the same document. This may not
+% be possible if there are not enough choices to satisfy the number of declared versions.
+%
+% The \cs{xdb@unique} seems to work when the \pkg{eqexam} document has multiple parts (more then one
+% \env{exam} environments). The id files for the parts are all combined; ideally, for multiple part
+% exams, the second part draws form a set of DB test files different from the first part, as long as there are
+% enough problems to choose from.
+%
+% Note that, if there is not a unique choice for a question from the designated DB test file,
+% \cs{xdb@unique} reverts to the original choice so there may be duplicates across versions of the document.
+% \begin{macrocode}
+\def\rt@NoAltChoice#1#2{\PackageWarning{ran_toks}
+ {Cannot find an alternative to #1-#2,\MessageBreak
+ will use it but it may be a duplicate\MessageBreak
+ question}}
+\def\xdb@unique#1{\@tempcnta\z@
+ \def\rt@STOP{\relax}%
+% \end{macrocode}
+%We use the randomized list for the \ameta{name}
+%\begin{verbatim}
+% \@nameuse{#1-List} is the randomized list: eg,
+% \\{3}\\{2}\\{4}\\{5}\\{1}
+%\end{verbatim}
+% \begin{macrocode}
+ \let\\\relax\edef\x{\@nameuse{#1-List}}%
+ \toks@=\expandafter{\x}\let\\\getR@nIndx
+ \the\toks@\\\rt@STOP
+% \end{macrocode}
+% We take as the default choice the original choice
+% \begin{macrocode}
+ \xdef\rt@next{\noexpand
+ \@nameuse{rtRanTok\rt@orig@Indx#1}}%
+% \end{macrocode}
+% Begin to look at the results of |\the\toks@\\\rt@STOP|,
+% \begin{macrocode}
+ \ifnum\ranIndx>\m@ne
+% \end{macrocode}
+% If \cs{ranIndx} is -1, we use the original index.
+% \begin{macrocode}
+ \edef\rt@orig@ranIndx{\ranIndx}%
+ \expandafter
+ \ifx\csname#1-\ranIndx\endcsname\relax
+% \end{macrocode}
+% This question has not been chosen earlier, so we'll use it.
+% \begin{macrocode}
+ \xdef\rt@next{\noexpand
+ \@nameuse{rtRanTok\Indx#1}}%
+ \else
+% \end{macrocode}
+% The question has been chosen in an earlier version of the document.
+% Find the next higher unused one (cycle search).
+% \begin{macrocode}
+ \@tempcntb\z@
+ \rt@nCnt\rt@orig@Indx\relax
+% \end{macrocode}
+% As we move into the \cs{@whilenum} loop, we take as the default
+% the original index. The loop may overwrite the definition of
+% \cs{rt@next}.
+% \begin{macrocode}
+ \xdef\rt@next{\noexpand\rt@NoAltChoice{#1}{\rt@orig@Indx}\noexpand
+ \@nameuse{rtRanTok\rt@orig@Indx#1}}%
+ \@whilenum\@tempcntb<\@nameuse{nMax4#1}\do{%
+ \advance\@tempcntb\@ne
+ \advance\rt@nCnt\@ne
+% \end{macrocode}
+% If the count is at the \texttt{nMax4} value, we start over from
+% the beginning.
+% \begin{macrocode}
+ \ifnum\rt@nCnt>\@nameuse{nMax4#1}\rt@nCnt\@ne\fi
+% \end{macrocode}
+% We search through \cs{toks@} again, so we have the initialize
+% the dependent variables: \cs{Indx}, the index to search for; \cs{@tempcnta}
+% the counter that is used by \cs{getR@nIndx}; nothing has changed
+% |\let\\\getR@nIndx| should still be in effect.
% \begin{macrocode}
+ \edef\Indx{\the\rt@nCnt}\@tempcnta\z@
+ \the\toks@\\\rt@STOP
+% \end{macrocode}
+% If \cs{ranIndx} is -1, we use the original index.
+% \begin{macrocode}
+ \ifnum\ranIndx>\m@ne
+ \expandafter
+ \ifx\csname#1-\ranIndx\endcsname\relax
+ \pkgNotifType{ran_toks}{#1-\rt@orig@ranIndx\space
+ has already been used,\MessageBreak
+ will use #1-\ranIndx}%
+ % exit the \@whilenum loop
+ \@tempcntb\@nameuse{nMax4#1}%
+ \advance\@tempcntb\@ne
+ \fi
+ \fi
+ \xdef\rt@next{\noexpand\@nameuse{rtRanTok\Indx#1}}%
+ }% do
+ \ifnum\@tempcntb=\@nameuse{nMax4#1}\relax
+ \xdef\rt@next{\noexpand
+ \rt@NoAltChoice{#1}{\rt@orig@ranIndx}\noexpand
+ \@nameuse{rtRanTok\rt@orig@Indx#1}}%
+ \fi
+ \fi
+ \fi
+}
+% \end{macrocode}
+% Here is the operational definition of \DescribeMacro\uniqueXDBChoicesOn
+% \cs{uniqueXDBChoicesOn}; when executed in the preamble, an attempt is made
+% the select only problems that have not already been chosen in any prior
+% renditions of the same source file.
+% \begin{macrocode}
+\renewcommand{\uniqueXDBChoicesOn}{\xDBUniquetrue
+ \let\xdbunique\xdb@unique}
+% \end{macrocode}
+% \begin{macro}{\InputUsedIDs} Input the user ID (CUT) files. These are files
+% that document which questions were used for the various versions of the exam.
+% \begin{macrocode}
+\newif\ifrt@InputUsedIDs\rt@InputUsedIDsfalse
+\def\InputUsedIDs{\rt@InputUsedIDstrue
+ \bgroup
+ \setcounter{eq@count}{0}%
+ \let\rt@InputUsedIDs\@empty
+ \let\rt@InputUsedIDsFIs\@empty
+ \@whilenum \value{eq@count}<\eq@nVersions\relax\do
+ {%
+ \stepcounter{eq@count}%
+ \g@addto@macro\rt@InputUsedIDs{\if\selVersion}%
+ \g@addto@macro\rt@InputUsedIDsFIs{\fi}%
+ \edef\x{\Alph{eq@count}}%
+ \edef\y{\noexpand\g@addto@macro\noexpand
+ \rt@InputUsedIDs{\x\expandafter\noexpand
+ \csname else\endcsname\noexpand\rt@IIFE}}\y
+ \edef\x{{\x}}\expandafter
+ \g@addto@macro\expandafter\rt@InputUsedIDs\expandafter{\x}%
+ }% do
+ \expandafter\g@addto@macro\expandafter
+ \rt@InputUsedIDs\expandafter{\rt@InputUsedIDsFIs}%
+ \egroup
+ \rt@InputUsedIDs
+ \AtBeginDocument{\rt@ABD}%
+}
+\@onlypreamble\InputUsedIDs
+% \end{macrocode}
+% \end{macro}
+% A convenience command used by \cs{InputUsedIDs}.
+% \begin{macrocode}
+\def\rt@IIFE#1{\InputIfFileExists{\jobname-ver#1.cut}
+ {\PackageInfo{ran_toks}{Inputting \jobname-ver#1.cut}}
+ {\PackageInfo{ran_toks}{Cannot find \jobname-ver#1.cut}}}
+% \end{macrocode}
+% \begin{macrocode}
+%</dbapp>
+%<*package>
%</package>
% \end{macrocode}
% \Finale