summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/ran_toks
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
parent31152d888efa58265aef8521042ad58c300f9576 (diff)
CTAN sync 202101260301
Diffstat (limited to 'macros/latex/contrib/ran_toks')
-rw-r--r--macros/latex/contrib/ran_toks/README.md12
-rw-r--r--macros/latex/contrib/ran_toks/docs/ran_toks.pdfbin106437 -> 284544 bytes
-rw-r--r--macros/latex/contrib/ran_toks/docs/rantoks_man.pdfbin226760 -> 255885 bytes
-rw-r--r--macros/latex/contrib/ran_toks/docs/rantoks_man.tex431
-rw-r--r--macros/latex/contrib/ran_toks/examples/ctrl-build.tex58
-rw-r--r--macros/latex/contrib/ran_toks/examples/db1.tex2
-rw-r--r--macros/latex/contrib/ran_toks/examples/db2.tex4
-rw-r--r--macros/latex/contrib/ran_toks/examples/db3.tex4
-rw-r--r--macros/latex/contrib/ran_toks/examples/db4.tex4
-rw-r--r--macros/latex/contrib/ran_toks/examples/mc-db.tex72
-rw-r--r--macros/latex/contrib/ran_toks/examples/mc-dbu-ctrld.tex62
-rw-r--r--macros/latex/contrib/ran_toks/examples/mc-dbu.tex75
-rw-r--r--macros/latex/contrib/ran_toks/examples/ran-toks.tex (renamed from macros/latex/contrib/ran_toks/examples/ran_toks.tex)1
-rw-r--r--macros/latex/contrib/ran_toks/examples/rt-cb.tex36
-rw-r--r--macros/latex/contrib/ran_toks/examples/rt-tst-eqe.tex (renamed from macros/latex/contrib/ran_toks/examples/random_tst.tex)5
-rw-r--r--macros/latex/contrib/ran_toks/examples/rt-tst-qz.tex (renamed from macros/latex/contrib/ran_toks/examples/random_tst_qz.tex)24
-rw-r--r--macros/latex/contrib/ran_toks/examples/viewDB.tex40
-rw-r--r--macros/latex/contrib/ran_toks/ran_toks.dtx470
-rw-r--r--macros/latex/contrib/ran_toks/ran_toks.ins1
19 files changed, 1101 insertions, 200 deletions
diff --git a/macros/latex/contrib/ran_toks/README.md b/macros/latex/contrib/ran_toks/README.md
index c4c67686b7..8c3b618c71 100644
--- a/macros/latex/contrib/ran_toks/README.md
+++ b/macros/latex/contrib/ran_toks/README.md
@@ -1,6 +1,6 @@
The ran_toks Package
Author: D. P. Story
-Dated: 2019-12-28
+Dated: 2021-01-19
This short package, with minimal requirements, defines macros for
randomizing a list of tokens. There are two approaches:
@@ -40,7 +40,15 @@ tokens in the myList list.
For users of AeB or eqexam, the latter structure can be used to randomize
the order of the questions on a quiz or exam.
-What's New (2019-12-28 ) Defined \rtVWHook to insert at the top of the
+What's New (2021-01-19) A new option, usedbapp, was added to
+support a DB application. Extensive work was done on the DB
+application. Added \uniqueXDBChoicesOn, which if expanded, tries
+to choose a random token that has not already been chosen,
+across versions of a multi-version eqexam document. Changes are
+discussed in the documentation and in the new examples in the
+distribution.
+
+What's New (2019-12-28) Defined \rtVWHook to insert at the top of the
rtVW environment. Also created an alternate package name of ran-toks.
What's new in v1.1: Added the convenience command \useTheseDBs to input files for
diff --git a/macros/latex/contrib/ran_toks/docs/ran_toks.pdf b/macros/latex/contrib/ran_toks/docs/ran_toks.pdf
index 8896ea676c..bfc8e7bc9b 100644
--- a/macros/latex/contrib/ran_toks/docs/ran_toks.pdf
+++ b/macros/latex/contrib/ran_toks/docs/ran_toks.pdf
Binary files differ
diff --git a/macros/latex/contrib/ran_toks/docs/rantoks_man.pdf b/macros/latex/contrib/ran_toks/docs/rantoks_man.pdf
index 8d7c1e06e9..62ee68da81 100644
--- a/macros/latex/contrib/ran_toks/docs/rantoks_man.pdf
+++ b/macros/latex/contrib/ran_toks/docs/rantoks_man.pdf
Binary files differ
diff --git a/macros/latex/contrib/ran_toks/docs/rantoks_man.tex b/macros/latex/contrib/ran_toks/docs/rantoks_man.tex
index c17c9e9a7e..8f8b0c6246 100644
--- a/macros/latex/contrib/ran_toks/docs/rantoks_man.tex
+++ b/macros/latex/contrib/ran_toks/docs/rantoks_man.tex
@@ -1,8 +1,9 @@
+\RequirePackage[!use=preview,!use=efpmca,!use=usebw]{spdef}
\documentclass{article}
\usepackage[fleqn]{amsmath}
\usepackage[
web={centertitlepage,designv,forcolorpaper,
- latextoc,pro}, %tight,
+ latextoc,extended},
eforms,aebxmp
]{aeb_pro}
\usepackage{ran_toks}
@@ -16,6 +17,7 @@
\let\pkg\textsf
\let\env\texttt
+\let\opt\textsf
%\rtdebugtrue
%\ranToksOn
@@ -50,6 +52,19 @@
\def\takeMeasurei#1{\global\setbox\webtempboxi\hbox{\ttfamily#1}\egroup}
\def\bxSize{\wd\webtempboxi+2\fboxsep+2\fboxrule}
+\newcommand{\FmtMP}[2][0pt]{\mbox{}\marginpar{%
+ \raisebox{.5\baselineskip+#1}{%
+ \expandafter\parbox\expandafter[\parboxValign]%
+ {\marginparwidth}{\aebbkFmtMp#2}}}}
+\def\aebbkFmtMp{\kern0pt\itshape\small
+ \ifusebw\color{gray}\else\color{blue}\fi
+ \raggedleft\hspace{0pt}}\newcommand{\BlogArticle}{%
+ \makebox[0pt][l]{\hspace{-1pt}\color{blue}\Pisymbol{webd}{254}%
+ }\raisebox{.5pt}{\ifusebw\color{black}\else
+ \color{red}\fi\ding{045}}}
+\def\parboxValign{t}
+
+
\usepackage[active]{srcltx}
\let\amtIndent\leftmargini
@@ -72,8 +87,8 @@
email={dpstory@acrotex.net},
subject=Documentation for the ran\_toks package,
talksite={\url{www.acrotex.net}},
- version={1.2, 2019/12/28},
- Keywords={LaTeX,PDF,random, tokens, JavaScript,Adobe Acrobat},
+ version={1.3.1, 2021/01/19},
+ Keywords={LaTeX, PDF, random, tokens, JavaScript, Adobe Acrobat},
copyrightStatus=True,
copyrightNotice={Copyright (C) \the\year, D. P. Story},
copyrightInfoURL={http://www.acrotex.net}
@@ -155,37 +170,65 @@ _path=_path.substring(0,pos)+"/"+manualfilename;
\section{Introduction}
This is a short package for randomizing the order of tokens. The package
-is long overdue; users of \textbf{AeB} and of \textsf{eqexam} have long asked for a way to
+is long overdue; users of \textsf{\textbf{AeB}} and of \pkg{eqexam} have long asked for a way to
randomize the order of the problems in a test or quiz, or anything for
that matter.
-\newtopic\noindent\exSrc The \texttt{examples} folder contains three demonstration files:
+\newtopic\noindent\exSrc The \texttt{examples} folder contains nine demonstration files:
\begin{enumerate}
- \item \texttt{ran\_toks.tex} reproduces the sample code of this manual.
- \item \texttt{random\_tst.tex} shows how to use \pkg{ran\_toks} to
+ \item \texttt{ran-toks.tex} reproduces the sample code of this manual.
+ \item \texttt{rt-tst-eqe.tex} shows how to use \pkg{ran\_toks} to
randomize the \emph{questions} of an exam document created by the
\pkg{eqexam} package.
- \item \texttt{random\_tst\_qz.tex} shows how to randomize choices of a
+ \item \texttt{rt-tst-qz.tex} shows how to randomize choices of a
multiple choice field in a \env{quiz} environment of the
\pkg{exerquiz} package, when the choices contain verbatim text.
- \item \texttt{mc-db.tex} is an \pkg{eqexam} file that draws from the
+ \item \texttt{rt-cb.tex} is a demonstration of how to use the
+ \pkg{collectbox} package to place verbatim content into a token list
+ (see \cs{ranToks}, \hyperref[s:ranToks]{Section~\ref*{s:ranToks}}).
+\xdef\svEnumi{\the\value{enumi}}
+\end{enumerate}
+The next five files concern the DB application and require the \opt{usedbapp} option,
+they are discussed in \hyperref[s:DBApp]{Section~\ref*{s:DBApp}}.
+\begin{enumerate}\setcounter{enumi}{\svEnumi}
+ \item \texttt{mc-db.tex} is an \pkg{eqexam} file, draws from the
database files \texttt{db1.tex}, \texttt{db2.tex},
\texttt{db3.tex}, and \texttt{db4.tex}, to construct the questions
of the exam. The questions are drawn at random from the DB files. Refer
- to \hyperref[s:DBConcept]{Section~\ref*{s:DBConcept}} for a few more details.
+ to \hyperref[s:DBApp]{Section~\ref*{s:DBApp}} for a few more details.
+ \item \texttt{mc-dbu.tex} is an \pkg{eqexam} file that draws from the
+ database test file, draws from the database files \texttt{db1.tex},
+ \texttt{db2.tex}, \texttt{db3.tex}, and \texttt{db4.tex}, to
+ construct the questions of the exam. However, \texttt{mc-dbu.tex}
+ differs from \texttt{mc-db.tex} for it selects unique questions
+ cross the four versions of the document. Refer to
+ \hyperref[s:DBApp]{Section~\ref*{s:DBApp}} for a few more details.
+ \item \texttt{viewDB.tex} A demo file of how to view the DB files for
+ the purpose of reviewing the questions, modifying them, or adding
+ to them.
+ \item \texttt{mc-dbu-ctrld.tex} is a variation on \texttt{mc-dbu.tex},
+ it is not meant to be compiled directly, but by the file
+ \texttt{ctrl-build.tex}.
+ \item \texttt{ctrl-build.tex} is a simple TEX file that controls the
+ compilation of a targeted file (\texttt{mc-dbu-ctrld.tex} in this
+ example) over the various versions supported by the targeted file.
+ Try it, you'll like it. Uses the \pkg{shellesc} package to control
+ the process.
\end{enumerate}
\section{The Preamble and Package Options}
The preamble for this package is
-\bVerb\takeMeasure{\string\usepackage\darg{ran\_toks}}%
+\bVerb\takeMeasure{\string\usepackage[\ameta{options}]\darg{ran\_toks}}%
\begin{minipage}{\bxSize}\kern0pt
-\begin{Verbatim}[frame=single]
-\usepackage{ran_toks}
+\begin{Verbatim}[frame=single,commandchars=!()]
+\usepackage[!ameta(options)]{ran_toks}
\end{Verbatim}
\end{minipage}\eVerb
-The package itself has no options.
+The one option of \pkg{ran\_toks} is \opt{usedbapp}\FmtMP{\opt{usedbapp} option}, which brings in
+specialized code to support a database test application. This option is
+discussed in \hyperref[s:DBApp]{Section~\ref*{s:DBApp}}, beginning on page~\pageref*{s:DBApp}.
The requirements for \textsf{ran\_toks} are the \textsf{verbatim} package
(part of the standard {\LaTeX} distribution, and the macro file
@@ -198,52 +241,52 @@ There are two styles for defining a series of tokens to be randomized,
using either the \cs{ranToks} command or the \cs{bRTVToks}/\cs{eRTVToks}
pair. Each of these is discussed in the next two subsections.
-\subsection{The \texorpdfstring{\protect\cs{ranToks}}{\CMD{ranToks}} command}
+\subsection{The \texorpdfstring{\protect\cs{ranToks}}{\CMD{ranToks}} command}\label{s:ranToks}
The \cs{ranToks} command was the original concept; declare a series of
tokens to be randomized.
-\bVerb\takeMeasure{\string\ranToks\darg{\meta{name}}\{\%\enspace}%
+\bVerb\takeMeasure{\string\ranToks\darg{\ameta{name}}\{\%\enspace}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\ranToks{!meta(name)}{%
- {!meta(token!SUB(1))}
- {!meta(token!SUB(2))}
- ...
- {!meta(token!SUB(n))}
+\ranToks{!ameta(name)}{%
+!quad{!ameta(token!SUB(1))}
+!quad{!ameta(token!SUB(2))}
+!quad...
+!quad{!ameta(token!SUB(n))}
}
\end{Verbatim}
\end{minipage}\eVerb
-were \meta{token\SUB{k}} is any non-verbatim content;\footnote{Any token that
-can be in the argument of a command.} each token is enclosed in braces
-(\darg{}), this is required. The \meta{name} parameter is required, and
+were \ameta{token\SUB{k}} is any non-verbatim content;\footnote{However, for workarounds, see
+\texttt{rt-cb.tex} and \texttt{rt-tst-qz.tex.}} each token is enclosed in braces
+(\darg{}), this is required. The \ameta{name} parameter is required, and
must be unique for the document; it is used to build the names of internal
macros. Of course several such \cs{ranToks} can be used in the document,
either in the preamble or in the body of the document. Multiple
-\cs{ranToks} commands must have a different \meta{name} parameter.
+\cs{ranToks} commands must have a different \ameta{name} parameter.
\emph{After} a \cs{ranToks} command has been executed, the number of tokens
counted is accessible through the \cs{nToksFor} command,
-\bVerb\takeMeasure{\string\nToksFor\darg{\meta{name}}}%
+\bVerb\takeMeasure{\string\nToksFor\darg{\ameta{name}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\nToksFor{!meta(name)}
+\nToksFor{!ameta(name)}
\end{Verbatim}
\end{minipage}\eVerb
-The one argument is \meta{name}, and will expand to the total number
+The one argument is \ameta{name}, and will expand to the total number
of tokens listing as argument in the \cs{ranToks} command by the same
name.
The \cs{ranToks} command does not display the randomized tokens, for that
the command \cs{useRanTok} is used.
-\bVerb\takeMeasure{\string\useRTName\darg{\meta{name}}}%
+\bVerb\takeMeasure{\string\useRTName\darg{\ameta{name}}}%
\begin{minipage}{\bxSize}
\begin{Verbatim}[frame=single,commandchars=!()]
-\useRanTok{!meta(num)}
-\useRTName{!meta(name)}
+\useRanTok{!ameta(num)}
+\useRTName{!ameta(name)}
\end{Verbatim}
\end{minipage}\eVerb
The argument of \cs{useRanTok} is a positive integer between 1 and
-\cs{nToksFor\darg{\meta{name}}}, the number of tokens declared by
+\cs{nToksFor\darg{\ameta{name}}}, the number of tokens declared by
\cs{ranToks}, inclusive. There is no space created following the
\cs{useRanTok} command, so if these are to be used ``inline'', enclose them
in braces (\darg{}), for example, \darg{\cs{useRanTok\darg{1}}}. The use of
@@ -285,10 +328,10 @@ arguments.\footnote{{\ttfamily\string\ranToks\darg{myPals}\darg{\darg{Jim}\darg{
are \useRanTok{1}, \useRanTok{2}, \useRanTok{3}, \useRanTok{4},
{\useRanTok{5}} and \useRanTok{6}.'' A new order?
An alternative to re-executing \cs{ranToks} is to use the \cs{reorderRanToks} command:
-\bVerb\takeMeasure{\string\reorderRanToks\darg{\meta{name}}}%
+\bVerb\takeMeasure{\string\reorderRanToks\darg{\ameta{name}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\reorderRanToks{!meta(name)}
+\reorderRanToks{!ameta(name)}
\end{Verbatim}
\end{minipage}\eVerb Now, executing \verb~\reorderRanToks{myPals}~ and compiling the sentence again yields,
``I have {\nToksFor{myPals}} pals, they are
@@ -297,7 +340,7 @@ An alternative to re-executing \cs{ranToks} is to use the \cs{reorderRanToks} co
the same token list in the same document is not very likely something you
need to do.
-The \cs{reorderRanToks\darg{\meta{name}}} rearranges the list of tokens
+The \cs{reorderRanToks\darg{\ameta{name}}} rearranges the list of tokens
associated with \ameta{name}, which may not be what you want; the
\cs{copyRanToks} command, on the other hand, makes a (randomized) copy of its
first required argument \ameta{name\SUB1} and saves it as \ameta{name\SUB2}, without
@@ -327,36 +370,55 @@ and verbatim environments.
Sometimes the content to be randomized is quite large or contains verbatim
text. For this, it may be more convenient to use the
\cs{bRTVToks}/\penalty0\cs{eRTVToks} command pair. The syntax is
-\bVerb\takeMeasure{\string\bRTVToks\darg{\meta{name}}\quad}%
-\edef\WIDTH{\the\wd\webtempboxi}%
-\def\1{\rlap{\hspace*{\WIDTH}\texttt{\% <-{\sffamily{ End token listing}}}}}%
-\takeMeasure{\string\bRTVToks\darg{\meta{name}}\quad\% <-{\sffamily{ Begin token listing}}}%
+\bVerb\takeMeasure{\string\bRTVToks\darg{\ameta{name}}}%
+%\edef\WIDTH{\the\wd\webtempboxi}%
+\def\1{\rlap{\hspace*{\linewidth}\texttt{\%{\sffamily{ \raisebox{1pt}{<--}Begin token listing}}}}}%
+\def\2{\rlap{\hspace*{\linewidth}\texttt{\%{\sffamily{ \raisebox{1pt}{<--}End token listing}}}}}%
+%\takeMeasure{\string\bRTVToks\darg{\ameta{name}}\quad\%{\sffamily{ <-Begin token listing}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\bRTVToks{!meta(name)}!quad% <-!sffamily( Begin token listing)
+!1\bRTVToks{!ameta(name)}
\begin{rtVW}
-!qquad!ameta(content!SUB(1))
+!quad!ameta(content!SUB(1))
\end{rtVW}
...
...
\begin{rtVW}
-!qquad!ameta(content!SUB(n))
+!quad!ameta(content!SUB(n))
\end{rtVW}
-!1\eRTVToks
+!2\eRTVToks
\end{Verbatim}
\end{minipage}\eVerb
-The \cs{bRTVToks}\texttt{\{\meta{name}\}} command begins the (pseudo)
+%\bVerb\takeMeasure{\string\bRTVToks\darg{\ameta{name}}\quad}%
+%\edef\WIDTH{\the\wd\webtempboxi}%
+%\def\1{\rlap{\hspace*{\WIDTH}\texttt{\% <-{\sffamily{ End token listing}}}}}%
+%\takeMeasure{\string\bRTVToks\darg{\ameta{name}}\quad\% <-{\sffamily{ Begin token listing}}}%
+%\begin{minipage}{\bxSize}\kern0pt
+%\begin{Verbatim}[frame=single,commandchars=!()]
+%\bRTVToks{!ameta(name)}!quad% <-!sffamily( Begin token listing)
+%\begin{rtVW}
+%!quad!ameta(content!SUB(1))
+%\end{rtVW}
+%...
+%...
+%\begin{rtVW}
+%!quad!ameta(content!SUB(n))
+%\end{rtVW}
+%!1\eRTVToks
+%\end{Verbatim}
+%\end{minipage}\eVerb
+The \cs{bRTVToks}\texttt{\darg{\ameta{name}}} command begins the (pseudo)
environment and is ended by \cs{eRTVToks}. Between these two are a series of
\texttt{rtVW} (random toks verbatim write) environments. When the document is
compiled, the contents (\ameta{content\SUB{i}}) of each of these environments
are written to the computer hard drive and saved under a different name
-(based on the parameter \meta{name}). Later, using the \cs{useRanTok}
+(based on the parameter \ameta{name}). Later, using the \cs{useRanTok}
commands, they are input back into the document in a random order.
-The \env{rtWVW} environment also writes the command
+The \env{rtVW} environment also writes the command
\cs{RTVWHook}\marginpar{\small\itshape\flushright\cs{RTVWHook}} to the top of
-the file. Its initial value is \cs{relax}. It can be redefined using the convenience
-command \cs{rtVWHook\darg{\ameta{arg}}}, which expands to
+the file. Its initial value is \cs{relax}. It can be redefined with
+\cs{rtVWHook\darg{\ameta{arg}}}, which expands to
\verb|\def\RTVWHook{|\ameta{arg}\verb|}|.
The use of \cs{useRTName} and \cs{useRanTok} were explained and illustrated
@@ -436,7 +498,7 @@ The command \cs{copyRanToks} works for list created by
\paragraph*{On the \cs{displayListRandomly} command.}\label{para:DLR}
In the enumerate example immediately above, the items in the list are
-explicitly listed as \cs{item \cs{useRanTok\darg{1}}} and so one; an
+explicitly listed as \cs{item \cs{useRanTok\darg{1}}} and so on; an
alternate approach is to use the command \cs{displayListRandomly}, like so,
\begin{Verbatim}[xleftmargin=\amtIndent]
\begin{enumerate}
@@ -444,17 +506,17 @@ alternate approach is to use the command \cs{displayListRandomly}, like so,
\end{enumerate}
\end{Verbatim}
The full syntax for \cs{displayListRandomly} is displayed next.
-\bVerb\takeMeasure{\string\displayListRandomly[\ameta{prior}][\ameta{post}]\darg{\meta{name}}}%
+\bVerb\takeMeasure{\string\displayListRandomly[\ameta{prior}][\ameta{post}]\darg{\ameta{name}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\displayListRandomly[!ameta(prior)][!ameta(post)]{!meta(name)}
+\displayListRandomly[!ameta(prior)][!ameta(post)]{!ameta(name)}
\end{Verbatim}
\end{minipage}
\eVerb The action of \cs{displayListRandomly} is to expand all tokens that
-are listed in the \meta{name} token list, each entry is displayed as
+are listed in the \ameta{name} token list, each entry is displayed as
\ameta{prior}\cs{useRanTok\darg{i}}\ameta{post}, where \texttt{i}
-goes from~1 to \cs{nToksFor\darg{\meta{name}}}. In the example above,
-\meta{prior} is \cs{item}, but normally, its default is empty. The defaults
+goes from~1 to \cs{nToksFor\darg{\ameta{name}}}. In the example above,
+\ameta{prior} is \cs{item}, but normally, its default is empty. The defaults
for \ameta{prior} and \ameta{post} are both empty.
\subparagraph*{The optional arguments.} When only one optional argument is present,
@@ -492,16 +554,16 @@ Hint: a solution involves the other command \cs{lessone}.
\section{Additional arguments and commands}\label{AddCmds}
The syntax given earlier for \cs{useRanTok} was not completely specified.
-It is
-\bVerb\takeMeasure{\string\useRanTok[\meta{name}]\darg{\meta{num}}}%
+It is,
+\bVerb\takeMeasure{\string\useRanTok[\ameta{name}]\darg{\ameta{num}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\useRanTok[!meta(name)]{!meta(num)}
+\useRanTok[!ameta(name)]{!ameta(num)}
\end{Verbatim}
\end{minipage}\eVerb
-The optional first parameter specifies the \meta{name} of the list from
-which to draw a random token; \meta{num} is the number of the
-token in the range of 1 and \cs{nToksFor\darg{\meta{name}}},
+The optional first parameter specifies the \ameta{name} of the list from
+which to draw a random token; \ameta{num} is the number of the
+token in the range of 1 and \cs{nToksFor\darg{\ameta{name}}},
inclusive. The optional argument is useful in special circumstances when
you want to mix two random lists together.
@@ -517,23 +579,23 @@ Without the \texttt{minipage}, the text would wrap around normally.
\paragraph*{Accessing the original order.} The original order of the list of tokens is not lost, you can retrieve
them using the command \cs{rtTokByNum},
-\bVerb\takeMeasure{\string\rtTokByNum[\meta{name}]\darg{\meta{num}}}%
+\bVerb\takeMeasure{\string\rtTokByNum[\ameta{name}]\darg{\ameta{num}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\rtTokByNum[!meta(name)]{!meta(num)}
+\rtTokByNum[!ameta(name)]{!ameta(num)}
\end{Verbatim}
\end{minipage}\eVerb
-This command expands to the token declared in the list named \meta{name}
-that appears at the \meta{num} place in the list. (Rather awkwardly written.)
+This command expands to the token declared in the list named \ameta{name}
+that appears at the \ameta{num} place in the list. (Rather awkwardly written.)
For example, my really best pals are {\rtTokByNum[myPals]{3}} and
\rtTokByNum[myPals]{4}, but don't tell them. The listing is,
\begin{Verbatim}[xleftmargin=\amtIndent]
For example, my really best pals are {\rtTokByNum[myPals]{3}}
and \rtTokByNum[myPals]{4}, but don't tell them.
\end{Verbatim}
-In some sense, \cs{rtTokByNum[\meta{name}]} acts like a simple array, the
-length of which is \cs{nToksFor\{\meta{name}\}}, and whose $k^{\text{th}}$
-element is \cs{rtTokByNum[\meta{name}]\{\meta{k}\}}.
+In some sense, \cs{rtTokByNum[\ameta{name}]} acts like a simple array, the
+length of which is \cs{nToksFor\{\ameta{name}\}}, and whose $k^{\text{th}}$
+element is \cs{rtTokByNum[\ameta{name}]\{\ameta{k}\}}.
\paragraph*{Turning off randomization.} The randomization may be turned off
using \cs{ranToksOff} or turned back on with \cs{ranToksOn}.
@@ -596,7 +658,7 @@ Normally, the pseudo-random number generator provided by
you recompile again before another minute, you'll get the same initial
seed value.
-\paragraph*{Controlling the initial seed value.} To obtain a new initial seed
+\paragraph*{Controlling the initial seed value.}\label{para:ControlSeed} To obtain a new initial seed
value each time you compile, place \cs{useLastAsSeed} in the preamble.
\bVerb\takeMeasure{\string\useLastAsSeed}%
\begin{minipage}{\bxSize}\kern0pt
@@ -612,14 +674,14 @@ exist, the generator will be initialized by its usual method, using the time and
The command \cs{useThisSeed} allows you to reproduce a previous
pseudo-random sequence.
-\bVerb\takeMeasure{\string\useThisSeed\darg{\meta{init\_seed\_value}}}%
+\bVerb\takeMeasure{\string\useThisSeed\darg{\ameta{init\_seed\_value}}}%
\begin{minipage}{\bxSize}\kern0pt
\begin{Verbatim}[frame=single,commandchars=!()]
-\useThisSeed{!meta(init_seed_value)}
+\useThisSeed{!ameta(init_seed_value)}
\end{Verbatim}
\end{minipage}\eVerb
This command needs to be placed in the preamble. The value of
-\meta{init\_seed\_value} is an integer, normally taken from the
+\ameta{init\_seed\_value} is an integer, normally taken from the
first line of the \cs{jobname\_rt.sav} file.
When creating tests (possibly using \textsf{eqexam}), the problems, or
@@ -653,17 +715,47 @@ If you are using \textsf{eqexam}, the process can be automated as follows:
\end{Verbatim}
Again, this goes in the preamble.
-\section{Commands to support a DB application}\label{s:DBConcept}
+\section{Commands to support a DB application}\label{s:DBApp}
+
+The commands described in this section are only available with the \opt{usedbapp} option,
+\begin{Verbatim}
+\usepackage[usedbapp]{ran_toks}
+\end{Verbatim}
+This option was designed for an \pkg{eqexam} document.
+
+\subsection{Basic functionality}\label{s:basicFunc}
+
+The premise here is that you have an \pkg{eqexam} document (a test) and you have a series
+of standard questions you ask students. Over the years, you have accumulated questions of a similar type
+that you like to pose to your students. The questions of a similar type are placed in a DB test file. For example,
+you have a file named \texttt{db1.tex} containing questions on a certain narrow topic. The format for this file
+is,
+\begin{Verbatim}[commandchars=!()]
+%
+% !textsf(Questions on some narrow topic)
+%
+\bRTVToks{DB1} %<-!textsf(DB !ameta(name))
+\begin{rtVW}
+% !textsf(an !pkg(eqexam) question is contained in this rtVW environment)
+\end{rtVW}
+\begin{rtVW}
+% !textsf(an !pkg(eqexam) question is contained in this rtVW environment)
+\end{rtVW}
+...
+\eRTVToks
+\end{Verbatim}
+Refer to the file \texttt{db1.tex}, \texttt{db2.tex},\dots, \texttt{db4.tex} for more specific
+examples. The DB \ameta{name} must be unique among all the DB test files used.
-One user wanted to create exams using \pkg{eqexam}, but wanted to randomly
-select questions from a series of `database' files. My thought was that
-\pkg{ran\_toks} would do the job for him. After setting up a demo for him, I
-added the new command \cs{useTheseDBs} to \pkg{ran\_toks}:
+The next step is to input your DB files. To do this, execute either of the commands
+\cs{useTheseDBs} or \cs{useProbDBs} prior to the opening of an \env{exam} environment (\pkg{eqexam}),
+or perhaps in the preamble. The syntax is,
\bVerb\takeMeasure{\string\useTheseDBs\darg{\ameta{db\SUB{1}},\ameta{db\SUB{2}},...,\ameta{db\SUB{n}}}}%
-\begin{minipage}{\bxSize}\kern0pt
+\setlength\eflength{\bxSize}%
+\begin{minipage}{\bxSize}\kern0pt\def\1{\rlap{\sffamily\hskip\eflength(An alias for \cs{useTheseDBs})}}\relax
\begin{Verbatim}[frame=single,commandchars=!()]
\useTheseDBs{!ameta(db!SUB(1)),!ameta(db!SUB(2)),...,!ameta(db!SUB(n))}
-\useProbDBs{!ameta(db!SUB(1)),!ameta(db!SUB(2)),...,!ameta(db!SUB(n))}
+!1\useProbDBs{!ameta(db!SUB(1)),!ameta(db!SUB(2)),...,!ameta(db!SUB(n))}
\end{Verbatim}
\end{minipage}\eVerb The argument of \cs{useTheseDBs} is a comma-delimited
list of file names. Each file name contains a
@@ -678,11 +770,190 @@ emitted if one or more of the files are not found. The default extension is
\texttt{db2.db}, if they exist. The command \cs{useProbDBs} is an alias for
\cs{useTheseDBs}.
-The placement of \cs{useTheseDBs} is anywhere prior to the insertion of the
-problems into the document, usually in the preamble.
+Once the database files have been input, in the body of the document you can extract
+questions using \cs{useRanTok}; for example, \cs{useRanTok[DB1]\darg{1}} extracts the question
+with an index of 1 from the database file DB1;\footnote{It is assumed that DB1 is the \ameta{name}
+is the required argument of \cs{bRTVToks}, which is declared in the \texttt{db1.tex} file.} \cs{useRanTok[DB2]\darg{2}} extracts the question
+with an index of 2 from the database file DB2, and so on.
Refer to the demonstration file \texttt{mc-db.tex} for an example.
+\subsection{Striving for uniqueness of choices}
+
+By default, when you expand \cs{useRanTok\darg{1}} and later you expand
+\cs{useRanTok\darg{1}} again you get the exact same result;\footnote{Here, we
+are assuming the \ameta{name} of the token list is the same for both
+expansions of \cs{useRanTok\darg{1}}.} this is the normal behavior. However,
+in the context of posing questions from a database of questions, repeating
+the questions is not what is wanted necessarily. In the next two subsections,
+we speak to the problem, first within a single-version document, and
+secondly, within a multi-version document.
+
+
+\subsubsection{For documents with a single version}
+
+The issue of not wanting to repeat a question from a database comes up when
+you want to pose several questions from a given database file. We illustrate
+using the demo file \texttt{mc-db.tex} found in the \texttt{examples} folder.
+In that file, the exam has two parts, as shown in
+\hyperref[fig:2prts]{Figure~\ref*{fig:2prts}}.\footnote{The verbatim listing
+here has been simplified.}
+\begin{figure}[htb]\centering
+\settowidth{\eflength}{\ttfamily\string\useRanTok[DB1]\darg{1}}%
+\edef\x{\the\eflength}%
+\setlength\eflength{\x+\widthof{\textsf{\quad\%An alternate approach}\texttt{ }}}%
+\def\0{\rlap{\hskip\x\relax\quad\% \textsf{An alternate approach}}}%
+\def\1{\rlap{\hskip\x\relax\quad\% \cs{begin\darg{Part2}}}}%
+\def\2{\rlap{\hskip\x\relax\quad\% \cs{useRanTok[DB1]\darg{3}}}}%
+\def\3{\rlap{\hskip\x\relax\quad\% \cs{useRanTok[DB1]\darg{4}}}}%
+\def\4{\rlap{\hskip\x\relax\quad\% \cs{end\darg{Part2}}}}%
+\fboxsep0pt
+\begin{minipage}{\eflength}
+\begin{Verbatim}[commandchars=!()]
+\begin{Part1}
+\useRanTok[DB1]{1}
+\useRanTok[DB1]{2}
+\end{Part1}
+
+!0% !textsf( First approach)
+!1\begin{Part2}
+!2\useRanTok[DB1]{1}
+!3\useRanTok[DB1]{2}
+!4\end{Part2}
+\end{Verbatim}
+\end{minipage}
+\caption{Simplified two-part exam}\label{fig:2prts}
+\end{figure}
+For \textsf{Part1}, we take two problems (at random) from \textsf{DB1}. In
+\textsf{Part2}, we take two problems again from \textsf{DB1}; these two will
+be the \emph{same} as the ones chosen from \textsf{Part1}. To get two
+\emph{different} questions the natural approach is to write
+\cs{useRanTok[DB1]\darg{3}} and \cs{useRanTok[DB1]\darg{4}}, as shown on the
+right in \hyperref[fig:2prts]{Figure~\ref*{fig:2prts}}. Now, returning to the \textsf{First approach}, there is a way of forcing
+\pkg{ran\_toks} to choose two different question even though the indexes used are the same.
+
+To have different questions appear when you specify \verb~\useRanTok[DB1]{1}~
+and \verb~\useRanTok[DB1]{2}~, first expand the command
+\cs{uniqueXDBChoicesOn}, perhaps between parts or in the preamble. When
+\cs{uniqueXDBChoicesOn} is expanded, \cs{useRanTok} tries to find an
+``unused'' choice.
+\begin{Verbatim}[xleftmargin=\parindent,commandchars=!()]
+\uniqueXDBChoicesOn
+\begin{document}
+...
+\begin{Part1}
+\useRanTok[DB1]{1}
+\useRanTok[DB1]{2}
+\end{Part1}
+
+%\uniqueXDBChoicesOn
+
+\begin{Part2}
+\useRanTok[DB1]{1}
+\useRanTok[DB1]{2}
+\end{Part2}
+\end{Verbatim}
+The command \cs{uniqueXDBChoicesOff} turns off the feature of striving to
+find ``unused'' choices. Additional discussion on \cs{uniqueXDBChoicesOn} is
+found in the next section; the command \cs{InputUsedIDs}, discussed in the
+next section, is not needed when the \pkg{eqexam} document \emph{does not
+have} multiple versions. You can experiment with striving to find unused
+questions in the demo file \texttt{mc-db.tex}.
+
+\subsubsection{For documents with multiple versions}
+
+The scheme outlined in \hyperref[s:basicFunc]{Section~\ref*{s:basicFunc}} works well for an
+\pkg{eqexam} document that only has one version in the source file. The way
+\pkg{ran\_toks} works, it will not repeat random choices --- unless you
+sample from a same DB file more times than there are problems in that file;
+for example, suppose \texttt{db1.tex} has two questions in it, if you execute
+\cs{useRanTok[DB1]\darg{1}}, \cs{useRanTok[DB1]\darg{2}}, and
+\cs{useRanTok[DB1]\darg{3}}, then the problem selected by
+\cs{useRanTok[DB1]\darg{3}} is the same as \cs{useRanTok[DB1]\darg{1}}. This
+latter situation is not likely, is it?
+
+One of the very powerful features of \pkg{eqexam} is that a single source
+file can have multiple versions in it.
+\begin{Verbatim}[xleftmargin=\parindent,commandchars=!()]
+\examNum{1}
+\numVersions{4}
+\forVersion{a} %!textsf( a, b, c, d)
+\vA{\useThisSeed{54356}}
+\vB{\useThisSeed{577867}}
+\vC{\useThisSeed{6746788}}
+\vD{\useThisSeed{856785}}
+\end{Verbatim}
+The above shows how to set up a multi-version \pkg{eqexam} document, see the
+\pkg{eqexam} documentation for more details. Here, as in the demo file
+\texttt{mc-dbu.tex}, we declare 4 versions (a, b, c, and d).
+\cs{forVersion\darg{a}} declares the next compile is for version a (or A,
+either one). List also is a method of passing an initial seed to the
+pseudo-random number generator, for each version. (These can be arbitrarily
+typed in, or obtained by the methods discussed in
+\textbf{\nameref{para:ControlSeed}} on page~\pageref*{para:ControlSeed}.)
+
+\paragraph*{The problem.} For a multi-version \pkg{eqexam} document, where
+each version samples from the same set of DB Test files, later versions of the exam
+may have questions that are repeats of the ones posed in earlier versions of
+the same source file. This may or may not be a problem if the different
+versions are given to different classes at approximately the same time where
+there is no opportunity for the details of the test to ``leak out'' from one
+class to another.
+
+\paragraph*{The solution.} The solution to this problem requires the introduction of several
+new commands.
+\bVerb\takeMeasure{\string\uniqueXDBChoicesOn}%
+\setlength\eflength{\bxSize}%
+\begin{minipage}{\bxSize}\kern0pt\def\1{\rlap{\sffamily\hskip\eflength\%\textsf{ to view the IDs of problems used}}}\relax
+\def\2{\rlap{\sffamily\hskip\eflength\%\textsf{ preamble only (required)}}}\relax
+\def\3{\rlap{\sffamily\hskip\eflength\%\textsf{ there is also \cs{uniqueXDBChoicesOff} (the default)}}}\relax
+\begin{Verbatim}[frame=single,commandchars=!()]
+!3\uniqueXDBChoicesOn
+!2\InputUsedIDs
+!1%\viewIDstrue
+\end{Verbatim}
+\end{minipage}\eVerb The \cs{uniqueXDBChoicesOn} command
+brings some special code into the \cs{useRanTok} command; this special code
+tries to select problems that have not already been selected by earlier
+versions of the source document. Key to this selection process is that the
+special code needs to know which questions were earlier selected; that is the
+role of the \cs{InputUsedIDs}. This latter command uses the value declared in
+\cs{numVersions}, so it must appear \emph{after} the declaration of the
+number of versions.
+
+When \cs{uniqueXDBChoicesOn} is expanded, as the source document is compiled,
+an auxiliary file named \cs{jobname-ver\ameta{Ltr}.cut} is written. This
+file keeps a record of the problem ID of the problems selected, believe it or
+not. \cs{InputUsedIDs} inputs the appropriate CUT files:
+\begingroup\tightsettings
+\begin{itemize}
+\item for version B, \cs{jobname-verA.cut} is input;
+\item for version C, \cs{jobname-verA.cut}, \cs{jobname-verB.cut} are input;
+\item for version D, \cs{jobname-verA.cut}, \cs{jobname-verB.cut}, \cs{jobname-verC.cut} are input;
+\item and so on.
+\end{itemize}
+\endgroup\noindent
+In this way, when you compile version \ameta{Ltr}, the document inputs all
+the information it needs about previous versions to make in informed choice.
+
+\paragraph*{Workflow.} When compiling a multi-version \pkg{eqexam} document, do the following:
+\begin{enumerate}
+ \item Build each version in \emph{alphabetical order}, that is, compile with \cs{forVersion\darg{a}},
+ then \cs{forVersion\darg{b}}, and so on.
+ \item Rename PDF produced to reflect the version \ameta{Ltr}; eg, \verb~\jobname-verA.pdf~ or
+ \verb!\jobname-sec02.pdf!, or whatever.\footnote{The demo file \texttt{ctrl-build.tex} shows
+ how to build all versions and rename the final PDF files all from one controlling file.}
+\end{enumerate}
+
+%\paragraph*{Final comments.} \cs{uniqueXDBChoicesOn} does several things, it causes \cs{useRanTok}
+%to use some special code to ensure cross-version uniqueness of choices, but
+%it also initiates writing of the choice history to the auxiliary CUT files
+%\cs{jobname-ver\ameta{Ltr}.cut}. By placing \cs{uniqueXDBChoicesOff} in
+%the body of the document (outside a group, perhaps) that turns off the
+%execution of the special code as well and writing to the CUT files. I believe
+%you can later in the document turn this back on with \cs{uniqueXDBChoicesOn},
+%though I have not done a lot of testing of this.
+
\newtopic\noindent
Now, I simply must get back to my retirement. \dps
diff --git a/macros/latex/contrib/ran_toks/examples/ctrl-build.tex b/macros/latex/contrib/ran_toks/examples/ctrl-build.tex
new file mode 100644
index 0000000000..c5401a303d
--- /dev/null
+++ b/macros/latex/contrib/ran_toks/examples/ctrl-build.tex
@@ -0,0 +1,58 @@
+\documentclass{article}
+\usepackage{shellesc}
+\usepackage{fancyvrb}
+
+\newif\ifcompileit \compileittrue
+
+\begin{document}
+
+\noindent
+This is a dummy file to help compile multiple versions of the same source file.
+The commands are very simple, they can be improved in a variety of ways.
+
+\def\basename{mc-dbu-ctrld} % base name of target file
+\def\altbasename{mc-dbu} % base name of output file
+% define a simple \forVersion command, convert letter to upper case
+\def\forVersion#1{\uppercase{\edef\selVersion{#1}}}
+
+% select the version letter (upper or lower case)
+\forVersion{a}
+% define a suffix that follows \altbasename, redefine as desired
+\edef\altsuffix{%
+ \if\selVersion Asec01\else
+ \if\selVersion Bsec02\else
+ \if\selVersion Csec03\else
+ \if\selVersion Dsec04\fi\fi\fi\fi}
+
+\begin{VerbatimOut}[commandchars=!()]{build-info.tex}
+\examNum{1}
+\numVersions{4}
+\forVersion{!selVersion}
+\vA{\useThisSeed{54356}}
+\vB{\useThisSeed{577867}}
+\vC{\useThisSeed{6746788}}
+\vD{\useThisSeed{856785}}
+%\viewIDstrue % to view the IDs of problems used
+\end{VerbatimOut}
+
+\medskip\noindent
+Compiling the file \texttt{\basename.tex} for version~\selVersion\space(\altsuffix), and renaming the final
+PDF produced to \texttt{\altbasename-\altsuffix.pdf}
+
+
+\ifcompileit
+
+% compile using the PDF creator of your choice, copy and paste this next
+% line to execute multiple compiles to bring labels, if any, up to date
+\ShellEscape{pdflatex \basename}
+%\ShellEscape{pdflatex \basename}
+%\ShellEscape{pdflatex \basename}
+
+% copy the newly created file to a new file name
+\ShellEscape{move \basename.pdf \altbasename-\altsuffix.pdf}
+% delete build-info.tex
+\ShellEscape{del build-info.tex}
+
+\fi
+
+\end{document} \ No newline at end of file
diff --git a/macros/latex/contrib/ran_toks/examples/db1.tex b/macros/latex/contrib/ran_toks/examples/db1.tex
index 45a8b67124..f51bf5b74b 100644
--- a/macros/latex/contrib/ran_toks/examples/db1.tex
+++ b/macros/latex/contrib/ran_toks/examples/db1.tex
@@ -1,7 +1,7 @@
%
% First DB, uses ran_toks and eqexam
%
-\bRTVToks{DB1-}
+\bRTVToks{DB1}
\begin{rtVW}
\begin{problem}[5]
diff --git a/macros/latex/contrib/ran_toks/examples/db2.tex b/macros/latex/contrib/ran_toks/examples/db2.tex
index dc18b86faa..bb1cfb8e75 100644
--- a/macros/latex/contrib/ran_toks/examples/db2.tex
+++ b/macros/latex/contrib/ran_toks/examples/db2.tex
@@ -2,7 +2,7 @@
% Second DB, uses ran_toks and eqexam
%
-\bRTVToks{DB2-}
+\bRTVToks{DB2}
\begin{rtVW}
\begin{problem}[5]
@@ -62,4 +62,4 @@ DB2: Fourth: Which is correct?
\eRTVToks
-\endinput \ No newline at end of file
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/ran_toks/examples/db3.tex b/macros/latex/contrib/ran_toks/examples/db3.tex
index 1948692f1f..099eeb2c7b 100644
--- a/macros/latex/contrib/ran_toks/examples/db3.tex
+++ b/macros/latex/contrib/ran_toks/examples/db3.tex
@@ -2,7 +2,7 @@
% Third DB, uses ran_toks and eqexam
%
-\bRTVToks{DB3-}
+\bRTVToks{DB3}
\begin{rtVW}
\begin{problem}[5]
@@ -62,4 +62,4 @@ DB3: Fourth: Which is correct?
\eRTVToks
-\endinput \ No newline at end of file
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/ran_toks/examples/db4.tex b/macros/latex/contrib/ran_toks/examples/db4.tex
index 64b1d241ef..b6b4556a6f 100644
--- a/macros/latex/contrib/ran_toks/examples/db4.tex
+++ b/macros/latex/contrib/ran_toks/examples/db4.tex
@@ -2,7 +2,7 @@
% Fourth DB, uses ran_toks and eqexam
%
-\bRTVToks{DB4-}
+\bRTVToks{DB4}
\begin{rtVW}
\begin{problem}[5]
@@ -62,4 +62,4 @@ DB4: Fourth: Which is correct?
\eRTVToks
-\endinput \ No newline at end of file
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/ran_toks/examples/mc-db.tex b/macros/latex/contrib/ran_toks/examples/mc-db.tex
index 1eb2ce548a..549da16f2c 100644
--- a/macros/latex/contrib/ran_toks/examples/mc-db.tex
+++ b/macros/latex/contrib/ran_toks/examples/mc-db.tex
@@ -1,7 +1,9 @@
-\documentclass{article}
-\usepackage[allowrandomize,nosolutions,
- forpaper,pointsonleft,noparttotals]{eqexam}
-\usepackage{ran_toks}
+\documentclass[a4paper]{article}
+\usepackage[%
+ allowrandomize,
+ nosolutions,
+ forpaper,pointsonleft,noparttotals]{eqexam}
+\usepackage[usedbapp]{ran_toks}
\useLastAsSeed
% To reproduce the same pseudo-random sequence, you need to supply a seed
@@ -13,14 +15,21 @@
\subject[MC]{My Course}
\date{Spring \the\year}
\keywords{Test~\nExam, Section 001}
-
-\university
+ \university
{%
THE UNIVERSITY OF AKRON\\
Theoretical and Applied Mathematics
}
\email{dpstory@uakron.edu}
+
+
+%\uniqueXDBChoicesOn
+%\viewIDstrue % to view the IDs of problems used\university
+%\doNotRandomizeChoices % eqexam 2021/01/20
+%\allowRandomizedChoices % eqexam 2021/01/20
+
+
% Input the DB files used in the demo file
\useTheseDBs{db1,db2,db3,db4}
@@ -38,38 +47,47 @@ This part demonstrates how to not only randomly pull problems (two from each of
to randomize the order they are listed in the exam.
\end{instructions}
-\ranToks{myExam}{%
- {\useRanTok[DB1-]{1}}
- {\useRanTok[DB1-]{2}}
- {\useRanTok[DB2-]{1}}
- {\useRanTok[DB2-]{2}}
- {\useRanTok[DB3-]{1}}
- {\useRanTok[DB3-]{2}}
- {\useRanTok[DB4-]{1}}
- {\useRanTok[DB4-]{2}}
+\ranToksOff
+
+\ranToks{myExam}
+{%
+ {\useRanTok[DB1]{1}}
+ {\useRanTok[DB1]{2}}
+ {\useRanTok[DB2]{1}}
+ {\useRanTok[DB2]{2}}
+ {\useRanTok[DB3]{1}}
+ {\useRanTok[DB3]{2}}
+ {\useRanTok[DB4]{1}}
+ {\useRanTok[DB4]{2}}
}
\displayListRandomly{myExam}
\end{exam}
+\newpage
+
+%\uniqueXDBChoicesOff
+
\begin{exam}{Part2}
\begin{instructions}
-In this part, we take the same two problems from each of the four DB files, but do not randomize
-the order of the questions.
+In this part, when \verb~\uniqueXDBChoicesOff~ (the default) is
+expanded, we take the same two problems from each of the four DB
+files, but here, we do not randomize the order of the questions. However,
+when \verb~\uniqueXDBChoicesOn~ is expanded in the preamble,
+this set of eight questions are entirely different from the ones
+of \textsf{Part1}.
\end{instructions}
-\useRanTok[DB1-]{1}
-\useRanTok[DB1-]{2}
-\useRanTok[DB2-]{1}
-\useRanTok[DB2-]{2}
-\useRanTok[DB3-]{1}
-\useRanTok[DB3-]{2}
-\useRanTok[DB4-]{1}
-\useRanTok[DB4-]{2}
+\useRanTok[DB1]{1}
+\useRanTok[DB1]{2}
+\useRanTok[DB2]{1}
+\useRanTok[DB2]{2}
+\useRanTok[DB3]{1}
+\useRanTok[DB3]{2}
+\useRanTok[DB4]{1}
+\useRanTok[DB4]{2}
\end{exam}
\end{document}
-
-
diff --git a/macros/latex/contrib/ran_toks/examples/mc-dbu-ctrld.tex b/macros/latex/contrib/ran_toks/examples/mc-dbu-ctrld.tex
new file mode 100644
index 0000000000..0f0b9b140a
--- /dev/null
+++ b/macros/latex/contrib/ran_toks/examples/mc-dbu-ctrld.tex
@@ -0,0 +1,62 @@
+\documentclass{article}
+\usepackage[allowrandomize,nosolutions,
+ forpaper,pointsonleft,noparttotals]{eqexam}
+\usepackage[usedbapp]{ran_toks}
+
+%\rtdebugtrue
+
+% This file is not compiled directly, but by the file ctrl-build.tex, see that file for details
+\input{build-info}
+
+\uniqueXDBChoicesOn
+\InputUsedIDs
+
+\title[T\nExam]{Test \nExam}
+\author{D. P. Story}
+\subject[MC]{My Course}
+\date{Spring \the\year}
+\keywords{Test~\nExam, Section 001}
+\altTitle{Section~%
+ \if\selVersion A01\else
+ \if\selVersion B02\else
+ \if\selVersion C03\else
+ 04\fi\fi\fi\space(Version~\selVersion)}
+
+\makeInfoAWarning
+
+\university
+{%
+ THE UNIVERSITY OF AKRON\\
+ Theoretical and Applied Mathematics
+}
+\email{dpstory@uakron.edu}
+
+% Input the DB files used in the demo file
+\useTheseDBs{db1,db2,db3,db4}
+
+\begin{document}
+
+\maketitle
+
+\begin{exam}{Part1}
+
+\begin{instructions}
+Solve each without error. Passing is 100\%.
+
+\medskip\noindent
+This part demonstrates how to not only randomly pull problems (two from each of the DB files), but
+to randomize the order they are listed in the exam.
+\end{instructions}
+
+\ranToks{myExam}
+{%
+ {\useRanTok[DB1]{1}}
+ {\useRanTok[DB2]{1}}
+ {\useRanTok[DB3]{1}}
+ {\useRanTok[DB4]{1}}
+}
+\displayListRandomly{myExam}
+
+\end{exam}
+
+\end{document}
diff --git a/macros/latex/contrib/ran_toks/examples/mc-dbu.tex b/macros/latex/contrib/ran_toks/examples/mc-dbu.tex
new file mode 100644
index 0000000000..b0790c8bba
--- /dev/null
+++ b/macros/latex/contrib/ran_toks/examples/mc-dbu.tex
@@ -0,0 +1,75 @@
+\documentclass{article}
+\usepackage[allowrandomize,nosolutions,
+ forpaper,pointsonleft,noparttotals]{eqexam}
+\usepackage[usedbapp]{ran_toks}
+
+%\rtdebugtrue
+
+%\useLastAsSeed
+% To reproduce the same pseudo-random sequence, you need to supply a seed
+%\useThisSeed{1125676795}
+
+\examNum{1}
+\numVersions{4}
+\forVersion{d}
+\vA{\useThisSeed{54356}}
+\vB{\useThisSeed{577867}}
+\vC{\useThisSeed{6746788}}
+\vD{\useThisSeed{856785}}
+
+\uniqueXDBChoicesOn
+\InputUsedIDs
+\viewIDstrue % to view the IDs of problems used
+
+\title[T\nExam]{Test \nExam}
+\author{D. P. Story}
+\subject[MC]{My Course}
+\date{Spring \the\year}
+\keywords{Test~\nExam, Section 001}
+\altTitle{Section~%
+ \if\selVersion A01\else
+ \if\selVersion B02\else
+ \if\selVersion C03\else
+ 04\fi\fi\fi\space(Version~\selVersion)}
+
+%\makeInfoAWarning
+
+\university
+{%
+ THE UNIVERSITY OF AKRON\\
+ Theoretical and Applied Mathematics
+}
+\email{dpstory@uakron.edu}
+
+% Input the DB files used in the demo file
+\useTheseDBs{db1,db2,db3,db4}
+
+\begin{document}
+
+\maketitle
+
+\begin{exam}{Part1}
+
+\begin{instructions}
+Solve each without error. Passing is 100\%.
+
+\medskip\noindent
+This part demonstrates how to not only randomly pull problems
+(two from each of the DB files), but to randomize the order they
+are listed in the exam.
+\end{instructions}
+
+\ranToksOff % turn off randomization of the order
+
+\ranToks{myExam}
+{%
+ {\useRanTok[DB1]{1}}
+ {\useRanTok[DB2]{1}}
+ {\useRanTok[DB3]{1}}
+ {\useRanTok[DB4]{1}}
+}
+\displayListRandomly{myExam}
+
+\end{exam}
+
+\end{document}
diff --git a/macros/latex/contrib/ran_toks/examples/ran_toks.tex b/macros/latex/contrib/ran_toks/examples/ran-toks.tex
index e10238aa5a..0408003d24 100644
--- a/macros/latex/contrib/ran_toks/examples/ran_toks.tex
+++ b/macros/latex/contrib/ran_toks/examples/ran-toks.tex
@@ -57,6 +57,7 @@ How did that other stuff get in there?
\begin{enumerate}
\displayListRandomly[\item]{myThoughts}
\end{enumerate}
+
Use \verb!\useRTName! command when another list separates the current
position from the list you want to use. Here we want to use the list named
\texttt{myPals}, but since that definition, a new list named
diff --git a/macros/latex/contrib/ran_toks/examples/rt-cb.tex b/macros/latex/contrib/ran_toks/examples/rt-cb.tex
new file mode 100644
index 0000000000..c8e20e4d17
--- /dev/null
+++ b/macros/latex/contrib/ran_toks/examples/rt-cb.tex
@@ -0,0 +1,36 @@
+\documentclass{article}
+\usepackage{ran_toks}
+\usepackage{collectbox}
+
+\useLastAsSeed
+
+\newbox\rtcollectbox
+
+\parindent0pt
+
+
+\begin{document}
+
+In this file, a method of placing verbatim content in as a token argument of
+\verb~\ranToks~ The key is to use the \textsf{collectbox} package, and collect
+the verbatim content with \verb~\collectboxto~.
+
+\def\cbCont{\def\myVerb{\usebox{\rtcollectbox}}}
+\collectboxto{\rtcollectbox}{\cbCont}{\verb!$x^2+1$!}
+
+%\ranToksOff
+\ranToks{CB}
+{%
+ {Don-1}
+ {Kira-2}
+ {Alex-3}
+ {Jim-4}
+ {Rick-5}
+ {\myVerb-6}
+}
+
+\useRanTok{1}, \useRanTok{2}, \useRanTok{3}, \useRanTok{4}, \useRanTok{5},
+\useRanTok{6}%, \useRanTok{7}
+
+
+\end{document}
diff --git a/macros/latex/contrib/ran_toks/examples/random_tst.tex b/macros/latex/contrib/ran_toks/examples/rt-tst-eqe.tex
index 1f64c79907..5d4d665396 100644
--- a/macros/latex/contrib/ran_toks/examples/random_tst.tex
+++ b/macros/latex/contrib/ran_toks/examples/rt-tst-eqe.tex
@@ -8,8 +8,7 @@
\usepackage{ran_toks}
\useLastAsSeed
-%\useThisSeed{452836675} % fi,t,f,s
-
+%\useThisSeed{452836675}
\examNum{1}
\title[T\nExam]{Test \nExam}
\author{D. P. Story}
@@ -25,6 +24,7 @@
\email{dpstory@uakron.edu}
\begin{document}
+
\maketitle
@@ -97,7 +97,6 @@ Fourth: Which is correct?
% Ok, now display this questions in a random order.
\displayListRandomly{Exam\nExam}
-
\end{exam}
\end{document}
diff --git a/macros/latex/contrib/ran_toks/examples/random_tst_qz.tex b/macros/latex/contrib/ran_toks/examples/rt-tst-qz.tex
index 3ca3c4043e..07be773883 100644
--- a/macros/latex/contrib/ran_toks/examples/random_tst_qz.tex
+++ b/macros/latex/contrib/ran_toks/examples/rt-tst-qz.tex
@@ -8,14 +8,16 @@
\documentclass{article}
\usepackage[designiv]{web}
\usepackage[allowrandomize,showgrayletters]{exerquiz}
-\usepackage{ran_toks}
+\usepackage{ran-toks} % alt pkg name
+
+% \previewOn\pmpvOn
% When using cross-referencing and \useLastAsSeed, the cross-references are never up to date.
-% Once you randomize, read the auxiliary file (\jobname_rt.save), copy the first seed listed
-% and paste in as the argument of \useThisSeed. Compile a few more times to bring cross-refereces
+% Once you randomize, read the auxiliary file (\jobname_rt.sav), copy the first seed listed
+% and paste in as the argument of \useThisSeed. Compile a few more times to bring cross-references
% up to date.
%\useLastAsSeed
-\useThisSeed{1327548830}
+\useThisSeed{955908747}
\rowsepDefault{3pt}
@@ -27,7 +29,7 @@
\begin{questions}
\item Try to guess the correct answer.
\begin{answers}{2}
- \bChoices[random]
+ \bChoices[random=true]
\Ans0 1 a choice\eAns
\Ans1\label{eq} 2 another choice\eAns
\Ans0 3 still another choice\eAns
@@ -38,8 +40,8 @@
\Ans0 8 too many\eAns
\Ans0 9 choices\eAns
\Ans0 10 \input{mytext.verb}\eAns
- \eFreeze
- \Ans0 10 None of these\eAns
+ \eFreeze
+ \Ans0 11 None of these\eAns
\eChoices
\end{answers}
\end{questions}
@@ -71,10 +73,10 @@ Solve each.
\useRTName{myChoices}
\begin{manswers}*{1}
\bChoices[random=true,label=rtAns]
- \Ans{1}\label{rtAns3}\rtTokByNum{1}\eAns
+ \Ans{1}\label{rtAns3} \rtTokByNum{1}\eAns
\Ans{0} Wow, \rtTokByNum{2}, this is great!\eAns
- \Ans{0}\rtTokByNum{3}\eAns
- \Ans{0}\rtTokByNum{4}\eAns
+ \Ans{0} \rtTokByNum{3}\eAns
+ \Ans{0} \rtTokByNum{4}\eAns
\eFreeze
\Ans{1} Hello mom!\eAns
\eChoices
@@ -110,6 +112,6 @@ The answer is \hyperref[rtAns1]{(\REF*{rtAns1})} found in the
\eChoices
\end{answers}
\end{questions}
-\end{quiz*}
+\end{quiz*}\quad\ScoreField\currQuiz\CorrButton\currQuiz
\end{document}
diff --git a/macros/latex/contrib/ran_toks/examples/viewDB.tex b/macros/latex/contrib/ran_toks/examples/viewDB.tex
new file mode 100644
index 0000000000..be9c5623b5
--- /dev/null
+++ b/macros/latex/contrib/ran_toks/examples/viewDB.tex
@@ -0,0 +1,40 @@
+\documentclass[12pt]{article}
+\usepackage[usedbapp]{ran_toks}
+
+\usepackage[%allowrandomize,
+ nosolutions,forcolorpaper,pointsonleft,noparttotals]{eqexam}
+
+\everymath{\displaystyle}
+
+\examNum{1}
+\title[ViewDB]{View a DB Test File}
+\author{D. P. Story}
+\subject[MC]{Demo file}
+\university
+{%
+ THE UNIVERSITY OF AKRON\\
+ Theoretical and Applied Mathematics
+}
+\email{dpstory@uakron.edu}
+
+\useProbDBs{db1,db2,db3,db4}
+\viewIDstrue
+
+\begin{document}
+
+
+\begin{exam}{View}
+
+%%%%%%%%%%%%%%%%
+% Typeset a DB %
+%%%%%%%%%%%%%%%%
+% The problems are input in the order they appear in the DB, the alternatives
+% are not randomized either.
+\viewDB{DB1} % DB1, DB2, DB3, DB4
+
+
+\end{exam}
+\end{document}
+
+
+
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
diff --git a/macros/latex/contrib/ran_toks/ran_toks.ins b/macros/latex/contrib/ran_toks/ran_toks.ins
index 4d2d77d191..1d84cf5ce6 100644
--- a/macros/latex/contrib/ran_toks/ran_toks.ins
+++ b/macros/latex/contrib/ran_toks/ran_toks.ins
@@ -46,6 +46,7 @@
{%
\file{ran_toks.sty}{\from{ran_toks.dtx}{copyright,package}}
\file{ran-toks.sty}{\from{ran_toks.dtx}{copyright,altpkgname}}
+ \file{rt-dbapp.def}{\from{ran_toks.dtx}{copyright,dbapp}}
}
\Msg{***************************************************************}