% \iffalse %<*copyright> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% dps.sty package, %% %% Copyright (C) 2006--2020 D. P. Story %% %% dpstory@acrotex.net %% %% %% %% This program can redistributed and/or modified under %% %% the terms of the LaTeX Project Public License %% %% Distributed from CTAN archives in directory %% %% macros/latex/base/lppl.txt; either version 1 of the %% %% License, or (at your option) any later version. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{dps} % [2020/06/03 v1.7 Das Puzzle Spiel (dps)] %<*driver> \documentclass{ltxdoc} \usepackage[colorlinks,hyperindex=false]{hyperref}[2012/10/12] \usepackage{fancyvrb} \pdfstringdefDisableCommands{\let\\\textbackslash}% \EnableCrossrefs \CodelineIndex \RecordChanges \bgroup\ttfamily \gdef\brpr#1{\char123\relax#1\char125\relax}\egroup \let\darg\brpr \let\env\texttt \let\opt\texttt \let\app\textsf \def\visispace{\symbol{32}} \def\ameta#1{\ensuremath{\langle\textit{\texttt{#1}}\rangle}} \def\meta#1{\textsl{\texttt{#1}}} \def\SUB#1{\ensuremath{{}_{\mbox{\scriptsize\ttfamily#1}}}} \def\ltag{<}\def\rtag{>} \def\EXCL{!} \let\app\textsf\let\pkg\textsf %\OnlyDescription % comment out for implementation details \InputIfFileExists{aebdocfmt.def}{\PackageInfo{dps}{Inputting aebdocfmt.def}} {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro} \let\setupFullwidth\relax \PackageInfo{dps}{aebdocfmt.def cannot be found}} \begin{document} \GetFileInfo{dps.sty} \title{The \texttt{dps} Package} \author{D. P. Story\\ Email: \texttt{dpstory@acrotex.net}} \date{processed \today} \value{secnumdepth}=3 \value{tocdepth}=3 \maketitle \tableofcontents \let\Email\texttt \DocInput{dps.dtx} \IfFileExists{\jobname.ind}{\newpage\setupFullwidth\PrintIndex}{\paragraph*{Index} The index goes here.\\Execute \texttt{makeindex -s gind.ist -o dps.ind dps.idx} on the command line and recompile \texttt{dps.dtx}.} \IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here.\\Execute \texttt{makeindex -s gglo.ist -o dps.gls dps.glo} on the command line and recompile \texttt{dps.dtx}.} \end{document} % % \fi % \MakeShortVerb{|} % \InputIfFileExists{aebdonotindex.def}{\PackageInfo{eforms}{Inputting aebdonotindex.def}} % {\PackageInfo{eforms}{aebdonotindex.def cannot be found}} % \begin{macrocode} %<*package> % \end{macrocode} % \section{Introduction} % The \textsf{dps} Package (Das Puzzle Spiel) provides the commands to create a matching % game and associated puzzle. As the user answers each question, another part of the puzzle % is filled in. After the user has correctly answered all the questions, the message contained % in the puzzle is fully visible. The user answers the question by first clicking the checkbox % of that question, reading and solving the question, then by finding the correct answer listed % amongst the answer columns. This game was inspired by one of the handout work sheets of my % son's eighth grade pre-algebra class. % % \section{Options} % We bring in the \textsf{xkeyval} Package so we can gather our options using % it's commands, rather than the default \textsf{keyval} commands. % \begin{macrocode} \RequirePackage{xkeyval} % \end{macrocode} % \leavevmode\IndexOpt{nonrandomized}\ignorespaces % The default behavior is to randomize the questions and answers. With this option, the % questions and answers are listed in the order they were written in the source file; good % for debugging, and testing the document. We also have the option \IndexOpt[\protect\EXCL]{!nonrandomized}\opt{!nonrandomized} % to `cancel' \opt{nonrandomized}. % \begin{macrocode} \DeclareOptionX{nonrandomized}{\werandomizefalse} \DeclareOptionX{!nonrandomized}{\werandomizetrue} % \end{macrocode} % \leavevmode\IndexOpt{viewmode}\ignorespaces % Used for developing the puzzle. When \texttt{viewmode} is optioned, the puzzle and letters in % the puzzle are seen. By adjusting the argument of \cs{insertPuzzle} you can get the distribution % of the puzzle that you want. See also the comments preceding the definition of \cs{makeTextField} below. % The \IndexOpt[\protect\EXCL]{!viewmode}\opt{!viewmode} option cancels the \opt{viewmode} option. % \begin{macrocode} \DeclareOptionX{viewmode}{\viewModetrue\previewtrue} \DeclareOptionX{!viewmode}{\viewModefalse\previewfalse} % \end{macrocode} % \leavevmode\IndexOpt{showletters}\ignorespaces % When this option is taken, in the answer columns, the letters that the answers correspond to appear; % and in the puzzle, the question number that corresponds to that letter. Generally, this is used % when web is put in \texttt{forpaper} mode, but can be used in ``screen'' mode. The convenience % option of \IndexOpt[\protect\EXCL]{!showletters}\opt{!showletters} is also provided. % \begin{macrocode} \DeclareOptionX{showletters}{\showletterstrue} \DeclareOptionX{!showletters}{\showlettersfalse} % \end{macrocode} % \leavevmode\IndexOpt{showanswerlabels}\ignorespaces % We give the user the option of showing the label for the answer, in the case % of for screen presentation. %\changes{v1.0}{2006/10/31} %{ % Added the \string\texttt{showanswerlabels} option %} % \begin{macrocode} \DeclareOptionX{showanswerlabels} {% \ifeqforpaper\else\def\dpsAitemOptArg{}\fi } \DeclareOptionX{!showanswerlabels}{% \def\dpsAitemOptArg{[]}} \def\dpsAitemOptArg{[]} % \end{macrocode} % \leavevmode\IndexOpt{showanswerkey}\ignorespaces % When this option is taken, the solution key appears in the footer. If the % graphicx package is loaded, the answer key is rotated 180 degrees. The % answer key is always computed and saved in the macro \cs{AnswerKey}. Selecting % \opt{showanswerkey} also activates the \opt{showletters} option. % The convenience option \IndexOpt[\protect\EXCL]{!showanswerkey}\opt{!showanswerkey} is also % provided. % \begin{macrocode} \DeclareOptionX{showanswerkey}{\showsolutiontrue \ExecuteOptionsX{showletters}} \DeclareOptionX{!showanswerkey}{\showsolutionfalse} % \end{macrocode} % \paragraph*{Options for posing questions.} There are two methods of posing longer questions: % (1) (\opt{usebtnappr}) Place these questions in the appearance of a button; or % (2) (\opt{uselayers}) Place the questions in their own layer (OCG). Only one of these % two options is allowed. Neither option is also permitted (short questions only). % \begin{macrocode} % \end{macrocode} % \leavevmode % \IndexOpt{usebtnappr}\ignorespaces % A required option when you want to pose longer questions. We have a complex % workflow for placing the questions as a button appearance. This option brings in supporting commands. % \begin{macrocode} \DeclareOptionX{usebtnappr}{\usebtnapprtrue \ifuseocgappr \PackageWarningNoLine{dps} {Options usebtnappr and uselayers both used.\MessageBreak Will use the uselayers option}% \usebtnapprfalse \let\dpsInputBtnAppr\relax \else \def\dpsInputBtnAppr{\InputIfFileExists{usebtnappr.def}{}{}}% \fi} \let\dpsInputBtnAppr\relax % \end{macrocode} % \leavevmode % \IndexOpt{uselayers} % A required option when you want to pose longer questions. Longer questions % are placed in OCG (layers). This option brings in supporting commands. % \begin{macrocode} \DeclareOptionX{uselayers}{\useocgapprtrue \ifusebtnappr \PackageWarningNoLine{dps} {Options usebtnappr and uselayers both used.\MessageBreak Will use the usebtnappr option}% \useocgapprfalse \let\dpsInputOcgAppr\relax \else \def\dpsInputOcgAppr{\InputIfFileExists{useocgappr.def}{}{}}% \fi} \let\dpsInputOcgAppr\relax % \end{macrocode} % \leavevmode\IndexOpt{savedata}\ignorespaces % When this option is taken, the solution key appears in the footer. If the % graphicx package is loaded, the answer key is rotated 180 degrees. The % answer key is always computed and saved in the macro \cs{AnswerKey}. % The negation of \opt{savedata}, \IndexOpt[\protect\EXCL]{!savedata}\opt{!savedata}, is also % provided. % \begin{macrocode} \DeclareOptionX{savedata}{\savepuzzledatatrue} \DeclareOptionX{!savedata}{\savepuzzledatafalse} % \end{macrocode} % Various switches used by this package % \begin{macrocode} \newif\ifwerandomize \werandomizetrue \newif\ifviewMode \viewModefalse \newif\ifshowletters\showlettersfalse \newif\ifshowsolution\showsolutionfalse \newif\ifsavepuzzledata\savepuzzledatafalse \newif\ifusebtnappr \usebtnapprfalse \newif\ifuseocgappr \useocgapprfalse % \end{macrocode} % (20/06/03) New default is is \cs{wrtContenttrue}. % \changes{v1.7}{20/06/03}{Changing from \string\cs{wrtContentfalse} % as the default to \string\cs{wrtContenttrue} as the default.} % \begin{macrocode} \newif\ifwrtContent\wrtContenttrue % \end{macrocode} % If a paper option is taken, we show the letters. % \begin{macrocode} \ifeqforpaper\showletterstrue\fi % \end{macrocode} % \leavevmode\IndexOpt{lang}\ignorespaces % The only language localizations are the clever commands that appear in the message box. % We offer two language options, \opt{english} (the default) and \opt{german}. There % is a custom option for the author to provide his/her own language localizations. % \begin{macrocode} \define@choicekey*+{dps.sty}{lang}[\val\nr]{english,german,custom} {% \ifcase\nr\relax \def\dps@lang@type{\input{dps_str_us.def}}\or \def\dps@lang@type{\input{dps_str_de.def}}\or \def\dps@lang@type{\input{dps_str_cus.def}}\else \def\dps@lang@type{\input{dps_str_us.def}}\fi }{\PackageWarning{dps}{Bad choice for lang, permissible values are english, german and custom. Try again}} \def\dps@lang@type{\input{dps_str_us.def}} % \end{macrocode} % \begin{macrocode} \AtEndOfPackage{\dps@lang@type} \ProcessOptionsX \edef\dps@restoreCats{% \catcode`\noexpand\"=\the\catcode`\"\relax \catcode`\noexpand\,=\the\catcode`\,\relax \catcode`\noexpand\_=\the\catcode`\_\relax } \@makeother\"\@makeother\,\@makeother\_ % \end{macrocode} % \section{Required Packages} % \begin{macrocode} \RequirePackage{web} \RequirePackage{eforms} \ifxetex\makeXasPDOff\fi \RequirePackage{graphicx} % \end{macrocode} % In addition to the \pkg{web} and \pkg{eforms} packages, the following are % used in the macro package. % \begin{macrocode} \RequirePackage{verbatim} \RequirePackage{calc} \RequirePackage{multicol} \RequirePackage{multido} % \end{macrocode} % \begin{macrocode} \hypersetup{pdfencoding=pdfdoc} % \end{macrocode} % Input JavaScript for the \opt{usebtnappr} option % \begin{macrocode} \ifusebtnappr \def\x{\AtEndOfPackage{\dpsInputBtnAppr}}% \expandafter\x\fi % \end{macrocode} % Input JavaScript for the \opt{uselayers} option % \begin{macrocode} \ifuseocgappr \def\x{\AtEndOfPackage{\dpsInputOcgAppr}}% \expandafter\x\fi % \end{macrocode} % For \opt{usebtnappr}, we require \pkg{icon-appr} to embed the graphics, % and make them appearances of buttons. % \begin{macrocode} \ifusebtnappr \def\dps@RP{\RequirePackage{icon-appr}[2020/06/05]} \expandafter\dps@RP \fi % \end{macrocode} % \changes{v1.7}{20/06/03}{Detect if \string\texttt{icons-pglst.sav}, if yes % set \string\cs{wrtContentfalse}} % (20/06/03) If the file \texttt{icons-pglst.sav} is present, that means % the author has already compiled \texttt{icons.tex}, so we can % set \cs{wrtContentfalse}. For the \opt{usebtnappr} option: If \cs{ifwrtContent} is true (\texttt{icons.tex} % has not produced the \texttt{icons-pglst.sav} file yet), we set % \cs{savepuzzledatatrue}; otherwise, if \cs{ifwrtContent} is false, we set % \cs{savepuzzledatafalse}. % \begin{macrocode} \def\dps@ckForpglst{\IfFileExists{icons-pglst.sav} {\global\wrtContentfalse}{} \ifusebtnappr \ifwrtContent \global\savepuzzledatatrue \else \global\savepuzzledatafalse \fi \fi } \ifusebtnappr \def\dps@emitEOP{\AtEndOfPackage{\dps@ckForpglst}} \expandafter\dps@emitEOP\fi % \end{macrocode} % \paragraph*{Input \app{random.tex}.} Input and make modifications. % \begin{macrocode} \@ifundefined{nextrandom}{\input{random.tex}}{} % \end{macrocode} % We modify \cs{nextrandom} to save the startup seed. % \begin{macrocode} \def\dps@nextrandom{% \def\nextrandom{\begingroup \ifnum\randomi<\@ne % then initialize with time \global\randomi\time \global\multiply\randomi388 \global\advance\randomi\year \global\multiply\randomi31 \global\advance\randomi\day \global\multiply\randomi97 \global\advance\randomi\month \message{Randomizer initialized to \the\randomi.}% \nextrandom \nextrandom \nextrandom \xdef\ds@saveRandomSeed{\the\randomi}% \fi \count@ii\randomi \divide\count@ii 127773 % modulus = multiplier * 127773 + 2836 \count@\count@ii \multiply\count@ii 127773 \global\advance\randomi-\count@ii % random mod 127773 \global\multiply\randomi 16807 \multiply\count@ 2836 \global\advance\randomi-\count@ \ifnum\randomi<\z@ \global\advance\randomi 2147483647\relax\fi \endgroup } } \newif\ifnextrandomredefd\nextrandomredefdfalse % \end{macrocode} % This package modifies \cs{nextrandom} from \pkg{random.tex}; however, % other package, most notably, also use the \pkg{random.tex} macros and overwrite % this definition of \cs{nextrandom}. To work around this problem, this package % delays the redefinition of \cs{nextrandom} until is is first used in the preamble % The command \cs{redefnextrandomAsNeeded} appears in the \cs{ds@randomizeList}, which % is where all randomization occurs. % \begin{macrocode} \def\redefnextrandomAsNeeded{\ifnextrandomredefd\else \global\let\nextrandom\dps@nextrandom \global\nextrandomredefdtrue\fi} % \end{macrocode} % \leavevmode\DescribeMacro\useRandomSeed\hskip-\marginparsep % \texttt{\darg{\ameta{pos-num}}} % Use the number \ameta{pos-num} as the initial seed. % \begin{macrocode} \def\useRandomSeed#1{\randomi=#1 \def\ds@saveRandomSeed{#1}} % \end{macrocode} % With \DescribeMacro\inputRandomSeed\cs{inputRandomSeed}, you input a seed value earlier saved % with the option savedata. That way, you always get the same seed % value as you move from the puzzle file to the icons file and back % again. % \begin{macrocode} \def\inputRandomSeed{\ifwerandomize \InputIfFileExists{\jobname_data.sav}{}{}% \edef\ds@saveRandomSeed{\the\randomi}\fi} % \end{macrocode} % \leavevmode % \DescribeMacro\useLastSeed\cs{inputRandomSeed} Input a last seed value % that was available at the end of the last compile. (This assumes \opt{savedata} % is an active option.) If the SAV file does not exists, the seed used is based % on the data and time. % \begin{macrocode} \def\dpsLastSeed#1{\def\dps@LastSeed{#1}} \def\useLastSeed{\ifwerandomize \InputIfFileExists{\jobname_data.sav}{}{}% \@ifundefined{dps@LastSeed}{} {\randomi=\dps@LastSeed\relax}% \edef\ds@saveRandomSeed{\the\randomi}\fi } % \end{macrocode} % % \section{Switches and things} % % \begin{macrocode} \newif\ifforquestions \forquestionstrue \newcount\ds@nCnt \newcount\ds@nMax \newcount\ds@qNumber\ds@qNumber=0 \newcount\ds@aNumber\ds@aNumber=0 \newcount\ds@probCnt \ds@probCnt=0 \newcount\ds@nCntCols \ds@nCntCols=0 \newcount\ds@getRanNum \newtoks\ds@listIn \ds@listIn={} \newtoks\ds@newListIn \ds@newListIn={} \newtoks\ds@listOut \ds@listOut={} \newtoks\ds@tmpToks \ds@tmpToks={} \newtoks\ds@qlistOut \ds@qlistOut={} \newtoks\ds@alistOut \ds@alistOut={} \newtoks\ds@PuzzleAppearancetoks \ds@PuzzleAppearancetoks={} \newtoks\ds@QuesAppearancetoks \ds@QuesAppearancetoks={} \newtoks\ds@AnsAppearancetoks \ds@AnsAppearancetoks={} \newwrite \ds@question@write \setlength{\multicolsep}{\topsep} \def\csarg#1#2{\expandafter#1\csname #2\endcsname} \let\dps@One=1 \let\dps@Zero=0 % \end{macrocode} % \section{Building the Puzzle} % \subsection{Declaring the puzzle} % \begin{macro}{\DeclarePuzzle}\hskip-\marginparsep\texttt{\darg{\ameta{puzzle-arg}}}, where % \ameta{puzzle-arg} is a series of \emph{pairs of arguments}. %\begin{quote}\ttfamily % \string\DeclarePuzzle\{\%\\ % \null\quad\darg{\ameta{letter\SUB1}}\darg{\ameta{name\SUB1}}\\ % \null\quad\darg{\ameta{letter\SUB2}}\darg{\ameta{name\SUB2}}\\ % \null\quad\dots\\ % \null\quad\dots\\ % \null\quad\darg{\ameta{letter\SUB{n}}}\darg{\ameta{name\SUB{n}}}\\ % \} %\end{quote} % The argument \ameta{letter} represents a letter in the puzzle; \ameta{letter} plays two roles: (1) % it is used to typeset the letters into the document when certain options, such as \opt{viewmode}, are used; % (2) it is used as the default value of a text fields that is created (when the puzzle is built to be interactive). % This creates a problem for special characters, such as \"{u}; on one hand the letter is \verb~\"{u}~ (when typeset), % and is \verb~\string\374~ when placed into a text field (\cs{341}) is the (octal) PDFDocEncoding of u-umlaut. % The way around this conundrum is to use \cs{texorpdfstring}: use \ameta{letter} to be \verb~{\texorpdfstring{\"{u}}{\string\374}}~. % % The second argument pair is \ameta{name}, this is a unique name that is used in the construction of the underlying % text field name: the name of the field becomes \texttt{puzzle.\ameta{name}}. As a result, \ameta{name} needs to be % a JavaScript identifier (or, basically consist of letters and numbers). In the case of special characters such as our umlaut problem, we can assign a name like so: %\begin{Verbatim}[xleftmargin=\parindent,codes={\def\OR{\llap{\rlap{\textsf{or}}\kern\parindent}}\catcode`\%=9},commandchars={!()}] %\texorpdfstring{\protect\"{u}}{\ifxetex ü\else\string\374\fi}}{uml} %!OR %\tops{\protect\"{u}}{\ifxetex ü\else\string\374\fi}}{uml} %\end{Verbatim} %where \cs{tops} is an alias for \cs{texorpdfstring}. This argument pair is seen several times in the demonstration files. There are %two special names, these are \texttt{space} and \texttt{punc}; as a argument pair, these should appear as follows: %\verb!{}{space}! and \verb~{,}{punc}~, respectively. Spaces and punctuation are not normally part of the puzzle to be discovered %by answering questions, though they could be. % % \begin{macrocode} \def\DeclarePuzzle#1{% \gdef\puzzleParameters{#1}% \let\DPSNamesList\@gobble \dps@getNames#1\relax\relax } \def\dps@getNames{\begingroup\dps@getNames@i} \def\dps@getNames@i#1#2{% \ifx#2\relax\let\getNextN@me\endgroup \else\let\getNextN@me\dps@getNames@i % \end{macrocode} % We skip adding to \cs{DPSNamesList} if \texttt{\#2} is \texttt{space}, % \texttt{punc}, \texttt{cr}, or \texttt{\#2} has already been added. % \begin{macrocode} \def\@rgii{#2}\ifx\@rgii\ds@myspace\else \ifx\@rgii\ds@punc\else \ifx\@rgii\ds@cr\else \@ifundefined{ds@name@#2}{\g@addto@macro\DPSNamesList{,"#2"}% \csarg\let{ds@name@#2}\@empty}{}% \fi\fi\fi \fi \getNextN@me } % \end{macrocode} % \leavevmode\DescribeMacro\nPuzzleCols\hskip-\marginparsep\texttt{\darg{\ameta{nCols}}} % As a convenience, we provide a way to pass the number of columns for the puzzle to the % \cs{insertPuzzle\darg{\ameta{nCols}}} command. % \begin{macrocode} \def\nPuzzleCols#1{\def\nCols{#1}} \let\nCols\@empty % \end{macrocode} % \subsection{The underlying text fields of the puzzle} %\leavevmode % \DescribeMacro{\PuzzleAppearance}\hskip-\marginparsep\texttt{\darg{\ameta{KV-pairs}}} % The command \cs{PuzzleAppearance} can be used to change the appearance of the text fields for % the puzzle, where, \ameta{KV-pairs} is a set of \pkg{eforms} key-value pairs. %\changes{v1.0}{2006/10/31} %{ % Added a token list to hold any user changes in the appearance of the puzzle, as % as suggested by Robert Marik. %} % \begin{macrocode} \def\PuzzleAppearance#1{\ds@PuzzleAppearancetoks={#1}} % \end{macrocode} % \leavevmode % \DescribeMacro\ds@makeTextField\hskip-\marginparsep\texttt{\darg{\ameta{letter}}\darg{\ameta{name}}} % The command acts on each pair of arguments of the command \cs{DeclarePuzzle}; it either creates % a text field or an underlined space, depending on the options. Control the width of the fields % with \DescribeMacro\wdPuzzleFields\cs{wdPuzzleFields\darg{\ameta{width}}} and the height % with \DescribeMacro\htPuzzleFields\cs{htPuzzleFields\darg{\ameta{height}}}. % \changes{v1.1}{2020/04/21}{Added \string\cs{wdPuzzleFields} and \string\cs{htPuzzleFields}} % \begin{macrocode} \def\wdPuzzleFields#1{\bgroup\setlength\@tempdima{#1}% \xdef\wd@fPF{\the\@tempdima}\egroup} \def\wd@fPF{1.6em} \def\htPuzzleFields#1{\bgroup\setlength\@tempdima{#1}% \xdef\ht@fPF{\the\@tempdima}\egroup} \def\ht@fPF{11bp} \def\dps@strut{\rule{0pt}{\ht@fPF}} % \end{macrocode} % The definition of \cs{ds@makeTextField} is a function of the mode the document is in: % for paper versus view mode. % \begin{macrocode} \ifeqforpaper \ifviewMode \def\ds@makeTextField#1#2{\def\argii{#2}\ifx\argii \ds@myspace\let\ds@ul\relax\else\let\ds@ul\underbar\fi \ifshowletters\raisebox{-10pt}{% \makebox[0pt][l]{\makebox[\wd@fPF][c]{\footnotesize \ds@getProbNumber{#1}{#2}}}}\fi \ds@ul{\makebox[\wd@fPF][c]{\dps@strut \Hy@pdfstringfalse#1}}} \else \def\ds@makeTextField#1#2{\def\argii{#2}\ifx\argii\ds@myspace \let\ds@ul\relax\else\let\ds@ul\underbar\fi \ifshowletters\raisebox{-10pt}{% \makebox[0pt][l]{\makebox[\wd@fPF][c]{\footnotesize \ds@getProbNumber{#1}{#2}}}}\fi \ds@ul{\makebox[\wd@fPF][c]{\dps@strut\hfil}}} \fi \else \ifviewMode \def\ds@makeTextField#1#2{\ifshowletters\raisebox{-10pt}{% \makebox[0pt][l]{\makebox[\wd@fPF][c]{% \footnotesize\ds@getProbNumber{#1}{#2}}}}\fi \underbar{\makebox[\wd@fPF][c]{\dps@strut \Hy@pdfstringfalse#1}}} \else \def\ds@makeTextField#1#2{\ifshowletters \raisebox{-10pt}{\makebox[0pt][l]{\makebox[\wd@fPF][c]{% \footnotesize\ds@getProbNumber{#1}{#2}}}}\fi \edef\textfieldTmp{\noexpand\textField[\noexpand\Q{1}% \noexpand\S{U}\noexpand\Ff\noexpand\FfReadOnly \the\ds@PuzzleAppearancetoks\noexpand\DV{#1}]% {puzzle.#2}{\wd@fPF}{\ht@fPF}}\Hy@pdfstringtrue\textfieldTmp} \fi \fi % \end{macrocode} % \end{macro} % Later in this package the \cs{ds@buildAnswerKey} is defined and must be expanded % at the appropriate moment. The command uses information from all components % of the puzzle: the puzzle, the questions, and the answers. So, we must wait until % all components have been typeset. This is the purpose of \cs{dps@emitAK}; its value % is increased when each component is typeset. When it reaches a value of $4$, it is % at that time \cs{ds@buildAnswerKey} is expanded. % \begin{macrocode} \def\dps@emitAK{0} \def\dps@AddToEmitAK#1{\bgroup \@tempcnta=\dps@emitAK\relax \advance\@tempcnta by#1\relax \xdef\dps@emitAK{\the\@tempcnta}\egroup } \def\dps@ckEmitAK{\ifnum\dps@emitAK>\thr@@\expandafter \ifshowletters\expandafter\ds@buildAnswerKey\fi\fi} % \end{macrocode} % \subsection{Inserting the puzzle into the document} % \begin{macro}{\insertPuzzle} The command element that inserts the puzzle data that has already % been declared with \cs{DeclarePuzzle}. % Use \cs{insertPuzzle} to insert the puzzle at the location desired. The puzzle is placed % in a tabular environment. The only argument of this command is the number of columns % you want for this tabular environment. For example, \verb!\insertPuzzle{18}! distributes % the puzzle so that there are $18$ columns per row, one letter per column. % \begin{macrocode} \def\insertPuzzle#1{\begingroup\def\@rgi{#1}% \ifx\@rgi\@empty \ifx\nCols\@empty \PackageWarning{dps}{\string\insertPuzzle\space needs an argument, use\MessageBreak either \string\insertPuzzle{} or\MessageBreak declare \string\nPuzzleCols{} in preamble.\MessageBreak Setting to 10 for now}\gdef\nCols{10}% \fi \else \xdef\nCols{#1}% \fi \ifviewMode\Hy@pdfstringfalse\else\Hy@pdfstringtrue\fi \let\tops\texorpdfstring\expandafter\dps@Puzzle \expandafter{\puzzleParameters}\endgroup \dps@AddToEmitAK{1}\dps@ckEmitAK } % \end{macrocode} % \end{macro} % \begin{macro}{\rowsep} % This command is used to adjust the space between row of the tabular environment % for the puzzle. The default is \verb!\rowsep{2ex}!. % \begin{macrocode} \def\rowsep#1{\gdef\@rowsep{[#1]}\gdef\@rowskip{#1}} \rowsep{\rowsep@default} \def\rowsep@default{2ex} % \end{macrocode} % \end{macro} % This code create the tabular environment, creating a new row when necessary, % and inserts the text field or typesets the puzzle (in the case of \texttt{viewmode}). % \changes{v1.1}{2020/04/21}{Replace \string\env{tabular*} with \string\env{tabular} % in \string\cs{insertPuzzle}} % \begin{macrocode} \def\eq@tabSep{&}\def\ds@punc{punc} % \end{macrocode} % The command that \cs{insertPuzzle} calls, the argument is the paired % \texttt{\darg{\ameta{letter}}\allowbreak\darg{\ameta{name}}} data structure. % We insert \cs{relax}\cs{relax} to identify the end of the data-structure, % then pass on to \cs{dps@@Puzzle} % \begin{macrocode} \def\dps@Puzzle#1{\edef\eq@tabEnd{\noexpand\\\@rowsep}% \dps@@Puzzle#1\relax\relax}% % \end{macrocode} % \cs{dps@@Puzzle} begins a \env{tabular}, then passes the ball % to \cs{@dpsPuzzlei}. % \begin{macrocode} \def\dps@@Puzzle{\begin{tabular} {@{}*{\nCols}l@{}}\@dpsPuzzlei } % \end{macrocode} % Parse the data structure, taking care to handle \texttt{punc} and \texttt{cr} correctly. % to \cs{@dpsPuzzlei}. % \begin{macrocode} \def\@dpsPuzzlei#1#2{\ifx#2\relax \gdef\nextPuzzleChar{\@dpsPuzzleDone}\else \gdef\nextPuzzleChar{\@dpsPuzzleii{#1}{#2}}\fi \nextPuzzleChar } % \end{macrocode} % We've checked for \cs{relax} and we're OK to continue. The next pair % may be a special pair, we don't make a field if its a special field % (\texttt{cr} or \texttt{punc}). % \changes{v1.6}{2020/05/31}{Improved parsing for \string\texttt{punc} % and \string\texttt{cr}} % \begin{macrocode} \def\@dpsPuzzleii#1#2{\def\argii{#2}% \ifx\argii\ds@punc % so something with punc \def\@puzzNext{#1\@takeaPeek}%\@setSep@dpsPuzzleii}% \else\ifx\argii\ds@cr % do something with cr \def\@puzzNext{\global\ds@nCntCols\z@ \eq@tabEnd\@dpsPuzzlei}% \else % ok to make a field \def\@puzzNext{\ds@makeTextField{#1}{#2}\@takeaPeek}% \fi\fi \@puzzNext } \def\ds@cr{cr} \def\@takeaPeek#1#2{\def\argii{#2}% \ifx\argii\ds@punc % \end{macrocode} % A punctuation can be followed by the \texttt{cr} token, we better check, % by taking another peek. % \begin{macrocode} \def\@puzzNext{#1\@takeaPeek}% \else % \end{macrocode} % We allow a markup to end the tabular line before reaching the number of \cs{nCols}. % This may be needed when there is an long puzzle, and a \cs{nCols} gives weird % row breaks. % \begin{macrocode} \ifx\argii\ds@cr \def\@puzzNext{\global\ds@nCntCols\z@ \eq@tabEnd\@dpsPuzzlei}% \else \def\@puzzNext{\@setSep@dpsPuzzleii{#1}{#2}}% \fi \fi \@puzzNext } \def\@setSep@dpsPuzzleii{\global\advance\ds@nCntCols\@ne \ifnum\ds@nCntCols=\nCols\relax \expandafter\eq@tabEnd \global\ds@nCntCols\z@\else \expandafter\eq@tabSep\fi \@dpsPuzzlei} \def\@dpsPuzzleDone{\end{tabular}\ifnum\ds@nCntCols=0\relax \ifshowletters\vskip\@rowskip\relax \else\vskip3pt\fi \vskip-2\baselineskip \fi\kern0pt} % \end{macrocode} %\subsection{The answer key} % \begin{macro}{\AnswerKey} % The command \cs{AnswerKey} is defined by \cs{ds@buildAnswerKey}, which is expanded % after all components of the puzzle have been typeset. % and it (\cs{AnswerKey}) is available thereafter for manual insertion into the document. If the \texttt{showanswerkey} % option is taken, it is displayed at the bottom of the page. If the \texttt{savedata} % option is taken, the answer key is save to a file along with the random seed that generated % this answer key. The file name containing the puzzle data is \cs{jobname\_data.sav}. % \begin{macrocode} \def\AnswerKey{The answer key is not available.\PackageWarning{dps} {The showletters option is required to generate\MessageBreak an answer key,}} \def\ds@buildAnswerKey {% {% local \Hy@pdfstringfalse \let\tops\texorpdfstring \let\protect\@unexpandable@protect \count@\z@\toks@={}% \loop \advance\count@\@ne \edef\y{\@nameuse{dps@probLetterii\the\count@}}% \edef\x{\@nameuse{dps@probLetterKey\y}}% \expandafter\ifx\x\relax\else \csarg\xdef{dps@probLetter\the\count@}{\expandafter\noexpand \csname dps@probLetterAlt\y\endcsname}\fi \xdef\AnswerKey{\the\toks@ \the\count@--\@nameuse{dps@probLetter\the\count@}; }% \toks@=\expandafter{\AnswerKey}% \ifnum\count@ < \ds@qNumber\repeat }% \ifshowsolution \cfooter{\let\tops\texorpdfstring \footnotesize\@ifundefined{rotatebox}{\AnswerKey}% {\rotatebox{180}{\AnswerKey}}}\fi } \def\ds@writePuzzleData{\ifsavepuzzledata \newwrite \ds@savedata \begingroup \immediate\openout \ds@savedata \jobname_data.sav \def\msgi{Initial seed} \def\msgii{Answer key:} \let\verbatim@out\ds@savedata \uccode`c=`\%\uppercase{% \ifwerandomize \dps@IWVO{\string\randomi=\ds@saveRandomSeed\space c \msgi}% \dps@IWVO{\string\dpsLastSeed{\the\randomi}}\fi \ifshowletters\let\tops\texorpdfstring \set@display@protect \dps@IWVO{c \msgii\space\AnswerKey}\fi } \immediate\closeout\ds@savedata \endgroup \fi} \AtEndDocument{\ds@writePuzzleData} % \end{macrocode} % \end{macro} % \leavevmode\DescribeMacro\setdpsfootskip\hskip-\marginparsep\texttt{\darg{\ameta{skip}}} % When the \opt{showanswerkey} is in force, \cs{AnswerKey} is placed % in the running footer (\cs{cfooter}) of \pkg{web}. To facilitate the positioning % of the running footer, we define a convenience command to set \cs{web@footskip} % used by \pkg{web}. % \changes{v1.1}{2020/04/21}{Added \string\cs{setdpsfootskip}} % \begin{macrocode} \def\setdpsfootskip#1{\bgroup \setlength\@tempdima{#1}\ifeqforpaper\else \xdef\web@footskip{\the\@tempdima}\fi \egroup\InitLayout % a web command } \setdpsfootskip{.25in} % \end{macrocode} % \subsection{Support for a sideshow} % A sideshow consists of a tiled graphic that is revealed as the player works the puzzle. % The techniques used to build a sideshow depends on the options \opt{usebtnappr} and \opt{uselayers}. % The command \DescribeMacro\randomizePicMappings\cs{randomizePicMappings}, when expanded in the % preamble, will randomize the order the tiles appear in the slideshow; the default is no randomization. % \begin{macrocode} \let\DPSIndxList\@empty \let\DPSNamesList\@empty \def\randomizePicMappings{\def\bRandPicMaps{true}} \def\bRandPicMaps{false} % \end{macrocode} % \leavevmode\DescribeMacro\sortPicMappings Pictures are randomly placed in the sideshow % and the bubble sort is used to sort them out, as a final event when the puzzle is solved. % This command does nothing if the \opt{usebtnappr} option is not taken; that is, this is a % feature of the \opt{usebtnappr} option. % \begin{macrocode} \ifusebtnappr \def\sortPicMappings{% \InputIfFileExists{sortjs.def}{}{}% \OpenAction{\JS{try{if(!hasBeenRandomized) {hasBeenRandomized=true;mixupDPS();showDPS();} }catch(e){}}}% } \else \let\sortPicMappings\relax \fi % \end{macrocode} % \leavevmode\DescribeMacro\sideshowPackaged % The side show pictures are packaged into a single PDF, the order of the pages are as expected. % The default is they are not packaged. It is assumed the filename is \texttt{\ameta{basename}\_package.pdf} % (When in a package, the pictures must be in a PDF file). % \begin{macrocode} \newif\if@isPackaged \@isPackagedfalse \def\sideshowPackaged{\@isPackagedtrue} % \end{macrocode} % % \section{Questions and Answers} % \begin{environment}{Composing} % This is the environments in which the composing of questions and answers are made. % Use the \env{cQ} and \env{cA} for this purpose. % \begin{macrocode} \newenvironment{Composing} {\global\ds@qNumber=0 \global\ds@aNumber=0} {\aftergroup\ds@publishRandomLists} % \end{macrocode} % \end{environment} % Here are the two environment (\env{cQ} and \env{cA}) for composing questions and answers. The argument % of each environment corresponds to a form field in the puzzle. Each of these % environments are verbatim write environments; they write each question and solution % to a separate \texttt{.cut} file. These individual files are ultimately input % in a random order. A typical pair of environments looks like these two: % % \begin{environment}{cQ} Sets the content of the question. % \changes{v1.1}{2020/04/21}{Modified \string\textsf{cQ}, using \string\cs{set@display@protect} % and \string\cs{set@typeset@protect}} % \begin{macrocode} \newenvironment{cQ}[1] {% \global\advance\ds@qNumber\@ne \immediate\openout \ds@question@write \jobname_q\the\ds@qNumber.cut \let\verbatim@out\ds@question@write\set@display@protect \dps@IWVO{\protect\dpsQ{#1}}% \set@typeset@protect \verbatimwrite }{% \endverbatimwrite \immediate\closeout \ds@question@write } % \end{macrocode} % The \env{cA} environment has an optional argument. This optional argument is only used % when the document is compiled with the showletters option. The value of the argument % is a letter to appear in the answers column. Normally, first entry of the argument pair % \texttt{\darg{\ameta{letter}}\darg{\ameta{name}}} of % \cs{DeclarePuzzle} is used. Cases where you would want to include this optional % argument are (1) when giving an answer that does not correspond to a question; (2) the % letter is capitalized, suggesting a proper name or the beginning of a sentence, use the % optional argument to list the letter in lower case. The latter case is common, for example, %\begin{verbatim} % \begin{cQ}{H} % Who wrote this package? % \end{cQ} % \begin{cA}[h]{H} % D.P. Story % \end{cA} %\end{verbatim} %The capital `H' begins the puzzle, but we don't want the player to see a capital `H' if %the \opt{showletters} option is taken. % \begin{environment}{cA} % Sets the contents of the answer. % \changes{v1.1}{2020/04/21}{Modified \string\textsf{cA}, using \string\cs{set@display@protect} % and \string\cs{set@typeset@protect}} % \begin{macrocode} \newenvironment{cA}[2][] {% \def\argi{#1}\global\advance\ds@aNumber\@ne \immediate\openout \ds@question@write \jobname_a\the\ds@aNumber.cut \let\verbatim@out\ds@question@write \set@display@protect \dps@IWVO{\protect\dpsA\ifshowletters \ifx\argi\@empty\else[#1]\fi\fi{#2}}% \set@typeset@protect \verbatimwrite} {% \endverbatimwrite \immediate\closeout \ds@question@write } % \end{macrocode} % \end{environment} % \end{environment} % \begin{macro}{\QuesAppearance} % \begin{macro}{\AnsAppearance} % These two commands can be used to change the appearance of the checkboxes for the questions and answers. % When the \texttt{forpaper} \textsf{web} option is taken, these have no effect. % \begin{macrocode} \def\QuesAppearance#1{\ds@QuesAppearancetoks={#1}} \def\AnsAppearance#1{\ds@AnsAppearancetoks={#1}} % \end{macrocode} % \end{macro} % \end{macro} % The commands \cs{dpsQ} and \cs{dpsA} are the ones that produce the checkboxes, and define the % JavaScript actions. % % The two commands \DescribeMacro\afterQhookA\cs{afterQhookA} and \DescribeMacro\OnFocusQhookAA\cs{OnFocusQhookAA} can be redefined % for additional JS action, the first is a hook into the mouse up action, and the second is % a hook to the on focus action. These two can be redefined as needed, but be sure to preserve the JS % functionality. % \begin{macrocode} \def\afterQhookA#1{if(PlayerSignIn());} %\let\afterQhookA\@gobble \let\OnFocusQhookAA\@gobble % \end{macrocode} %\leavevmode\DescribeMacro\widestFmtdQNum\hskip-\marginparsep\texttt{\darg{\ameta{text}}} %Sets the width of the underlying checkbox for the question. % \changes{v1.1}{2020/04/21}{Added \string\cs{widestFmtdNum} to set width of % the checkbox for questions} % \begin{macrocode} \def\widestFmtdQNum#1{\bgroup \settowidth{\@tempdima}{#1}% \ifxetex\advance\@tempdima2.5bp\else \advance\@tempdima.5pt\fi \xdef\Qwidth{\the\@tempdima}\egroup} \widestFmtdQNum{00.} \def\htOfQ#1{\setlength{\@tempdima}{#1}\ifxetex \advance\@tempdima2bp\relax\fi\edef\Qht{\the\@tempdima}} \htOfQ{13bp} % \end{macrocode} % Set the checkboxes and JS action for questions. Allow also, changes to appearance % through the \cs{QuesAppearance} command. % \begin{macro}{\dpsQ} % Sets the checkbox and content of a question. % \begin{macrocode} \newcommand{\dpsQ}[1]{\item\relax\ifeqforpaper\else \edef\checkboxTmp{\noexpand\checkBox[\the\ds@QuesAppearancetoks \noexpand\textSize{0}\noexpand \A{\noexpand\JS{activeQuestion = event.target.name;\noexpand \r clearRedCrosses();\noexpand\r\noexpand\afterQhookA{#1}}}% \noexpand\AA{\noexpand\AAOnFocus{\noexpand\JS{% this.resetForm(["ckbxQ"]);\noexpand\r\noexpand \OnFocusQhookAA{#1}}}}]{ckbxQ.#1}{\Qwidth}{\Qht}{Yes}}% \makebox[0pt][r]{\strut \smash{\checkboxTmp}\efKern{-.5pt}{-1.5pt}\enspace}\fi \ignorespaces } % \end{macrocode} % Set the checkboxes and JS action for answers. Allow also, changes to appearance % through the \cs{AnsAppearance} command. This command obeys the \texttt{showanswerlabels} % option by re-defining the command \cs{dpsAitemOptArg}. The default definition % is \verb!\def\dpsAitemOptArg{[]}!, which cancels the display of the item labels. % \changes{v1.1}{2020/04/21}{Added \string\cs{ltrFmtA} to format the answer letter} % \begin{macrocode} % \end{macrocode} % \leavevmode\DescribeMacro\ltrFmtA\hskip-\marginparsep\texttt{\darg{\ameta{fmt-cmds}}} % When the \opt{showletters} option is in effect, the letters appear amongst the answers. % the letters may be formatted through \cs{ltrFmtA}. The symbolic \texttt{\#1} represents % the letter to be formatted; eg, \verb~\ltrFmtA{\textbf{#1}}~ give letters in bold. % The default is no formatting. % \begin{macrocode} \def\ltrFmtA#1{\def\@ltrFmtA##1{#1}} \ltrFmtA{#1} % \end{macrocode} % \leavevmode\DescribeMacro\widestFmtdALtr\hskip-\marginparsep\texttt{\darg{\ameta{text}}} % Sets the width of the checkbox around the letter. There is a built in with of 8pt. % \begin{macrocode} \def\widestFmtdALtr#1{\bgroup \settowidth{\@tempdima}{#1}\ifxetex \addtolength{\@tempdima}{2bp+8pt}\else \addtolength{\@tempdima}{8pt}\fi \xdef\Awidth{\the\@tempdima}\egroup} \widestFmtdALtr{w} \def\htOfA#1{\setlength{\@tempdima}{#1}\ifxetex \advance\@tempdima2bp\relax\fi\edef\Aht{\the\@tempdima}} \htOfA{13bp} % \end{macrocode} % \begin{macro}{\dpsA} % Checkbox for the answer. % \begin{macrocode} \newcommand{\dpsA}[2][]{\expandafter \item\dpsAitemOptArg\relax \ifeqforpaper\else \edef\checkboxTmp{\noexpand \checkBox[\the\ds@AnsAppearancetoks \noexpand\textSize{0}\noexpand \A{\noexpand\JS{processChoice("#2");}}]% {ckbxA.#2}{\Awidth}{\Aht}{Yes}}% \makebox[0pt][r]{\strut \smash{\checkboxTmp}\enspace}% \fi \def\argi{#1}% \bgroup % dps \let\tops\texorpdfstring \Hy@pdfstringfalse \ifx\argi\@empty \global\csarg\let{dps@probLetterKey#2}\relax \else \csarg\gdef{dps@probLetterKey#2}{#2}% \csarg\gdef{dps@probLetterAlt#2}{#1}% \fi \egroup \ifshowletters \ifx\argi\@empty \let\getLetterNext\relax \let\ds@foundLetter\dps@Zero\def\ds@currFN{#2}% \def\getLetterNext{\ds@typesetPuzzleLetter}% \expandafter\getLetterNext \else \makebox[0pt][r]{\let\tops\texorpdfstring \Hy@pdfstringfalse\@ltrFmtA{#1}\enspace\kern4bp}% \fi \fi \ignorespaces } % \end{macrocode} % \end{macro} % \end{macro} % \begin{macrocode} \def\ds@typesetPuzzleLetter{\expandafter \typeset@PuzzleLetter\expandafter{\puzzleParameters}} \def\typeset@PuzzleLetter#1{\typeset@@PuzzleLetter#1\relax\relax}% \def\typeset@@PuzzleLetter#1#2{% \ifx#1\relax \gdef\nextPuzzleLetter{\relax}\else \gdef\nextPuzzleLetter{\typeset@PuzzleLetteri{#1}{#2}}\fi \nextPuzzleLetter } \def\typeset@PuzzleLetteri#1#2{\def\argii{#2}\ifx\argii\ds@currFN \ifx\ds@foundLetter\dps@Zero \makebox[0pt][r]{\let\tops\texorpdfstring \Hy@pdfstringfalse\@ltrFmtA{#1}\enspace\kern4bp}% \let\ds@foundLetter\dps@One\fi \expandafter\typeset@@PuzzleLetter \else \expandafter\typeset@@PuzzleLetter \fi } % \end{macrocode} % This command is called at \verb!\end{Composing}!, which, in turn, calls % the macros \cs{ds@randomizeQuestionList} and \cs{ds@randomizeAnswerList} which randomly % permutes the \verb!1, 2, ... \the\ds@qNumber! and \verb!1, 2, ... \the\ds@aNumber!, % where \cs{ds@qNumber} and \cs{ds@aNumber} are the number of questions and answers, % respectively. % \begin{macrocode} \def\ds@publishRandomLists{% \ds@randomizeQuestionList{\the\ds@qNumber}% \ds@randomizeAnswerList{\the\ds@aNumber}% } \def\ds@myspace{space} \def\ds@getProbNumber#1#2{% \gdef\ds@currentArgi{#1}\gdef\ds@currentArgii{#2}% \ifx\ds@currentArgii\ds@myspace\def\ds@probNumNext{\relax}\else \def\ds@probNumNext{% \@ifundefined{dps@probNum#2}{\global\advance\ds@probCnt\@ne \ds@@getProbNumber{\the\ds@probCnt}} {\csname dps@probNum#2\endcsname}% }% \fi \ds@probNumNext } \def\ds@@getProbNumber#1{% {\count@\z@ \let\\=\ds@getNthOne\the\ds@qlistOut}% \csname dps@probNum\ds@currentArgii\endcsname } \def\ds@getNthOne#1{\advance\count@\@ne \ifnum\ds@probCnt=#1\relax \csarg\xdef{dps@probNum\ds@currentArgii}{\the\count@}% \toks@=\expandafter{\ds@currentArgi}% dps \csarg\xdef{dps@probLetter\the\count@}{\the\toks@}% dps \csarg\xdef{dps@probLetterii\the\count@}% {\ds@currentArgii}% \fi } % \end{macrocode} % \begin{macro}{\writeComposingEnv} % This is a helper macro. After you declare your puzzle, \cs{DeclarePuzzle}, % you can place this command just after, if needed, like so %\begin{verbatim} %\writeComposingEnv %\end{verbatim} %In the case where \cs{DeclarePuzzle} is in the preamble; above, we begin the doc % and end the doc; assuming you have not developed your questions yet. The command % writes to the file \cs{jobname\_comp.def}. This file will be a skeleton of your % Composing environment, with correct labeling. Copy and paste it into your document % in some appropriate location, and begin writing your questions. % \changes{v1.1}{2020/04/21}{\string\cs{writeComposingEnv} no longer needs to be % followed by begin and end document} % \begin{macrocode} \def\writeComposingEnv{% \newwrite \ds@composing@write \immediate\openout \ds@composing@write \jobname_comp.def \let\verbatim@out\ds@composing@write \dps@IWVO{\string\begin{Composing}}% \dps@IWVO{}% \expandafter\write@ComposingEnv\expandafter{\puzzleParameters}% } \def\write@ComposingEnv#1{\write@@ComposingEnv#1\relax\relax}% \newcommand{\ComposingEnvMsg}{\begin{quote}An outline of your \texttt{Composing}environment is written to \texttt{\jobname\_comp.def}, based on data in the argument of your \texttt{\string\DeclarePuzzle} command. Copy and paste the contents of this file into your puzzle document following \texttt{\string\DeclarePuzzle} then fill in your questions and answers. Good luck.\end{quote}} \def\write@@ComposingEnv#1#2{\ifx#1\relax \gdef\nextPuzzlePair{% \dps@IWVO{\string\end{Composing}}% \immediate\closeout \ds@composing@write}% \begin{document} \ComposingEnvMsg \end{document} \else\gdef\nextPuzzlePair{\write@@@ComposingEnv{#1}{#2}}\fi \nextPuzzlePair}% \def\write@@@ComposingEnv#1#2{% \gdef\ds@currentArgi{#1}\gdef\ds@currentArgii{#2}% \ifx\ds@currentArgii\ds@myspace \def\ds@probNumNext{\write@@ComposingEnv}% \else \ifx\ds@currentArgii\ds@punc \def\ds@probNumNext{\write@@ComposingEnv}\else \def\ds@probNumNext{% \@ifundefined{dps@compQ#2}{% write to file \expandafter\gdef\csname dps@compQ#2\endcsname{found}% \dps@IWVO{\string\begin{cQ}{\noexpand#1}}% \dps@IWVO{\string\end{cQ}}% \dps@IWVO{\string\begin{cA}{\noexpand#1}}% \dps@IWVO{\string\end{cA}}% \dps@IWVO{}% }{}% \write@@ComposingEnv }% \fi \fi \ds@probNumNext } % \end{macrocode} % \end{macro} % A standard \cs{verbatim} write used in exerquiz and other package in the AeB family. % \begin{macrocode} \def\verbatimwrite{\@bsphack \let\do\@makeother\dospecials \catcode`\^^M\active \catcode`\^^I=12 \def\verbatim@processline{% \immediate\write\verbatim@out {\the\verbatim@line}}% \verbatim@start} \def\endverbatimwrite{\@esphack} \def\dps@IWVO{\immediate\write\verbatim@out} % \end{macrocode} % \cs{ds@populateList} is a utility command, its argument is a positive integer, \texttt{n}, % and it generates a list of the form \verb!\\{1}\\{2}...\\{n}!. This listing is later % randomly permuted by \cs{ds@randomizeQuestionList} and \cs{ds@randomizeAnswerList}. % \begin{macrocode} \def\ds@populateList#1{% \ds@listIn={}% \ds@nCnt\z@ \@whilenum \ds@nCnt < #1\do {% \advance\ds@nCnt\@ne \edef\ds@listInHold{\the\ds@listIn\noexpand\\{\the\ds@nCnt}}% \ds@listIn = \expandafter{\ds@listInHold}% }% } % \end{macrocode} % Used in \cs{ds@randomizeList} to build the permuted list of numbers. % \begin{macrocode} \def\ds@processi#1{\advance\ds@nCnt\@ne \ifnum\ds@nCnt=\ds@getRanNum\edef\ds@listOutHold{\the\ds@listOut}% \global\ds@listOut=\expandafter{\ds@listOutHold\\{#1}}% \else \edef\ds@listInHold{\the\ds@newListIn}% \ds@tmpToks = \expandafter{\ds@listInHold\\{#1}}% \ds@newListIn = \expandafter{\the\ds@tmpToks}% \fi } % \end{macrocode} % Used in \cs{displayRandomizedQuestions} to input the questions. % \begin{macrocode} \def\ds@processii#1{\input{\jobname_q#1.cut}} % \end{macrocode} % Used in \cs{displayRandomizedAnswers} to input the answers. % \begin{macrocode} \def\ds@processiii#1{\input{\jobname_a#1.cut}} % \end{macrocode} % Used in \cs{displayRandomizedAnswersLeftPanel} to input the top half % of the permuted list. % \begin{macrocode} \def\ds@processL#1{\advance\count@\@ne \ifnum\count@>\ds@aNumber\relax\else\input{\jobname_a#1.cut}\fi} % \end{macrocode} % Used in \cs{displayRandomizedAnswersRightPanel} to input the bottom half % of the permuted list. % \begin{macrocode} \def\ds@processR#1{\advance\count@\@ne \ifnum\count@>\ds@aNumber\relax\input{\jobname_a#1.cut}\fi} % \end{macrocode} % \begin{macro}{\displayRandomizedQuestions} % \begin{macro}{\displayRandomizedAnswers} % \begin{macro}{\displayRandomizedAnswersLeftPanel} % \begin{macro}{\displayRandomizedAnswersRightPanel} % These are user commands that actually display the randomized questions % and answers. % \begin{macrocode} \def\displayRandomizedQuestions{\let\\=\ds@processii\the\ds@qlistOut \dps@AddToEmitAK{1}\dps@ckEmitAK} \def\displayRandomizedAnswers{\set@typeset@protect \let\\=\ds@processiii\the\ds@alistOut \dps@AddToEmitAK{2}\dps@ckEmitAK} % dps \def\displayRandomizedAnswersLeftPanel{{\set@typeset@protect \let\\=\ds@processL\count@\z@ \divide\ds@aNumber\tw@ \xdef\lastOnLeft{\the\ds@aNumber}% \the\ds@alistOut}% \dps@AddToEmitAK{1}\dps@ckEmitAK} \def\displayRandomizedAnswersRightPanel{{\set@typeset@protect \let\\=\ds@processR\count@\z@ \divide\ds@aNumber\tw@ \the\ds@alistOut}% \dps@AddToEmitAK{1}\dps@ckEmitAK} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % Develop a random permuted list for the questions. % \begin{macrocode} \def\ds@randomizeQuestionList#1{% \global\ds@listIn={}\global\ds@newListIn={}\global\ds@listOut={}% \global\ds@tmpToks={}%\global\ds@qlistOut={}\global\ds@alistOut={}% \ds@nMax=#1\relax\ds@populateList{\the\ds@nMax}% \global\forquestionstrue \ifwerandomize \expandafter\ds@randomizeList \else \global\ds@qlistOut=\expandafter{\the\ds@listIn} \fi } % \end{macrocode} % Develop a random permuted list for the answers. Note that \cs{ifwerandomize} % we randomize, else, the output list is the same as the input list. % \begin{macrocode} \def\ds@randomizeAnswerList#1{% \global\ds@listIn={}\global\ds@newListIn={}\global\ds@listOut={}% \global\ds@tmpToks={}%\global\ds@qlistOut={}\global\ds@alistOut={}% \ds@nMax=#1\relax\ds@populateList{\the\ds@nMax}% \global\forquestionsfalse \ifwerandomize \expandafter\ds@randomizeList \else \global\ds@alistOut=\expandafter{\the\ds@listIn}% \fi } % \end{macrocode} % The loop that does all the work for randomizing. % \begin{macrocode} \def\ds@randomizeList{\redefnextrandomAsNeeded \let\\=\ds@processi \setrannum{\ds@getRanNum}{1}{\ds@nMax}% \ds@nCnt\z@ %\typeout{LISTING: \the\ds@listIn}% \the\ds@listIn \ds@loopTest } % \end{macrocode} % The loop that does all the work for randomizing. % \begin{macrocode} \def\ds@loopTest{\advance\ds@nMax\m@ne\relax \ifnum\ds@nMax>\z@ \def\@next{% \ds@listIn=\expandafter{\the\ds@newListIn}% \ds@newListIn={}\ds@randomizeList}% \else \let\@next\relax \ifforquestions \global\ds@qlistOut=\expandafter{\the\ds@listOut}% %\typeout{\ds@qlistOut = \the\ds@qlistOut}% \else \global\ds@alistOut=\expandafter{\the\ds@listOut}% %\typeout{\ds@alistOut = \the\ds@alistOut}% \fi \fi \@next } % \end{macrocode} % \begin{macro}{\placeMessageField} % The command inserts the required message field. The optional % first parameters enables the author to change the appearance % of the field, the second two required arguments are the width % and the height of the text field. % \begin{macrocode} \newcommand{\placeMessageField}[3][]{\ifeqforpaper\else \textField[\Ff\FfReadOnly\BC{}#1 \Ff\FfMultiline]{report}{#2}{#3}\fi} % \end{macrocode} % \end{macro} % \section{Miscellaneous Settings} % \begin{macro}{\threshold} % \begin{macro}{\penaltypoints} % \begin{macro}{\passing} % Threshold for number of incorrect answers for trying to answer one question. % If the threshold is exceeded, \cs{dspenaltypoints} are added to the final % points. Passing is missing no more than \cs{dspassing}. % \begin{macrocode} \newcommand{\threshold}[1]{\def\dsthreshold{#1}} \threshold{3} \newcommand{\penaltypoints}[1]{\def\dspenaltypoints{#1}} \penaltypoints{3} \newcommand{\passing}[1]{\def\dspassing{#1}} \passing{4} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \begin{macrocode} % % \end{macrocode} % % \section{Advanced features} % % One problem when building an interactive puzzle is the lack of space for a rather long % or complex question. All of the standard designs leave little space for the questions. % Over the years, I've developed two methods to create more space for asking questions: % (1) Place the questions in push button appearances; (2) Place the questions in layers % (ocgs). In this section we provide define some basic commands to make if ``easy'' to % ask longer question using either of these two methods. % \subsection{Icon button appearances} % In this case, in some central region we create a series of push buttons, all of which are initialy % hidden. Push button can have an icon (a graphic) for its appearance. As the student % works through the puzzle, the buttons are made visible to pose the question. The question % is hidden again as the student moves on to the next question. % % For this solution, two files are required: (1) the main puzzle file; and (2) an ``icon'' file. % The next two subsections include commands and environments for each of these two files. % % To use the icon button approach, the \IndexOpt{usebtnappr}\opt{usebtnappr} must be specified; in this case the % package \pkg{icon-appr} in input by this package. % % \paragraph*{Workflow:} Creating a finished puzzle is a three step process: % \begin{enumerate} % \item Compile the puzzle file with the option \IndexOpt{wrtContent}\opt{wrtContent} % \item Compile the \texttt{icons.tex} file to create one or more % icons files % \item Compile the puzzle file with the option \IndexOpt[\protect\EXCL]{!wrtContent}\opt{!wrtConent} % \end{enumerate} % % \subsubsection{Macros for the main puzzle document} % % \begin{macrocode} %<*btnadv> % \end{macrocode} % \begin{environment}{setContent}\hskip-\marginparsep\texttt{\darg{\ameta{name}}} % (Where \ameta{name} is the second argument of the \cs{DeclarePuzzle} data structure.) % An environment to set content of the question. The contents of the \env{setContent} % is written verbatim to the file \cs{jobname-sc(\cs{theenumi}).cut}. This obviously % assumes the list of questions is in an \texttt{enumerate} environment. These individual % files are compiled together (in the \texttt{icons.tex} file to a PDF of all the questions. % The formatting command \DescribeMacro\quesNumTxt\cs{quesNumTxt} is used to format the % question header; the default is \textbf{Problem \ameta{num}}. Additionally, % \DescribeMacro\quesNumTxTPost\cs{quesNumTxTPost} that expands immediatelly % after \cs{quesNumTxt}. % \goodbreak % \begin{macrocode} \newcommand{\quesNumTxt}[1]{\protect\textbf{Problem #1}} \newcommand{\quesNumTxTPost}{\protect\newline} \newenvironment{setContent}[1]{% \immediate\write\@auxout{\string\csarg \string\xdef{ltrpg#1}{\theenumi}}% \ifwrtContent \def\CommentCutFile{\jobname-sc(\theenumi).cut}% \immediate\openout\CommentStream=\CommentCutFile \begingroup \set@display@protect \let\verbatim@out\CommentStream \dps@IWVO{\quesNumTxt{\theenumi}\quesNumTxTPost}% \set@typeset@protect \expandafter\verbatimwrite \else \edef\x{\noexpand\pl@ceQues{\theenumi}}\x\expandafter \comment \fi }{\ifwrtContent\expandafter \endverbatimwrite \endgroup \immediate\closeout\CommentStream \else \expandafter\endcomment \fi } % \end{macrocode} % \leavevmode\DescribeMacro\ltrToNum\hskip-\marginparsep\texttt{\darg{\ameta{num}}} % The \env{setContent} environment above defines a series of commands that % associate with each \ameta{name}, the corresponding problem number (\ameta{num}). % \begin{macrocode} \def\ltrToNum#1{\@nameuse{ltrpg#1}} % \end{macrocode} % \end{environment} % \paragraph*{Embedding commands}\leavevmode\par\medskip\noindent % \DescribeMacro{\dpsEmbedIcons} After creating the CUT files, as described in the % previous environment, we need to compile the CUT files into one or more PDF(s). % This is done in the other \texttt{icon.tex} file, described below. % The \cs{dpsEmbedIcons} command goes within the \env{embedding} environment %\begin{verbatim} % \begin{embedding} % \dpsEmbedIcons % \end{embedding} %\end{verbatim} %The \env{embedding} environment is defined in the \pkg{icon-appr} package. % \cs{dpsEmbedIcons} embeds icons images into the puzzle document. % \begin{macrocode} \def\pglstWarningMsg{\PackageWarningNoLine{dps} {The file icons-pglst.sav not found.\MessageBreak Icons may not appear. Build the\MessageBreak icons.tex file}} \ifwerandomize\else\let\pglstWarningMsg\@empty\fi \def\dpsEmbedIcons{% \InputIfFileExists{icons-pglst.sav}{\wrtContentfalse} {\pglstWarningMsg\def\pagelist{}}% \edef\TFOR{\noexpand\@tfor\noexpand\n:=\pagelist}% \ifxetex \TFOR\do{\embedIcon[name=Q\n]{icons-\n.pdf}}% \else\ifpdf \TFOR\do{\embedIcon[name=Q\n,hyopts={page=\n}]{icons.pdf}}% \else % pdfmark \TFOR\do{\embedIcon[name=Q\n,placement=btnQ.\n,% page={\n-1}]{icons.pdf}}% \fi\fi } % \end{macrocode} % \paragraph*{Icon button fields}\leavevmode\par\medskip\noindent % \DescribeMacro\dpsQuesIcon\hskip-\marginparsep\texttt % {[\ameta{opts}]\darg{\ameta{num}}\darg{\ameta{wd}}\darg{\ameta{ht}}} The command % that create a push button with an icon appearance. The \ameta{num} is the question number. % The field name is \verb~"btnQ.~\ameta{num}\texttt"; the value of the \cs{I} key is an indirect % reference to the embedding of the image to be use, the reference is \texttt{Q\ameta{num}}. % \begin{macrocode} \newcommand{\dpsQuesIcon}[4][]{% \pushButton[\Ff{\FfReadOnly}\BG{}\S{S}#1\TP{1}\F{\FHidden} \I{\csOf{Q#2}}\PA{.5 1}]{btnQ.#2}{#3}{#4}} % \end{macrocode} %\leavevmode\DescribeMacro\dpsOtherIcon\hskip-\marginparsep\texttt % {[\ameta{opts}]\darg{\ameta{fieldname}}\darg{\ameta{wd}}\darg{\ameta{ht}}} % There is allowance for displaying additional button images. The % \begin{macrocode} \newcommand{\dpsOtherIcon}[4][]{% \I{\csOf{name}} required \pushButton[\Ff{\FfReadOnly}\BG{}\S{S}#1\TP{1}\F{\FHidden} \PA{.5 1}]{#2}{#3}{#4}} % \end{macrocode} % \paragraph*{Placing the button icons.} There are several ways of placing % the image buttons; I have use both the \pkg{textpos} and the \pkg{eso-pic} % packages, lately, I've preferred the latter package. Examples of both are contained % in the examples. % \begin{macrocode} % \end{macrocode} % \leavevmode\DescribeMacro\placeQuesIcon\hskip-\marginparsep\texttt{\darg{\ameta{place \cs{dpsQuesIcon}}}} % We illustrate %\begin{verbatim} % \placeQuesIcon{\AddToShipoutPictureFG*{\AtTextCenter{\put(-72,0) % {\dpsQuesIcon{#1}{2.25in}{9\baselineskip}}}}} %\end{verbatim} %using the \pkg{eso-pic} package. The argument \texttt{\#1} is eventually %the problem number. \cs{placeQuesIcon} defines a macro \cs{pl@ceQues}, which appears %in the \DescribeEnv{setContent}\env{setContent} environment above. % \begin{macrocode} \long\def\placeQuesIcon#1{\@ifundefined{textblock} {\let\dps@mode\relax}{\let\dps@mode\par}% \def\pl@ceQues##1{\dps@mode #1}} % \end{macrocode} % \DescribeMacro\placeOtherIcon\hskip-\marginparsep\texttt{\darg{\ameta{place \cs{dpsOtherIcon}}}} % Places an image other than a question. %\begin{verbatim} % \placeOtherIcon{\AddToShipoutPictureFG*{\AtTextCenter{\put(-72,0) % {\dpsOtherIcon[\I{\csOf{Emoji}}]{btnEmoji}{2.25in}{9\baselineskip}}}}} %\end{verbatim} %Both of the above examples are from \texttt{examples/advanced/stat\_match1.tex}. % \begin{macrocode} \long\def\placeOtherIcon#1{#1} % \end{macrocode} % Define hooks into the question checkbox event. % The two commands \cs{afterQhookA} and \cs{OnFocusQhookAA} are hooks onto % the \cs{dpsQ} command. This allows us to post process % the user's choice of a questions, and allows us to execute JS on focus. % \begin{macrocode} \def\afterQhookA#1{% if(!event.target.isBoxChecked(0))dpsHideQFields();\r else\pdfSP if(PlayerSignIn())dpsShowQues("\ltrToNum{#1}");} \def\OnFocusQhookAA#1{dpsHidePreviousQues("\ltrToNum{#1}")} % \end{macrocode} % \paragraph*{Support for a sideshow} A sideshow is a tiled picture that is % revealed as the player solves the puzzle. % % \subparagraph*{Embedding sideshow graphics}\leavevmode\vskip3pt\noindent % \DescribeMacro\dpsEmbedSideShow\hskip-\marginparsep\texttt{[\ameta{ext}]\darg{\ameta{n-pics}}\darg{\ameta{path}}} % We take a graphic and explode it into rows and columns, \ameta{n-pics} is the total number % of tiled pictures. We assume the tiles are created row-wise. We assume also a naming convention % for the tiles if \texttt{mypic} is the basename of the picture or graphic, then the tiles are % named \texttt{mypic\_01}, \texttt{mypic\_02}, \texttt{mypic\_03}, \dots. It is assumed a single digit % index has a leading 0. Use the command \DescribeMacro\sideshowPackaged % \cs{sideshowPackaged} prior to \cs{dpsEmbedSideShow}. % \changes{v1.5}{2020/08/06}{Support for packaged sideshow graphics} % \begin{macrocode} \newcommand{\dpsEmbedSideShow}[3][]{\begingroup % \def\dps@NumSideShowPics{#2}% \gdef\dpsNumSideShowPics{#2}% \def\@Ext{#1}\ifx\@Ext\@empty\def\@Ext{.pdf}\else\def\@Ext{.#1}\fi \@tempcnta\z@ \let\@embedList\@empty \let\DPSIndxList\@gobble \@whilenum \@tempcnta < \dpsNumSideShowPics \do{% \ds@nCnt\@tempcnta \advance\ds@nCnt\@ne \ifnum\ds@nCnt<10 \edef\x{0\the\ds@nCnt}\else \edef\x{\the\ds@nCnt}\fi \edef\z{\noexpand\g@addto@macro\noexpand\DPSIndxList{,"\x"}}\z \ifxetex\if@isPackaged \PackageWarning{dps} {There is no support for embedding packaged\MessageBreak PDFs with xelatex. Ignoring the \string\isPackaged\MessageBreak command}% \@isPackagedfalse \fi\fi \if@isPackaged \ifpdf \edef\y{\noexpand \embedIcon[name=pic\x,% hyopts={page=\x}]{#3_package.pdf}}% \else \edef\y{\noexpand \embedIcon[name=pic\x,placement=btnpic.\x,% page=\x-1]{#3_package.pdf}}% \fi \else \edef\y{\noexpand \embedIcon[name=pic\x,placement=btnpic.\x]{#3_\x\@Ext}}% \fi \expandafter\g@addto@macro\expandafter\@embedList\expandafter{\y}% \@tempcnta\ds@nCnt }% do \toks@=\expandafter{\@embedList}\the\toks@ \endgroup } % \end{macrocode} % \subparagraph*{Inserting sideshow graphics}\leavevmode\vskip3pt\noindent % \DescribeMacro\insertSideshow\hskip-\marginparsep % \texttt{\darg{\ameta{rows}}\darg{\ameta{cols}}\darg{\ameta{wd}}\darg{\ameta{ht}}} % Command for placing the tiles of a picture. We assume that the pictures are number % consecutively across rows. % \begin{quote} % \begin{description} % \item[\ameta{rows}] the number of rows % \item[\ameta{cols}] the number of columns % \item[\ameta{wd}] the width of a tile % \item[\ameta{ht}] the height of a tile % \end{description} % \end{quote} % \leavevmode\DescribeMacro\tileKVs\hskip-\marginparsep\texttt{\ameta{KV-pairs}} % A way to pass \pkg{eform} key-values to the optional % argument of the underlying push button. % \begin{macrocode} \def\tileKVs#1{\def\tile@KVs{#1}} \tileKVs{} \newcommand\insertSideshow[4]{\begingroup \offinterlineskip\@tempcnta\z@ \multido{\iR=1+1}{#1}{\hbox{% \multido{\iC=1+1}{#2}{% \global\advance\@tempcnta\@ne \ifnum\@tempcnta<10\relax \edef\x{0\the\@tempcnta}\else \edef\x{0\the\@tempcnta}\fi \edef\iconPresets{\noexpand\I{\noexpand\csOf{pic\x}}}% \dpsOtherIcon[\BC{}\FB{true}\presets{\iconPresets} \presets{\tile@KVs}]{btnpic.\x}{#3}{#4}% }% inner multido }}% hbox, outer multido \endgroup } % \end{macrocode} % \begin{macrocode} % % \end{macrocode} % \subsubsection{Macros for the icon document} % The icon document is separate from the puzzle document, so we need to create % a special package (\marginpar{\small\raggedleft\pkg{icon-doc} package}\pkg{icon-doc}) for it. % \begin{macrocode} %<*icondoc> \NeedsTeXFormat{LaTeX2e}[1997/12/01] \ProvidesPackage{icon-doc} [2020/04/21 v1.0 icon-doc: Build Icon file and explode same (dps)] \newif\ifdpsuseacrobat \dpsuseacrobatfalse % \end{macrocode} % The \pkg{icon-doc} package\marginpar{\small\raggedleft\app{xelatex} author} has one option (and one convenience option). % Both options are targeted at users of \app{xelatex}. % If the \app{xelatex} has \app{Acrobat} then use the \IndexOpt{useacrobat}\opt{useacrobat} option; otherwise, use % use the \IndexOpt[\protect\EXCL]{!useacrobat}\opt{!useacrobat} option. The default is \opt{!useacrobat} so this option need not appear in the option list. % More on the problems of \app{xelatex} in the description of \cs{@MultiQuesFiles} below. % \begin{macrocode} \DeclareOption{useacrobat}{\dpsuseacrobattrue} \DeclareOption{!useacrobat}{\dpsuseacrobatfalse} \DeclareOption{twice}{\dpscomptwicetrue} \newif\ifdpscomptwice \dpscomptwicefalse \ProcessOptions\relax \RequirePackage{ifxetex} \RequirePackage{shellesc} \RequirePackage{web} \RequirePackage{eforms} \execJSOn \pagestyle{empty} \parindent0pt \parskip0pt \newwrite \wrtPkg \newwrite\wrticonbody \def\IWB#1{\immediate\write\wrticonbody{#1}} \def\IWP#1{\immediate\write\wrtPkg{#1}} % \end{macrocode} % Some standard code for writing verbatim to a file. % \begin{macrocode} \def\verbatimwrite{\@bsphack \let\do\@makeother\dospecials \catcode`\^^M\active \catcode`\^^I=12 \def\verbatim@processline{% \immediate\write\verbatim@out {\the\verbatim@line}}% \verbatim@start} \def\endverbatimwrite{\@esphack} % \end{macrocode} % \begin{environment}{icondoc} % Through the \env{icondoc} environment, you can set the {\LaTeX} document % into which the question content will be inserted. This environment is only used % for the case of a \app{xelatex} user without \app{Acrobat}. % The environment writes the is contents verbatim to the file % \marginpar{\small\raggedleft\texttt{icons-template}}\texttt{icons-template.tex}. % This file is later input by \cs{@MultiQuesFiles} to build individual % icon files. % \begin{macrocode} \newenvironment{icondoc} {% \immediate\openout \wrticonbody icons-template.tex \let\verbatim@out\wrticonbody \IWB{\string\RequirePackage{tmp}}% \verbatimwrite }{% \endverbatimwrite \immediate\closeout \wrticonbody } % \end{macrocode} % \end{environment} % The prototype, as well as the default definition of \env{icondoc}, based on % \texttt{examples/\allowbreak advanced/\allowbreak stat\_match1.tex} % \begin{macrocode} \ifxetex\ifdpsuseacrobat\else \begin{icondoc} \documentclass{article} \usepackage{web} \margins{3pt}{3pt}{3pt}{3pt} \screensize{9\baselineskip}{2.25in} \parindent0pt \begin{document} \small \dpsInputContent % required, defined in \@MultiQuesFiles \end{document} \end{icondoc} \fi\fi % \end{macrocode} % During the course of compiling the icon document, we keep track % of which questions have an icon. It may be that some questions % are short enough to fit in the questions area. \cs{addToPageList} % appearing in both \cs{@SnglQuesFile} and \cs{@MultiQuesFiles}. % The resulting list \cs{pageList} is automatically written to the % file \texttt{icons-pglst.sav} at the end of the icon document. % \begin{macrocode} \let\pageList\@empty \def\addToPageList#1{\edef\x{{#1}}\expandafter \g@addto@macro\expandafter \pageList\expandafter{\x}} % \end{macrocode} % \leavevmode\DescribeMacro\@SnglQuesFile (An internal command) % Under certain conditions, the command publicly known as \cs{createRequiredIcons}. % This command is used for non-\app{xelatex} users, and by \app{xelatex} users who % use \app{Acrobat}. % \begin{macrocode} \def\@SnglQuesFile#1#2{% \@tempcnta#1\relax\advance\@tempcnta\@ne \edef\N{\the\@tempcnta}% \@tempcnta\@ne\relax \@whilenum\@tempcnta < \N \do{% \begingroup % \end{macrocode} % Here is a key point. If the target file does not exist, % that means that question does not use an icon appearance, % so we create a blank PDF icon and do not register it % with \cs{addToPageList}; otherwise, we do register it % with \cs{addToPageList}. % \begin{macrocode} \InputIfFileExists{#2-sc(\the\@tempcnta).cut} {\addToPageList{\the\@tempcnta}}{\null}\par \endgroup % \end{macrocode} % One icon per page. % \begin{macrocode} \newpage \advance\@tempcnta\@ne }% } % \end{macrocode} % \leavevmode\DescribeMacro\@MultiQuesFiles % This command is publicly known as \cs{createRequiredIcons} % when the author is a \app{xelatex} user who does not have \app{Acrobat}. % \par\medskip\noindent % \textbf{Problem with xelatex.} When it comes to embedding a PDF in the document, % \app{xelatex} does not recognize the \texttt{page} key; as a result, the questions % must be wrapped in a separate icon file to be later imported into the puzzle document. % In all other cases, we can conveniently place a questions in a single icon file, and % import a particular page into the document corresponding to the question. % \begin{macrocode} \def\@MultiQuesFiles#1#2{% \@tempcnta#1\relax\advance\@tempcnta\@ne \edef\N{\the\@tempcnta}% \@tempcnta\@ne\relax \@whilenum\@tempcnta < \N \do{% \IfFileExists{#2-sc(\the\@tempcnta).cut} {\addToPageList{\the\@tempcnta}}{} % \end{macrocode} % The above lines are the same as in \cs{@SnglQuesFile}. Here's % where we differ. We begin by creating a temporary package named % \pkg{tmp} that contains the definition of \cs{dpsInputContent}. % \begin{macrocode} \immediate\openout\wrtPkg tmp.sty \IWP{\string\def\string\dpsInputContent{\string \InputIfFileExists{#2-sc(\the\@tempcnta).cut}% {}{\string\null}}}% \immediate\closeout\wrtPkg % \end{macrocode} % Key to the workflow for the author using \app{xelatex} without \app{Acrobat} % is to use \marginpar{\small\raggedleft\cs{ShellEscape}}\cs{ShellEscape}. % We compile (using \app{xelatex}) \texttt{icons-template} twice, for no apparent % reason, followed by renaming the resultant PDF to \texttt{icons-\ameta{num}.pdf}, % which is the name expected by the puzzle document. % \begin{macrocode} \ShellEscape{xelatex icons-template.tex}% \ifdpscomptwice\ShellEscape{xelatex icons-template.tex}\fi \ShellEscape{copy icons-template.pdf icons-\the\@tempcnta.pdf}% \advance\@tempcnta\@ne }\null % content for the icons.tex file % \end{macrocode} % We finish up by deleting all of working files, including the temporary % package \pkg{tmp}. % \begin{macrocode} \ShellEscape{del tmp.sty icons-template.*}% } % \end{macrocode} % \begin{macro}{\createRequiredIcons}\hskip-\marginparsep % \texttt{\darg{\ameta{n-ques}}\darg{\ameta{puzzle-basename}}} This command creates % either a single file containing \ameta{n-ques} pages of the required icons, or it creates \ameta{n-ques} % icon files, each file containing one of the questions. For non-\app{xelatex} users, we use % \cs{@SnglQuesFile} if the \opt{useacrobat} option is taken, otherwise, we use % \cs{@MultiQuesFiles}. In all other cases, \cs{@SnglQuesFile} is used. % \begin{macrocode} \ifxetex \ifdpsuseacrobat \let\createRequiredIcons\@SnglQuesFile \else \let\createRequiredIcons\@MultiQuesFiles \fi \else \let\createRequiredIcons\@SnglQuesFile \fi % \end{macrocode} % This JavaScript is used by \app{xelatex} users who have \app{Acrobat}. % I should mention, this code assumes the document author has \pkg{aeb\_pro} installed, % including, most importantly, the correct installation of % \marginpar{\small\raggedleft\texttt{aeb.js \& aeb\_pro.js}}\texttt{aeb.js} and \texttt{aeb\_pro.js}. % \end{macro} % \begin{macrocode} \begin{defineJS}[\def\defineJSjsR{^^J}]{\execExplode} /* Extract pages to folder */ // Regular expression used to acquire the base name of file try { for (var i = 0; i < this.numPages; i++) aebTrustedFunctions(this,aebExtractPages,{ nStart: i, cPath: "icons-" + (i+1) +".pdf" }); } catch (e) { console.println("Aborted: " + e); } \end{defineJS} % \end{macrocode} % Write the file \texttt{icons-pglst.sav} at end of the document. % \begin{macrocode} \def\wrtPageList{\newwrite\pagelist \immediate\openout \pagelist icons-pglst.sav \immediate\write\pagelist{\string\def\string\pagelist{\pageList}} \immediate\closeout\pagelist } % \end{macrocode} % One last case for \app{xelatex} users. If the author has \app{Acrobat}, % we ``explode'' the single icon document into into its individual pages % with the correct naming convention. % \begin{macrocode} \ifxetex\ifdpsuseacrobat \begin{execJS}{expl} \execExplode \end{execJS} \fi\fi % \end{macrocode} % Finally, we write \texttt{icons-pglst.sav} and the end of the document. % \begin{macrocode} \AtEndDocument{\wrtPageList} \let\WriteBookmarks\relax % \end{macrocode} % \begin{macrocode} % \end{macrocode} % \begin{macrocode} % % \end{macrocode} % \subsection{OCG methods} % Using OCG methods does not require an ``\texttt{icons.tex}'' file, the puzzle file % is entirely self contained. The questions are typeset into their own layer, which we make % visible or invisible, depending on the question selected. We require the % \marginpar{\raggedleft\small\pkg{aeb\_pro} required}\pkg{aeb\_pro} % package (with its \opt{uselayers} option) to be properly installed with its JS files, % as described in the manual of that package. % In the preamble you can conveniently type, %\begin{verbatim} % \usepackage[% % web={pro,tight}, % eforms, % uselayers % ]{aeb_pro} %\end{verbatim} % \begin{macrocode} %<*ocgadv> % \end{macrocode} % Define hooks into the question checkbox event. % The two commands \cs{afterQhookA} and \cs{OnFocusQhookAA} are hooks onto % the \cs{dpsQ} command. This allows us to post process % the user's choice of a questions, and allows us to execute JS on focus. % \begin{macrocode} \@ifpackageloaded{textpos}{\let\dps@mode\par}{\let\dps@mode\relax} \def\afterQhookA#1{% if(!event.target.isBoxChecked(0))dpsHideLayer("#1");\r else\pdfSP if(PlayerSignIn())dpsShowLayer("#1");} \def\OnFocusQhookAA#1{dpsHidePreviousLayer("#1")} % \end{macrocode} % Parse the argument (\ameta{name}-\ameta{num}) to get the \ameta{name}. % \begin{macrocode} \def\dps@getOCGName#1-#2\@nil{\def\dps@OcgName{#1}} % \end{macrocode} % \leavevmode\DescribeMacro\fmtOCGQues\hskip-\marginparsep\texttt{\darg{\ameta{various}}} % Use this command to format the question layer. Within the argument of \ameta{various} you % should place \verb~\dpsQuesLayer{#1}~, which input the content file \cs{jobname-sc(\#1).cut}. % The following two examples use \pkg{eso-pic} and \pkg{textpos} packages respectively. %\begin{verbatim} %\fmtOCGQues{% eso-pic pkg % \parbox[t][9\baselineskip][t]{2.25in}{\kern0pt\small\hfuzz11pt % \psshadowbox[framesep=0pt]{\fcolorbox{red}{cornsilk}{% % \parbox{\linewidth}{\dpsQuesLayer{#1}\vskip3pt}}}}} % %\fmtOCGQues{% textpos pkg % \parbox[t][9\baselineskip][t]{2.25in}{\kern0pt\small\hfuzz11pt % \psshadowbox[framesep=0pt]{\fcolorbox{red}{cornsilk}{% % \parbox{\linewidth}{\dpsQuesLayer{#1}\vskip3pt}}}}} %\end{verbatim} % \begin{macrocode} \def\fmtOCGQues#1{\def\fmtOCGQues@i##1{#1}} % \end{macrocode} % \leavevmode\DescribeMacro\dpsQuesLayer\hskip-\marginparsep\texttt{\darg{\ameta{\ameta{name}-\ameta{num}}}} % Inputs the appropriate content file. The command is placed in the \cs{fmtOCgQues} and its argument remains % symbolic (\verb~\dpsQuesLayer{#1}~), as seen in the examples above. The argument is never specified explicitly, % but is only symbolically referenced with the \cs{placeQuesLayer} command; for example, %\begin{verbatim} % \placeQuesLayer{% eso-pic pkg % \AddToShipoutPictureFG*{\AtTextCenter{\put(-72,72) % {\insertQuesLayer{#1}}}}} % % \placeQuesLayer{% textpos pkg % \begin{textblock*}{2.25in}[0,0](2.5in+.725in,3in) % \insertQuesLayer{#1} % \end{textblock*}} %\end{verbatim} % \begin{macrocode} \def\dpsQuesLayer#1{\input{\jobname-sc(#1).cut}} % \end{macrocode} % \leavevmode\DescribeMacro\placeQuesLayer\texttt{\darg{\ameta{various}}} Use this command % to place your question content on the page. The argument \ameta{various} depends on the % package used (\pkg{eso-pic} or \pkg{textpos}. Examples are shown above under \cs{dpsQuesLayer}. % \begin{macrocode} \long\def\placeQuesLayer#1{\@ifundefined{textblock} {\let\dps@mode\relax}{\let\dps@mode\par}% \def\pl@ceQuesL@yer##1{\dps@mode #1}} % \end{macrocode} % \leavevmode\DescribeMacro\placeOtherLayer\texttt{\darg{\ameta{various}}} A general purpose % command for creating another layer, not associated with a question. The \ameta{various} % argument is roll-your-own for inserting a graphic in a layer with a specific name. For example, %\begin{verbatim} % \placeOtherLayer{% eso-pic pkg % \AddToShipoutPictureFG*{\AtTextCenter{\put(-72,36) % {\xBld{owclogo}\parbox{2.25in} % {\includegraphics[width=\linewidth]{owc_self}}\eBld}}}} %\end{verbatim} %The above creates a layer named \texttt{owclogo} consisting of a graphic. The placement %is indicated as well. % \begin{macrocode} \long\def\placeOtherLayer#1{#1} % \end{macrocode} % \DescribeMacro\insertQuesLayer\hskip-\marginparsep\texttt{\darg{\ameta{name}-\ameta{num}}} % Places the formatted question content (\cs{fmtOCGQues@i}) within a layer % created by the \cs{xBld}/\allowbreak\cs{eBld} pair, the layer's name is \ameta{name} (parsed % as \cs{dps@OcgName}). % \begin{macrocode} \def\insertQuesLayer#1{\dps@getOCGName#1\@nil \edef\x{\noexpand\xBld{\dps@OcgName}}\x \fmtOCGQues@i{#1}\eBld} % \end{macrocode} % \DescribeMacro\quesNumTxt\cs{quesNumTxt} and \DescribeMacro\quesNumTxTPost % \cs{quesNumTxTPost} are the same, as described for button icon appearances. % \begin{macrocode} \newcommand{\quesNumTxt}[1]{\protect\textbf{Problem #1}} \newcommand{\quesNumTxTPost}{\protect\newline} % \end{macrocode} % \leavevmode\DescribeEnv{setContent}\hskip-\marginparsep\texttt{\darg{\ameta{name}}} % The \env{setContent} is the counterpart % to the environment of the same name for button icon appearances. % It performs a similar function, but yet is different. The \env{setContent} % environment is placed within the \env{cQ} environment. The \env{setContent} follows % the question prompt. % \begin{macrocode} \newenvironment{setContent}[1]{% \gdef\scArg{#1}% save the argument for the end env % \end{macrocode} % The \cs{jobname-sc} CUT file is indexed by \ameta{name}-\cs{theenumi}. % Thus, we have the \ameta{name} and problem number available to us. % \begin{macrocode} \def\CommentCutFile{\jobname-sc(#1-\theenumi).cut}% \immediate\openout\CommentStream=\CommentCutFile \begingroup \set@display@protect \let\verbatim@out\CommentStream \dps@IWVO{\quesNumTxt{\theenumi}\quesNumTxTPost}% \set@typeset@protect \verbatimwrite }{% \endverbatimwrite \endgroup \immediate\closeout\CommentStream \edef\x{\noexpand\pl@ceQuesL@yer{\scArg-\theenumi}}\x } % \end{macrocode} % \subsubsection{Support for a sideshow} % \leavevmode\DescribeMacro\insertSideshow\hskip-\marginparsep % \texttt{[\ameta{ext}]\darg{\ameta{rows}}\darg{\ameta{cols}}[\ameta{hy-opts}]\darg{\ameta{path}}} % Command for placing the tiles of the picture. We assume that the pictures are numbered % consecutively across rows. %\begin{quote} %\begin{description} % \item[\ameta{ext}] optional extension of the image % \item[\ameta{rows}] number of rows % \item[\ameta{cols}] number of columns % \item[\ameta{hy-opts}] optional arguments for the \cs{includegraphics} command % \item[\ameta{path}] base name of picture files (The files are index as follows: % \texttt{mypic\_01}, \texttt{mypic\_02}, \texttt{mypic\_03}, \dots. The basename is % \texttt{mypic}, the underscore is added in by this command. %\end{description} %\end{quote} % Usage: \begin{flushleft}\quad\verb~\insertSideshow{3}{2}[width=.5\linewidth]{flowers2/rose}~\end{flushleft} % \begin{macrocode} \newcommand{\insertSideshow}[3][]{\begingroup \def\@Ext{#1}\ifx\@Ext\@empty\else\def\@Ext{.#1}\fi \def\@nrows{#2}\def\@ncols{#3}\insertSideshow@i } \newcommand\insertSideshow@i[2][]{\offinterlineskip \@tempcnta\z@ \let\DPSIndxList\@gobble \multido{\iR=1+1}{\@nrows}{\hbox{% \multido{\iC=1+1}{\@ncols}{% \global\advance\@tempcnta\@ne \ifnum\@tempcnta<10\relax \edef\x{0\the\@tempcnta}\else\edef\x{\the\@tempcnta}\fi \edef\z{\noexpand\g@addto@macro\noexpand\DPSIndxList{,"\x"}}\z \xBld{pic\x}\includegraphics[#1]{#2_\x\@Ext}\eBld }% inner multido }}% hbox, outer multido % \end{macrocode} % Write the results of building the \cs{DPSIndxList} to the aux file. A typical % result is \verb~\gdef\DPSIndxList{"01","02","03","04","05","06"}~, which are the % indices for the sideshow picture graphics. % \begin{macrocode} \immediate\write\@auxout{\string\gdef\string \DPSIndxList{\DPSIndxList}}% \endgroup } % \end{macrocode} % \begin{macrocode} % % \end{macrocode} % \section{Language Cutomizations} % Below are the strings that are displayed in the message box. Wording may be % changed to suite your needs.\par\medskip\noindent % (2020/04/21) Changed \texttt{( nMissed > n )} to \texttt{( nMissed > nPassing )} % in the definition of \cs{congratFinished}. % \changes{v1.1}{2020/04/21}{In the definition of \string\cs{regretPleased}, % changed \string\texttt{( nMissed > n )} to \string\texttt{( nMissed > nPassing )}} % \begin{macrocode} %<*english> \def\chooseQ{"You must choose a question to answer before you answer!"} \def\triedTooMuch{"You have tried this problem too many times, I'm adding " + \dspenaltypoints + " points, and resetting the penalty counter. Bad boy/girl!"} \def\congratFinished{"Congratulations! You finished the puzzle" +((nMissed==0) ? " without missing a single problem, amazing!" : ", but you missed " + nMissed + " questions in the process!")} \def\regretPleased{(( nMissed > nPassing ) ? "I regret to report that you did not pass the test because you missed too many questions." : "I am pleased to report that you passed the test!")} \def\reportPenaltyPoints{"The number of penalty points is " + nPenaltyPoints +"."} \def\finalPenaltyScore{"Final penalty score is " + nTotalPenaltyPoints + ". "} \def\aPenaltyScale{[-1,0], [0,4], [4, 10], [10,25], [25,5000]} \def\aPenaltyMsgs {% "Perfect!", "Very nice performance!", "This is not looking good. Perhaps a review is in order!", "Are you trying? No one could do so badly, you only need a seventh grade education!", "You're hopeless!" } \dlJSStr[noquotes]{\signInMsg}{% You must enter your name in the field at the top of the page to get credit for this assignment.} % %<*german> \def\chooseQ{"Du musst erst eine Frage ausw\string\344hlen bevor Du antwortest!"} \def\triedTooMuch{"Du hast es leider zu oft versucht, ich z\string\344hle " + \dspenaltypoints + " Punkte dazu und setze den Z\string\344hler dann zur\string\374ck. Bitte streng Dich an!"} \def\congratFinished{"Herzlichen Gl\string\374ckwunsch! Du hast das Puzzle beendet" + ((nMissed==0) ? " ohne auch nur einen Fehler zu machen, wunderbar!" : ", aber leider " + nMissed + " Mal falsch geantwortet!")} \def\regretPleased{(( nMissed > nPassing ) ? "Ich bedauere Dir mitteilen zu m\string\374ssen, dass Du den Test leider nicht bestanden hast, weil Du zu viele Fragen falsch beantwortet hast." : "Ich bin \string\344usserst erfreut Dir mitteilen zu d\string\374rfen, dass Du den Test bestanden hast!")} \def\reportPenaltyPoints{"Die Anzahl der Strafpunkte ist " + nPenaltyPoints +"."} \def\finalPenaltyScore{"Die Gesamtanzahl der Strafpunkte ist damit " + nTotalPenaltyPoints + ". "} \def\aPenaltyScale{[-1,0], [0,4], [4, 10], [10,25], [25,5000]} \def\aPenaltyMsgs {% "Perfekt!", "Sehr gute Vorstellung!", "Es sieht nicht sonderlich gut aus. Vielleicht w\string\344re eine Wiederholung gut!", "R\string\344tst Du eigentlich nur? Niemand kann wirklich so schlecht sein. Das ist Stoff aus der siebten Klasse!", "Du bist ein hoffnungsloser Fall!" } \dlJSStr[noquotes]{\signInMsg}{% You must enter your name in the field at the top of the page to get credit for this assignment.} % %<*package> % \end{macrocode} % % \section{Form and document actions} % % \begin{macro}{\printPDF}\hskip-\marginparsep\texttt{[\ameta{opts}]\darg{\ameta{wd}}\darg{ht}} % Opens the print dialog box, pre-populates some print parameters. % \begin{macrocode} \newcommand{\printDPS}[3][]{% \pushButton[\CA{Print}\A{\JS{% var pp = this.getPrintParams();\r pp.firstPage=1;\r pp.lastPage=1;\r pp.pageHandling = pp.constants.handling.shrink;\r var fv = pp.constants.flagValues;\r pp.flags |= (fv.suppressCenter | fv.suppressRotate);\r this.print(pp);}}#1]{printDPS}{#2}{#3}% } % \end{macrocode} % \end{macro} % \begin{macro}{\resetPDF}\hskip-\marginparsep\texttt{[\ameta{opts}]\darg{\ameta{wd}}\darg{ht}} % Clears the puzzle board. % \begin{macrocode} \newcommand{\resetDPS}[3][]{% \pushButton[\CA{Clear}\A{\JS{resetDPS();}}#1]{resetDPS}{#2}{#3}% } % \end{macrocode} % \end{macro} % \begin{macro}{\clearOnCloseOrSave} % Try to prevent the student from saving the game (for some other student) % we clear the game board if either student closes or save the document. % \begin{macrocode} \def\dpsWCSWrnMsg{The file dps-wcs.def could not be found} \newcommand{\clearOnCloseOrSave}{\InputIfFileExists{dps-wcs.def}{} {\PackageWarning{dps}{\dpsWCSWrnMsg}}} % \end{macrocode} % \end{macro} % \begin{macrocode} % %<*willCloseSave> % \end{macrocode} % This is the mechanism for preventing the student from saving the document % and continuing at a later time. When the student tries to save or close the document, % the entire puzzle board is cleared. % \begin{macrocode} \begin{willClose} resetDPS(); \end{willClose} \begin{willSave} resetDPS(); \end{willSave} % % \end{macrocode} % % \section{JavaScript Support} % \subsection{JavaScript common to all options} % \begin{macrocode} %<*package> \def\lngthOfMsg{2000} % in milliseconds % \end{macrocode} % \leavevmode\DescribeMacro\dpsResetHook\hskip-\marginparsep\texttt{\darg{\ameta{js-code}}} % Can be used to add code lines to the \texttt{dpsReset()} function. % \begin{macrocode} \def\dpsResetHook#1{\def\dpsresethook{#1}} \dpsResetHook{;} % \end{macrocode} % \leavevmode\DescribeMacro\dpsFinishedEvent\hskip-\marginparsep\texttt{\darg{\ameta{js-code}}} % Can be used to add code lines to the \texttt{dpsFinishedHook()} function, a function that is % called when the puzzle is complete. % \begin{macrocode} \def\dpsFinishedEvent#1{\def\dpsfinishedevent{#1}} \dpsFinishedEvent{;} % \end{macrocode} % The main JavaScript segment for DPS % \begin{macrocode} \begin{insDLJS}{match}{DPS: JavaScript support Das Puzzle Spiel} var playerSignedIn = false; var missesByQuestion = new Object(); var nPassing = \dspassing; var nMissed = 0; var nPenaltyPoints = 0; var activeQuestion = ""; var f=this.getField("ckbxQ"); var g=f.getArray(); var QBC=g[0].strokeColor; var pic = new Object(); var _dpsTO; // time out variable var bRandPicMaps=\bRandPicMaps; % \end{macrocode} % \leavevmode\IndexJS{PlayerSignIn}\hskip-\marginparsep\texttt{()} Manages whether a player % must sign into the \texttt{dpsSignInName} field. If this field does not exit, no % sign-in is required. % \begin{macrocode} function PlayerSignIn() { if ( !playerSignedIn ) { var f = this.getField("dpsSignInName"); if (f != null) { var nameField = f.value; if ( nameField.replace(/\s*/g,"") == "" ) { app.alert("\signInMsg"); event.target.value="Off"; } else playerSignedIn = true; } else playerSignedIn = true; } return playerSignedIn; } % \end{macrocode} % \leavevmode\IndexJS{processChoice}\hskip-\marginparsep\texttt{(\ameta{name})} This % is the mouse up action of the answer check boxes. % \begin{macrocode} function processChoice(name) { // Get the question field that corresponds to this question, // see if checked. var f = this.getField("ckbxQ."+name); if ( (f != null) && (f.isBoxChecked(0)) ) { // right clearRedCrosses (); this.resetForm(["puzzle."+name]); event.target.textColor = ["RGB", 0, 0.6, 0]; f.strokeColor = ["RGB", 0, 0.6, 0]; f.readonly = true; event.target.readonly=true; try { afterCorrectChoiceHook() } catch(e) {}; checkForFinished(); } else { // wrong if ( activeQuestion != "" ) var h = this.getField(activeQuestion); if ( (activeQuestion=="") || (h.readonly) ) { // active question already answered event.target.value = "Off"; var g = this.getField("report"); str = \chooseQ; g.value = str; var to = app.setTimeOut("clearMessages()", \lngthOfMsg); } else { event.target.style = style.cr; event.target.textColor = color.red; ++nMissed; if ( typeof missesByQuestion[activeQuestion] !="number" ) missesByQuestion[activeQuestion] = 1; else missesByQuestion[activeQuestion] += 1; if (missesByQuestion[activeQuestion] > \dsthreshold) { var f = this.getField("report"); str = \triedTooMuch; f.value = str; nPenaltyPoints += \dspenaltypoints; missesByQuestion[activeQuestion] = 0; clearRedCrosses (); var to = app.setTimeOut("clearMessages()", \lngthOfMsg); } } } } % \end{macrocode} % \leavevmode\IndexJS{clearMessages}\hskip-\marginparsep\texttt{()} Clears the text % field named \texttt{report}, which is created by \DescribeMacro\placeMessageField % \cs{placeMessageField}. % \begin{macrocode} function clearMessages() { var f = this.getField("report"); f.value = ""; } % \end{macrocode} % \leavevmode\IndexJS{clearRedCrosses}\hskip-\marginparsep\texttt{()} Clears % all answer check boxes what are marked with a cross, meaning wrong choice. % Part of the mouse up action question check boxes. % \begin{macrocode} function clearRedCrosses () { var g = this.getField("ckbxA"); h = g.getArray(); for ( i=0; i < h.length; i++) { if ( h[i].style == style.cr) h[i].checkThisBox(0,false); h[i].style = style.ch; } } % \end{macrocode} % \leavevmode\IndexJS{checkForFinished}\hskip-\marginparsep\texttt{()} Determines % if all questions have been answered. Called from \texttt{processChoice()}. % \begin{macrocode} function checkForFinished() { var f = this.getField("puzzle"); var g = f.getArray(); var anyEmpty = false; for ( var i=0; i < g.length; i++) { if ( (g[i].name != "puzzle.space") && % (g[i].value.replace(/\s/g,"") == "") ) { anyEmpty = true; break; } } var nTotalPenaltyPoints=nMissed + nPenaltyPoints; if ( !anyEmpty ) { try { dpsFinishedHook() } catch (e) {}; var f = this.getField("report"); str = \congratFinished + "\n" + \regretPleased + "\n" + \reportPenaltyPoints + "\n" + \finalPenaltyScore + " " + finalRating(nTotalPenaltyPoints); f.value = str; } } % \end{macrocode} % \leavevmode\IndexJS{finalRating}\hskip-\marginparsep\texttt{(\ameta{penalty-points})} % A function that returns a message string from the array (\cs{aPenaltyMsgs}) of penalty messages. % Choice of messages is based on where the value \ameta{penalty-points} falls into % the penalty scale array (\cs{aPenaltyScale}). This function is called from % \texttt{checkForFinished()}. % \begin{macrocode} function finalRating(n) { var aPenaltyScale = new Array( \aPenaltyScale\space); var aPenaltyMsgs = new Array( \aPenaltyMsgs\space); for ( var i=0; i aPenaltyScale[i][0]) && (n <= aPenaltyScale[i][1]) ) return aPenaltyMsgs[i]; } % \end{macrocode} %\leavevmode\IndexJS{resetDPS}\hskip-\marginparsep\texttt{()} % A JavaScript function to reset the puzzle board. May be used as a push button % action or within the \env{willClose} and \env{willSave} environments. % \changes{v1.1}{2020/04/21}{Added \texttt{resetDPS()} JavaScript function.} % \begin{macrocode} function resetDPS() { this.delay=true; this.resetForm(); var f=this.getField("puzzle"); var g=f.getArray(); for (var i=0; i 0 ) for (var i=0; i % \end{macrocode} % \Finale \endinput