diff options
author | Norbert Preining <norbert@preining.info> | 2017-07-12 23:26:39 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2017-07-12 23:26:39 +0900 |
commit | 01c9ee84c09adfc3efe1cd93191a9c0473f985fe (patch) | |
tree | 6fe7c1648fa25e3dcc9b4c67657b89ac1525f289 /texmf-dist/source/latex/acrotex/exerquiz.dtx | |
parent | 542c5a785f8db8d4469e296c69c86bc030285f68 (diff) |
add acrotex
Diffstat (limited to 'texmf-dist/source/latex/acrotex/exerquiz.dtx')
-rw-r--r-- | texmf-dist/source/latex/acrotex/exerquiz.dtx | 13306 |
1 files changed, 13306 insertions, 0 deletions
diff --git a/texmf-dist/source/latex/acrotex/exerquiz.dtx b/texmf-dist/source/latex/acrotex/exerquiz.dtx new file mode 100644 index 00000000..0cae45ef --- /dev/null +++ b/texmf-dist/source/latex/acrotex/exerquiz.dtx @@ -0,0 +1,13306 @@ +% \iffalse +% makeindex -s gglo.ist -o exerquiz.gls exerquiz.glo +% makeindex -s gind.ist -o exerquiz.ind exerquiz.idx +%<*copyright> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Exerquiz.sty package, %% +%% Copyright (C) 1999-2017 D. P. Story %% +%% dpstory@uakron.edu %% +%% %% +%% 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. %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%</copyright> +%<package>\NeedsTeXFormat{LaTeX2e} +%<package>\ProvidesPackage{exerquiz} +%<driver>\ProvidesFile{exerquiz.drv} +%<aebjs>\ProvidesFile{aebjs.def} +%<eqexam>\ProvidesFile{eqexam.def} +%<randomize>\ProvidesFile{aebrandom.def} +%<sumrytbls>\ProvidesFile{aebsumrytbls.def} +%<template>\ProvidesFile{template.def} +%<package|driver|aebjs|eqexam|randomize|sumrytbls|template> [2017/03/16 v7.8g % +%<package> Exerquiz: Exercises and Quizzes for LaTeX/PDF package (dps)] +%<driver> Exerquiz documentation driver file (dps)] +%<aebjs> Exerquiz document level JavaScript (dps)] +%<eqexam> Exerquiz support file for eqexam (dps)] +%<randomize> Exerquiz support for randomization (dps)] +%<sumrytbls> Exerquiz support for summary tables (dps)] +%<template> Exerquiz template for language support (dps)] +%<eqfr>\ProvidesFile{eqfr.def} +%<eqde>\ProvidesFile{eqde.def} +%<eqno>\ProvidesFile{eqno.def} +%<eqnl>\ProvidesFile{eqnl.def} +%<eqes>\ProvidesFile{eqes.def} +%<eqit>\ProvidesFile{eqit.def} +%<eqru>\ProvidesFile{eqru.def} +%<eqda>\ProvidesFile{eqda.def} +%<eqpo>\ProvidesFile{eqpo.def} +%<eqfin>\ProvidesFile{eqfin.def} +%<eqcat>\ProvidesFile{eqcat.def} +%<eqcz>\ProvidesFile{eqcz.def} +%<eqbr>\ProvidesFile{eqbr.def} +%<eqtr>\ProvidesFile{eqtr.def} +%<*driver> +\documentclass{ltxdoc} +\usepackage[colorlinks,hyperindex=false]{hyperref} +\pdfstringdefDisableCommands{\let\\\textbackslash} +\OnlyDescription % comment out for implementation details +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\InputIfFileExists{aebdocfmt.def}{\PackageInfo{exerquiz}{Inputting aebdocfmt.def}} + {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax + \PackageInfo{exerquiz}{aebdocfmt.def cannot be found}} +\begin{document} + \let\env\texttt\let\pkg\textsf + \GetFileInfo{exerquiz.sty} + \title{Exerquiz: Exercises and Quizzes for \LaTeX/PDF} + \author{D. P. Story\\ + Email: \texttt{dpstory@uakron.edu}} + \date{processed \today} + \maketitle + \tableofcontents + \let\Email\texttt + \DocInput{exerquiz.dtx} +\IfFileExists{\jobname.ind}{\newpage\setupFullwidth\PrintIndex}{\paragraph*{Index} + The index goes here.\\Execute + \texttt{makeindex -s gind.ist -o exerquiz.ind exerquiz.idx} on the command line + and recompile \texttt{exerquiz.dtx}.} +\IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of + changes goes here.\\Execute + \texttt{makeindex -s gglo.ist -o exerquiz.gls exerquiz.glo} on the command line + and recompile \texttt{exerquiz.dtx}.} +\end{document} +%</driver> +% \fi +% +% \MakeShortVerb{|} +% \InputIfFileExists{aebdonotindex.def}{\PackageInfo{exerquiz}{Inputting aebdonotindex.def}} +% {\PackageInfo{exerquiz}{aebdonotindex.def cannot be found}} +% +% \begin{macrocode} +%<*package> +% \end{macrocode} +% \changes{v7.7k}{2016/04/18}{Minor bug fixes, improved driver recognition} +% \changes{v7.7j}{2016/04/05}{Change in eforms to 2016/04/05 v2.8f} +% +% \section{Package options and setup}\label{options} +% +% Introduce a number of useful options for \textsl{exerquiz}. +% \subsection{Options for paper, solutions, JavaScript and preview} +% \begin{macrocode} +\usepackage{keyval} +% \end{macrocode} +%\changes{v6.4t}{2012/06/18}{Added ifpdf as a required package} +% \begin{macrocode} +\RequirePackage{ifpdf}[2006/02/20] +\RequirePackage{ifxetex}[2006/08/21] +\@ifundefined{exqtable}{\def\exqtable{table}}{} +\IfFileExists{xcolor.sty}{% + \def\eq@ColorPackage{xcolor}% + \PassOptionsToPackage{\exqtable,hyperref}{xcolor}} + {\def\eq@ColorPackage{color}} +% \end{macrocode} +% \IndexOpt{noxcolor} An option to force +% the use of the \textsf{color} package. +% \begin{macrocode} +\DeclareOption{noxcolor}{\def\eq@ColorPackage{color}} +% \end{macrocode} +% \IndexOpt{forpaper}\IndexOpt{forcolorpaper} +% Pass the |monochrome| option to the color package +%\changes{v6.06a}{2007/04/09} +%{ +% Added the \texttt{forcolorpaper} option for those using +% \textsf{exerquiz} without \textsf{web}. +%} +% \begin{macrocode} +\DeclareOption{forpaper}{% + \eqforpapertrue\PassOptionsToPackage{monochrome}{\eq@ColorPackage} + \AtBeginDocument{\ifnum\eq@drivernum=4 \else\AllowPeeking\fi} +} +\DeclareOption{forcolorpaper}{\eqforpapertrue % for print + \AtBeginDocument{\ifnum\eq@drivernum=4 \else\AllowPeeking\fi} +} +% \end{macrocode} +% \IndexOpt{preview} +% With this option, the bounding boxes of all form fields appear in the +% dvi preview. Use this option of properly positioning your fields, then +% remove this option on the final build of the document. This option is no +% appropriate for the \texttt{pdftex} option which does not have a dvi preview. +% \begin{macrocode} +\DeclareOption{preview}{\PassOptionsToPackage{preview}{eforms}} +% \end{macrocode} +% \IndexOpt{nosolutions} +% With the option, the solutions to the exercises are not +% included in the typeset document. +% \begin{macrocode} +\DeclareOption{nosolutions}{\eq@nosolutionstrue\eq@nolinktrue} +% \end{macrocode} +% \IndexOpt{noquizolutions} +% No solutions for quizzes (shortquiz and quiz environments). +% \begin{macrocode} +\DeclareOption{noquizsolutions}{\eq@noquizsolutionstrue\eq@nolinktrue} +% \end{macrocode} +% \IndexOpt{online} +% An \texttt{online} options. +% \begin{macrocode} +%</package> +%<*package|eqexam> +\let\eq@YES=y \let\eq@NO=n +\let\eq@One=1 \let\eq@Zero=0 +\def\eq@r{r}\let\eq@f=f \let\eq@l=l +%</package|eqexam> +%<*package> +\DeclareOption{online}{\let\eq@online\eq@YES} +\let\eq@online\eq@NO +% \end{macrocode} +% \IndexOpt{nohiddensolutions}\IndexOpt{noHiddensolutions} +% Overrides any hidden solutions specified with the \texttt{exercise} +% environment. +% \begin{macrocode} +\DeclareOption{nohiddensolutions}{\eq@globalshowsolutionstrue} +\DeclareOption{noHiddensolutions}% + {\eq@globalshowsolutionstrue\AtBeginDocument{\def\Hidesymbol{h}}} +% \end{macrocode} +% \IndexOpt{solutionsafter} +% Solutions will appear after the statement of the exercise. +% \begin{macrocode} +\DeclareOption{solutionsafter}{\eq@solutionsaftertrue\eq@nolinktrue} +% \end{macrocode} +% \IndexOpt{solutionsonly} +% Here is a highly specialized option, put in at the request of a former friend. +%\changes{v6.2f}{2007/12/21}{Added a solutionsonly option} +% \begin{macrocode} +\DeclareOption{solutionsonly}{\solutionsonlytrue\answerkeytrue + \therearesolutionstrue\AtEndOfPackage{\let\exerSolnsHeadnToc\relax}} +\newif\ifsolutionsonly\solutionsonlyfalse +% \end{macrocode} +% \IndexOpt{contsolns} +% This option requires both \textsf{web} and \textsf{exerquiz}. The package +% tests for the presence of the \textsf{web} and whether webheadings pagestyle +% is used. +% \begin{macrocode} +\DeclareOption{contsolns}{\AtEndOfPackage{\InputIfFileExists + {contsolns.def}{\contsolnsInputMsg}{\contsolnsErrorMsg}}} +\def\contsolnsInputMsg{\PackageInfo{exerquiz}{contsolns option, + inputting file contsolns.def}} +\def\contsolnsErrorMsg{\PackageWarning{exerquiz}{contsolns option, + cannot find file contsolns.def}} +% \end{macrocode} +% \IndexOpt{nocorrections} +% The code for correcting the |quiz| environment is +% not written; this results in a smaller file. +% \begin{macrocode} +\DeclareOption{nocorrections}{\nocorrectionstrue} +% \end{macrocode} +% \IndexOpt{proofing} +% An option for marking the correct answers for shortquiz and quiz +% \begin{macrocode} +\DeclareOption{proofing}{\eq@proofingtrue} +% \end{macrocode} +% \IndexOpt{showgrayletters} +% When this option is in effect, capital letters in gray appear under +% the multiple choice question boxes of quizzes. +% \begin{macrocode} +\newif\ifaebshowgrayletters\aebshowgraylettersfalse +\DeclareOption{showgrayletters}{\aebshowgrayletterstrue} +% \end{macrocode} +% \IndexOpt{vspacewithsolns} +% This is for the \texttt{vspacewithsolns} option designed for +% \textsf{eqexam}, but can be used in \textsf{exerquiz}. The switch +% \cs{ifvspacewithsolns} is defined in \textsf{eqexam}, and we olnly +% define it here is \textsf{eqexam} is not loaded. +% \changes{v6.3x}{2011/04/05}{Added \texttt{vspacewithsolns}} +% \begin{macrocode} +\@ifundefined{ifvspacewithsolns}{% + \DeclareOption{vspacewithsolns}{\vspacewithsolnstrue} + \newif\ifvspacewithsolns\vspacewithsolnsfalse +}{} +% \end{macrocode} +% \IndexOpt{nodljs} +% An option for excluding all DLJS from the document. Useful with the +% \texttt{forpaper} option, or a document destined to be printed. Pass +% on to insdljs package. +% \begin{macrocode} +\DeclareOption{nodljs}{\PassOptionsToPackage{nodljs}{insdljs}% + \AtEndOfPackage{\let\importdljs\eq@YES}} +% \end{macrocode} +% \IndexOpt{execAfter} +% Execute any JS defined within the \texttt{execJS} environment. Works only for +% authors using Acrobat 5.0 or Acrobat Approval. +% \begin{macrocode} +\DeclareOption{execJS}{\PassOptionsToPackage{execJS}{insdljs}} +% \end{macrocode} +% \IndexOpt{exercisesonly} +% If the document author wants only to create a series of exercises, no quizzes, there is no +% need for the Document-level JavaScript. So, we have a couple of convenience options. +% \begin{macrocode} +\DeclareOption{exercisesonly}{\PassOptionsToPackage{nodljs}{insdljs}} +% \end{macrocode} +% \IndexOpt{debug} +% An option for debugging JavaScript. Pass on to insdljs package. +% \begin{macrocode} +\DeclareOption{debug}{\PassOptionsToPackage{debug}{insdljs}} +% \end{macrocode} +% \IndexOpt{allowrandomize} +% Beginning with version 6.1 of \textsf{exerquiz}, it is possible to randomize +% the choices in a multiple choice question. These choices must be set off +% by the command \cs{bChoices}/\cs{eChoices} pair. The command \cs{bChoices} now has +% two optional arguments \texttt{nCols} and \texttt{random}. See \autoref{randomize}. +% \begin{macrocode} +\DeclareOption{allowrandomize}{\AtEndOfPackage{\inputRandomizeChoices}} +\def\inputRandomizeChoices{\InputIfFileExists{aebrandom.def} + {\PackageInfo{exerquiz}{inputting aebrandom.def}} + {cannot find aebrandom.def}} +% \end{macrocode} +% \IndexOpt{usesumrytbls} +% \begin{macrocode} +\newif \ifusesumrytbls \usesumrytblsfalse +\DeclareOption{usesumrytbls}{\usesumrytblstrue + \def\inputSumryTblCode{\InputIfFileExists{aebsumrytbls.def} + {\PackageInfo{exerquiz}{inputting aebsumrytbls.def}}% + {cannot find aebsumrytbls.def}}} +\let\inputSumryTblCode\relax +% \end{macrocode} +% The \IndexOpt{usemcfi}\texttt{usemcfi} option inputs special code for creating a MC/math fill-in question, a type +% of question suggested to me by Stefka K.\ of Bulgaria. +% \begin{macrocode} +\DeclareOption{usemcfi}{% + \def\inputMCFICode{\InputIfFileExists{usemcfi.def} + {\PackageInfo{exerquiz}{inputting usemcfi.def}}% + {cannot find usemcfi.def}}} +\let\inputMCFICode\relax +% \end{macrocode} +% \changes{v7.7o}{2016/07/08}{Added switch \string\cs{ifwithinMCFI}} +% The switch \cs{ifwithinMCFI} help to determine if a quiz problem occurs within +% the command \cs{bMCFI}/\cs{eMCFI} pair. +% \begin{macrocode} +\newif\ifwithinMCFI\withinMCFIfalse +% \end{macrocode} +% +% \subsection{Driver Options} +% The \textsf{web} package passes these driver options to \textsf{exerquiz}. +% These options are needed is \textsf{exerquiz} is used without +% \textsf{web}; in this case, the options below must explicitly included. +% \IndexOpt{dvipsone}\IndexOpt{dvips}\IndexOpt{pdftex} +% Set the driver dependent code for the |quiz| environments. +% \begin{macrocode} +% \def\eq@drivernum{5} % 5 = no choice +\DeclareOption{dvipsone}{% + \def\eq@drivernum{0}\def\eq@driver{dvipsone}% + \PassOptionsToPackage{dvipsone}{eforms} +} +\DeclareOption{dvips}{% + \def\eq@drivernum{0}\def\eq@driver{dvips}% + \PassOptionsToPackage{dvips}{eforms} +} +\DeclareOption{pdftex}{% + \def\eq@drivernum{1}\def\eq@driver{pdftex}% + \PassOptionsToPackage{pdftex}{\eq@ColorPackage} + \PassOptionsToPackage{pdftex}{eforms} +} +% \end{macrocode} +% \IndexOpt{dvipdfm}\IndexOpt{dvipdfmx}\IndexOpt{xetex} +% Set the driver dependent code for the \texttt{quiz} and \texttt{quiz} +% environments. +% \begin{macrocode} +\DeclareOption{dvipdfm}{% + \def\eq@drivernum{2}\def\eq@driver{dvipdfm}% + \PassOptionsToPackage{dvipdfm}{\eq@ColorPackage}% + \PassOptionsToPackage{dvipdfm}{eforms}% +} +\DeclareOption{dvipdfmx}{% + \def\eq@drivernum{2}\def\eq@driver{dvipdfmx}% + \PassOptionsToPackage{dvipdfmx}{\eq@ColorPackage}% + \PassOptionsToPackage{dvipdfmx}{eforms}% +} +\DeclareOption{xetex}{% + \def\eq@drivernum{2}\def\eq@driver{xetex}% + \PassOptionsToPackage{xetex}{\eq@ColorPackage} + \PassOptionsToPackage{xetex}{eforms}% +} +% \end{macrocode} +% \IndexOpt{textures} +% This option, and testing are due to Ross Moore 3/6/02 +% \begin{macrocode} +\DeclareOption{textures}{\def\eq@drivernum{3}% + \def\eq@driver{textures}% + \PassOptionsToPackage{textures}{\eq@ColorPackage}% + \PassOptionsToPackage{textures}{eforms}% +} +% \end{macrocode} +% \IndexOpt{dviwindo} +% Set \cmd{\eq@noformstrue}, this inserts an \cmd{\endinput} just after +% the end of the |exercise| environment. No quizzes for +% \texttt{dviwindo}. +% \begin{macrocode} +\DeclareOption{dviwindo}{\def\eq@drivernum{4}\def\eq@driver{dviwindo}% + \eq@noformstrue\PassOptionsToPackage{nodljs}{insdljs}} +% \end{macrocode} +% If no driver is passed to \textsf{exerquiz}, assume it is +% dvipsone or dvips---\textsf{hyperref} defines the specials. +% Default driver dvipsone/dvips +% \def\eq@drivernum{5} +% \def\eq@driver{dvipsone/dvips} +% \def\eq@driver{no driver specified} +% \IndexOpt{unicode} +% Passes the unicode option to \textsf{hyperref}. +% \changes{v6.3}{2008/03/19} +% { +% Added the \texttt{unicode} option, which is passed to hyperref. +% } +% \begin{macrocode} +\DeclareOption{unicode}{\PassOptionsToPackage{unicode}{hyperref}} +% \end{macrocode} +% \IndexOpt{useui} +% Passes the useui option to eforms. With this option, +% the key-value pairs \textsl{\'{a} la xkeyval} can be used. +% \changes{v6.3}{2008/03/19} +% { +% Added the \texttt{useui} option, which is passed to eforms. +% } +% \begin{macrocode} +\DeclareOption{useui}{\PassOptionsToPackage{useui}{eforms}} +% \end{macrocode} +% +% \subsection{Language Options} +% \textsf{exerquiz} uses many language dependent typeset labels +% and JavaScript messages. These messages are defined in the +% English language in Section~\ref{ss:ldm}. The language options +% defines the macro \cmd{\LangRedefinition} to input language +% dependent redefinitions of these messages. Initially, +% \cmd{\LangRedefinition} is set to relax and no redefinition files +% are input. +% \begin{macrocode} +\let\LangRedefinitions\relax +% \end{macrocode} +% \IndexOpt{french} +% Translations due to Jean-Michel SARLAT. +% \begin{macrocode} +\DeclareOption{french}{% + \def\LangRedefinitions{\InputIfFileExists{eqfr.def}% + {\PackageInfo{exerquiz}{Inputting French Option}}% + {\PackageInfo{exerquiz}{French Option: Cannot find the file + eqfr.def, using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{german} +% Translation due to Michael Wiedmann. +% \begin{macrocode} +\DeclareOption{german}{% + \def\LangRedefinitions{\InputIfFileExists{eqde.def}% + {\PackageInfo{exerquiz}{Inputting German Option}}% + {\PackageInfo{exerquiz}{German Option: Kann die Datei eqde.def + nicht finden, benutze Default, Englisch.}}}} +% \end{macrocode} +% \IndexOpt{norsk} +% Translation due to Hans Fredrik Nordhaug. +% \begin{macrocode} +\DeclareOption{norsk}{% + \def\LangRedefinitions{\InputIfFileExists{eqno.def}% + {\PackageInfo{exerquiz}{Inputting Norsk Option}}% + {\PackageInfo{exerquiz}{Norsk Option: Cannot find the file eqno.def, + using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{dutch} +% Translation due to Henny Wilbrink +% \begin{macrocode} +\DeclareOption{dutch}{% + \def\LangRedefinitions{\InputIfFileExists{eqnl.def}% + {\PackageInfo{exerquiz}{Inputting Dutch Option}}% + {\PackageInfo{exerquiz}{Dutch Option: Kan bestand eqnl.def niet + vinden, gebruik default, Engels.}}}} +% \end{macrocode} +% \IndexOpt{spanish} +% Translation due to Pedro Luis Luque +% \begin{macrocode} +\DeclareOption{spanish}{% + \def\LangRedefinitions{\InputIfFileExists{eqes.def}% + {\PackageInfo{exerquiz}{Inputting Spanish Option}}% + {\PackageInfo{exerquiz}{Spanish Option: Opci\'on Espa\~nola: no puede + encontrar el fichero eqes.def, usar\'a por defecto, English.}}}} +% \end{macrocode} +% \IndexOpt{italian} +% Translation due to PierLuigi Zezza +% \begin{macrocode} +\DeclareOption{italian}{% + \def\LangRedefinitions{\InputIfFileExists{eqit.def}% + {\PackageInfo{exerquiz}{Opzione Lingua Italiana}}% + {\PackageInfo{exerquiz}{pzione Italiano: Non trovo il file eqit.def, + utilizzo quello di default, English.}}}} +% \end{macrocode} +% \IndexOpt{russian} +% Translation due to Sergei V. Znamenskii +% \begin{macrocode} +\DeclareOption{russian}{% + \@ifpackageloaded{hyperref}{% + \ifHy@unicode\else\PackageWarning{exerquiz}{% + The unicode option recommended for hyperref\MessageBreak}\fi + }{\PassOptionsToPackage{unicode}{hyperref}} + \def\LangRedefinitions{\InputIfFileExists{eqru.def}% + {\PackageInfo{exerquiz}{Inputting Russian Option}}% + {\PackageInfo{exerquiz}{Russian Option: Cannot find the file + eqru.def, using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{dansk} +% Translation due to Erik Leimand +% \begin{macrocode} +\DeclareOption{dansk}{% + \def\LangRedefinitions{\InputIfFileExists{eqda.def}% + {\PackageInfo{exerquiz}{Inputting Dansk Option}}% + {\PackageInfo{exerquiz}{Dansk Option: Cannot find the file eqda.def, + using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{polish} +% Translation due to Jerzy Mycielski +% \begin{macrocode} +\DeclareOption{polish}{% + \def\LangRedefinitions{\InputIfFileExists{eqpo.def}% + {\PackageInfo{exerquiz}{Inputting Polish Option}}% + {\PackageInfo{exerquiz}{Polish Option: Cannot find the file + eqpo.def, using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{finnish} +% Translation due to Paivi Porras +% \begin{macrocode} +\DeclareOption{finnish}{% + \def\LangRedefinitions{\InputIfFileExists{eqfin.def}% + {\PackageInfo{exerquiz}{Inputting Finnish Option}}% + {\PackageInfo{exerquiz}{Finnish Option: Cannot find the file + eqfin.def, using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{catalan} +% Translation due to Ramon Ballester +% \begin{macrocode} +\DeclareOption{catalan}{% + \def\LangRedefinitions{\InputIfFileExists{eqcat.def}% + {\PackageInfo{exerquiz}{Inputting Catalan Option}}% + {\PackageInfo{exerquiz}{Catalan Option: Cannot find the file + eqcat.def, using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{czech} +% Translation due to Robert Marik +% \begin{macrocode} +\DeclareOption{czech}{% + \def\LangRedefinitions{\InputIfFileExists{eqcz.def}% + {\PackageInfo{exerquiz}{Inputting Czech Option}}% + {\PackageInfo{exerquiz}{Czech Option: Cannot find the file eqcz.def, + using the default, English.}}}} +% \end{macrocode} +% \IndexOpt{brazil} +% Translation due to Koichi Sameshima +% \begin{macrocode} +\DeclareOption{brazil}{% + \def\LangRedefinitions{\InputIfFileExists{eqbr.def}% + {\PackageInfo{exerquiz}{Inputting Brazilian Portuguese Option}}% + {\PackageInfo{exerquiz}{Portuguese Option: Opc\~ao Portugu\^es: + n\~ao foi poss\'ivel encontrar o arquivo eqbr.def, usaremos + o padr\~ao, English.}}}} +% \end{macrocode} +% \IndexOpt{turkish} +% Translation due to Mahmut Ko\c{c}ak +% \begin{macrocode} +\DeclareOption{turkish}{% + \@ifpackageloaded{hyperref}{% + \ifHy@unicode\else\PackageWarning{exerquiz}{% + The unicode option recommended for hyperref\MessageBreak}\fi + }{\PassOptionsToPackage{unicode}{hyperref}} + \def\LangRedefinitions{\InputIfFileExists{eqtr.def}% + {\PackageInfo{exerquiz}{Inputting Turkish Option}}% + {\PackageInfo{exerquiz}{Cannot find the file eqtk.def, + using the default, English.}}}} +% \end{macrocode} +% \begin{macrocode} +\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{\eq@ColorPackage}} +\@ifpackageloaded{xcolor}% +{% + \@ifpackagelater{xcolor}{2004/07/04}{} + {% + \PackageError{exerquiz}{% + *************************************************\MessageBreak + * Your Version of `xcolor.sty' is too old!\MessageBreak + * You need the version from 2004/07/04 or newer\MessageBreak + * or use: \string\usepackage[noxcolor]{exerquiz}\MessageBreak + *************************************************}{}% + }% +}{} +% \end{macrocode} +% \subsection{Switches} +% Boolean switches used by the declared options. +% \begin{macrocode} +\let\iterate\relax +\newif\ifeq@solutionsafter \eq@solutionsafterfalse +\newif\ifeq@hidesolution \eq@hidesolutionfalse +\newif\ifeq@globalshowsolutions \eq@globalshowsolutionsfalse +\newif\ifeq@nosolutions \eq@nosolutionsfalse +\newif\ifeq@proofing \eq@proofingfalse +\providecommand\turnProofingOn{\eq@proofingtrue} +\providecommand\turnProofingOff{\eq@proofingfalse} +\newif\ifeqforpaper \eqforpaperfalse +%</package> +%<*package|eqexam> +\newif\ifeq@noforms \eq@noformsfalse +\newif\ifeq@noquizsolutions \eq@noquizsolutionsfalse % dps new +\newif\ifnocorrections \nocorrectionsfalse +% changed \ifeq@nocorrections to \ifnocorrections +%\newif\ifeq@nocorrections \eq@nocorrectionsfalse +% \end{macrocode} +% (4/28/11) A switch to control whether the declared vertical space +% for the \texttt{solution} environment will be preserved during the \texttt{answerkey} +% option. This is an \textsf{eqexam} feature. +%\changes{v6.3z}{2011/04/28}{% +%Created a switch \cs{ifkeepdeclaredvspacing}, used primarily by \textsf{eqexam}} +% \begin{macrocode} +\newif\ifkeepdeclaredvspacing \keepdeclaredvspacingfalse +\newif\ifeq@nolink \eq@nolinkfalse +\def\eq@ckglobalhide{\ifeq@globalshowsolutions\eq@hidesolutionfalse\fi} +\def\hidesymbol{h}\def\Hidesymbol{H} +% \end{macrocode} +% When the first solution is written, \cs{therearesolutions} is +% made true. When the solutions are input back into the file, and +% this switch is still false, then no exercise header is typeset; +% this avoids an empty exercise section with only the header. +% \begin{macrocode} +\newif\iftherearesolutions \therearesolutionsfalse +% \end{macrocode} +%\DescribeMacro{\ifIsRespBox}\cmd{\ifIsRespBox} is a switch used to detect the presence +% of a response box, math or text, on a page. The switch is used to automatically place +% an \cs{AnswerField} in the running footer. +% \begin{macrocode} +\newif\ifIsRespBox \global\IsRespBoxfalse +% \end{macrocode} +% \begin{macro}{\SolutionsAfter} +% \begin{macro}{\SolutionsAtEnd} +% \begin{macro}{\NoSpaceToWork} +% \begin{macro}{\SpaceToWork} +% Some macros to turn \cs{eq@solutionsafter} on or off, and to suppress +% the vertical space in the solutions environment when the \texttt{nosolutions} +% option is in effect. Concerning leaving space to work, the default is to +% leave space to work (\cs{SpaceToWork}). +% \begin{macrocode} +\def\SolutionsAfter{\eq@solutionsaftertrue\eq@nolinktrue} +\newif\ifcqSA\cqSAfalse +\def\SolutionsAtEnd{\eq@solutionsafterfalse\eq@nolinkfalse} +\def\NoSpaceToWork{\let\eq@insertverticalspace\eq@NO} +\def\SpaceToWork{\let\eq@insertverticalspace\eq@YES} +\SpaceToWork +% \end{macrocode} +% (2017/03/16) Made def of \cs{ifNoSolutions} long. +% \changes{v7.8g}{2017/03/16}{Made def of \string\cs{ifNoSolutions} long} +% \begin{macrocode} +\long\def\ifNoSolutions#1#2{% + \ifeq@nosolutions\expandafter#1\else + \expandafter#2\fi +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% Some switches to control the randomization process, which comes into play +% with the \texttt{allowrandomize} option. These are set to \texttt{false} initially, +% The first one is set locally by the random option of \cs{bChoices}; the second +% one overrides the first so that all multiple choice questions can be randomized +% without having to edit every \cs{bChoices} command. The user has access to this +% switch through the \cs{turnOnRandomize} and \cs{obeyLocalRandomize} commands. +% The topic of randomizing the choices is taken up in \autoref{randomize}. +% \begin{macrocode} +\newif\ifeq@randomizeChoices \eq@randomizeChoicesfalse +\newif\ifeq@randomizeallChoices \eq@randomizeallChoicesfalse +% \end{macrocode} +% \begin{macro}{\turnOnRandomize} +% \begin{macro}{\obeyLocalRandomize} +% When the \texttt{allowrandomize} option is in effect, the randomization can be +% turned on and off locally by the optional parameter in \cs{bChoices}. These +% two commands can be used to override \texttt{random=false}. Consequently, +% by saying \cs{turnOnRandomize} you can convert your old multiple choice +% questions so that are randomly arranged, without having to edit them and +% add the optional \texttt{random} key. +% \begin{macrocode} +\def\turnOnRandomize{\eq@randomizeallChoicestrue} +\def\obeyLocalRandomize{\eq@randomizeallChoicesfalse} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\saveRandomSeed} +% \begin{macro}{\inputRandomSeed} +% These two commands are used when the \texttt{allowrandomize} option is in effect, +% Until then, they do nothing. See the definition in the section \autoref{randomize}. +% \begin{macrocode} +\let\saveRandomSeed\relax +\let\inputRandomSeed\relax +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \begin{macro}{\CorrectionsOn} +% \begin{macro}{\CorrectionsOff} +% Use these macros to locally turn on or off the inclusion +% of the correction code. +% \begin{macrocode} +\def\CorrectionsOn{\global\nocorrectionsfalse} +\def\CorrectionsOff{\global\nocorrectionstrue} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \subsection{Process Options and Require Packages} +% The \texttt{quiz} environments use Acrobat forms and JavaScript +% so we need to load in the AcroForm Dictionary---unless the +% \texttt{dviwindo} (\cmd{\eq@noformstrue}) option is requested. +%\changes{v6.3y}{2011/04/23}{% +% As per Heiko's suggestion, I've change the \texttt{Form} environment +% no longer creates a grouping. This was causing problems with +% the \textsf{atveryend} package. +%} +% \begin{macrocode} +\AtBeginDocument{\ifeq@noforms\else\Form\fi} +\AtEndDocument{% + \include@solutions + \ifeq@noforms\else\include@quizsolutions\fi + \clearpage + \csname endForm\endcsname +% \end{macrocode} +% (04/12/07) I put a \cs{clearpage} for some good reason, can't remember, I think +% it had to do with templates, but dvipdfm has problems with this. The document +% level JavaScript are not inserted, they are cleared out by the \cs{clearpage}. +% So, we'll only to a \cs{clearpage} if the driver is not dvipdfm. +% \begin{macrocode} + \if\eq@drivernum2\else\clearpage\fi +} +% \end{macrocode} +% \subsection{Load Configuration File: exerquiz.cfg} +% Look for configuration file, exerquiz.cfg. +%\begin{verbatim} +% \ExecuteOptions{noquizsolutions,nocorrections} +%\end{verbatim} +% sets several options. +% \begin{macrocode} +\InputIfFileExists{exerquiz.cfg}{}{} +% \end{macrocode} +% If web is already loaded, we use its driver. +% \changes{v6.4t}{2012/06/18}{Testing for pdflatex and xetex} +% \begin{macrocode} +\@ifpackageloaded{web}{% + \ExecuteOptions{\eq@driver@name}% +}{% + \ifpdf\ExecuteOptions{pdftex}\else + \ifxetex\ExecuteOptions{xetex}\else + \InputIfFileExists{web.cfg}{} + {\@ifundefined{l@tex@@@@driver}{\ExecuteOptions{dvips}} + {\ExecuteOptions{dvipsone}}}\fi\fi +} +% \end{macrocode} +% \begin{macrocode} +\ProcessOptions +% \end{macrocode} +% Input required packages. +% \changes{v7.03}{2015/03/02}{Added the \texttt{array} package, mostly +% for use in the tabular setup of parts in tabular mode.} +% \begin{macrocode} +\RequirePackage{array} +\RequirePackage{\eq@ColorPackage} +\RequirePackage{verbatim} +\RequirePackage{comment} +\RequirePackage{hyperref} +\RequirePackage{amssymb}% used for return symbols +\RequirePackage{eforms}[2012/06/20] +% \end{macrocode} +% \begin{macrocode} +\@ifundefined{eq@drivernum}{% + \PackageError{exerquiz}% + {You have not specified dvips, dvipsone, pdftex, dvipdfm, + dvipdfmx, or xetex + \MessageBreak in the option list of the exerquiz package} + {Place one of the drivers dvips, dvipsone, pdftex, dvipdfm, + dvipdfmx, or xetex + \MessageBreak in the option list of the exerquiz package.} +}{} +% \end{macrocode} +% Determine whether we have solutions at end. +% \begin{macrocode} +\@ifundefined{ifsolutionsAtEnd} + {\newif\ifsolutionsAtEnd\solutionsAtEndtrue}{} +\ifeq@nosolutions\solutionsAtEndfalse\fi +\ifeq@solutionsafter\solutionsAtEndfalse\fi +\@ifundefined{if@fleqn}{\let\fleqnOn\relax\let\fleqnOff\relax} + {\def\fleqnOn{\@fleqntrue}\def\fleqnOff{\@fleqnfalse}} +% \end{macrocode} +% \changes{v7.7o}{2016/07/08}{Added Boolean \string\cs{if@inclkey} in support of the +% \string\textsf{eq2db} package} +% \begin{macrocode} +\@ifundefined{if@inclkey}{\newif\if@inclkey\@inclkeytrue}{} +%</package> +% \end{macrocode} +% \subsection{The Template \& Language dependent messages}\label{ss:ldm} +% The following define labels and messages for the exercise and +% various quiz environments. They are all redefined when a +% language option is used. All of them can be redefined to +% customize a users document. +% +% In attempt to better manage the language localizations, I've placed the +% template for Web and Exerquiz in the Exerquiz.dtx file. +% \begin{macrocode} +%<*template> +%%------------- Instructions ------------------------------------ +%% Make your language localizations to this file and rename it to +%% something like \texttt{eq<mylang>.def}, where \texttt{<mylang>} +%% is a short 2-letter designator of the language. Test the tile +%% by inputting it in the preamble of your document +%% \input{eq<mylang>.def}. When satisfied, send it to me at +%% dpstory@uakron.edu or dpstory@acrotex.net. +%</template> +%<template>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%<template>%% Web.sty %% +%<template>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%<template>% Language dependent definitions for Web.sty +%<*template> +\DeclareOption{newlanguage}{% + \AtEndOfPackage{% + \def\today{\ifcase\month\or January + \or February \or March \or April + \or May \or June \or July \or August + \or September \or October \or November + \or December \fi \the\day, \the\year} + \def\web@versionlabel{Version} + \def\web@toc{Table of Contents} + \def\web@continued{cont.} + \def\web@article{Begin \hyperlink{section.1}{Article}} + \def\web@directory{Directory} + \def\web@revision{Last Revision Date:} + \def\web@copyright{Copyright} + \def\web@section{Section} + % Label Navibar + \def\web@back{Back} + \def\web@doc{Doc}} % restricted to three characters + \PassOptionsToPackage{newlanguage}{exerquiz} +} +%</template> +% \end{macrocode} +% \begin{macrocode} +%<template>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%<template>%% Exerquiz.sty %% +%<template>%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%<template>\DeclareOption{newlanguage}{% +%<template> \def\LangRedefinitions{\InputIfFileExists{eqlang.def}% +%<template> {\PackageInfo{exerquiz}{Inputting a New Language Option}}% +%<template> {\PackageInfo{exerquiz}{Language Option: Cannot find the file +%<template> eqpo.def, using the default, English.}}}} +%<template> +%<package>\def\eqretnSymb{$\blacksquare$}%{\rule{6bp}{6.8bp}} +% The exercise label +%<package>\newcommand\exlabel{Exercise} +%<package>\newcommand\exlabelsol{\exlabel} +%<template>% The exercise label +%<template>% Accents: \renewcommand\exlabel{\"Ubung} (German) +%<template>\renewcommand\exlabel{Exercise} +%<template>% The value of this macro is written to \jobname.sol, +%<template>% accented characters must be protected with a \protect +%<template>% E.g., \renewcommand\exlabelsol{\protect\"Ubung} (German) +%<template>\renewcommand\exlabelsol{\exlabel} +% \end{macrocode} +% \begin{macrocode} +% Title of exercise solution section +%<package>\newcommand\exsectitle{Solutions to \exlabel s} +%<package>\newcommand\exsecrunhead{\exsectitle} %% change to @ form +%<template> +%<template>% Title of exercise solution section +%<template>% E.g.: \renewcommand\exsectitle +%<template>% {L\"osungen der \exlabel en} (German) +%<template>\renewcommand\exsectitle{Solutions to \exlabel s} +%<template>\renewcommand\exsecrunhead{\exsectitle} %% change to @ form +% \end{macrocode} +% \begin{macrocode} +%<*package|eqexam> +% \end{macrocode} +% \begin{macro}{\exsolafter} +% Solution label for \texttt{solutionafter} option for exercise, this is a command +% that may be redefined. Either by a \cs{recommand} or by the use of +% \cs{renameSolnAfterTo}. +% \begin{macro}{\resetSolnAfterToDefault} +% This command resets \cs{exsolafter} to the default value. +% \begin{macro}{\exsolafterDefault} +% Takes one argument, the argument is the default value of \cs{exsolafter} +% \begin{macro}{\renameSolnAfterTo} +% This command takes one command, it redefines \cs{exsolafter}, but does +% not change the default value. +%\changes{v6.05g}{2007/01/28} +%{ +% Added to commands for use in exerquiz or in \textsf{eqexam}. They are +% \cs{renameSolnAfterTo} for conveniently changing the solution +% after label, and \cs{resetSolnAfterToDefault} for resetting +% back to the default. +%} +% \begin{macrocode} +\newcommand{\exsolafter}{\eq@exsolafterDefault} +\newcommand{\resetSolnAfterToDefault}{% + \def\exsolafter{\eq@exsolafterDefault}} +\newcommand{\exsolafterDefault}[1]{\def\eq@exsolafterDefault{#1}% + \def\exSolafterDefault{#1}\resetSolnAfterToDefault} +\exsolafterDefault{\textit{Solution}:} +\newcommand{\renameSolnAfterTo}[1]{\def\exsolafter{#1}} +\def\recoverDisplayBelow{\vskip\belowdisplayskip} +\newcommand{\adjDisplayBelow}{\vskip-\lastskip\vskip-\baselineskip} +% \ifsolutionsAtEnd\recoverDisplayBelow\fi} +\newcommand{\adjDisplayBelowPlus}{\adjDisplayBelow\recoverDisplayBelow} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +%</package|eqexam> +%<template> +%<template>% Solution label for solutionafter option for exercise +%<template>\renewcommand\exsolafter{\textit{Solution}:} +% \end{macrocode} +% \begin{macrocode} +% Title of quiz solution section +%<package>\newcommand\eq@sqslsectitle{Solutions to Quizzes} +%<package>\newcommand\sqslsectitle{\eq@sqslsectitle} +%<template> +%<template>% Title of short quiz solution section +%<template>% Example: \renewcommand\eq@sqslsectitle +%<template>% {L\"osungen der Aufgaben} (German) +%<template>\renewcommand\eq@sqslsectitle{Solutions to Quizzes} +%<template>\renewcommand\sqslsectitle{\eq@sqslsectitle} +% \end{macrocode} +% \begin{macrocode} +% Running header/section title for solutions to short quizzes +%<package>\newcommand\eq@sqslsecrunhead{Solutions to Quizzes} +% User access +%<package>\newcommand\sqslsecrunhead{\eq@sqslsecrunhead} +%<template> +%<template>% Running header/section title for solutions to short quizzes +%<template>\renewcommand\eq@sqslsecrunhead{Solutions to Quizzes} +%<template>% User access +%<template>\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} +% \end{macrocode} +% \begin{macrocode} +% Label for solutions to quizzes, appears in solutions sections +%<package>\newcommand\eq@sqsllabel{\protect\textbf{Solution to Quiz:}} +% User access +%<package>\newcommand\sqsllabel{\eq@sqsllabel} +%<template> +%<template>% Label for solutions to short quizzes, appears +%<template>% in solutions sections +%<template>% Protect accents with \protect +%<template>% E.g.: \renewcommand\eq@sqsllabel +%<template>% {\string\textbf{L\protect\"osung zu Aufgabe:}} (German) +%<template>\renewcommand\eq@sqsllabel{\string\textbf{Solution to Quiz:}} +%<template>% User access +%<template>\renewcommand\sqsllabel{\eq@sqsllabel} +% \end{macrocode} +% \begin{macrocode} +% Solution label for solutionafter option for shortquiz +%<package>\newcommand\sqsolafter{\textit{Solution}:} +%<template> +%<template>% Solution label for solutionafter option for shortquiz +%<template>\renewcommand\sqsolafter{\textit{Solution}:} +% \end{macrocode} +% \begin{macrocode} +% Here is the default short quiz label. +%<package>\newcommand{\sqDefaultFmtTitle}[1]% +%<package> {\def\eq@sqlabel{#1}\def\sqlabel{#1}} +% User access to shortquiz label +%<package>\newcommand\sqlabel{\eq@sqlabel} +%<package>\sqDefaultFmtTitle{\textcolor{red}{Quiz}} +%<template> +%<template>% User access to shortquiz label +%<template>\renewcommand\sqlabel{\eq@sqlabel} +%<template>% Here is the default short quiz label. +%<template>\sqDefaultFmtTitle{\textcolor{red}{Quiz.}} +% \end{macrocode} +% \begin{macrocode} +% Here is the default short quiz return label +% No formatting allowed +%<package>\newcommand\eq@sqslrtnlabel{\protect\eqretnSymb} +% User access to shortquiz label +%<package>\newcommand\sqslrtnlabel{\eq@sqslrtnlabel} +%<template> +%<template>% Here is the default short quiz return label +%<template>% No formatting allowed +%<template>\renewcommand\eq@sqslrtnlabel{End Quiz} +%<template>% User access to shortquiz label +%<template>\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} +% \end{macrocode} +% \begin{macrocode} +% Short quiz feedback messages +%<package>\newcommand\eqsqrtmsg{"Right!"} +%<package>\newcommand\eqsqwgmsg{"Wrong!"} +%<package>\newcommand\doNotShowAgainMsg{Do not show this message again} +%<template> +%<template>% Short quiz feedback messages +%<template>\renewcommand\eqsqrtmsg{"Right!"} +%<template>\renewcommand\eqsqwgmsg{"Wrong!"} +%<template>\renewcommand\doNotShowAgainMsg{Do not show this message again} +% \end{macrocode} +% \begin{macrocode} +% Here is the default quiz label. +%<package>\newcommand\eq@bqlabel{Begin Quiz} +% User access to quiz label +%<package>\newcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen +%<package>\newcommand\eq@bqlabelISO{\eq@bqlabel} +%<package>\newcommand\bqlabelISO{\eq@bqlabelISO} +% Default title for a quiz used for \verb!\@currentlablename! +%<package|eqexam>\newcommand\setDefShortQuizLabelName[1]% +%<package|eqexam> {\def\eq@defaultShortQuizLabelName{#1}} +%<package|eqexam>\setDefShortQuizLabelName{Quiz} +%<package>\newcommand\setDefQuizLabelName[1] +%<package> {\def\eq@defaultQuizLabelName{#1}} +%<package>\setDefQuizLabelName{Quiz} +%<template> +%<template>% Here is the default quiz label. +%<template>% No formatting allowed +%<template>% For Example: \renewcommand\eq@bqlabel{D\'ebut} (French) +%<template>\renewcommand\eq@bqlabel{Begin Quiz} +%<template>% User access to shortquiz label +%<template>\renewcommand\bqlabel{\eq@bqlabel} +%<template>% Used for writing JavaScript Messages on screen. +%<template>% Use PDFDocEncoding +%<template>% For Example: +%<template>% \renewcommand\eq@bqlabelISO{D\string\351but} (French) +%<template>% Use \string not \protect, this helps out +%<template>% TeX4ht by Eitan Gurari. +%<template>\renewcommand\eq@bqlabelISO{\eq@bqlabel} +%<template>\renewcommand\bqlabelISO{\eq@bqlabel} +%<template>% Default title for a quiz used for \verb!\@currentlablename! +%<template>\setDefShortQuizLabelName{Quiz} +%<template>\setDefQuizLabelName{Quiz} +% \end{macrocode} +% \begin{macrocode} +% Here is the default quiz label. +% No formatting allowed +%<package>\newcommand\eq@eqlabel{End Quiz} +% User access to quiz label +%<package>\newcommand\eqlabel{\eq@eqlabel} +%<template> +%<template>% Here is the default quiz label. +%<template>% No formatting allowed +%<template>\renewcommand\eq@eqlabel{End Quiz} +%<template>% User access to shortquiz label +%<template>\renewcommand\eqlabel{\eq@eqlabel} +% \end{macrocode} +% \begin{macrocode} +% JavaScript Messages for Quiz Environments +%<package>\newcommand\eq@Score{Score:}\newcommand\eq@OutOf{out of} +%<package>\newcommand\eq@ptScore{Score:} +%<package>\newcommand\stOutOf{of} +%<package>\newcommand\eqScore{\eq@Score}\newcommand\eqOutOf{\eq@OutOf} +%<package>\newcommand\eqptScore{\eq@ptScore} +%<template> +%<template>% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +%<template>% Note: Use \string rather than \protect for escape codes, +%<template>% i.e. \string\374 +%<template>% +%<template>% In the Text Field showing the score, there is the default +%<template>% phrase in English +%<template>% Score: 2 out of 3, the word "Score" and "out of" needs +%<template>% translation. +%<template>\renewcommand\eq@Score{Score:}\renewcommand\eq@OutOf{out of} +%<template>\renewcommand\eq@ptScore{Score:} +%<template>% used in summary tables +%<template>\renewcommand\stOutOf{of} +% \end{macrocode} +% \begin{macrocode} +%<package>\newcommand\eqInitQuizMsg{% +%<package> "You must initialize the Quiz! Click on "+msg+"."} +%<template>% If you are taking a quiz and click on an alternative without +%<template>% initializing the quiz +%<template>% first, this message appears. +%<template>% This string is placed in the DLJS, so the escape sequences +%<template>% need to be protected more. Instead of \string\340 we need +%<template>% \string\\340. +%<template>% Example: \renewcommand\eqInitQuizMsg{% (German) +%<template>% "Sie m\string\\374ssen die Aufgaben initialisieren! +%<template>% Bitte klicken Sie auf "+msg+"."} +%<template>\renewcommand\eqInitQuizMsg{% +%<template> "You must initialize the Quiz! Click on "+msg+"."} +% \end{macrocode} +% \begin{macrocode} +%<package>\newcommand\eqQuizTotalMsg{% +%<package> "\eqScore\space"+Score+" \eqOutOf\space"+nQuestions} +%<package>\newcommand\eqQuizPointsMsg{% +%<package> "\eqptScore\space"+ptScore+" \eqOutOf\space"+nPointTotal} +%<package>\newcommand\eqQuizPercentMsg{pcScore+"\%"} +%<package>\newcommand\eqQuizGradeMsg{quizGrade} +%<template> +%<template>% This macro doesn't usually need translation, it uses \eqScore +%<template>% and \eqOutOf. However, if the sentence "Score: 2 out of 3" +%<template>% does not translate conveniently into a particular language, +%<template>% this macro may have to be modified. It's the one that puts +%<template>% the message in the message box. +%<template>\renewcommand\eqQuizTotalMsg +%<template> {"\eqScore\space"+Score+" \eqOutOf\space"+nQuestions} +%<template>\renewcommand\eqQuizPointsMsg{% +%<template> "\eqptScore\space"+ptScore+" \eqOutOf\space"+nPointTotal} +%<template>\renewcommand\eqQuizPercentMsg{pcScore+"\%"} +%<template>\renewcommand\eqQuizGradeMsg{quizGrade} +% \end{macrocode} +% \begin{macrocode} +%<package>\newcommand\eqMadeChoice{% +%<package> "You have already made a choice." +%<package> + " Your choice was ("+Responses[probno]+")." +%<package> + " Do you want to change it?"} +%<template> +%<template>% In the link form of a quiz, of you change your choice, +%<template>% this message appears. This string is placed in the +%<template>% DLJS, so the escape sequences need to be protected more. +%<template>% Instead of \string\340 we need \string\\340. +%<template>% For Example: \renewcommand\eqMadeChoice{% +%<template>% "Vous avez d\string\\351j\string\\340 fait un choix, +%<template>% ce choix est ("+Responses[probno]+"). +%<template>% Souhaitez vous le modifier ?"} (French) +%<template>\renewcommand\eqMadeChoice{% +%<template> "You have already made a choice. +%<template> Your choice was ("+Responses[probno]+"). +%<template> Do you want to change it?"} +% \end{macrocode} +% Default language phrases used by \cmd{\eqButton}. These are overwritten by the +% language options. +% \begin{macrocode} +%<package>\newcommand\eq@local@CA{Correct} +%<package>\newcommand\eq@local@RC{My Answers!} +%<package>\newcommand\eq@local@AC{Please!} +%<template>% Default button labels for \eqButton +%<template>% Accents are handled as above: +%<template>% A French Language Example +%<template>% \renewcommand\eq@local@CA{R\string\351ponses} +%<template>% \renewcommand\eq@local@RC{Correctes} +%<template>% \renewcommand\eq@local@AC{SVP !} +%<template>\renewcommand\eq@local@CA{Correct} +%<template>\renewcommand\eq@local@RC{My Answers!} +%<template>\renewcommand\eq@local@AC{Please!} +% \end{macrocode} +% Default language phrases used by \cmd{\CorrAnsButton}. These are overwritten by the +% language options. +% \begin{macrocode} +%<package>\newcommand\eq@local@CorrAnsButton{Ans} +%<template> +%<template>% Default button label of \CorrAnsButton. +%<template>\renewcommand\eq@local@CorrAnsButton{Ans} +%<package>\newcommand{\eq@local@sqClearButton}{Clear} +%<template>% Default button label of \sqClearButton +%<template>\renewcommand{\eq@local@sqClearButton}{Clear} +%<template>% Short string used by the \PromptButton +%<template>\renewcommand{\AnsPromptBtnStr}{Answer:\space} +% \end{macrocode} +% The following are (error) messages generated from the math fill-in questions. +% \begin{macrocode} +%<*package> +\newcommand\eqerrABS{"Absolute values not balanced. Please correct."} +\dlJSStr[noquotes]\eqerrBadMathFunc{"The expression \""+aF[i] + +"\" is neither a defined function nor a valid math expression."} +\newcommand\eqParens{"Parentheses"} +\newcommand\eqBrackets{"Brackets"} +\newcommand\eqBraces{"Braces"} +\newcommand\eqerrDelimNotBal{aGroup[i][2] + " not balanced. + Please correct."} +\newcommand\eqerrBadExp{"Invalid mathematical expression. + A problem with one of the exponents. Please correct."} +\newcommand\eqerrUnfinishQuiz{"There is an unfinished quiz, + please finish before moving on to another."} +\newcommand\noPeekMsg{"Viewing Solutions to quizzes is not allowed + until you take or finish this quiz!"} +\newcommand\highThresholdMsg{"You are required to respond to all + questions before the quiz is evaluated."} +\newcommand\eqSyntaxErrorUndefVar{"Syntax Error: Possibly an undefined + variable present, or an expression is not written in an expected + format."} +\dlJSStr[noquotes]{\eqSyntaxErrorComma}{% + "Syntax Error: A comma was found" + + " in your response \"" + + UserAns + "\". Please remove the comma, or this answer" + + " will be marked as wrong."} +\newcommand{\limSelWarningMsg}{"For this question, you are allowed to + make at most " + n + " selections."} +\newcommand{\defaultReqFormMsg}{% + "The expression is not in the expected form."} +%</package> +%<template> +%<template>% These (error) messages are generated when the user enters an +%<template>% invalid math expression into a math fill-in response box. +%<template>% The messages come in the form of an eqAppAlert() so +%<template>% PDFDocEncoding needs to be used. +%<*template> +\renewcommand\eqerrABS{"Absolute values not balanced. Please correct."} +\renewcommand\eqerrBadMathFunc{"The expression \""+aF[i]+"\" is neither + a defined " +"function, nor a valid math expression."} +\renewcommand\eqParens{"Parentheses"} +\renewcommand\eqBrackets{"Brackets"} +\renewcommand\eqBraces{"Braces"} +\renewcommand\eqerrDelimNotBal{aGroup[i][2] + " not balanced. + Please correct."} +\renewcommand\eqerrBadExp{"Invalid mathematical expression. + A problem with one of the exponents. Please correct."} +\renewcommand\eqerrUnfinishQuiz{"There is an unfinished quiz, + please finish before moving on to another."} +\renewcommand\noPeekMsg{"Viewing Solutions to quizzes is not allowed + until you take or finish this quiz!"} +\renewcommand\highThresholdMsg{"You are required to respond to all + questions before the quiz is evaluated."} +\renewcommand\eqSyntaxErrorUndefVar{"Syntax Error: Possibly an + undefined variable present."} +\newcommand{\eqSyntaxErrorComma}{"Syntax Error: A comma was found" + + " in your response \\"" + + UserAns + "\\". Please remove the comma, or this answer" + + " will be marked as wrong."} +\renewcommand{\limSelWarningMsg}{"For this questions, you are allowed to + make at most " + n + " selections."} +\renewcommand{\promptButtonMsg}{% + "Would you like to see the correct answer at this time? " + + "Your current answer will be the one that will be scored. " + + "If you click on \\"Yes\\", + you will not be able to change your answer." +} +\renewcommand{\defaultReqFormMsg}{% + "The expression is not in the expected form."} +\renewcommand\eqAnd{and} +%</template> +%<*template> +%%%%%%%%%%%%%%%%%%%%%% End Message Section %%%%%%%%%%%%% +%% Some typeout messages %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% In exerquiz.sty +\typeout{Inputting French Option} +\typeout{French Option: Cannot find the file eqfr.def, using the + default, English.} +\typeout{Solutions not allowed with this option} +\typeout{Check: `#1' is not an acceptable option, inserting + default, `check'.} +%</template> +% \end{macrocode} +% +% Announce driver option +% \begin{macrocode} +%<*package> +\typeout{^^Jexerquiz: * Using \eq@driver\space option *^^J} +% \end{macrocode} +% \subsection{Handles, counters and such} +% Handles to write solutions to quizzes and exercises to a file. +% \begin{macrocode} +%</package> +%<*package|eqexam> +\ifsolutionsonly +\InputIfFileExists{\jobname_xdefs.cut}{% + \typeout{^^JExerquiz|Eqexam: Reading \jobname_xdefs.cut^^J}} + {\PackageWarningNoLine{exerquiz|eqexam}{% + \jobname_xdefs.cut not found.\MessageBreak + Recompile file under the vspacewithsolns\MessageBreak + option, then compile with the solutionsonly\MessageBreak + option}} +\else +\newwrite\ex@solns \immediate\openout \ex@solns \jobname.sol +\newcommand{\writeToExSolns}[1]{% + \set@display@protect + \immediate\write\ex@solns{#1}% + \set@typeset@protect +} +% \end{macrocode} +% If we are not in \cs{ifsolutionsonly} mode, we write some definitions to a .def +% file to be read back in at the beginning of the document. +% \begin{macrocode} +\newwrite\eq@xrefdefns \immediate\openout\eq@xrefdefns\jobname_xdefs.cut +\fi +\newwrite\quiz@solns \immediate\openout \quiz@solns \jobname.qsl +\newcommand{\writeToQzSolns}[1]{% + \set@display@protect + \immediate\write\quiz@solns{#1}% + \set@typeset@protect +} +\def\eq@IWAuxOut#1{\immediate\write\@auxout{#1}} +\def\eq@IWDefs#1{\immediate\write\eq@xrefdefns{#1}} +% \end{macrocode} +% Counters to keep track of exercise questions. +% \begin{macrocode} +\newcounter{eqexno} \setcounter{eqexno}{0} +\newcounter{@exno} \setcounter{@exno}{0} % running exno +% \end{macrocode} +% Counter to keep track of quiz questions. +% \begin{macrocode} +\newcounter{quizno} \setcounter{quizno}{0} +\renewcommand\thequizno{\alph{quizno}} +%</package|eqexam> +%<*package> +\def\theHquizno{\curr@quiz.\theeqquestionnoi.% + \ifcase\@eqquestiondepth\or\or\arabic{eqquestionnoii}.% + \or\arabic{eqquestionnoii}.\roman{eqquestionnoiii}.% + \else\fi\alph{quizno}} +% \end{macrocode} +% (2016/05/17) \cs{eqemargin} is used in \textsf{eqexam}, but some calculations use it for the list version of +% answers. We declare this length to be 0pt. The \textsf{eqexam} resets this value. +% \begin{macrocode} +\newlength\eqemargin \eqemargin=0pt +% \end{macrocode} +% \begin{macrocode} +%</package> +%<*package|eqexam> +% \end{macrocode} +% Keep track of point values of quizzes +% \begin{macrocode} +\newcounter{eqpointvalue} \setcounter{eqpointvalue}{0} +% \end{macrocode} +% Some scratch registers and boxes. +% \begin{macrocode} +\newlength\eq@tmplength +\newlength\eqtmplength +% \end{macrocode} +% \begin{macro}{eqquestionno} +% The counter that keeps track of the question number. +% Used by the \texttt{questions environment} +% \begin{macrocode} +\newcounter{questionno} +\newcounter{eqquestionnoi} +\newcounter{eqquestionnoii} +\newcounter{eqquestionnoiii} +\newcount\@eqquestiondepth \@eqquestiondepth=0 +% \end{macrocode} +% \begin{macrocode} +%</package|eqexam> +%<*package> +\newcounter{grpquestionno} +%</package> +% \end{macrocode} +% \end{macro} +% \begin{macro}{partno} +% This counter keeps track of the parts of an exercise, when the *-option +% is used. +% \begin{macrocode} +%<*package|eqexam> +\newcounter{partno} +% \end{macrocode} +% (2017/01/11) Added \DescribeMacro{\numberParts}\cs{numberParts} to change how this counter is displayed +% as a number. The default is \DescribeMacro{\alphaParts}\cs{alphaParts} to display the \texttt{partno} +% counter as a letter. +%\begin{verbatim} +% \renewcommand{\partnoFmt}{\arabic} +% \setPartsWidth{(00)} +% \partsformat{\makebox[\widthOfParts][c]{(\hfil\thepartno\hfil)}} +%\end{verbatim} +% With this code, the items in the \texttt{parts} environment are numbered. +% \changes{v7.8d}{2017/01/11}{Added \string\cs{partnoFmt} to change how this counter is displayed} +% \begin{macrocode} +\newif\ifuseNumForParts\useNumForPartsfalse +\def\alphaParts{\def\partnoFmt{\alph}\useNumForPartsfalse}\alphaParts +\def\numberParts{\def\partnoFmt{\arabic}\useNumForPartstrue} +\renewcommand\thepartno{\partnoFmt{partno}} +\newtoks\eq@scratchtoks +%</package|eqexam> +%<*package> +\def\theHpartno{partno\the@exno\thepartno} +%</package> +%<*package|eqexam> +% \end{macrocode} +% \end{macro} +% \subsection{Write to a file} +% We must have a way to write the solutions of our exercises and +% quizzes to a file. The following \cmd{\verbatimwrite} was +% taken from the \texttt{moreverb} package, it uses the +% \texttt{verbatim} package. +% +% \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} +% \section{The \texttt{exercise} Environment} +% +% We use \cmd{\raggedright} within a \texttt{tabular} environment, +% so we must use a little trick, illustrated in the \textsl{\LaTeX\ +% Companion} by M. Goossens et al. This macro is used with \texttt{exercise} +% with parts, \texttt{shortquiz} and \texttt{quiz} environments. +% \begin{macrocode} +\providecommand\PBS[1]{\let\temp=\\#1\let\\=\temp} +%</package|eqexam> +%<*package> +% \end{macrocode} +% Define some formatting commands. These can all be redefined to +% customize the document. +% \begin{macro}{\exlabelformat} +% This is the formatted label for the exercise environment. +% \begin{macrocode} +\newcommand\exlabelformat{{\scshape\exlabel\ \theeqexno.}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\exlabelformatwp} +% This is the formatted label for the exercise environment with parts. +% When an exercises has parts, the word `Exercise' is not a link, +% so we color this word for emphasis. +% \begin{macrocode} +%\newcommand\exlabelformatwp{{\scshape\exlabel\ \theeqexno.}} +\newcommand\exlabelformatwp{\exlabelformat} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\exsllabelformat} +% This is the formatted solution label. +% \begin{macrocode} +\newcommand\exsllabelformat{\protect\textbf{\exlabelsol\ \theeqexno.}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\exsllabelformatwp} +% This is the formatted solution when the *-options is use, that is, +% when there are multiple parts to the question. +% \begin{macrocode} +\newcommand\exsllabelformatwp + {\protect\textbf{\exlabelsol\ \theeqexno(\thepartno)}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\exrtnlabelformat} +% This is the formatted return label (return from the solution). +% \begin{macrocode} +\newcommand\exrtnlabelformat{$\square$} +%\newcommand\exrtnlabelformat{\exlabelsol\ \theeqexno} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\exrtnlabelformat} +% This is the formatted return label (return from the solution), +% for an exercise with parts. +% \begin{macrocode} +\newcommand\exrtnlabelformatwp{$\square$} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\aboveexskip} +% \begin{macro}{\belowexskip} +% Amount of skip before and after exercise environment +% \begin{macrocode} +%</package> +%<*package|eqexam> +\newcommand{\belowexskip}[1]{\setlength{\eq@tmplength}{#1}% + \edef\eq@exerskip{\noexpand\removelastparskip + \noexpand\vskip\the\eq@tmplength\relax\kern0pt}} +\let\eqexerskip\belowexskip +\belowexskip{\medskipamount} +\newcommand{\aboveexskip}[1]{\setlength{\eq@tmplength}{#1}% + \edef\eq@priorexskip{\noexpand\vskip\the\eq@tmplength\relax + \kern0pt}} +\let\priorexskip\aboveexskip +\aboveexskip{\medskipamount} +\let\eq@postexerciseHook\relax +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\belowexsolnskip} +% Amount of skip after solutions, this one is written to a file, so +% we must protect it from early expansion. +% \begin{macrocode} +\newcommand\belowexsolnskip{\protect\medskip} +%\let\eqafterexersolnskip\belowexsolnskip +% \end{macrocode} +% \changes{v7.4}{2015/03/23}{added \cmd\removelastparskip} +% \DescribeMacro\removelastparskip removes last \cmd\parskip, as needed. +% \begin{macrocode} +\def\removelastparskip{\ifdim\parskip>0pt\vskip-\parskip\fi} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \begin{macro}{\nolinkcolor} +% This is the color to paint the word 'Exercise' with parts; +% or it colors all the 'Exercise's when the nosolutions option +% has been used +% \changes{v6.05a}{2006/05/08} +% { +% Changed \cs{nolinkcolor} into a text fill-in. Now, the command \cs{nolinkcolor} +% fills in \cs{@nolinkcolor}, which holds the named color. +% } +% \begin{macrocode} +\newcommand{\nolinkcolor}[1]{\def\@nolinkcolor{#1}} +\nolinkcolor{blue} +% \end{macrocode} +% \end{macro} +% \subsection{Define \texttt{exercise} Environment} +% Defines the \texttt{exercise} environment for writing exercises, +% and solutions. The solutions are written to the file +% \cmd{\jobname.sol}, and input at the end of the file. Hypertext +% links connect the statement of the exercise with its solution. +% +%\smallskip\noindent\textbf{Basic usage} +%\begin{verbatim} +%\begin{exercise} +%The exercise question is posed. +%\begin{solution} +%The solution to exercise goes here. +%\end{solution} +%\end{exercise} +%\end{verbatim} +% These environments should be nested as illustrated above. +% +% The \texttt{exercise} environment has three optional arguments. The syntax +% for an exercise without parts is\dots +%\begin{verbatim} +% \begin{exercise}[<ctr>][h|H] ...\end{exercise} +%\end{verbatim}% +% +% (1) The value of this first optional argument, \texttt{<ctr>}, is a counter. +% You can use the \texttt{exercise} +% environment then to create other environments with their own +% counters. A special value of zero (0) for this optional argument, +% means not to associate any counter with the environment. These +% features can be used in combination with the \cs{SolutionsAfter} +% and \cs{SolutionsAtEnd} commands to obtain different effects, +% see the manual for examples +% +% (2) The second optional argument is an `\texttt{h}' or an \texttt{H}, this signals that the +% solution to the exercise should not be written to the \cmd{\jobname.sol} +% file. See manual for examples. +% +% The \texttt{exercise} environment has three optional arguments. The syntax +% for an exercise with parts is\dots +%\begin{verbatim} +% \begin{exercise}[<ctr>]* ...\end{exercise} +% \begin{exercise*}[<ctr>] ...\end{exercise*} +%\end{verbatim}% +% +% (1) The value of this first optional argument, \texttt{<ctr>}, is a counter. +% You can use the \texttt{exercise} +% environment then to create other environments with their own +% counters. A special value of zero (0) for this optional argument, +% means not to associate any counter with the environment. These +% features can be used in combination with the \cs{SolutionsAfter} +% and \cs{SolutionsAtEnd} commands to obtain different effects, +% see the manual for examples +% +% (2) The second argument is a star \texttt{*}. The presence of a * signals +% that this exercise has multiple parts. See the manual for the proper +% syntax. +% +% Beginning with version 6.07, there is now a \texttt{exercise*} +% environment, this is what I should have done originally, but now its +% done. The \texttt{exercise*} signals an exercise with parts. It takes +% one optional parameter, the name of a counter \texttt{<ctr>} that is to +% be used. +% \begin{macro}{\exerSolnInExtFile} +% With the exercises, you have the option of including them in the main document, or putting them +% in an external document. The \cs{exerSolnsInExtFile} command lets you specify an external file name. +% Just use the \textit{basename}, hyperref will add the extension. If an external file is specified, all +% solution links are changed to links between documents. Usage: +%\begin{verbatim} +%\exerSolnsInExtFile{myExSonls} +%\end{verbatim} +% \begin{macrocode} +\newcommand{\exerSolnsInExtFile}[2][] + {\let\exerSolns@ExtFile\eq@YES\gdef\eq@exerSolns@fileName{#2}% + \gdef\exerSolns@ReturnPath{#1}} +\let\exerSolns@ExtFile\eq@NO +\def\exerSolns@ReturnPath{} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +%</package> +%<*package|eqexam> +% \end{macrocode} +%\DescribeMacro{\marginparpriorhook}\DescribeMacro{\marginparafterhook} +%\DescribeMacro{\afterlabelhskip} Various hooks into an exercise. +% \begin{macrocode} +\let\marginparpriorhook\@empty % used to material before the exercise +\let\marginparafterhook\@empty % used to material after the exercise +\let\afterlabelhskip\space +% \end{macrocode} +% \DescribeMacro{\exersolnheadhook} +% Inserted in the header of each exercise solution. May be used for inserting +% addition text or macros in the solution. +% \begin{macrocode} +\let\exersolnheadhook\@empty +\let\exer@solnheadhook\@empty +% \end{macrocode} +% \begin{macro}{\eqexheader} +% \begin{macro}{\eqexheader@wrapper} +% \cs{eqexheader} typesets `Exercise xx'. \cs{eqexheader@wrapper} creates a hypertarget +% at the heading. Portions of \cs{eqexheader} is also used by \textsf{eqExam}. +% \begin{macrocode} +\newcommand{\eqexheader} +{% +%</package|eqexam> +%<*package> + \ifeq@nolink % no link to solution +%</package> +%<*package|eqexam> + \mbox{\color{\@nolinkcolor}\if\exerstar*\exlabelformatwp\else + \exlabelformat\fi}% +%</package|eqexam> +%<*package> + \else + \if\exerSolns@ExtFile\eq@YES + \mbox{\href{\eq@exerSolns@fileName\#ex.\the@exno}% + {\exlabelformat}}% + \else + \mbox{\hyperlink{ex.\the@exno}{\exlabelformat}}% + \fi + \fi +%</package> +%<*package|eqexam> +} +\def\eqexheader@wrapper{\hypertarget{qex.\the@exno}{\eqexheader}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\eqexlisttabheader} +% \cs{eqexlisttabheader} typesets `(a)' when we have exercises with parts. +% Portions are also used by \textsf{eqExam}. +% \begin{macrocode} +\newcommand{\partsformat}[1]{\def\eq@partsformat{#1}} +\partsformat{(\hfil\thepartno\hfil)} +\newcommand{\defaultpartsformat}{% + \partsformat{(\hfil\thepartno\hfil)}} +\let\exlisttabheaderpriorhook\@empty +\let\exlisttabheaderafterhook\@empty +\newcommand{\eqexlisttabheader} +{% + \exlisttabheaderpriorhook +%</package|eqexam> +%<*package> + \ifeq@nolink +%</package> +%<*package|eqexam> + \color{\@nolinkcolor}\eq@partsformat +%</package|eqexam> +%<*package> + \else + \if\exerSolns@ExtFile\eq@YES + \href{\eq@exerSolns@fileName\#ex.\the@exno\thepartno}% + {\eq@partsformat}% + \else + \hyperlink{ex.\the@exno\thepartno}{\eq@partsformat}% + \fi + \fi +%</package> +%<*package|eqexam> +} +% \end{macrocode} +% \end{macro} +% Introduce a method of copying questions from \env{exercise} environment to solution page. The \env{cq@CQ} +% is \cs{let} to the \env{cq} environment, only defined within the \env{exercise} environment. +% \changes{v7.8}{2016/11/02}{Added support to copy questions in the exercise environment to solution pages.} +% \begin{macrocode} +\newcount\cq@Cnt +\def\cq@CutName{cq-\the\cq@Cnt.cut} +% \end{macrocode} +% \begin{environment}{cq} +% The \env{cq} environment is \cs{let} to the \env{cq@CQ} environment at the beginning of +% the \env{exercise} environment, \env{cq@CQ} begin the internal name of the environment. +% \par\medskip\noindent\textbf{Example} +%\begin{verbatim} +% \begin{exercise} +% \begin{cq} +% This is the question +% \end{cq} +% \begin{solution} +% This is its solution +% \end{solution} +% \end{exercise} +%\end{verbatim} +% \begin{macrocode} +\let\cq@star\eq@NO +% \end{macrocode} +% We declare a new switch \cs{ifcqs} +% \changes{v7.8}{2016/11/02}{Added code to copy questions of exercises to +% the solution page} +% \begin{macrocode} +\newif\ifcqqs \cqqstrue +\newif\ifcqIsActive \cqIsActivefalse +\def\cqQS{\@ifstar{\cqQSV}{\cqQSA}} +\def\cqQSA#1#2{\ifcqqs#1\else#2\fi} +% \end{macrocode} +% Also defined in the \pkg{web} package. +% \begin{macrocode} +\@ifpackageloaded{web}{\@ifundefined{IF@AorBswitch}{% + \PackageWarningNoLine{A version of the web package + dated\MessageBreak 2016/11/03 or later is required + for \string\cqQS}}}{}% +\@ifundefined{webtempboxi}{\newbox\webtempboxi + \newbox\webtempboxii}{} +\providecommand\SHOWTEMPBOXi{\unhbox\webtempboxi} +\providecommand\TRUEACTIONi{\aftergroup\SETTEMPBOXii} +\providecommand\TRUEACTIONia{\aftergroup\SHOWTEMPBOXi} +\providecommand\FALSEACTIONii{\aftergroup\SETTEMPBOXi} +\providecommand\FALSEACTIONiia{\aftergroup\SHOWTEMPBOXi} +\providecommand\SETTEMPBOXi{\IF@AorBswitch\else + \afterassignment\TRUEACTIONia\fi + \setbox\webtempboxi=\hbox} +\providecommand\SETTEMPBOXii{\IF@AorBswitch + \afterassignment\FALSEACTIONiia\fi + \setbox\webtempboxii=\hbox} +\def\cqQSV{\let\IF@AorBswitch\ifcqqs + \IF@AorBswitch + \def\eq@next{\afterassignment\TRUEACTIONi\SETTEMPBOXi}\else + \def\eq@next{\afterassignment\FALSEACTIONii\SETTEMPBOXii}\fi + \eq@next} +\def\eq@turnMessageOff{\let\save@message\message + \let\message\@gobble} +\def\eq@turnMessageOn{\let\message\save@message} +\def\eqCQDeclarations{\cqqsfalse\eq@turnMessageOff + \includecomment{sPage}\excludecomment{qPage}% + \eq@turnMessageOn} +\def\eqTopOfSolnPage{\cqSAfalse + \eqCQDeclarations} +\eq@turnMessageOff +\includecomment{qPage}\excludecomment{sPage} +\eq@turnMessageOn +%</package|eqexam> +%<*package> +\def\writecqQSfalse{\writeToExSolns{\protect\eqTopOfSolnPage}} +\AtBeginDocument{\writecqQSfalse} +%</package> +%<*package|eqexam> +\newenvironment{cq@CQ} +{% +% \end{macrocode} +% Begin verbatim write, the listing is saved to \cs{cq@CutName}, indexed by +% \cs{cq@Cnt}. +% \begin{macrocode} + \global\cqIsActivetrue + \global\advance\cq@Cnt1\relax + \immediate\openout\CommentStream=\cq@CutName + \let\verbatim@out\CommentStream + \verbatimwrite +}{% + \endverbatimwrite + \immediate\closeout\CommentStream +% \end{macrocode} +% Close out the stream, define \cs{cq@INPUTCUT}, which is then input back in +% after the end of the group. +% \begin{macrocode} + \ifx\cq@star\eq@YES + \xdef\cq@INPUTCUT{\noexpand\cqqstrue + \noexpand\input{\cq@CutName}\noexpand + \def@QuesToSoln}\else + \xdef\cq@INPUTCUT{\noexpand\cqqstrue + \noexpand\input{\cq@CutName}\noexpand + \p@ssQuesToSoln}\fi + \aftergroup\cq@INPUTCUT +} +% \end{macrocode} +% \end{environment} +% \begin{environment}{cq*} +% The \env{cq*} version of \env{cq}; within the \env{exercise} environment \env{cq*} +% is \cs{let} to \env{cqs@CQ}. This version does not automatically paste the question +% into the solution, instead, the command \cs{cqCopiedQues} is defined for that solution, +% which expands to the question statement. +% \begin{macrocode} +\newenvironment{cqs@CQ}{\let\cq@star\eq@YES\cq@CQ}{\endcq@CQ} +% \end{macrocode} +% \end{environment} +% The default formatting on the solution page is, when \env{cq} is used, +%\begin{flushleft} +%\textbf{Exercise 1.} \emph{Question}: This is the question +%\medskip\par +%\emph{Solution}: This is its solution +%\end{flushleft} +%The word `Question' may be localized using \cs{declCQQuesStr}\DescribeMacro{\declCQQuesStr}, the default is +%seen below. The word `Solution' can be localized with \cs{declCQSolStr}\DescribeMacro{\declCQSolStr}, the default is seen below. +% \begin{macrocode} +\def\declCQQuesStr#1{\def\cqQStr{#1}} +\declCQQuesStr{Question} +\def\declCQSolStr#1{\def\cqSStr{#1}} +\declCQSolStr{Solution} +% \end{macrocode} +% Aside from the words `Question' and `Solution', the way these two are formatting is determined +% through \cs{declCQPre}\DescribeMacro{\declCQPre} and \cs{declCQPost}\DescribeMacro{\declCQPost}. +% These declarations are seen below. The \cs{declCQPost} is more complicated in that it handles the +% formatting after the copied question; in the default definition, we skip a \cs{medskip} and do a \cs{indent}. +% Trailing the string \cs{cqSStr}, the internal command defined by \cs{declCQSolnStr}, is a space and +% an \cs{ignorespaces}. Use \cs{writeToExSolns} to make local changes, for example, +%\begin{verbatim} +%... +%\end{exercise} +% Changed the string from Solution to Answer, do this prior to the +% exercise. +%\writeToExSolns{\protect\declCQSolStr{Answer}} +% +%\begin{exercise*} +%... +%\end{verbatim} +%Best placed between exercises. +% \begin{macrocode} +\newcommand\declCQPre[1]{\def\cq@Pre{#1}} +\declCQPre{\emph{\cqQStr}:\space} +\newcommand\declCQPost[1]{\def\cq@Post{#1}} +\declCQPost{\par\medskip\noindent\emph{\cqSStr}:\space\ignorespaces} +% \end{macrocode} +% The command \cs{cqFmtPasteQues}\DescribeMacro{\cqFmtPasteQues} inputs the copied question text, +% along with \cs{cq@Pre} to the left and \cs{cq@Post} to the right. This command is normally +% not redefined. +% \begin{macrocode} +\def\cqFmtPasteQues#1{\cq@Pre\input{#1}\cq@Post} +% \end{macrocode} +% The command \cs{p@ssQuesToSoln} does the work of formatting the question that is pasted +% to the solution page. It is executed at the end of the \env{cq} environment. +% \begin{macrocode} +\def\p@ssQuesToSoln{\ifeq@hidesolution\else +% \end{macrocode} +% Inform the system that the definition of \cs{eqterminex} is changing. This to prevent +% writing the same line multiple times. +% \begin{macrocode} + \global\terminexchangedtrue % dps cq + \writeToExSolns{\protect + \decleqterminex{\protect\cqFmtPasteQues{\cq@CutName}}}\fi} +\def\declCopyQues#1{\def\cqCopiedQues{#1}} +\def\def@QuesToSoln{\restoreNormalSolns +% \end{macrocode} +% Here we restore \cs{eqterminex} to its default value, we set the stitch to false. +% \begin{macrocode} + \global\terminexchangedfalse % dps cq + \ifeq@hidesolution\else\writeToExSolns{\protect + \declCopyQues{\protect\input{\cq@CutName}}}\fi} +% \end{macrocode} +% \cs{restoreNormalSolns}\DescribeMacro{\restoreNormalSolns} restores \cs{eqterminex} to its +% default definition. It is place between exercises. +% \begin{macrocode} +\newcommand\restoreNormalSolns{% + \writeToExSolns{\protect\decleqterminex{\protect\eqterminexDEF}}} +% \end{macrocode} +% \begin{environment}{exercise} +% With some of the preliminaries out of the way, we begin the exercise `environment'. +% \begin{macrocode} +\newcommand{\eq@CommonCmd}[1]{\def\eq@@CommonCmd{#1}#1} +\let\eq@@CommonCmd\@empty +\newcommand\gExCommonCmd[1]{\gdef\gEx@CommonCmd{\eq@CommonCmd{#1}}} +\let\gEx@CommonCmd\@empty +\let\endexerhook\@empty +\newenvironment{exercise} +{% + \let\cq\cq@CQ\let\endcq\endcq@CQ + \csarg\let{cq*}\cqs@CQ + \csarg\let{endcq*}\endcqs@CQ + \par\removelastskip\eq@priorexskip\noindent + \let\eqCommonCmd\eq@CommonCmd + \def\eq@argi{eqexno}%% use eqexno counter + \if\eq@exerstarEnv*\def\exerstar{*}\else\def\exerstar{x}\fi + \def\currhideopt{x}% + \@ifnextchar[{\exercise@}% + {\if\exerstar*\def\eq@next{\@exercise}\else + \def\eq@next{\exercise@@}\fi\eq@next}% +}{\eq@postexerciseHook\endexerhook\par + \global\eq@exerciseheadingtrue\removelastskip\eq@exerskip} +% \end{macrocode} +% the exercise environment takes two sets of optional parameter, +% the first one is a counter (or 0) and second one is either \texttt{h} or \texttt{H}. +% \begin{macrocode} +\def\exercise@[#1]{\edef\eq@arg{#1}% + \if\eq@arg h\def\currhideopt{h}% + \eq@hidesolutiontrue\eq@nolinktrue% + \ifeq@globalshowsolutions + \eq@hidesolutionfalse\eq@nolinkfalse\fi + \def\eq@next{\@exercise}% h, no *, no counter + \else + \if\eq@arg H% + \edef\currhideopt{\Hidesymbol}% + \eq@hidesolutiontrue\eq@nolinktrue% + \ifeq@globalshowsolutions + \eq@hidesolutionfalse\eq@nolinkfalse + \fi + \def\eq@next{\@exercise}% H, no *, no counter + \else + \def\currhideopt{x}% + \ifx\eq@arg\@empty\else\def\eq@argi{#1}\fi + \if\exerstar*\def\eq@next{\@exercise}\else + \def\eq@next{\exercise@@}\fi + \fi + \fi +\eq@next} +% \end{macrocode} +% Specified counter, test for * +% \begin{macrocode} +\def\exercise@@{\@ifstar{\def\exerstar{*}\@exercise}{\exercise@@@}} +% \end{macrocode} +% We have recorded the presence of a star, is there +% another optional argument, h +% \begin{macrocode} +\def\exercise@@@{\@ifnextchar[{\exercise@@@@}{\@exercise}} +% \end{macrocode} +% \begin{macrocode} +\def\exercise@@@@[#1]{\edef\eq@arg{#1}% + \if\eq@arg h\def\currhideopt{h}% + \eq@hidesolutiontrue\eq@nolinktrue + \ifeq@globalshowsolutions + \eq@hidesolutionfalse\eq@nolinkfalse\fi + \def\eq@next{\@exercise}% h, no *, no counter + \else + \if\eq@arg H\edef\currhideopt{\Hidesymbol}% + \eq@hidesolutiontrue\eq@nolinktrue% + \def\eq@next{\@exercise}% h, no *, no counter + \else + \def\currhideopt{x}% + \PackageWarning{exerquiz}{The option #1 is not recognized} + \let\eq@next\relax + \fi + \fi +\eq@next} +% \end{macrocode} +% \begin{macro}{\exerSolnHeader} +% When a solution is written to the .sol file, there is a header line that contains formatting information. +% This command can be redefined as desired. We also introduce to markers, \cs{eqEXt} and \cs{endeqEXt} which +% can be used in any way your imaginations can conjure up. Basically, the mark the beginning and ending of the solution. +% \begin{macrocode} +\newif\ifeq@exerciseheading \eq@exerciseheadingtrue +% \end{macrocode} +% \changes{v6.7q}{2013/12/15}{Added this hook for use by \textsf{contsolns.dtx}} +% \begin{macrocode} +\let\prior@exerSolnHeaderHook\@empty +\newcommand\exerSolnHeader[3]{% + \prior@exerSolnHeaderHook + \ifeqforpaper\else\webnewpage\fi\markright{#1}%\par\noindent% +%</package|eqexam> +%<*package> + \noindent\hypertarget{#2}{#3}\relax +%</package> +%<*eqexam> + #3% +%</eqexam> +%<*package|eqexam> + \solnhspace +} +% \end{macrocode} +% (2015/05/18) Made this definition conditional on whether \textsf{eqexam} +% is loaded. The command is meant for \textsf{eqexam}. The \textsf{exerquiz} +% package should be loaded after \textsf{eqexam} if the two are to be used +% together, preferably by the \texttt{links} or \texttt{online} options of \textsf{eqexam}. +% \begin{macrocode} +%\newif\iffirstitem +\let\solnItemMngt\relax +%\def\eqeSolnItemMngt{\iffirstitem\global\firstitemfalse +% \let\eqe@next\@empty\else\let\eqe@next\item\fi\eqe@next\relax} +%\@ifpackageloaded{eqexam}{\let\solnItemMngt\eqeSolnItemMngt} +% {\let\solnItemMngt\relax} +% \end{macrocode} +% \end{macro} +% \DescribeMacro{\eqEXt}These two mark the beginning and end of solution to an exercise. \cs{eqEXt} is +% set up to have two required arguments, usually both empty. The arguments are +% used for filtering. The first might be a number, so we can filter out even numbered +% exercises from odd ones. The second one is a keyword, we can filter by keyword. +%\changes{v6.7}{2013/04/07}{Changing \cs{eqEXt} so that it has two +%required arguments} +% \begin{macrocode} +%\let\eqEXt\@gobble +\let\eqEXt\@gobbletwo +\let\endeqEXt\relax +% \end{macrocode} +% \DescribeMacro{\eqExtArg}\cs{eqExtArg} and \DescribeMacro{\eqFilterArg}\cs{eqFilterArg} +% are the arguments for \cs{eqEXt}. They are redefined at the creation of the +% exercise. +% \begin{macrocode} +\let\eqExtArg\@empty +\let\eqFilterArg\@empty +% \end{macrocode} +% The format of the solutions to exercises as they appear in the SOL file is, +%\begin{verbatim} +%\eqEXt{\eqExtArg}{\eqFilterArg}\exerSolnHeader +% {\exsecrunhead}{ex.1}{\textbf{Exercise\ 1.}}\relax +% ... +% <solution content> +% ... +%\ReturnTo{qex.1}{\hbox {$\square $}}\endeqEXt\par\medskip +%\end{verbatim} +% \changes{v6.7a}{2013/05/03}{Change name of \cs{eq@writeexheader} to \cs{eqExerSolnHeader}} +% \begin{macrocode} +\let\eqExerSolnHeader\@empty +%\let\eq@writeexheader\@empty +% \end{macrocode} +% The \cs{solutionparshape} is a command that supports the \cs{leadinitem} command +% of \texttt{eqexam}. Its normal value is \cs{@empty}. +% \begin{macrocode} +\let\solutionparshape\@empty +% \end{macrocode} +%\changes{v7.2}{2015/03/22}{added \cs{setPrbSolnAftrIndent}} +% \DescribeMacro{\setPrbSolnAftrIndent}\cmd{\setPrbSolnAftrIndent} sets the amount of indent +% for the statement of problem and the solution-after solution. The command saves its argument +% in \cs{eq@pslnaindnt} (default \texttt{0pt}) and sets the hook +% \cs{eq@setPrbSolnAftrIndnt}. This latter macro appears in \cs{@exercise} below. Its +% initial value is \cs{relax}; otherwise, it sets \cs{parindent=\#1}. +% \begin{macrocode} +\def\eq@pslnaindnt{0pt} +\let\eq@setPrbSolnAftrIndnt\relax +\newcommand{\setPrbSolnAftrIndent}[1]{\ifdim#1=0pt + \def\eq@pslnaindnt{0pt}\let\eq@setPrbSolnAftrIndnt\relax\else + \edef\eq@pslnaindnt{#1}\edef\eq@setPrbSolnAftrIndnt{% + \expandafter\noexpand\expandafter\parindent#1\noexpand\relax}\fi +} +% \end{macrocode} +%\changes{v7.2}{2015/03/22}{added \cs{restorejustify}} +%The command \DescribeMacro\restorejustify\cmd{\restorejustify} is designed +%for use in the \texttt{solution} environment of an \cs{item} within the +%\texttt{parts} environment in \texttt{tabular} mode. By default, +%\texttt{parts[2]}, for example, sets up a tabular, each entry is in a +%paragraph (\texttt{p\{\}}) but \cs{raggedright} is used. We change this for +%the solution using \cmd{\restorejustify}. Use \DescribeMacro\restoreJustifyOn\cmd{\restoreJustifyOn} +% to turn on this feature and \DescribeMacro\restoreJustifyOff\cmd{\restoreJustifyOff} +% to turn it off (default). +% \begin{macrocode} +\newif\if@restorejustify \@restorejustifyfalse +\newcommand\restoreJustifyOn{\@restorejustifytrue} +\newcommand\restoreJustifyOff{\@restorejustifyfalse} +\def\restorejustify{\if@restorejustify + \@rightskip\z@skip \rightskip\@rightskip + \leftskip\z@skip \let\\\@normalcr\fi} +% \end{macrocode} +% The \DescribeMacro\@exercise definition of the \texttt{exercise} environment continues here. +% \begin{macrocode} +\def\@exercise{% + \global\let\solutionparshape\@empty + \let\verbatim@out=\ex@solns + \if\eq@argi0\else\refstepcounter{\eq@argi}\fi\stepcounter{@exno}% + \if\exerstar*% if exercise with parts + \eq@nolinktrue + \else + \if\currhideopt H% + \else + \ifeq@solutionsafter + \eq@nolinktrue % no link to solution + \else + \eq@ckglobalhide % + \ifeq@hidesolution\else +% \end{macrocode} +% Here's where we write the header to the .sol file. +% \begin{macrocode} + \global\let\eqExerSolnHeader\eq@@writeexheader + \fi + \fi + \fi + \fi + \ifvmode\ifdim\lastskip>\z@ + \vskip-\lastskip + \fi\fi + \if\exerstar*% + \let\solution\solnexer@woparts + \let\endsolution\endsolnexer@woparts + \let\parts\exercise@parts + \let\endparts\endexercise@parts + \else + \let\solution\solnexer@woparts + \let\endsolution\endsolnexer@woparts + \let\parts\relax + \let\endparts\relax + \if\Hidesymbol h\eq@nolinkfalse\ifeq@solutionsafter + \eq@nolinktrue\fi\fi + \fi +% \end{macrocode} +% Here is where `Exercise' is typeset; the commands \cs{marginparpriorhook} and \cs{marginpartafterhook} +% can be used to insert content in before and after the `Exercise'. +% \begin{macrocode} + \eq@initializeContAnnot + \ifeq@exerciseheading + \prior@questionsHook\marginparpriorhook\noindent\eqexheader@wrapper + \afterlabelhskip\marginparafterhook\gEx@CommonCmd + \eq@setPrbSolnAftrIndnt\ignorespaces\fi +} +% \end{macrocode} +% \end{environment} +% \changes{v6.4z}{2012/11/28}{Extracted code to make it available elsewhere.} +% (2012/11/28) Extracted the code below from the macro above so it can be used +% elsewhere as well. +%\par\medskip\noindent +% The \cs{eqterminex} command is one that appears on the solution page, just after the exercise number. +% We redefine it to do our will. The convenience macro \cs{decleqterminex}\DescribeMacro{\decleqterminex} is used for that purpose. +% We use \cs{ifterminexchanged} to track whether the default definition is changed. +% \begin{macrocode} +\newif\ifterminexchanged \terminexchangedfalse % dps cq +\newcommand\decleqterminex[1]{\def\eqterminex{#1}} +% \end{macrocode} +% The default definition of \cs{eqterminex} is saved under \cs{eqterminexDEF}. +% \begin{macrocode} +\def\eqterminexDEF{\relax\ignorespaces} +\decleqterminex{\eqterminexDEF} +% \end{macrocode} +%\changes{v6.7}{2013/04/07}{Inserted another argument into \cs{eqEXt}} +% Added another argument into \cs{eqEXt}, used for filtering. +% \begin{macrocode} +\def\eqExerSolnHeaderSngl{% + \protect\eqEXt{\eqExtArg}{\eqFilterArg}\protect + \solnItemMngt\protect\exerSolnHeader{\exsecrunhead}{ex.\the@exno}% + {\exsllabelformat}\exer@solnheadhook + \exersolnheadhook\protect\eqterminex +} +\def\eq@@writeexheader{\set@display@protect + \immediate\write\verbatim@out{\eqExerSolnHeaderSngl}% + \set@typeset@protect +} +% \end{macrocode} +%\changes{v6.7}{2013/04/07}{Inserted another argument into \cs{eqEXt}} +% Added another argument into \cs{eqEXt}, used for filtering. +% \begin{macrocode} +\def\eqExerSolnHeaderList{% + \protect\eqEXt{\eqExtArg}{\eqFilterArg}\protect + \solnItemMngt\protect\exerSolnHeader{\exsecrunhead}% + {ex.\the@exno\thepartno}{\exsllabelformatwp}% + \exer@solnheadhook\exersolnheadhook\protect\eqterminex +} +\def\eq@@writeexheaderlist{\set@display@protect + \immediate\write\verbatim@out{\eqExerSolnHeaderList}% + \set@typeset@protect +} +% \end{macrocode} +% \subsection{Define \texttt{solution} Environment for \texttt{exercise}} +% \begin{macro}{solution} +% This is the \texttt{solution} environment for +% \texttt{exercise}; either start \cmd{\verbatim} or, +% \cmd{\eq@solutionsaftertrue} write the label \cmd{\exsolafter}. +% +% The solution macro for the \texttt{exercise} environment now takes an optional +% argument. This argument must be a vertical skip ( i.e., \texttt{[1in]} ). When the solution +% does not correspond to a tabular multi-part question, a vertical skip +% |\vspace{#1}| is introduced when the \texttt{nosolutions} is in effect and when +% \texttt{solutionsafter} is not. This feature may be useful for constructing +% tests in this space is left for the student to write in the answer; yet, later +% when \texttt{solutionsafter} is true, the solutions appear instead of the vertical +% white space. +% \begin{macrocode} +\long\def\setsolnspace#1{\def\newsolnspace{#1}% + \let\solnspace\newsolnspace} +% \end{macrocode} +% \begin{macro}{\ckSolnOpt} +% \begin{macro}{\noSolnOpt} +% \cs{noSolnOpt} turns off the check for the option argument +% of the \texttt{solution} environment for the \texttt{exercise} +% environment. Designed for use with \textsf{eqexam}. +% \changes{v6.4v}{2012/07/27}{Added \cs{ckSolnOpt} and \cs{noSolnOpt} +% to switch on and off checking for the optional vertical space in the +% \texttt{solution} environment.} +% \begin{macrocode} +\newif\ifeq@ckSolnVspace \eq@ckSolnVspacetrue +\def\ckSolnOpt{\global\eq@ckSolnVspacetrue} +\def\noSolnOpt{\global\eq@ckSolnVspacefalse} +\let\solnhspace\space +\let\solnspace\space +% \end{macrocode} +% \end{macro} +% \end{macro} +% This macro is the beginning of the \texttt{solution} environment for +% exercises. +% \begin{macrocode} +\def\solnexer@woparts{\def\bLeaveVspace{x}% = no vertical space added + \ifeq@ckSolnVspace + \def\eq@next{\@ifnextchar[{\solnexer@@woparts}% + {\solnexer@@woparts[\null]}}\else + \def\eq@next{\solnexer@@woparts[\null]}\fi +% \end{macrocode} +% The code below, now removed, used to deny the use of the optional parameter +% in the parts-tabular environment. (2013/03/26) +%\begin{verbatim} +% \ifx\endparts\endexercise@parts@tabular +% \def\eq@next{\solnexer@@@woparts}\fi +%\end{verbatim} +% \begin{macrocode} + \eq@next +} +\let\eqPriorVspace\@gobble +\newif\if@eqlinedfiller \@eqlinedfillerfalse +\newcommand{\vspaceFiller}[1]{\vfill} +\newcommand{\vspaceFillerDefault}[1]{\vfill} +\def\eqWriteLine{\hfill} +\def\eq@linesXPgs{% + \begingroup\offinterlineskip\parskip0pt + \@tempcnta=0 + \@whilenum\@tempcnta<\soln@keys@nLines\relax\do + {\vskip0pt\penalty-50\vglue\wlVspace\eqWriteLine + \advance\@tempcnta1\relax}\par\endgroup +} +\newcommand{\vspaceFmt}[1]{% + \ifx\solutionparshape\@empty\else +% \end{macrocode} +% This must be part of the solution for a \cs{leadinitem} question. +% We need to make an adjustment to the \cs{linewidth}. +% \begin{macrocode} + \advance\linewidth-\leadinIndentPrtSep\fi + \ifdim\sameVspace>0pt + \let\bLeaveVspace\@empty + \def\leavevspace{% + \ifx\eq@insertverticalspace\eq@YES\par + \eqPriorVspace{#1}{\nobreak\noindent +% \end{macrocode} +% If \texttt{nLines} is non-empty, we'll use some spacial code +% to generate the lines so it breaks across pages. +% \begin{macrocode} + \ifx\soln@keys@nLines\@empty + \if@eqlinedfiller + \def\eq@lines@next{\vspaceFiller{#1}}\else + \def\eq@lines@next{\parbox[b][#1][t]{\linewidth} + {\vspaceFiller{#1}}}\fi + \else + \def\eq@lines@next{\eq@linesXPgs}% + \fi\eq@lines@next + }% + \fi + }% + \fi +} +% \end{macrocode} +% \changes{v6.8g}{2014/04/08}{Added key-val here for \textsf{eqexam}.} +% New option for the \texttt{solution} environment, \IndexKey{nLines}\texttt{nLines}. +% \begin{macrocode} +\define@key{soln@keys}{nLines}[]{\def\soln@keys@nLines{#1}} +\let\soln@keys@nLines\@empty +% \end{macrocode} +% \cs{eqKV@errx} is a hack into the \textsf{keyval} package. The change, made +% below in \cs{solnexer@@woparts} is temporary. We use it to get the dimen +% of the \texttt{solution} env. Necessary since we have an \texttt{nLines} key defined +% for \textsf{eqexam}. +% \begin{macrocode} +% keyval package \@tempa contains undefined key +\def\eqKV@errx#1{\xdef\XKV@rm{\@tempa}} +% \end{macrocode} +% \begin{macrocode} +\def\eqSolnForEqexam#1{% + \let\soln@keys@nLines\@empty + \setkeys*{soln@keys}{#1}% + \ifx\soln@keys@nLines\@empty + \ifx\minVspacet@bs\@empty\xdef\sameVspace{\XKV@rm}\else + \xdef\sameVspace{\minVspacet@bs}\fi + \else + \@tempdima\wlVspace + \@tempdima=\soln@keys@nLines\@tempdima + \xdef\sameVspace{\the\@tempdima}% + \ifx\XKV@rm\@empty\else + \if@equsedim\let\soln@keys@nLines\@empty + \xdef\sameVspace{\XKV@rm}\fi + \fi + \fi + \ifx\sameVspace\@empty\gdef\sameVspace{0pt}\fi +} +% \end{macrocode} +% Now the beginning of the \textsf{solution} environment for \texttt{exercise} env. +% \begin{macrocode} +\def\solnexer@@woparts[#1]{% + \ifcqIsActive\else\ifterminexchanged +% \end{macrocode} +% If this problem does not use \env{cq} or \env{cq*}, we reset the solution page, +% to the default definition of \cs{eqterminex}. +% \begin{macrocode} + \restoreNormalSolns\fi\fi % dps cq + \global\cqIsActivefalse +% \end{macrocode} +% \changes{v6.3z}{2011/04/28}{Added definition of \cs{sameVspace} for the cases +% where there is no vertical space specified.} +% Is the argument \cs{null}? If yes, same as \texttt{0pt}. +% \begin{macrocode} + \def\eq@argi{#1}\def\eq@null{\null}% + \ifx\eq@argi\@empty\gdef\sameVspace{0pt}\else + \ifx\eq@argi\eq@null\gdef\sameVspace{0pt}\else +% \end{macrocode} +% \changes{v6.8g}{2014/04/08}{Added key-val here for \textsf{eqexam}.} +% Now, if the optional argument is non-null, we must discern the argument: +% is it a vertical space or a key-value? +% \begin{macrocode} + \@ifundefined{PointsOnLeft}{% + \let\eqKV@errx@SAVE\KV@errx + \let\KV@errx\eqKV@errx\let\XKV@rm\@empty + \edef\temp@exp{\noexpand\setkeys*{soln@keys}{#1}}\temp@exp + \let\KV@errx\eqKV@errx@SAVE + \ifx\soln@keys@nLines\@empty\else + \PackageInfo{exerquiz}{% + nLines key detected in solution environment,\MessageBreak + is not not recognized without eqexam,\MessageBreak + will remove it}% + \let\soln@keys@nLines\@empty\fi + \xdef\sameVspace{\XKV@rm}% + }{\eqSolnForEqexam{#1}}% +% \end{macrocode} +% (03/04/11) Try to insert a new option: if there are \cs{ifvspacewithsolns} option +% then \textsf{eqexam} should leave space for writing an answer, and put solutions at the end +% of the document. +% \begin{macrocode} + \ifx\sameVspace\@empty\gdef\sameVspace{0pt}\fi + \ifvspacewithsolns\vspaceFmt{\sameVspace}\fi + \ifeq@nosolutions\ifeq@solutionsafter\else + \vspaceFmt{\sameVspace}\fi\fi + \fi\fi + \solnexer@@@woparts +} +% \end{macrocode} +% \changes{v7.7q}{2016/07/22}{Added \string\cs{solnsafterSkip}} +% \begin{macrocode} +\def\solnsafterSkip#1{\setlength{\@tempdima}{#1}% + \def\solnsafterSkipAmt{\the\@tempdima}% + \def\solutionsafterSkip{\vskip#1\relax}} +\solnsafterSkip{\smallskipamount} +% \end{macrocode} +% The next two definitions are used for debugging the +% \cs{ifkeepdeclaredvspacing} feature (\textsf{eqexam} only). +% \begin{macrocode} +\def\eqe@debugVertSkip#1{} +\def\eqe@showEndHere#1{#1} +% \end{macrocode} +% Used to set the starting point of the solution +% \begin{macrocode} +\def\eqe@setStartSolns{% + \xdef\eq@startSoln{\the\pagetotal}% + \eqe@debugVertSkip{\marginpar{\smash{b[\sameVspace]}}}% +} +% \end{macrocode} +%\changes{v6.4b}{2011/06/30}{% +% Save the definitions of \cs{comment} and \cs{endcomment}. For some reason, +% yet to be determined, there are problems when using the \texttt{fortextbook} +% option when hiding solutions. +%} +% \begin{macrocode} +\let\eqSavedComment\comment +\let\eqSavedEndCommet\endcomment +% \end{macrocode} +%\changes{v7.4}{2015/03/23}{added \cs{setTabulrSolnEnv}} +% \begin{macrocode} +\def\setTabulrSolnEnv{% + \@ifundefined{@listii@SAVE}{\global\let\@listii@SAVE\@listii}{}% + \expandafter\def\expandafter\@listii\expandafter{\@listii@SAVE + \leftmargin\leftmarginii \labelwidth\leftmarginii + \advance\labelwidth-\labelsep}% + \def\everyparShape{\everypar{\parshape \@ne 0pt \linewidth}}% +% \end{macrocode} +% \cmd{\reset@doendpe} resets the definition of the core command +% \cmd{\@doendpe} so behavior is correct whether list environment +% starts in vertical mode or not. +% \begin{macrocode} + \reset@doendpe{\parshape \@ne 0pt \linewidth}% +% \expandafter\def\expandafter\@par\expandafter{\@par\everyparShape}% + \parshape \@ne 0pt \linewidth + \everyparShape +} +\newif\ifthereissolution +\let\priorexsolafterList\@empty +\let\priorexsolafterTab\@empty +\let\priorexsolafterSngl\@empty +\def\eq@Hid{H}\def\eq@hid{h} +\def\solnexer@@@woparts{% + \global\thereissolutiontrue + \def\exerwparts@cols{0}% + \let\verbatim@out\ex@solns + \if\currhideopt\eq@Hid +% \end{macrocode} +% (2017/02/09) Hide \cs{minVspacet@bs} for `H' option +% \changes{v7.8e}{2017/02/09}{Hide \string\cs{minVspacet@bs} for `H' option} +% \begin{macrocode} + \let\minVspacet@bs\@empty + \let\procsoln\eqSavedComment + \let\endprocsoln\eqSavedEndCommet + \def\eq@next{\procsoln}% + \else + \eq@ckglobalhide + \ifeq@hidesolution + \let\procsoln\eqSavedComment + \let\endprocsoln\eqSavedEndCommet + \else + \ifx\bLeaveVspace\@empty\leavevspace\fi + \ifeq@solutionsafter\else + \ifx\eq@@CommonCmd\@empty\else + \set@display@protect + \immediate\write\verbatim@out{\eq@@CommonCmd}% + \set@typeset@protect + \fi + \fi + \let\procsoln\verbatimwrite + \let\endprocsoln\endverbatimwrite + \fi + \def\eq@next{% + \ifeq@solutionsafter%\par + \removelastskip\removelastparskip + \cqSAtrue\eqCQDeclarations + \declCopyQues{\input{\cq@CutName}}% + \ifx\exsolafter\@empty +% \end{macrocode} +% If we have solutions after and there is no label and no vertical +% skip specified, we do nothing other than to execute \cs{eqe@setStartSolns}, +% which marks the beginning of the ``solution.'' +% \begin{macrocode} + \ifdim\sameVspace=0pt\eqe@setStartSolns + \else +% \end{macrocode} +% If there is vertical space specified, we do a standard skip, and mark the beginning +% of the solution with \cs{eqe@setStartSolns}. +% \begin{macrocode} + \solutionsafterSkip + \eqe@setStartSolns + \fi + \else\par\kern0pt + \solutionsafterSkip + \noindent\strut\eqe@setStartSolns + \fi + \parskip\eqeques@parsep + \ifx\endparts\endexercise@parts@tabular + \eq@setPrbSolnAftrIndnt + \restorejustify +% \expandafter\setTabulrSolnEnv + \fi +% \end{macrocode} +% (2017/02/09) Added prior \cs{exsolafter} hooks. +% \changes{v7.8e}{2017/02/09}{Added prior \string\cs{exsolafter} hooks} +% \begin{macrocode} + \ifx\endparts\endexercise@parts@tabular\expandafter + \priorexsolafterTab\else + \ifx\endparts\endexercise@parts@list\expandafter + \priorexsolafterList\else\expandafter + \priorexsolafterSngl\fi\fi +% \end{macrocode} +% The solution after label, followed by a space. +% \begin{macrocode} + \exsolafter\space\ignorespaces +% \end{macrocode} +% We set the shape of the solutionafter. +% This is empty if \cs{leadinitem} is not used. +% \begin{macrocode} + \solutionparshape + \else +% \end{macrocode} +% Write the solution header 11/03/05 +% \begin{macrocode} + \eqExerSolnHeader + \global\let\eqExerSolnHeader\@empty + \global\therearesolutionstrue\expandafter\procsoln + \fi + }% + \fi +\eq@next} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\let\endsolnexerhook\@empty +\let\pkg@endsolnexerhook\@empty +\let\endsolnexerhookaux\@empty +% \end{macrocode} +% This macro attempts to insert the return link at the end of the +% last paragraph of the solutions, this makes the return label +% look nice, and saves a little space. +% \begin{macrocode} +\def\eq@fititin#1{\noindent\unskip\nobreak\hfill\penalty100 + \hskip1em\hbox{}\nobreak\hfill#1}% +\let\eqfititin\eq@fititin +%</package|eqexam> +%<*package> +\def\ReturnTo#1#2{\eq@fititin{\hyperlink{#1}{#2}}} +\def\xReturnTo#1#2{\eq@fititin{\href{#1}{#2}}} +%</package> +% \end{macrocode} +% \begin{macro}{\eqExerSolnTrailer} +% The material that follows the solution in the .sol file. +% \begin{macrocode} +%<*package|eqexam> +\newcommand\eqExerSolnTrailer{% +%</package|eqexam> +%<*package> + \if\exerSolns@ExtFile\eq@YES\protect\xReturnTo + {\exerSolns@ReturnPath\jobname\#qex.\the@exno}% + \else\protect\ReturnTo{qex.\the@exno}\fi + {\protect\mbox{\if\exerstar*\exrtnlabelformatwp\else + \exrtnlabelformat\fi}}% + \protect\endeqEXt\ifeqforpaper\protect\par{\belowexsolnskip}\fi^^J% +%</package> +%<*eqexam> + \protect\ReturnTo{page.\the\c@page}% + {\protect\mbox{\if\exerstar*\exrtnlabelformatwp\else + \exrtnlabelformat\fi}}% + \protect\endeqEXt\ifeqforpaper\protect\par{\belowexsolnskip}\fi^^J% +%</eqexam> +%<*package|eqexam> +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\endsolnexer@woparts} +% Unless \cmd{\eq@solutionsaftertrue}, then \cmd{\endverbitim}, +% and write return labels. +% \begin{macrocode} +\def\endsolnexer@woparts{% + \if\currhideopt H% + \ifkeepdeclaredvspacing\vskip\sameVspace\fi + \csname endprocsoln\endcsname + \else +% \end{macrocode} +% If solutions after, we start a new paragraph, then add some kerning glue, +% this gives a better gauge for calculating the \cs{pagetotal}. +% \begin{macrocode} + \ifeq@solutionsafter + \if\exerstar*% + \eq@fititin{\mbox{\exrtnlabelformatwp}}\else + \eq@fititin{\mbox{\exrtnlabelformat}}\fi + \ifx\istabularexer\eq@YES\kern0pt\else\par\fi +% \ifnum\exerwparts@cols>0\relax\kern0pt\else\par\fi +% \end{macrocode} +% \changes{v6.3z}{2011/04/28}{if \cs{ifkeepdeclaredvspacing} is true, we attempt +% to preserve the vertical space declared by the \textsf{solution} environment when +% \cs{ifeq@solutionsafter} is true.} +% \begin{macrocode} +\ifx\minVspacet@bs\@empty + \ifkeepdeclaredvspacing +% \end{macrocode} +% We get the current \cs{pagetotal}, and subtract off the page total as recorded +% by \cs{eq@startSoln}. +% \begin{macrocode} + \@tempdima\pagetotal + \advance\@tempdima-\eq@startSoln +% \end{macrocode} +% \changes{v6.4w}{2012/26/27}{Added \cs{relax} following the assignment.} +% {\TeX} was looking ahead looking for the rest of the dimension, this caused +% problems because later code was expanded when it should not have been. Inserted +% \cs{relax}, \verb~\@tempdimb\sameVspace\relax~. +% \begin{macrocode} + \@tempdimb\sameVspace\relax +% \end{macrocode} +% if \cs{soln@keys@nLines} is nonempty, we put \cs{sameVspace} to \texttt{1sp}, +% unless the author asks for \texttt{1sp}, this is how it is set. +% \begin{macrocode} + \ifdim\@tempdimb>1sp\relax +% \end{macrocode} +% If there is a positive value for \cs{sameVspace}, we calculate +% the difference between\cs{@tempdimab} and \cs{@tempdima}, that is, we calculate +%\begin{verbatim} +% \sameVspace-(\pagetotal-\eq@startSoln) +%\end{verbatim} +% \begin{macrocode} + \advance\@tempdimb-\@tempdima +% \end{macrocode} +% If this difference is positive, we will skip this amount. +% \begin{macrocode} + \ifdim\@tempdimb>0pt\vglue\@tempdimb\kern0pt + \let\eqe@showEndHere\@gobble + \edef\tmp@exp{\noexpand\marginpar{% + \noexpand\smash{e: adj \the\@tempdimb}}}% + \eqe@debugVertSkip{\tmp@exp}% + \fi + \fi + \fi + \eqe@showEndHere{\eqe@debugVertSkip{\marginpar{\smash{e}}}}% +\fi + \else + \endprocsoln + \eq@ckglobalhide + \ifeq@hidesolution\else + \endsolnexerhookaux +% \end{macrocode} +% Here's were we write the trailer for the solution +% \begin{macrocode} + \set@display@protect + \immediate\write\verbatim@out{\eqExerSolnTrailer}% + \set@typeset@protect + \fi + \fi + \fi +\pkg@endsolnexerhook\endsolnexerhook} +% \end{macrocode} +% \end{macro} +% \subsection{The \texttt{exercise*} Environment: Exercises with Parts} +% Exercises with parts are enclosed within a \texttt{parts} environment. There are two types +% of parts listing: list-type and tabular-type. +% \begin{environment}{exercise*} +% For the exercise* environment, we set a flag to indicate that the \cs{exerstar} +% has been set in the star environment, the begin the \cs{exercise} and finished with +% \cs{endexercise}. +%\changes{v6.07}{2007/05/05} +%{ +% Created the \texttt{exercise*} environment, this is equivalent to the \texttt{*} option of the +% \texttt{exercise} environment. You can use either version, but now, \texttt{exercise*} is preferred. +%} +% \begin{macrocode} +\let\eq@exerstarEnv\relax +\newenvironment{exercise*}{\def\eq@exerstarEnv{*}\exercise} +{\endexercise} +% \end{macrocode} +% \end{environment} +% \begin{environment}{parts} +% Initially, we see if there is an optional argument, if yes, the +% tabular environment is used, the argument is the number of columns +% requested. Otherwise, we use a list environment. +% \begin{macrocode} +\def\exerwparts@cols{0} +\let\topofpartshook\relax +\let\@listiiredefined\eq@NO +\let\itsExerParts\eq@NO +% \end{macrocode} +% (2015/05/30) Added a feature for lead in for tabular mode for parts environment. +% \DescribeMacro{\tableadin}\cmd{\tableadin} is placed prior to +% \verb!\begin{parts}[2}!, no preamble leading into the question is assumed. +% Using the switch \cs{if@tableadinitem} we remove any \cs{par}s and \cs{vskip}s. +% \begin{macrocode} +\newif\if@tableadinitem\@tableadinitemfalse +\newcommand{\tableadin@external}{\PackageError{exerquiz/eqexam} + {The \string\tableadin\space command is designed\MessageBreak + for the problem* environment of eqexam}{Use \string\tableadin\space + in the problem* environment of eqexam.}% +} +\let\tableadin\tableadin@external +\newcommand{\eq@tableadinparts}{\item\relax + \PackageError{exerquiz/eqexam}{The \string\tableadin\space + command is not allowed in the\MessageBreak + parts environment}{Use \string\tableadin\space + in the problem* environment of eqexam.}% +} +% \end{macrocode} +% (2016/12/16) Define a flag \cs{istabularexer} that signals to the solution environment it is in a tab environment +% \changes{v7.8b}{2016/12/16}{Added \string\cs{istabularexer}} +% \begin{macrocode} +\let\istabularexer\eq@NO % dps 2016/12/16 +\def\exercise@parts{\let\rlspar\relax + \ifx\solutionparshape\@empty + \let\isitleadin\eq@NO +% \end{macrocode} +% If \cs{tableadin}, we remove the \cs{removelastskip} and \cs{par} that follows. +% \begin{macrocode} + \if@tableadinitem\let\rlspar\@gobbletwo\fi + \else\let\isitleadin\eq@YES\fi + \rlspar\removelastskip\par + \if\isitleadin\eq@YES +% \end{macrocode} +% \changes{v7.6}{2015/05/24}{Some vspace adjustment at the beginning of +% a leadinitem.} If there is a lead-in, we set \cs{topsep} to \texttt{0pt} +% and skip \cs{itemsep}. +% \begin{macrocode} + \def\eqparts@topsep{0pt}% dps88 + \vskip\eqparts@itemsep\relax\fi % dps88 + \topofpartshook + \let\itsExerParts\eq@YES % dps17 + \global\let\@listiiredefined\eq@NO + \def\exerwparts@cols{0}\@ifnextchar[% + {% +% \end{macrocode} +% When there is a \cs{tableadin}, we remove \cs{removelastparskip} because it does not occur above. +% \begin{macrocode} + \if@tableadinitem\else\removelastparskip\fi % dps11 +% \keepdeclaredvspacingfalse + \let\endparts\endexercise@parts@tabular\exercise@parts@tabular@}% + {\let\endparts\endexercise@parts@list\exercise@parts@list}} +% \end{macrocode} +% \subsubsection{List-type Parts Question} +% This is a redesigned \texttt{list} environment. Meant to be used with the +% \texttt{exercise} environment with the *-option. +% \begin{macrocode} +\def\eq@extralabelsep{0pt} +% \end{macrocode} +% \begin{macro}{\setPartsWidth} +% Convenience macro to set \cs{part@indent}. +%\changes{v6.4h}{2011/07/28}{% +% Added \cs{setPartsWidth} to set \cs{part@indent}. Also +% defined \cs{eqe@prtsepPrb}. +%} +% \begin{macrocode} +\newcommand{\setPartsWidth}[1]{\def\parts@indent{\normalfont#1}% + \bgroup\settowidth{\eq@tmpdima}{\parts@indent}% + \xdef\widthOfParts{\the\eq@tmpdima}\egroup} +\setPartsWidth{(d)} +% \end{macrocode} +% \end{macro} +% \DescribeMacro{\eqe@prtsepPrb} is used to set \cs{labelsep}. +% I've also added the two hooks \DescribeMacro{\prior@parts@hook}\cs{prior@parts@hook} and +% \DescribeMacro{\post@parts@hook}\cs{post@parts@hook} as well; these are used +% by \textsf{eqexam} for hanging the solutions with parts correctly. +% \begin{macrocode} +\def\eqe@prtsepPrb{\ } +\providecommand{\prbPrtsep}[1]{\def\eqe@prtsepPrb{#1}} +\providecommand{\exPrtsep}[1]{\def\eqe@prtsepPrb{#1}} +\providecommand{\eqequesparsep}[1]{\def\eqeques@parsep{#1}} +\eqequesparsep{0pt} +\let\prior@parts@hook\@empty +\let\post@parts@hook\@empty +\let\abovepartshook\@empty +\let\belowpartshook\@empty +\let\eqp@rtc@lcm@rk\relax +\let\eq@insertContAnnot\relax +% \end{macrocode} +% (2012/02/04) Common code to the definition of \cs{item} +% both list and tabular versions. +% \begin{macrocode} +\def\eq@item@common{\eq@insertContAnnot\eqp@rtc@lcm@rk + \def\currhideopt{x}\eq@hidesolutionfalse\eq@nolinkfalse + \@ifnextchar[{\@ckhide}{\eq@item}} +% \end{macrocode} +% \DescribeMacro{\eqpartsitemsep}(2012/02/03) Fine tune the control over space between +% parts. +%\changes{v6.4o}{2012/02/04} {Fine tune the control over space between parts.} +% \begin{macrocode} +\newcommand{\partsitemsep}[1]{{% dps88 + \setlength{\@tempdima}{#1}% + \xdef\eqparts@itemsep{\the\@tempdima}}} +\let\eqpartsitemsep\partsitemsep +\def\eqparts@itemsep{0pt} +\newcommand\partsparsep[1]{{% dps88 + \setlength{\@tempdima}{#1}% + \xdef\eqparts@parsep{\the\@tempdima}}} +\def\eqparts@parsep{0pt} +\newcommand\partstopsep[1]{{% dps88 + \setlength{\@tempdima}{#1}% + \xdef\eqparts@topsep{\the\@tempdima}}} +\def\eqparts@topsep{3pt} +% \end{macrocode} +% The next two commands are in support of the \cs{leadinitem} definition +% of \textsf{eqexam} +% \begin{macrocode} +\newcommand{\leadinitem@external}{\PackageError{exerquiz/eqexam} + {The \string\leadinitem\space command is designed to be\MessageBreak + the first item in the problem*\MessageBreak + environment above the parts environment} + {Use \string\leadinitem\space in the problem* environment.}% +} +\let\leadinitem\leadinitem@external +\let\itsforleadinitem\eq@NO +\newcommand{\eq@leadinitemparts}{\item\relax + \PackageError{exerquiz/eqexam}{The \string\leadinitem\space + command is not allowed in the\MessageBreak + parts environment} + {Use \string\leadinitem\space in the problem* environment.}% +} +% \end{macrocode} +% (2014/03/23) Problems when description env is used with parts env. The +% hook \cs{exlisttabheaderafterhook} is interfering with the optional argument. +% \begin{macrocode} +\def\eq@handleOptArg[#1]{\def\eq@optArg{[#1]}\eq@handleOptArgi} +\def\eq@handleOptArgi{\expandafter + \eq@item@latex\eq@optArg\exlisttabheaderafterhook} +% \end{macrocode} +% We add a new switch \cs{ifwithinparts} (2014/12/03) that is used to detect whether +% we are within the parts environment. +% \begin{macrocode} +\newif\ifwithinparts +\let\ex@listtabheader@fterhook\@empty +% \end{macrocode} +% Begin the list version of the parts environment. +% \begin{macrocode} +\newenvironment{exercise@parts@list}{% + \settowidth{\eq@tmplength}{\parts@indent}% + \edef\widthOfParts{\the\eq@tmplength}% + \eq@initializeContAnnot\eq@nolinkfalse\prior@parts@hook + \abovepartshook\list{\normalfont + \if\Hidesymbol h\eq@nolinkfalse\ifeq@solutionsafter + \eq@nolinktrue\fi\fi + \if\currhideopt H% + \else + \ifeq@solutionsafter + \eq@nolinktrue % no link to solution + \else + \ifeq@nosolutions + \eq@nolinktrue % no link to solution + \else + \eq@ckglobalhide + \ifeq@hidesolution\eq@nolinktrue\else +% \end{macrocode} +% Write the solution header to .sol for list type question. +% \begin{macrocode} + \global\let\eqExerSolnHeader\eq@@writeexheaderlist + \fi + \fi + \fi + \fi +% \end{macrocode} +% (2013/04/28) Inserted \texttt{[r]} +% \begin{macrocode} + \makebox[\widthOfParts][r]{\eqexlisttabheader}% +}{% + \usecounter{partno}% +% \end{macrocode} +% (2012/11/30) If \cs{solutionparshape} is nonempty, the user has used +% \cs{leadinitem}, so we increment \texttt{partno}. +% \begin{macrocode} + \if\isitleadin\eq@YES % dps7 + \settowidth{\eq@tmplength}{\parts@indent\eqe@prtsepPrb}% + \xdef\prtsIndntSep{\the\eq@tmplength}% dps7 +% \advance\linewidth-\prtsIndntSep\relax + \if\itsforleadinitem\eqe@YES\setcounter{partno}{\fliPartNo}\else + \setcounter{partno}{1}\fi\fi + \let\leadinitem\eq@leadinitemparts + \let\tableadin\eq@tableadinparts + \global\let\solutionparshape\@empty +% \setlength{\topsep}{3pt}% + \setlength{\topsep}{\eqparts@topsep}% +% \ifdim\parskip>\z@ +% \addtolength{\topsep}{-\parskip}\fi + \setlength{\parskip}{0pt}% + \setlength{\partopsep}{0pt plus 1pt minus 1pt}% + \ifdim\eqeques@parsep=0pt + \setlength{\parsep}{\eqparts@parsep}% +% \setlength{\itemsep}{\eqparts@itemsep-\eqparts@parsep}% + \else + \setlength{\parsep}{\eqeques@parsep}% +% \setlength{\itemsep}{\eqparts@itemsep-\eqeques@parsep}% + \fi + \setlength{\itemsep}{\eqparts@itemsep-\parsep}% + \setlength{\itemindent}{0pt}% + \setlength{\listparindent}{\parindent}% +% \end{macrocode} +% For \cs{itemsep}, we subtract off, for reasons not precisely known to me. +% This is done for \textsf{eqexam}, what effect does it have on a straight +% \textsf{exerquiz} file? +% \begin{macrocode} +% \setlength{\itemsep}{\eqparts@itemsep-\eqparts@parsep}% + \settowidth{\labelsep}{\normalfont\eqe@prtsepPrb}% + \addtolength{\labelsep}{\eq@extralabelsep}% + \settowidth{\labelwidth}{\parts@indent}% + \setlength{\leftmargin}{\labelwidth}% + \addtolength{\leftmargin}{\labelsep}% +% \end{macrocode} +% When a \texttt{trivlist} appear with the parts environment, it executes +% \cs{item}\cs{relax}, which causes problems because \cs{item} has been +% redefined. We try to correct this. +% \begin{macrocode} + \let\eq@item@latex\item +% \def\eq@item{\eq@item@latex\exlisttabheaderafterhook}% +% \end{macrocode} +% We handle the problem of seeing the optional argument by getting the argument, +% if there is one, and switching commands around. +% \begin{macrocode} + \def\eq@item{\@ifnextchar[{\eq@handleOptArg} + {\eq@item@latex\ex@listtabheader@fterhook + \exlisttabheaderafterhook}}% + \def\eqthisenv{parts}\withinpartstrue + \def\item{\ifx\@currenvir\eqthisenv + \def\eq@next{\eq@item@common}\else + \def\eq@next{\eq@item}\fi + \eq@next}% +}}{\endlist\global\let\leadinitem\leadinitem@external + \post@parts@hook\belowpartshook} +% \end{macrocode} +% The following command is inserted at the beginning of the parts environment +% and defines the current problem number and the page the \texttt{problem*} environment +% starts. The command is used by the \textsf{eqexam} package. +% \begin{macrocode} +\def\eq@initializeContAnnot{\@ifundefined{eqequestions} + {\global\let\eqeCurrProb\relax} + {\xdef\eqeCurrProb{\theeqquestionnoi}}% + \xdef\eq@currProbStartPage{\arabic{page}}% +} +% \end{macrocode} +% \subsubsection{Tabular-type Parts Question} +% Now for the tabular style of multi-part exercise, the argument +% \#1 is the number of columns requested.\medskip +% +% (2017/02/09) Added xkeyvals to optional argument of \texttt{parts}. Syntax is now +%\begin{verbatim} +% \begin{parts}[<num>|nCols=<num>,minVspace=<length>] +%\end{verbatim} +% \changes{v7.8e}{2017/02/09}{Added xkeyvals to optional argument of \string\texttt{parts}} +% \begin{macrocode} +\define@key{tabp@rts}{nCols}{\def\exerwparts@cols{#1}} +\define@key{tabp@rts}{minVspace}{\def\minVspacet@bs{#1}} +% \end{macrocode} +% Code to create vertical space when \texttt{answerkey} are in effect and +% \cs{vspacewithkeyOn} is present. +% \changes{v7.8e}{2017/02/09}{Added code for tab parts environment} +% \begin{macrocode} +\let\minVspacet@bs\@empty +\def\minVspacetabs#1{\def\minVspacet@bs{#1}} +\def\priorexsolafterTab{\ifkeepdeclaredvspacing + \ifeq@solutionsafter\ifx\minVspacet@bs\@empty\else + \priorexsolafterTab@cont\fi\fi\fi} +\def\priorexsolafterTab@cont{\let\exsolafter@save\exsolafter + \let\exsolafter\@empty + \makebox[0pt][r]{\parbox[t][\minVspacet@bs][t]{0pt} + {\strut\hfill\vfill\strut}}% + \minipage[t]{\linewidth}\exsolafter@save} +\def\pkg@endsolnexerhook{\ifkeepdeclaredvspacing + \ifeq@solutionsafter\ifx\minVspacet@bs\@empty\else + \endminipage\fi\fi\fi} +% \end{macrocode} +% Begin the core of the \texttt{parts} tabular-mode environment. +% \begin{macrocode} +\def\exercise@parts@tabular@[#1]{% +% \end{macrocode} +% \cs{inittabMark} initializes the auto-tab feature. (2013/03/26) +% \begin{macrocode} + \inittabMark +% \end{macrocode} +% locally, turn off continued annotations. Not allowed in tabular parts. +% \begin{macrocode} + \let\eq@insertContAnnot\relax + \let\exerwparts@cols\@empty + \setkeys*{tabp@rts}{#1}\ifx\exerwparts@cols\@empty + \edef\exerwparts@cols{\XKV@rm}\fi + \ifx\minVspacet@bs\@empty\keepdeclaredvspacingfalse\fi + \let\istabularexer\eq@YES + \@tempcnta\exerwparts@cols\relax + \ifnum\@tempcnta<2\relax + \PackageError{exerquiz}{% + The number of columns for parts\MessageBreak + needs to be an integer greater than 1} + {Enter an integer, 2 or larger}\fi + \exercise@parts@tabular} +% \end{macrocode} +% For the tabular environment for the \texttt{exercise*} environment, we try +% to automatically insert the column delimiter (\texttt{\&}) and the end of line. +% \cs{eq@extabColCnt} keeps track of the column number for the auto-tab feature. +% \begin{macrocode} +\newcount\eq@extabColCnt +% \end{macrocode} +% \DescribeMacro{\autotabOn} turns on the auto-tab feature for the \texttt{parts} environment, +% while \cs{autotabOff}\DescribeMacro{\autotabOff} turns it off. The off setting is the default. +% \begin{macrocode} +\def\autotabOn{\let\eq@tabMarkChk\relax% + \PackageInfo{exerquiz/eqexam}{Executing \string\autotabOn}} +\def\autotabOff{\let\eq@tabMarkChk\@gobble + \PackageInfo{exerquiz/eqexam}{Executing \string\autotabOff}} +\autotabOff +\def\inittabMark{\global\eq@extabColCnt=0 } +\def\resettabMark{\global\eq@extabColCnt=1 } +% \end{macrocode} +% \DescribeMacro{\autotabnewline} is the new line command for the auto-tab feature. +% It does a |\\| and resets the column counter \cs{eq@extabColCnt}. The user can use +% \texttt{[vspace]}, the default is \cs{eqparts@tabrowsep}. We use \cs{noalign} so that the space +% is added to the bottom of the whole row. +% \begin{macrocode} +\newcommand\autotabnewline[1][\eqparts@tabrowsep]{% +% \end{macrocode} +% If this is not tabular env, \cs{autotabnewline} does nothing +% \begin{macrocode} + \ifnum\exerwparts@cols>0\relax % dps cq + \ifx\eq@tabMarkChk\@gobble + \def\eq@atnext{\expandafter + \tabularnewline\expandafter[#1]}\else + \def\eq@atnext{\resettabMark\tabularnewline + \noalign{\expandafter\kern#1}}\fi % dps7 + \expandafter\eq@atnext\fi} +\def\eq@tabMark{% + \ifnum\eq@extabColCnt=0\relax + \global\advance\eq@extabColCnt1\relax + \let\eq@next\relax + \else + \ifnum\eq@extabColCnt=1\relax + \let\eq@next\relax + \else + \ifnum\eq@extabColCnt>\exerwparts@cols + \let\eq@next\autotabnewline + \else\def\eq@next{&}\fi + \fi + \fi + \eq@next + \global\advance\eq@extabColCnt1\relax +} +% \end{macrocode} +% Set up the tabular environment, after making a lot of decisions. +% \begin{macrocode} +\newcommand\partstabcolsep[1]{\def\eq@partstabcolsep{#1}} +\partstabcolsep{1.5pt} +\newcommand\partstabtopsep[1]{\def\eq@partstabtopsep{#1}} +\partstabtopsep{3pt} +\def\eq@vpartstabtopsep{\vskip\eq@partstabtopsep\relax} +\newcommand\partstabrowsep[1]{\setlength{\@tempdima}{#1}% + \edef\eqparts@tabrowsep{\the\@tempdima}} +\partstabrowsep{0pt} +\newenvironment{exercise@parts@tabular}{% +% \ifx\eq@tabMarkChk\@gobble +% \partstabrowsep{\@rowskip}\fi % detecting autotab off or on + \setcounter{partno}{0}% +% \end{macrocode} +% (2015/01/10) If \cs{solutionparshape} is nonempty, the user has used +% \cs{leadinitem}, so we increment \texttt{partno}. +% \begin{macrocode} + \def\tablrIndent{\hglue\prtsIndntSep\relax}% + \if\isitleadin\eq@YES % dps7 + \if$\the\everypar$\let\tablrIndent\relax\fi + \setcounter{partno}{1}\fi + \let\leadinitem\eq@leadinitemparts + \let\tableadin\eq@tableadinparts + \global\let\solutionparshape\@empty + \settowidth{\eq@tmplength}{\parts@indent\eqe@prtsepPrb}% + \xdef\prtsIndntSep{\the\eq@tmplength}% + \sbox{\eq@tmpbox}{\parts@indent}% + \let\eq@item@latex\item + \let\eq@item\item@part@tabular + \def\eqthisenv{parts}\withinpartstrue + \def\item{\ifx\@currenvir\eqthisenv + \def\eq@next{\eq@tabMarkChk\eq@tabMark\eq@item@common}\else + \def\eq@next{\eq@item@latex}\fi + \eq@next}\eq@nolinkfalse +% \end{macrocode} +%\changes{v6.4x}{2012/11/27}{Added control over row spacing in parts environment} +% Added control over row spacing in parts environment. The spacing +% is controlled by \cs{eqpartstabrowsep}, default value of \texttt{0pt}. The macro +% \cs{@xtabularcr} is from the {\LaTeX} core. Definition \cs{eq@xtabularcr} is found +% after the current definition block. +% \begin{macrocode} + \@ifundefined{@xtabularcr}{\let\@xarraycr\eq@xtabularcr} + {\let\@xtabularcr\eq@xtabularcr}% +% \end{macrocode} +% We reduce the width of the \cs{parbox}es (p|{width}|) by \cs{exertabsep} to leave +% room for \cs{tabcolsep=}\cs{exertabsep} between columns. +%\begin{verbatim} +% n=\exerwparts@cols +% width=(\linewidth-2*(n-1)*\tabcolsep)/n +%\end{verbatim} +% \begin{macrocode} + \eq@tmpdima=\linewidth +% \ifx\isitleadin\eq@NO + \advance\eq@tmpdima-\prtsIndntSep\relax +% \fi + \@tempcnta\exerwparts@cols\relax + \advance\@tempcnta-1\relax + \multiply\@tempcnta2\relax + \@tempdima\prtsIndntSep\relax + \divide\@tempdima 2\relax + \edef\halfWidth{\the\@tempdima}% +% \ifx\isitleadin\eq@YES\@tempdima0pt\fi + \advance\@tempdima\eq@partstabcolsep\relax +% \@tempdima\eq@partstabcolsep\relax + \tabcolsep\@tempdima + \multiply\@tempdima\@tempcnta + \advance\eq@tmpdima-\@tempdima + \divide\eq@tmpdima by\exerwparts@cols +% \ifx\isitleadin\eq@NO + \advance\eq@tmpdima\prtsIndntSep\relax +% \advance\eq@tmpdima\halfWidth\relax % dps17 +% \else\advance\eq@tmpdima\halfWidth\relax\fi +% \end{macrocode} +% If there is a \cs{tableadin}, we do not perform a \cs{vskip}. +% \begin{macrocode} + \if@tableadinitem\else\vskip\eq@partstabtopsep\relax\fi % dps11 + \noindent\normalbaselines\kern0pt + \prior@parts@hook\abovepartshook +% \end{macrocode} +%\changes{v7.03}{2015/03/02}{Added \texttt{>\{\cs{strut}\}}, this gives +% better control over vertical spacing.}% +% \changes{v7.4}{2015/03/23}{inserted \cmd\setTabulrSolnEnv}% +% \begin{macrocode} + \tablrIndent\tabular[t]{@{}*{\exerwparts@cols}{>{\setTabulrSolnEnv + \parskip\eqeques@parsep\relax + \parindent0pt\relax\strut}p{\eq@tmpdima}}@{\hidewidth}}% +}{\endtabular\kern0pt + \@ifundefined{@listii@SAVE}{}{\global\let\@listii\@listii@SAVE + \global\let\@listii@SAVE\relax}% + \post@parts@hook\belowpartshook +% \end{macrocode} +% \changes{v7.4}{2015/03/23}{added an adjustment to the command \cs{endexercise@parts@tabular}} +% A vertical space adjustment +% \begin{macrocode} +% \ifeq@solutionsafter\adjDisplayBelow +% \ifthereissolution\else\vskip\baselineskip\fi\fi +% \end{macrocode} +% (201/05/09) There is a problem of communicating the totals through +% the \cs{mark} command (use in \textsf{eqexam}). In \textsf{eqexam} +% the command \cs{eqe@innermarkpts} is defined. Once the group is closed +% we emit this mark. +% \begin{macrocode} + \aftergroup\eqe@innermarkpts + \aftergroup\eq@vpartstabtopsep} +% \end{macrocode} +% (201/05/09) We make a default definition for \cs{eqe@innermarkpts}, this is needed +% when \textsf{exerquiz} is used without \textsf{eqexam}. +% \begin{macrocode} +\let\eqe@innermarkpts\relax +% \end{macrocode} +% Redefine \verb+\item+, could be risky +% \begin{macrocode} +\def\item@part@tabular{\refstepcounter{partno}% +% \end{macrocode} +% As of 2013/03/25, I am allowing solutions after for tabular parts. I'm commenting +% out the following line.\\ +% |%\eq@solutionsafterfalse % no solutionsafter are allowed| +% \begin{macrocode} + \global\let\eqExerSolnHeader\@empty + \ifeq@solutionsafter + \eq@nolinktrue % no link to solution + \else\ifeq@nosolutions + \eq@nolinktrue % no link to solution + \else + \eq@ckglobalhide + \ifeq@hidesolution\eq@nolinktrue\else +% \end{macrocode} +% Write the solution header to \texttt{.sol} for tabular type question. +% \begin{macrocode} + \gdef\eqExerSolnHeader{\eq@@writeexheaderlist}% + \fi\fi\fi + \if@restorejustify\restorejustify\else\PBS\raggedright\fi + \settowidth{\eq@tmplength}{\parts@indent\eqe@prtsepPrb}% + \xdef\prtsIndntSep{\the\eq@tmplength}% + \sbox{\eq@tmpbox}{\parts@indent}% + \eq@tmpdima=\wd\eq@tmpbox + \addtolength\eq@tmplength{\eq@extralabelsep}% + \xdef\partshangamount{\the\eq@tmplength}% + \advance\linewidth-\eq@tmplength + \parshape \@ne 0pt \linewidth + \everypar{\parshape \@ne 0pt \linewidth}% + \eq@setPrbSolnAftrIndnt +% \end{macrocode} +% (2013/04/28) Inserted \texttt{[r]} +% \begin{macrocode} + \makebox[0pt][r]{\eqexlisttabheader\eqe@prtsepPrb}% + \ex@listtabheader@fterhook + \exlisttabheaderafterhook\ignorespaces +} +% \end{macrocode} +% \begin{macrocode} +\def\@ckhide[#1]{\edef\eq@arg{#1}% + \def\currhideopt{x}% + \ifx\eq@arg\@empty\else + \if\eq@arg\eq@Hid + \eq@hidesolutiontrue\eq@nolinktrue% + \edef\currhideopt{\Hidesymbol}% + \else + \ifeq@globalshowsolutions\else + \if\eq@arg\eq@hid + \eq@hidesolutiontrue\eq@nolinktrue% + \def\currhideopt{h}% + \fi + \fi + \fi\fi + \eq@item +} +% \end{macrocode} +% In the above tabular parts environment, \cs{@xtabularcr} is \cs{let} to +% equal to \cs{eq@xtabularcr}. +% \begin{macrocode} +\def\tabControlOn{\@ifundefined{@xtabularcr} + {\let\save@@xtabularcr\@xarraycr} + {\let\save@@xtabularcr\@xtabularcr}} +% \end{macrocode} +%\changes{v7.0}{2014/11/05}{Added \cs{tabControlOn} and \cs{tabControlOff}. +% Tab control is interfering with regular tabular environments, or anywhere +% \texttt{d} is used.} +% \begin{macrocode} +\def\tabControlOff{\@ifundefined{@xtabularcr} + {\let\@xarraycr\save@@xtabularcr} + {\let\@xtabularcr\save@@xtabularcr}} +\AtBeginDocument{\tabControlOn} +\def\eq@xtabularcr{\@ifnextchar[{\save@@xtabularcr} + {\eqe@tab@parts@rowsep}}% +\def\eqe@tab@parts@rowsep{\save@@xtabularcr + \noalign{\expandafter\kern\eqparts@tabrowsep}}% +% \end{macrocode} +% End of the \texttt{parts} environment. +% \end{environment} +% \begin{macrocode} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \subsection{Enumerating exercises} +% Here we provide the \texttt{exEnumerate} environment for enumerating exercises. +% We provide several key-values for adjusting the spacing of the environment. +% The keys defined here are \texttt{labelwidthTo}, \texttt{labelwidth}, \texttt{topsep}, +% \texttt{parsep},\texttt{itemsep}, \texttt{labelsep}, and \texttt{continue}.% +% \IndexKey{labelwidthTo}\IndexKey{labelwidth}\IndexKey{topsep}% +% \IndexKey{parsep}\IndexKey{itemsep}\IndexKey{labelsep}\IndexKey{continue}% +% \begin{macrocode} +\define@key{exEnum}{labelwidthTo}[\normalsize\normalfont\bfseries00.\ ]% + {\def\exE@labelwidthTo{#1}} +\define@key{exEnum}{labelwidth}[\@empty]{\def\exE@labelwidth{#1}} +\let\exE@labelwidth\@empty +\define@key{exEnum}{topsep}[3pt]{\def\exE@topsep{#1}} +\define@key{exEnum}{parsep}[3pt]{\def\exE@parsep{#1}} +\define@key{exEnum}{itemsep}[0pt]{\def\exE@itemsep{#1}} +\define@key{exEnum}{labelsep}[\normalsize\normalfont\ ]% + {\settowidth{\@tempdima}{#1}\edef\exE@labelsep{\the\@tempdima}} +\define@key{exEnum}{continue}[]{\let\eq@ExEnumResetCnt\@empty} +\def\eq@ExEnumResetCnt{\setcounter{questionno}{0}} +\setkeys{exEnum}{labelwidthTo,topsep,parsep,itemsep,labelsep}% +% \end{macrocode} +% \begin{environment}{exEnumerate} +% The environment for enumerating exercises. The companion definitions for +% these exercises follow. The argument is expanded first before being passed +% to \cs{setkeys}; therefore you can pass a command of key-value options through +% the optional argument: +% |\def\myOpts{topsep=0pt}|, |\begin{exEnumerate}[\myOpts]|. +% \begin{macrocode} +\newenvironment{exEnumerate}[1][]{\everypar{}% + \toks@=\expandafter{#1}% + \edef\tempexp{\noexpand\setkeys{exEnum}{\the\toks@}}\tempexp + \eq@ExEnumResetCnt + \let\afterlabelhskip\@empty + \let\solnhspace\@empty + \aboveexskip{0pt}\belowexskip{\exE@parsep}%\belowexskip{0pt}% + \def\eqexheader@wrapper{\makebox[0pt][r]{% + \hypertarget{qex.\the@exno}{\eqexheader}\hspace{\labelsep}}}% +% \end{macrocode} +% The next two definitions are to correctly format bookmarks for these exercises. +% \begin{macrocode} + \def\exbookmarkfmt{\thequestionno.\space} + \def\partbookmarkfmt{(\thepartno)\space} +% \end{macrocode} +% The definition of \cmd{\setEnum} supports the \texttt{contsolns} option. +% \begin{macrocode} + \def\setENum{\Elabel\if\exerstar*\thequestionno(\thepartno)\else + \thequestionno\fi}% + \ifExSolutionsSet\else + \writeToExSolns{\protect\begin{exEnumerate}}\fi + \list{}{% + \ifx\exE@labelwidth\@empty + \settowidth{\labelwidth}{\exE@labelwidthTo}\else + \setlength{\labelwidth}{\exE@labelwidth}\fi + \setlength{\topsep}{\exE@topsep}% + \ifdim\parskip>\z@\addtolength{\topsep}{-\parskip}\fi + \setlength{\parsep}{\exE@parsep}% + \setlength{\itemsep}{\exE@itemsep}% + \setlength{\itemindent}{0pt}% + \setlength{\listparindent}{0pt}% + \setlength{\itemindent}{0pt}% +% \setlength{\labelsep}{0pt}% + \settowidth{\labelsep}{\normalfont\ }% + \setlength{\leftmargin}{\labelwidth}% + }\item\relax}{\ifExSolutionsSet\else + \writeToExSolns{\protect\end{exEnumerate}}\fi +\endlist} +% \end{macrocode} +% \end{environment} +% \begin{environment}{enumex} +% \begin{environment}{enumex*} +% Prototype environments for enumerating exercises. These can be redefined as desired. +% \begin{macrocode} +\newenvironment{enumex}{% + \renewcommand\exlabelformat{\textbf{\thequestionno.}}% + \renewcommand\exsllabelformat + {\protect\makebox[0pt][r]{\protect\textbf{\thequestionno.\ }}}% +\begin{exercise}[questionno]}{\end{exercise}} +\newenvironment{enumex*}{% + \renewcommand\exlabelformatwp{\textbf{\thequestionno.}}% + \renewcommand\exsllabelformatwp + {\protect\makebox[0pt][r]{\protect\textbf{\thequestionno.}\ }% + \protect\textbf{(\thepartno)}\ }% +\begin{exercise*}[questionno]}{\end{exercise*}} +% \end{macrocode} +% \end{environment} +% \end{environment} +% \begin{macrocode} +%</package> +%<*package|eqexam> +% \end{macrocode} +% \subsection{Including the \texttt{exercise} Solutions} +% Include solutions to the exercises back into the file. This +% section also handles solutions to quizzes as well. This macro +% was taken from the \TeX book. +% \begin{macro}{\includeexersolutions} +% This macro inserts the solutions to the exercises, if there are +% any solutions. If a user uses this macro to insert the solutions +% elsewhere, \cmd{\include@solutions} is called, then put is to +% \cmd{\relax}. +% \begin{macrocode} +%\def\includeexersolutions{% +\def\includeexersolutions{\@ifstar + {\let\resetEXsolns\relax\includeexersolutionsi} + {\def\resetEXsolns{\global\let\include@solutions\relax}% + \includeexersolutionsi}% +} +\newcommand{\includeexersolutionsi}[1][]{% + \filterFor{#1}\includeexersolutionsii +} +\def\includeexersolutionsii{% +%</package|eqexam> +%<*package> + \if\exerSolns@ExtFile\eq@NO +%</package> +%<*package|eqexam> +% \end{macrocode} +% \cmd{\include@solutions} is the internal command that insert solutions. This command +% appears at the end of document, where it will insert the +% solutions, unless it has been redefined to \cmd{\relax} by +% \cmd{\includesolutions}. +% \begin{macrocode} + \include@solutions + \resetEXsolns + \let\eqFilterArg\@empty +%</package|eqexam> +%<*package> + \fi +%</package> +%<*package|eqexam> +} +% \end{macrocode} +% +%\subsection{Filtering solutions to exercises} +% +% The \cs{eqEXt} command has two arguments designed to be used to filter +% solutions to exercises. The demo document is \texttt{filter\_exercises.tex}, +% but basically, we can include the solutions several times, once for each set filtered set. +% \begin{macrocode} +\long\def\gobbleToEndEXt#1\endeqEXt{% + \ifeqforpaper\expandafter\@gobbletwo\fi} +% \end{macrocode} +% \DescribeMacro\filterFor is used to mark a exercise with a name +% \begin{macrocode} +\newcommand\filterFor[1]{\def\eqFilterArg{#1}} +\newcommand\inclEXtFilter[2]{\def\eqargii{#2}\ifx\eqargii\eqFilterArg + \else\expandafter\gobbleToEndEXt\fi} +% \end{macrocode} +% \end{macro} +% \DescribeMacro\useEXtFilter is used to \cs{let} \cs{eqEXt} to \cs{EXtFilter}, which does the +% filtering based on the value of \cs{eqFilterArg}. +% \begin{macrocode} +\newcommand\useEXtFilter{\let\eqEXt\inclEXtFilter} +% \end{macrocode} +% The basic methodology is as follows: We use \cs{filterFor} to mark an exercise, or block +% of exercises by a name, for example, \verb!\filterFor{Problems}!. Now, at the end of the document, we can +% say +%\begin{verbatim} +%\useEXtFilter +%\renewcommand\exsectitle{Solutions to Exercises} +%\includeexersolutions*[Exercises] +%\renewcommand\exsectitle{Solutions to Examples} +%\includeexersolutions*[Examples] +%\renewcommand\exsectitle{Solutions to Problems} +%\includeexersolutions[Problems] +%\end{verbatim} +% \DescribeMacro{\eqsolutionshook}\DescribeMacro{\priorexsectitle} +% \DescribeMacro{\priorexslinput} These are commands that can be +% redefined by the user, their location can be found below. +% \begin{macrocode} +\let\eqsolutionshook\@empty +\let\eq@solutionshook\@empty +\let\priorexsectitle\@empty +\let\priorexslinput\@empty +% \end{macrocode} +%\DescribeMacro{\exerSolnsHeadnToc} sets the section title for the solutions +% to the exercises. May be redefined, I suppose. +% \begin{macrocode} +\def\exerSolnsHeadnToc{\section*{\exsectitle}% + \addcontentsline{toc}{section}{% + \@ifundefined{web@latextoc}{}{% + \ifx\web@latextoc\eq@YES\else + \protect\numberline{}\fi}\exsectitle}} +% \end{macrocode} +%\changes{v6.4q}{2012/03/23}{define \cs{eq@defaultlheader}} +% Determine whether \textsf{web} package is loaded, and define \cs{eq@normallheader} +% and \cs{eq@defaultlheader}. These are designed to fix a problem of disappearing +% headers in the solutions section of the document. +% \begin{macrocode} +\@ifpackageloaded{web}{\def\eq@normallheader{\lheader{\rightmark}}} + {\let\eq@normallheader\relax} +\@ifpackageloaded{web}{\def\eq@defaultlheader{\lheader{\aeb@setmarks}}} + {\let\eq@defaultlheader\relax} +% \end{macrocode} +% \DescribeMacro{\exerSolnInput} is the macro that formats the opening page +% of the solutions page and inputs \cmd{\jobname.sol}. +% \begin{macrocode} +\newif\ifExSolutionsSet \ExSolutionsSetfalse +\newcommand{\exerSolnInput} +{% + \@ifundefined{eqe@IWO}{}{\ifsolutionsAtEnd%\ifvspacewithsolns + \eqe@IWO\@auxout{\string\expandafter\string\gdef + \string\csname\space eqExamQuesLastPage\string\endcsname + {\arabic{page}}}\fi} + \let\webnewpage\relax + \ifsolutionsonly\else\immediate\closeout\ex@solns\fi + \ifeq@nosolutions\else +% \end{macrocode} +%\changes{v6.3w}{2011/03/15}{% +% Moved \cs{eqsolutionshook} from below to a higher position +% in the macro \cs{exerSolnInput} so the running header for +% the solution page appears on the first page of the solutions. +%}% +% Moved the following line to two location below. +% \begin{macrocode} +% \eqsolutionshook % moved 2012/02/24 +% \end{macrocode} +% \changes{v6.4p}{2012/02/24}{Moved location of \cs{eqsolutionshook} again}% +% \begin{macrocode} + \iftherearesolutions + \ifsolutionsonly\eq@solutionshook + \eqsolutionshook + \else +% \end{macrocode} +% If there are solutions and this is not the \texttt{solutionsonly} option, +% we start a new page, clear the right mark and start a normal header. +% \changes{v6.4q}{2012/03/23}{Inserted \cs{eq@normalheader} after \cs{newpage} +% to get running headers to appear on each page of solutions}% +% Inserted |\markright{}| and \cs{eq@normalheader} to fix a problem with +% disappearing running headers. +% \begin{macrocode} + \newpage\eq@solutionshook + \eqsolutionshook\markright{}\eq@normallheader + \fi +% \end{macrocode} +% We are still under the assumption that there are solutions to be input. +% We set the mark of \cs{exsectitle}. +% \begin{macrocode} + \markright{\exsectitle}% + \ifx\webnewpage\relax +% \end{macrocode} +% \cs{webnewpage} is a mechanism to initially do nothing, then +% to be redefined to \cs{newpage}. It is used in \cs{exerSolnHeader}. +% The reasons for this definition are lost in time. +% \begin{macrocode} + \def\webnewpage{\let\webnewpage\newpage}% + \fi +% \end{macrocode} +% We have a prior command, followed by the section title +% \cs{exerSolnsHeadnToc}, followed by a post command. The prior and +% post commands may be defined as the document author wishes. +% Both of these are used in the \textsf{APB} pacakge. +% \begin{macrocode} + \priorexsectitle\exerSolnsHeadnToc\priorexslinput +% \end{macrocode} +% Finally, we input the solutions file, \cs{jobname.sol}, if one exists. +% \begin{macrocode} + \InputIfFileExists{\jobname.sol} + {\global\ExSolutionsSettrue}{\PackageWarning{exerquiz} + {!!! Solutions to exercises not found}}% + \global\ExSolutionsSetfalse +% \end{macrocode} +% Convert back to \cs{eq@defaultlheader} cleanly by first executing \cs{newpage} +% \begin{macrocode} + \newpage\eq@defaultlheader + \fi + \fi +} +% \end{macrocode} +% The \cs{include@solutions} is a wrapper command for \cs{exerSolnInput} +% \begin{macrocode} +\def\include@solutions{% +%</package|eqexam> +%<*package> + \if\exerSolns@ExtFile\eq@NO +%</package> +%<*package|eqexam> + \exerSolnInput +%</package|eqexam> +%<*package> + \fi +%</package> +%<*package|eqexam> +} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \subsection{Bookmarking Exercises} +% +% Someone asked how to bookmark the exercises, it was an interesting +% little exercise for a Saturday morning. So, here it is. +% \par\medskip\noindent +% \cs{eqexpdfentry} marks first entry into an exercise. +% \begin{macrocode} +\let\eqexpdfentry=0 +% \end{macrocode} +% \cs{eq@postexerciseHook}: Restores the \cs{Hy@currentbookmarklevel} bookmark level to what it was when +% we first entered the exercise. This is executed at the end of the exercise +% environment. +% \begin{macrocode} +\let\eq@postexerciseHook\relax +\def\eq@postexerciseHook@BM{% + \xdef\Hy@currentbookmarklevel{\eq@currentbookmarklevel}} +% \end{macrocode} +% \begin{macro}{\exbookmarkfmt} +% \begin{macro}{\partbookmarkfmt} +% \begin{macro}{\expdfbookmark} +% ``Intelligent'' bookmarking for \textsf{Exerquiz} exercises. Detects the correct bookmark level +% determines if this is a part of an exercise, or the entry into an exercise and +% automatically sets a unique destination. +% +% \cs{expdfbookmark} is the main interface to bookmarking an exercise. The single argument +% is the text that is to appear in the bookmark panel. \cs{exbookmarkfmt} and +% \cs{partbookmarkfmt} formats the exercise number and part letter. These can be redefined. +% +%\changes{v6.2a}{2007/11/10 } +%{ +% Added \cs{expdfbookmark} to bookmark exercises. +%} +% We have to increase the \texttt{tocdepth} so hyperref will create the bookmark at the +% subsection level. +% \begin{macrocode} +{\count0=\value{tocdepth} +\advance\count0by2 \xdef\eqbmkmrkdepth{\the\count0}} +\@ifundefined{Hy@bookmarksdepth} + {\setcounter{tocdepth}{\eqbmkmrkdepth}} + {\hypersetup{bookmarksdepth=\eqbmkmrkdepth}} +\newcommand{\exbookmarkfmt}{\exlabel\space\theeqexno.\space} +\newcommand{\partbookmarkfmt}{(\thepartno)\space} +\newcommand{\expdfbookmark}[1]{\relax + \def\expdfbookmarktitle{#1}% +% \end{macrocode} +% The default definition of \cs{eq@postexerciseHook} is \cs{relax}. We'll +% check if someone is using \cs{eq@postexerciseHook}. +% \begin{macrocode} + \ifx\eq@postexerciseHook\relax + \let\eq@postexerciseHook\eq@postexerciseHook@BM + \else +% \end{macrocode} +% Yes, \cs{eq@postexerciseHook} is in use, we'll add our stuff onto the end of it. +% \begin{macrocode} + \let\eq@postexerciseHook@save\eq@postexerciseHook + \def\eq@postexerciseHook@BM@plus{\eq@postexerciseHook@save + \eq@postexerciseHook@BM}% + \let\eq@postexerciseHook\eq@postexerciseHook@BM@plus + \fi + \if\exerstar*% +% \end{macrocode} +% If entering an exercise with parts for the first time, we also capture current bookmark level, +% and mark, using \cs{eqexpdfentry} that we have entered an exercises with parts. +% \begin{macrocode} + \if\eqexpdfentry0\let\eqexpdfentry=1 + \xdef\eq@currentbookmarklevel{\Hy@currentbookmarklevel}% + \def\eqex@next{\subpdfbookmark{\exbookmarkfmt#1}% + {qex.\the@exno}}% + \else +% \end{macrocode} +% Already in an exercise with parts, no need to reduce bookmark level again +% \begin{macrocode} + \def\eqex@next{\belowpdfbookmark{\partbookmarkfmt#1}% + {qex.\the@exno.\thepartno}}% + \fi + \else +% \end{macrocode} +% A regular exercise, no parts, we also capture current bookmark level +% \begin{macrocode} + \xdef\eq@currentbookmarklevel{\Hy@currentbookmarklevel}% + \def\eqex@next{\subpdfbookmark{\exbookmarkfmt#1}% + {qex.\the@exno}}% + \fi + \eqex@next\ignorespaces +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \section{Early end of input} +% +% There is no support for the Acrobat Forms features with the +% \texttt{dviwindo} option by \textsf{hyperref}; therefore there is +% none here as well. \textsf{dviwindo} can use the +% \texttt{exercise} environment, but not the quizzes, so end here. +% \begin{macrocode} +\ifeq@noforms\endinput\fi +% \end{macrocode} +% \section{Common code for quizzes.} +% Here, we include a few commands common to both +% quiz environments. +% +% Colors used by \textsf{exerquiz}: \texttt{webgreen} normally defined in \textsf{web} +% \begin{macrocode} +\definecolor{webgreen}{rgb}{0,.6,0} +% \end{macrocode} +% \begin{macro}{\proofingsymbol} +% \begin{macro}{\proofingsymbolColor} +% Proofing symbol and accompanying color (little green bullet) +% \changes{v6.05b}{2006/05/12} +% { +% added a command to change the color of the proofing symbol +% changed the definition of \cs{proofingsymbol} to a text fillin. This creates the command +% \cs{@proofingsymbol}. Can now control the symbol and the color (through \cs{proofingsymbolColor} +% } +% \begin{macrocode} +\newcommand{\proofingsymbolColor}[1]{\def\@proofingsymbolColor{#1}} +\proofingsymbolColor{red} +%\newcommand{\proofingsymbol}[1]{% +% \def\@proofingsymbol{\textcolor{\@proofingsymbolColor}{#1}}} +%\proofingsymbol{$\bullet$} +%\proofingsymbol{\ding{52}} +\let\@proofsymbolredefined=0 +\newcommand{\proofingsymbol}[1]{\let\@proofsymbolredefined=1% + \def\@proofingsymbol{\textcolor{\@proofingsymbolColor}{#1}}} +\def\@proofingsymbol{\textcolor{\@proofingsymbolColor}{\ding{52}}} +\def\setproofingsymbol{% + \if\@proofsymbolredefined1\else + \@ifpackageloaded{pifont}{\proofingsymbol{\ding{52}}} + {\proofingsymbol{$\bullet$}}\fi +} +\AtBeginDocument{\setproofingsymbol} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +%</package> +%<*package|eqexam> +% \end{macrocode} +% +% \subsection{The \texttt{questions} Environment} +% The \texttt{questions} environment is used inside the +% \texttt{shortquiz} and \texttt{quiz} environments, though it can +% also be used a stand alone list. Beginning with version 5.5, the \texttt{questions} +% environment can be nested three deep. +% \begin{macro}{questions} +% This is a redesigned \texttt{list} environment. +% \begin{macrocode} +\newcommand{\prior@questionsHook}{} +\let\qMark@Hook\@empty +\let\aebtitleQuiz\@empty +\newcommand{\post@questionsHook}{} +\newcommand{\quesNumColor}[1]{\def\eq@quesNumCol{#1}} +\quesNumColor{blue} +\renewcommand{\theeqquestionnoi}{\arabic{eqquestionnoi}} +\newcommand{\labeleqquestionnoi}{% + \color{\eq@quesNumCol}\bfseries\theeqquestionnoi.} +\renewcommand\theeqquestionnoii{(\alph{eqquestionnoii})} +\newcommand{\labeleqquestionnoii}{% + \color{\eq@quesNumCol}\bfseries\theeqquestionnoii} +\renewcommand\theeqquestionnoiii{(\roman{eqquestionnoiii})} +\newcommand{\labeleqquestionnoiii}{% + \color{\eq@quesNumCol}\bfseries\theeqquestionnoiii} +% \end{macrocode} +% \paragraph*{Properties of the questions environment.} (2013/07/10) These include +% \IndexKey{labelwidthTo}\texttt{labelwidthTo} and +% \IndexKey{labelwidth}\texttt{labelwidth}. +% \begin{macrocode} +\define@key{props@ques}{labelwidthTo}% + [\normalsize\normalfont\bfseries00.]% + {\def\propQ@labelwidthTo{#1}} +\define@key{props@ques}{labelwidth}[]{\def\propQ@labelwidth{#1}} +\let\propQ@labelwidth\@empty +% \end{macrocode} +% \IndexKey{topsep}\texttt{topsep}, \IndexKey{partopsep}\texttt{partopsep}, +% \IndexKey{parsep}\texttt{parsep}, and \IndexKey{itemsep}\texttt{itemsep}. +% \begin{macrocode} +\define@key{props@ques}{topsep}[\the\topsep]{\edef\propQ@topsep{#1}} +\define@key{props@ques}{partopsep}[\the\partopsep]% + {\edef\propQ@partopsep{#1}} +\define@key{props@ques}{parsep}[\the\parsep]{\edef\propQ@parsep{#1}} +\define@key{props@ques}{itemsep}[\the\itemsep]{\edef\propQ@itemsep{#1}} +% \end{macrocode} +% \IndexKey{labelsepTo}\texttt{labelsepTo} and \IndexKey{labelsep}\texttt{labelsep} +% \begin{macrocode} +\define@key{props@ques}{labelsepTo}[\normalsize\normalfont\ ]% + {\def\propQ@labelsepTo{#1}} +\define@key{props@ques}{labelsep}[\@empty]{\def\propQ@labelsep{#1}} +\let\propQ@labelsep\@empty +% \end{macrocode} +% \IndexKey{color}\texttt{color} +% \begin{macrocode} +\define@key{props@ques}{color}[blue]{\quesNumColor{#1}} +% \end{macrocode} +% The default properties of the \texttt{questions} environment. +% \begin{macrocode} +\setkeys{props@ques}{labelwidthTo,topsep,partopsep,parsep,% + itemsep,labelsepTo,color}% +% \end{macrocode} +% Now we begin the \texttt{questions} environment. There is an optional parameter +% wherein we pass the key-value pairs defined above. +% \begin{macrocode} +\newenvironment{questions}[1][] +{% + \ifnum\@eqquestiondepth>\tw@\@toodeep\else + \advance\@eqquestiondepth\@ne\fi + \def\@quesctr{eqquestionno\romannumeral\the\@eqquestiondepth}% + \toks@=\expandafter\expandafter\expandafter{#1}\expandafter + \xdef\csname quesOpts\@quesctr\endcsname{\the\toks@}% + \edef\tempexp{\noexpand\setkeys{props@ques}{\the\toks@}}\tempexp + \list{\qMark@Hook\prior@questionsHook\gdef\eqPTs{1}% + \global\let\eqQT\eq@na% +% \end{macrocode} +% (06/06/10) We create a macro \cs{@currentQues} that holds the current +% problem number 2(a)(i), for example. +% \begin{macrocode} + {\@tempcnta=0 \let\@thispr@b\@empty + \@whilenum\@tempcnta<\@eqquestiondepth\do{\advance\@tempcnta\@ne + \ifx\@thispr@b\@empty\edef\@thispr@b{% + \csname theeqquestionno\romannumeral\the\@tempcnta\endcsname}\else + \edef\@thispr@b{\@thispr@b% + \csname theeqquestionno\romannumeral\the\@tempcnta\endcsname}\fi + }\xdef\@currentQues{\@thispr@b}}% + \makebox[\labelwidth][r]{\normalfont\@nameuse{label\@quesctr}}% + \xdef\eq@pageThisQ{\the\c@page}% + \post@questionsHook}{\usecounter{\@quesctr}% +% \end{macrocode} +% We set the list parameter for the \texttt{questions} environment. +% \begin{macrocode} + \ifx\propQ@labelsep\@empty + \settowidth{\labelsep}{\propQ@labelsepTo}\else + \setlength{\labelsep}{\propQ@labelsep}\fi + \ifx\propQ@labelwidth\@empty + \settowidth{\labelwidth}% + {\propQ@labelwidthTo\hspace{\labelsep}}\else + \settowidth{\labelwidth}{\hspace{\propQ@labelwidth}% + \hspace{\labelsep}}\fi + \setlength{\topsep}{\propQ@topsep}% + \setlength{\partopsep}{\propQ@partopsep}% + \ifdim\parskip>\z@\addtolength{\topsep}{-\parskip}\fi + \setlength{\parsep}{\propQ@parsep}% + \setlength{\itemsep}{\propQ@itemsep}% + \setlength{\itemindent}{0pt}% + \setlength{\leftmargin}{\labelwidth}% + }% +% \setlength{\labelsep}{\propQ@labelsep}}% +}{\endlist} +% \end{macrocode} +% \begin{macro}{\pushquestions} +% \begin{macro}{\popquestions} +% Between \cs{item}s within a question environment, you can execute +% \cs{pushquestions}, this save the question counter, you are then free +% to make comments between problem, when finished, executed a \cs{popquestions} +% to return to questioning where you left off. +% \begin{macrocode} +\def\pushquestions{\expandafter\xdef\csname save\@quesctr\endcsname + {\expandafter\the\csname c@\@quesctr\endcsname}\end{questions}} +\def\popquestions{% + \begin{questions}[\csname quesOpts\@quesctr\endcsname]% + \setcounter{\@quesctr}{\csname save\@quesctr\endcsname}% + \@ifnextchar\popquestions{\item[]}{\@ifnextchar\begin{\item[]}{}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \section{The \texttt{shortquiz} and \texttt{shortquiz*} Environments} +% +% This \texttt{shortquiz} environment sets up multiple choice +% questions, with immediate feedback whether the user clicked on the +% right or wrong answer. Solutions to the \texttt{shortquiz} may, +% or may not be included. +% \begin{environment}{shortquiz} +% The \texttt{shortquiz} environment, really just a shell to define the +% \cmd{\Ans} macro and the \texttt{solution} environment that go with +% the \texttt{shortquiz} +%\par\medskip\noindent +% After all the parsing is done, the parameters for this environment are +%\begin{verbatim} +% \begin{shortquiz}*[<basename>] +%\end{verbatim} +%The `\texttt{*}' is optional and signals that forms should be used instead +%of links. This option is regressed. The user should use the \texttt{shortquiz*} +% environment. The \verb![<basename>]! is the basename of any form fields +% generated. If not present, an base fieldname is generated based on the +% \cs{@shortquizCnt} macro (not a counter). The actual name is given in \cs{@sqGenBaseName}. +%\par\medskip\noindent +% \DescribeMacro{\priorsqhook}\cmd{\priorsqhook} and \DescribeMacro{\abovesqskip}\cmd{\abovesqskip} +% are early hooks and skips. +% \begin{macrocode} +\newcommand{\priorsqhook}[1]{\def\sq@priorhook{#1}} +\priorsqhook{} +\newcommand{\abovesqskip}[1]{\def\sq@aboveskip{#1}} +\abovesqskip{\par\medskip} +% \end{macrocode} +%\changes{v6.4a}{2011/05/11}{% +% Added \cs{sq@afterhook} for use by \textsf{eqexam}, but may be useful elsewhere. +%} +%\DescribeMacro\endsqhook\cmd\endsqhook is a late hook +% \begin{macrocode} +\long\def\endsqhook#1{\def\sq@afterhook{#1}} +\endsqhook{} +\def\@shortquizCnt{0} +\def\@sqGenBaseName{eqSqBn\@shortquizCnt} +% \end{macrocode} +%\DescribeMacro\sqhspace\cmd\sqhspace\ is the space that follows \cmd\sqlabel +% \begin{macrocode} +\let\sqhspace\space +\newenvironment{shortquiz} +{% +% \end{macrocode} +% (06/08/10) The next two lines initialize the macros for registering the +% question label, i.e., \texttt{2(a)(ii)}. These two lines are repeated for +% the \texttt{oQuestion} and \texttt{quiz} environments. +% \begin{macrocode} + \xdef\eq@pageThisQ{\the\c@page}% + \let\@currentQues\@empty + {\count0=\@shortquizCnt \advance\count0by1\relax + \xdef\@shortquizCnt{\the\count0}}% + \goodbreak\@ifstar{\sqForms\@shortquiz}% + {\if\aeb@FLOverride\eq@f\def\sqstar{*}\else + \def\sqstar{}\sqLinks\fi\@shortquiz}% +}{\aeb@endshortquiz} +% \end{macrocode} +% \end{environment} +% \begin{environment}{shortquiz*} +% The \texttt{shortquiz*} is a short quiz that uses forms. +%\par\medskip\noindent +% The parameter for this environment is +%\begin{verbatim} +% \begin{shortquiz}[<basename>] +%\end{verbatim} +% The \verb![<basename>]! is the basename of any form fields +% generated. If not present, an base fieldname is generated based on the +% \cs{@shortquizCnt} macro (not a counter). The actual name is given in \cs{@sqGenBaseName}. +% \begin{macrocode} +\newenvironment{shortquiz*} +{% + \xdef\eq@pageThisQ{\the\c@page}% + {\count0=\@shortquizCnt\advance\count0by1\relax + \xdef\@shortquizCnt{\the\count0 }}% + \sqForms\@shortquiz +}{\aeb@endshortquiz} +% \end{macrocode} +% Determines if the next argument is optional, if yes, we pass to +% \cs{@@shortquiz}, else, we supply a automated form name, then +% continue to \cs{@@shortquiz}. +% \begin{macrocode} +\def\@shortquiz{\@ifnextchar[% + {\@@shortquiz}{\@@shortquiz[\@sqGenBaseName]}} +% \end{macrocode} +% \end{environment} +% \cs{@@shortquiz} continues the parsing of \texttt{shortquiz} and \texttt{shortquiz*}. +% Here we take in the basename for any fields generated. The basename is passed +% as a delimited parameter \texttt{\#1}. +% \begin{macrocode} +\def\sq@setCLN#1{\ifx\aebTitleQuiz\@empty + \protected@edef\@currentlabelname{#1}\else + \protected@edef\@currentlabelname{\@currentlabelname}\fi +} +% \end{macrocode} +% (2013/09/29) Added \cs{isQZ} and \cs{isSQZ} +% \begin{macrocode} +\let\isQZ=q \let\isSQZ=s +%</package|eqexam> +%<*package> +\def\sq@IDTxtField{\makebox[0pt][l]{\textField[\autoCenter{n}\BC{}\BG{} + \S{S}\textSize{0}\Ff{\FfReadOnly} + \AA{\AAFormat{% + var \oField=new Object;\r + \oField.Grp={}; + \ifx\defaultColorJSLoc\@empty\else\r + \oField.DefaultColorJSLoc=\defaultColorJSLoc;\fi + \ifx\rghtColorJSLoc\@empty\else\r + \oField.RightColorJSLoc=\rghtColorJSLoc;\fi + \ifx\wrngColorJSLoc\@empty\else\r + \oField.WrongColorJSLoc=\wrngColorJSLoc;\fi + \ifx\rghtAnsSymbJSLoc\@empty\else\r + \oField.RightAnsSymbJSLoc=\rghtAnsSymbJSLoc;\fi + \ifx\wrngAnsSymbJSLoc\@empty\else\r + \oField.WrongAnsSymbJSLoc=\wrngAnsSymbJSLoc;\fi + }}]{sqID\oField}{0bp}{0bp}}% +} +%</package> +%<*package|eqexam> +\def\@@shortquiz[#1]{%\begingroup + \gdef\oField{#1}\gdef\curr@quiz{#1}\gdef\currQuiz{#1}% +% \end{macrocode} +% We try to support {\LaTeX}'s cross-referencing system by defining +% \cs{@currentlabel}, \cs{@currentHlabel}, and \cs{@currentlabelname}. +% \begin{macrocode} + \global\let\eqQzQuesList\@empty + \let\eq@AddProbToQzQuesList\relax + \edef\@currentlabel{\@shortquizCnt}% + \edef\@currentHref{shortquiz.\@shortquizCnt}% + \global\let\eqQuizType\isSQZ\let\@qzsolndest\@empty + \if\sqstar*\relax + \let\@Ans\Ans@sq@f + \ifx\oField\@empty + \typeout{^^JExerquiz: Base field name required when using + shortquiz with '*' option}% + \PackageInfo{exerquiz}{Assuming link style^^J}% + \let\@Ans\Ans@sq@l + \fi + \else + \let\@Ans\Ans@sq@l + \fi + \setcounter{questionno}{0}% + \let\answers\answers@sq + \let\endanswers\endanswers@sq + \let\manswers\manswers@sq + \let\endmanswers\endmanswers@sq + \let\solution\solution@sq + \let\endsolution\endsolution@sq +% \end{macrocode} +% Lay down the question header. \cs{sqlabel} defaults to a red ``Quiz''. +% \begin{macrocode} +%</package|eqexam> +% \end{macrocode} +% The next segment is for \textsf{exerquiz} only, and not for eqexam. +% \begin{macrocode} +%<*package> + \let\ifstaroption\eq@ifstaroption + \if\eq@tq@star*% +% \end{macrocode} +% The next code lines supports the \cs{titleQuiz*} option. +% If its the star option, we define \cs{sqlabel}, and finished up with +% a \cs{@gobbletwo}, this eats up the next two tokens that immediately +% follow \cs{sqlabel} in the beginning of the \texttt{shortquiz} environment. +% \begin{macrocode} + \def\sqlabel{\aebtitleQuiz\@gobbletwo}% + \fi +% \end{macrocode} +% When the online (or email) options are used in eqexam, the \cs{hypertarget} +% command is adding vertical space. Normally \cs{sqlabel} is empty, so we don't +% need \cs{hypertarget} in this case here. +% \begin{macrocode} + \sq@aboveskip\sq@priorhook + \@ifundefined{PointsOnLeft}% + {\sq@setCLN{\eq@defaultShortQuizLabelName}% + \ifx\sqlabel\@empty\else\noindent\fi + \hypertarget{sqH\@currentHref}{}\sq@IDTxtField + \ifx\sqlabel\@empty\else\expandafter + \sqlabel\expandafter\sqhspace\fi + {\set@typeset@protect\aebtitleQuiz}}{}\ignorespaces +%</package> +%<eqexam> \sq@aboveskip\sq@priorhook\ignorespaces +%<*package|eqexam> +} +% \end{macrocode} +% \begin{macro}{\aeb@endshortquiz} +% \begin{macro}{\aftershortquizskip} +% We reset the labels to the default in case the author +% of the document has redefined them temporarily. The author can +% avoid this reset, by redefining the global variables. +% \begin{macrocode} +\newcommand\belowsqskip[1]{\def\aftershortquizskip{#1}} +\belowsqskip{\medskip} +\def\aeb@endshortquiz{\setcounter{quizno}{0}% + \sq@afterhook +%</package|eqexam> +%<*package> + \global\let\aebtitleQuiz\@empty + \global\let\aebTitleQuiz\@empty + \global\let\eq@tq@star\relax +%</package> +%<*package|eqexam> + \global\let\sqlabel\eq@sqlabel + \global\let\sqslrtnlabel\eq@sqslrtnlabel + \global\let\sqsllabel\eq@sqsllabel + \par\aftershortquizskip +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\sqLinks} +% \begin{macro}{\sqForms} +% (01/01/05) Use these two commands to locally change the style of multiple choice +% questions: link or form. +% \begin{macrocode} +\def\sqLinks{\def\sqstar{}}\sqLinks +\def\sqForms{\def\sqstar{*}} +\let\eq@tq@star\relax +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +%</package|eqexam> +%<*package> +% \end{macrocode} +% The \texttt{shortquiz} contains two other environments, each nested inside +% the next: The \texttt{answers} environment and the \texttt{solution} +% environment. The latter environment is optional. +% +% \smallskip\noindent\textbf{Basic Usage for the \texttt{shortquiz} environment} +%\begin{verbatim} +%No solutions included With Solutions +%\begin{shortquiz} \begin{shortquiz} +%The question The question +%\begin{answers} \begin{answers}[qz:mysoln] +%\Ans1 ... &\Ans0 &... &\Ans0 ... \Ans1 ... &\Ans0 &... &\Ans0 ... +%\end{answers} \begin{solution} +%\end{shortquiz} ..... +% \end{solution} +% \end{answers} +% \end{shortquiz} +%\end{verbatim} +% To further complicate matters, the \texttt{shortquiz} can be +% used with the \texttt{questions} environment to create a series of +% numbered short question quizzes. See the manual for examples. +% \texttt{solution} environment is defined next. +% \begin{macro}{solution} +% The \texttt{solution} environment does double duty, it is used by both +% the \texttt{shortquiz} and \texttt{quiz} environments. +% The macro \cmd{\solution@sq} is the one that actually does the work +% of \cmd{\solution}: It writes the solutions to the file +% \cmd{\jobname.qsl}. This macro obeys the \texttt{forpaper} +% option. In this case, solutions are separated by a +% \cmd{\medskip} rather then put on a separate page. It also +% obeys the \texttt{solutionsafter} option +% \changes{v6.4s}{2012/06/03}{Added hooks \cmd{\sqPostHeaderHook} and +% \cmd{\qPostHeaderHook}} +%\par\medskip\noindent +% Hooks \DescribeMacro\sqPostHeaderHook\cmd{\sqPostHeaderHook}, +% \DescribeMacro\qzPriorSolutionAfterHook\cmd\qzPriorSolutionAfterHook, +% \DescribeMacro\qPostHeaderHook\cmd{\qPostHeaderHook} +% \begin{macrocode} +%</package> +%<*package|eqexam> +\def\qzPriorSolutionAfterHook{\smallskip} +\let\sqPostHeaderHook\@empty +\let\qPostHeaderHook\@empty +% \end{macrocode} +% Private versions of the two above. Used by the \texttt{contsolns} option +% \begin{macrocode} +\let\eq@sqPostHeaderHook\@empty +\let\eq@qPostHeaderHook\@empty +\let\prior@eqQt\@empty +\let\prior@eqSQt\@empty +% \end{macrocode} +% \DescribeMacro\sqsolafterhspace The space after the solution label +% \begin{macrocode} +\def\sqsolafterhspace{\space} +\def\solution@sq{\let\eq@next\relax + \ifx\@qzsolndest\@empty + \PackageWarning{exerquiz}% + {* Solutions unexpected here, will *\MessageBreak + * assume solutionsafter option *}% + \eq@solutionsaftertrue + \fi + \ifeq@solutionsafter + \par\qzPriorSolutionAfterHook\noindent + \if!\sqsolafter!\else + \sqsolafter\sqsolafterhspace\fi\ignorespaces + \else + \global\therearequizsolutionstrue\let\verbatim@out=\quiz@solns + \set@display@protect + \immediate\write\verbatim@out{% +% \end{macrocode} +% Mark in the solutions files whether this is a quiz or a shortquiz solution. +% \begin{macrocode} + \if\eqQuizType\isQZ + \ifx\prior@eqQt\@empty\else\prior@eqQt\fi + \protect\eqQt{\eqFilterArg}\else + \ifx\prior@eqSQt\@empty\else\prior@eqSQt\fi + \protect\eqSQt{\eqFilterArg}\fi + \protect\quizSolnHeader\if\eqQuizType\isQZ\ifx\allow@peek\eq@NO + [{\curr@quiz}{\currQuizStartPage}]\fi\fi + {\@qzsolndest}{\sqsllabel}\protect\eqterminex + \if\eqQuizType\isQZ\expandafter\eq@qPostHeaderHook + \expandafter\qPostHeaderHook\else + \expandafter\eq@sqPostHeaderHook + \expandafter\sqPostHeaderHook\fi}% + \set@typeset@protect + \expandafter\verbatimwrite\fi +} +\let\qzSolutionsAfterHook\@empty +\def\endsolution@sq +{% + \ifeq@solutionsafter + \eq@fititin{\mbox{\sqslrtnlabel}}\par\qzSolutionsAfterHook + \aftergroup\ignorespaces + \else + \endverbatimwrite + \ifx\@qzsolndest\@empty\else\set@display@protect + \immediate\write\verbatim@out{\eqSqSolnTrailer}% + \set@typeset@protect + \fi + \fi + \global\let\@qzsolndest\@empty +} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \DescribeMacro{\promoteNewPageHere}\cmd{\promoteNewPageHere} promotes +% a new page. The argument is a vertical skip. If there is \texttt{\#1} +% or more space remaining on the page, the command does nothing, otherwise +% it issues a \cs{newpage}. +% \changes{v6.4s}{2012/06/03}{Added \cs{promoteNewPageHere}} +% \changes{v6.8a}{2014/01/01}{Made an optional argument, but test for required argument as swell.} +% \begin{macrocode} +\newcommand\pnphDflt{.1\textheight} +\newcommand{\promoteNewPageHere}[1][\pnphDflt]{% + \@ifnextchar\bgroup{\eq@promoteNewPageHere} + {\eq@promoteNewPageHere{#1}}% +} +\def\eq@promoteNewPageHere#1{\par + \bgroup\@nobreakfalse\addpenalty{-500}% + \setlength{\@tempdimb}{#1}% + \@tempdima \pagegoal \advance \@tempdima -\pagetotal + \ifdim \@tempdima<\@tempdimb\ifnum\col@number>\@ne\columnbreak + \else\newpage\penalty1\fi\fi\egroup +} +% \end{macrocode} +% \begin{macro}{\saveDest} +% \begin{macro}{\useDest} +% These two macros are used, as needed to save the destination name of a solution, then +% re-emitting it later, just prior to the solution. Useful for grouped questions. +% \begin{macrocode} +\newcommand{\saveDest}[1][]{% + \def\sd@arg{#1}\ifx\sd@arg\@empty + \xdef\holdDest{\@qzsolndest}\else + \xdef\@qzsolndest{#1}\xdef\holdDest{#1}\fi} +\def\useDest{\def\@qzsolndest{\holdDest}} +\let\holdDest\@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +%</package> +%<*package|eqexam> +\def\fpAfterSolutionsSkip{\par\medskip} +\let\eqSqSolnTrailerHook\@empty +\let\eqQzSolnTrailerHook\@empty +\newcommand\eqSqSolnTrailer{% + \if\eqQuizType\isQZ + \eqQzSolnTrailerHook + \protect\ReturnTo{page.\eq@pageThisQ}% + {\protect\mbox{\sqslrtnlabel}}\string\endeqQt + \else + \eqSqSolnTrailerHook + \protect\ReturnTo{page.\eq@pageThisQ}% + {\protect\mbox{\sqslrtnlabel}}\string\endeqSQt% + \fi + \ifeqforpaper\protect\fpAfterSolutionsSkip\fi^^J% +} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \begin{macro}{\eqQt} +% \begin{macro}{\endeqQt} +% \begin{macro}{\eqSQt} +% \begin{macro}{\endeqSQt} +% The \cmd{\eqQt} and \cmd{\eqSQt} are markers at the beginning of each +% quiz (short quiz, respectively) solution. These markers, along with +% ``end'' versions, \cmd{\endeqQt} and \cmd{\endeqSQt}, respectively, can be used to filter out the quiz solutions or the +% short quiz solutions. The following example removes all short quizzes. +%\begin{verbatim} +%\long\def\eqSQt#1\endeqSQt{} +%\begin{document} +%\input{mydoc.qsl} +%\end{document} +%\end{verbatim} +% \begin{macrocode} +%</package> +%<*package|eqexam> +\let\eqSQt\@gobble +\let\endeqSQt\relax +\let\eqQt\@gobble +\let\endeqQt\relax +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\quizSolnHeader} +% Each solution begins with \cmd{\quizSolnHeader}. This can be redefined +% for whatever reason. It takes three arguments, one of which is optional. +% \#1 is the \cmd{\noPeek} parameters; \#2 is the named destination to this +% solution; \#3 is the \cmd{\sqsllabel}. +% +% If you want to typeset solutions separately, you can redefine +% \cmd{\quizSolnHeader} as desired, and used in conjunction with +% \cmd{eqQt}. +% \changes{v6.7q}{2013/12/15}{Added this hook for use by \textsf{contsolns.dtx}} +% \begin{macrocode} +\let\prior@quizSolnHeaderHook\@empty +\newcommand\quizSolnHeader[3][]{% + \prior@quizSolnHeaderHook + \ifeqforpaper\else\webnewpage\fi\noindent +%</package|eqexam> +%<*package> + \def\eq@argi{#1}% + \ifx\eq@argi\@empty\else\noPeek#1\fi + \hypertarget{#2}{#3}\relax +%</package> +%<*eqexam> + #2% +%</eqexam> +%<*package|eqexam> + \solnspace +} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \begin{macro}{\NoPeeking} +% \begin{macro}{\AllowPeeking} +% A \texttt{quiz} solution has an additional (optional) feature. If +% \cmd{\NoPeeking} is executed, then an open action is placed on the opening +% page of each solution. This open action simply changes the page back to +% the page of the quiz. This is an attempt at keeping students from ``peeking'' +% at the solutions before, or while they are taking a quiz. \cmd{\AllowPeeking} +% is the default. +% \begin{macrocode} +\def\AllowPeeking{\global\let\allow@peek\eq@YES}\AllowPeeking +\def\NoPeeking{\global\let\allow@peek\eq@NO} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\noPeekAction} +% The default definition of \cmd{quizSolnHeader} contains a macro called +% \cmd{\noPeek}. This is the action that \cmd{\noPeek} performs. The actual +% definition of \cmd{\noPeek} is driver dependent, and is listed elsewhere. +% An open page action will be created with a JavaScript action, which calls +% a DLJS function \texttt{noPeek("\#1",\#2)}. The first parameter is the base +% name of the quiz; the second parameter is the page number the quiz starts from +% (so that we can return to that page when the student tries to view the solution +% when he is not authorized to). +% \begin{macrocode} +\def\noPeekAction#1#2{% + /AA <</O<</S/JavaScript/JS(noPeek("#1",#2))>> >> +} +% \end{macrocode} +% \end{macro} +% \subsection{The \texttt{shortquiz} Solutions} +% When the first solution is written, \cmd{\therearequizsolutions} is +% made true. When the solutions are input back into the file, and +% this switch is still false, then no quiz header is typeset; +% this avoids an empty quiz solutions section with only the header. +% \begin{macrocode} +%</package> +%<*package|eqexam> +\newif\iftherearequizsolutions \therearequizsolutionsfalse +\let\aeb@FLOverride\relax +% \end{macrocode} +% \begin{macro}{\includequizsolutions} +% This macro inserts the solutions to the short quizzes, if there are +% any solutions. If a user uses this macro to insert the solutions +% elsewhere, \cmd{\include@quizsolutions} is called, then put is to +% \cmd{\relax}. +% \begin{macrocode} +\def\includequizsolutions{\@ifstar + {\let\resetQZtsolns\relax\includequizsolutionsi} + {\def\resetQZtsolns{\global\let\include@quizsolutions\relax}% + \includequizsolutionsi}% +} +\newcommand{\includequizsolutionsi}[1][]{% + \filterFor{#1}\includequizsolutionsii +} +\def\includequizsolutionsii{% + \include@quizsolutions + \resetQZtsolns + \let\eqFilterArg\@empty +} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \DescribeMacro{\eqqzsolutionshook}\DescribeMacro{\priorsqslsectitle} +% \DescribeMacro{\priorsqslinput} are commands executed at the beginning of the page of quiz solutions. +% These may be defined by the document author. +% \begin{macrocode} +\let\eqqzsolutionshook\@empty +\let\priorsqslsectitle\@empty +\let\priorsqslinput\@empty +% \end{macrocode} +% \DescribeMacro{\quizSolnsHeadnToc} sets up the quiz solution title. +% \begin{macrocode} +\def\quizSolnsHeadnToc{\section*{\sqslsectitle}% + \addcontentsline{toc}{section}{% + \@ifundefined{web@latextoc}{}{% + \ifx\web@latextoc\eq@YES\else + \protect\numberline{}\fi}\sqslsectitle}} +% \end{macrocode} +% \DescribeMacro{\quizSolnInput} is the command that actually inputs +% the solutions file \cmd{\jobname.qsl}. +% \begin{macrocode} +\newcommand{\quizSolnInput} +{% + \let\webnewpage\relax + \immediate\closeout\quiz@solns + \ifeq@noquizsolutions\else +% \end{macrocode} +% If there are quiz solutions, we start a new page, and clear the right mark. +% We execute \cmd{\eq@normallheader} which sets the running left header, +% except on the page with a section head. We set the right mark as +% \cmd{\eq@sqslsecrunhead}. (2013/09/23) replaced \cmd{\eq@sqslsecrunhead} +% with \cmd{\sqslsecrunhead}, makes it easier to define running headers +% when solutions are filtered. +% \begin{macrocode} + \iftherearequizsolutions\newpage\markright{}% + \eq@normallheader\markright{\sqslsecrunhead}% + \ifx\webnewpage\relax + \def\webnewpage{\let\webnewpage\newpage}\fi +% \end{macrocode} +% Here we have various prior commands, and the setting of the +% section title. +% \begin{macrocode} + \priorsqslsectitle\quizSolnsHeadnToc\priorsqslinput +% \end{macrocode} +% Now input the solution file \cmd{\jobname.qsl}. +% \begin{macrocode} + \InputIfFileExists{\jobname.qsl}{}% + {!!! Solutions to quizzes not found} +% \end{macrocode} +% A hook for hanging things +% \begin{macrocode} + \eqqzsolutionshook +% \end{macrocode} +% Reset the running header cleanly +% \begin{macrocode} + \newpage\eq@defaultlheader + \fi + \fi +} +% \end{macrocode} +% The internal command that insert solutions. This command +% appears at the end of document, where it will insert the +% solutions, unless it has been redefined to \cmd{\relax} by +% \cmd{\includequizsolutions}. +% \begin{macrocode} +\def\include@quizsolutions{\quizSolnInput} +% \end{macrocode} +% +% \section{The \texttt{quiz} and \texttt{quiz*} Environments} +% +% In this section we introduce the \texttt{quiz} environment, and all its +% supporting elements. +% +% \subsection{Define the \texttt{quiz} Environment} +% \DescribeMacro{\priorqhook}\DescribeMacro{\aboveqskip} +% \DescribeMacro{\endqhook}\DescribeMacro{\belowqskip} These are hooks and skip +% before and after the \texttt{quiz} environment. +% \begin{macrocode} +\newcommand{\priorqhook}[1]{\def\q@priorhook{#1}} +\priorqhook{} +\newcommand{\aboveqskip}[1]{\def\q@aboveskip{#1}} +\aboveqskip{\par\medskip} +\newcommand{\qhspace}{\space} +\def\endqhook#1{\def\eq@prior@endQuiz{#1}} +\endqhook{} +\newcommand{\belowqHooknSkip}[1]{\def\eq@belowqskip{#1}} +\belowqHooknSkip{\medskip} +\def\belowqskip{\belowqHooknSkip} +% \end{macrocode} +% \begin{macrocode} +\let\eq@initializeServerSubmit\@empty +% \end{macrocode} +% \begin{macro}{\quiztype} +% \begin{macro}{\defaultquiztype} +% The command \cs{quiztype} can be used to force subsequent quizzes to be link +% style or form style, independent of the environment. Recognized values are +% \texttt{f} and \texttt{l}. Once the override \cs{quiztype} has been used, +% you can recover the default behavior of the quizzes by expanding +% \cs{defaultquiztype}. +% \begin{macrocode} +\newcommand{\quiztype}[1]{% + \def\@quiztype{#1}\def\aeb@FLOverride{#1}} +\let\@quiztype\@empty +\newcommand{\defaultquiztype}{\let\@quiztype\@empty + \let\aeb@FLOverride\relax} +\let\aeb@FLOverride\relax +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\def\@setFormLinkType{% + \if\qstar*% + \ifx\aeb@FLOverride\relax% + \def\@@quiztype{f}% + \else + \if\aeb@FLOverride l\def\@@quiztype{l}\else + \def\@@quiztype{f}\fi + \fi + \else + \ifx\aeb@FLOverride\relax + \def\@@quiztype{l}% + \else + \if\aeb@FLOverride f\def\@@quiztype{f}\else + \def\@@quiztype{l}\fi + \fi + \fi +} +\def\setdefault@Ans{\@setFormLinkType + \expandafter\global\expandafter + \let\expandafter\@Ans\expandafter=\csname Ans@\@@quiztype\endcsname +} +% \end{macrocode} +% \begin{macro}{\useForms} +% \begin{macro}{\useLinks} +% \begin{macro}{\restoreFLTypeDefault} +% For multiple choice questions, here we give the option of using a mixture of links +% and forms. +% \begin{macrocode} +%</package> +%<*package|eqexam> +\newcommand\useForms{\def\aeb@FLOverride{f}} +\newcommand\useLinks{\def\aeb@FLOverride{l}} +\newcommand\restoreFLTypeDefault{\global\let\aeb@FLOverride\relax} +\let\aeb@FLOverride\relax +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{environment}{quiz} +% The \texttt{quiz} environment takes an optional `\texttt*' +% and one required argument. There are two styles of quizzes: +% links or checkboxes. Beginning with v6.08, the use of the \texttt*-option +% is discouraged, use the quiz* environment instead. +%\begin{verbatim} +%\begin{quiz}[*]{<base_name>} +% ... +%\end{quiz} +%\end{verbatim} +% \begin{itemize} +% \item optional \texttt{*} $=$ use checkboxes, otherwise use links +% \item \texttt{<base\_name>}: required argument $=$ base name of quiz. +% \end{itemize} +% +% Note that I set \verb!\tabcolsep=0pt! in preparation for a tabular environment. +% If authors wants to use a tabular environment within a question, he/she must +% reset this value to its default, \verb!\setlength{\tabcolsep}{6pt}!. +% \begin{macrocode} +\newenvironment{quiz} +{\goodbreak\@ifstar{\gdef\qstar{*}\@quiz*f}{\gdef\qstar{x}\@quiz*l}} + {\aeb@endquiz} +\def\@quizCnt{0} +\def\@quiz*#1#2{% +% \end{macrocode} +% (06/08/10) The next two lines initialize the macros for registering the +% question label, i.e., \texttt{2(a)(ii)}. These two lines are repeated for +% the \texttt{oQuestion} and \texttt{shortquiz} environments. +% \begin{macrocode} + \xdef\eq@pageThisQ{\the\c@page}% + \let\@currentQues\@empty + \global\let\eqQzQuesList\@empty + \global\let\pointValuesArray\@empty +% \end{macrocode} +% Initialize \texttt{ptypeArray} to track problem types better +% \changes{v7.7m}{2016/07/04}{Initialize \string\texttt{ptypeArray} to track problem types better} +% \begin{macrocode} + \global\let\ptypeArray\@empty +% \end{macrocode} +% Initialize \texttt{corrAnsArray} to track the correct answers +% \changes{v7.7n}{2016/07/06}{Initialize \string\texttt{ptypeArray} to track problem types better} +% \begin{macrocode} + \global\let\corrAnsArray\@empty +% \end{macrocode} +% Update the internal quiz counter. +% \begin{macrocode} + {\count0=\@quizCnt\advance\count0by1\relax + \xdef\@quizCnt{\the\count0 }}% +% \end{macrocode} +% We try to support {\LaTeX}'s cross-referencing system by defining +% \cs{@currentlabel}, \cs{@currentHlabel}, and \cs{@currentlabelname}. +% \begin{macrocode} + \edef\@currentlabel{\@quizCnt}% + \edef\@currentHref{quiz.\@quizCnt}% + \sq@setCLN{\eq@defaultQuizLabelName}% + \setcounter{eqpointvalue}{0}\setcounter{questionno}{0}% + \eq@initializeServerSubmit + \global\let\eqQuizType\isQZ %\tabcolsep=0pt + \gdef\eqPTs{1}\global\let\eqQT\eq@na +% \end{macrocode} +% \changes{v6.3u}{2010/11/04}{% +% Added \cs{xdef}\cs{oField}\texttt{\{\#2\}}, this is +% needed for \textsf{apb.dtx}. +%} +% \begin{macrocode} + \gdef\quiz@total{#2}\xdef\curr@quiz{#2}\xdef\oField{#2}% + \xdef\currQuiz{#2}\xdef\currQuizStartPage{\thepage}% + \xdef\aPointType{0}% +% \end{macrocode} +% (2013/12/20) Pass \cs{bqlabelISO} through \cs{pdfstringdef}. +% \begin{macrocode} + \def\fieldJSStr@CMD{\fieldJSStr*[noquotes]\bqlabelISO}% + \expandafter\fieldJSStr@CMD\expandafter{\bqlabelISO}% + \ifx\@quiztype\@empty\gdef\@@quiztype{#1}\else + \xdef\@@quiztype{\@quiztype}\fi + \let\@qzsolndest\@empty + \let\answers\answers@q\let\endanswers\endanswers@q + \let\manswers\manswers@q\let\endmanswers\endanswers@q + \let\solution\solution@sq\let\endsolution\endsolution@sq + \expandafter% + \xdef\csname titleOf\currQuiz\endcsname{\aebTitleQuiz}% +% \end{macrocode} +% Modified the destination name of \cs{hypertarget} to avoid deplicate +% destinations. Did the same thing for the \texttt{shortquiz}. +% \changes{v7.8a}{2016/12/07}{Modified destination name of \string\cs{hypertarget}} +% \begin{macrocode} + \q@aboveskip\q@priorhook\noindent\hypertarget{qzH\@currentHref}{}% + \eq@beginQuiz\qhspace{\set@typeset@protect\aebtitleQuiz}% + \ignorespaces +} +% \end{macrocode} +% Here is the end for the \texttt{quiz} and \texttt{quiz*} environments. The +% \cs{eq@prior@endQuiz} can be used for whatever purposes a +% developer wants. +% \begin{macrocode} +\def\aeb@endquiz +{% + \eq@prior@endQuiz\noindent\eq@endQuiz + \global\let\eqQuizType\relax + \global\let\aebtitleQuiz\@empty + \global\let\aebTitleQuiz\@empty + \global\let\bqlabel\eq@bqlabel % reset beginning label to default + \global\let\eqlabel\eq@eqlabel % reset ending label to default +% \end{macrocode} +% (2013/10/18) Added \cs{sqsllabel} to list of commands that are reset. +% \begin{macrocode} + \global\let\sqsllabel\eq@sqsllabel + \global\let\sqslrtnlabel\eq@sqslrtnlabel + \global\let\bqlabelISO\eq@bqlabelISO + \eq@belowqskip +} +% \end{macrocode} +% \end{environment} +% +% \subsection{Define the \texttt{quiz*} Environment} +% +% \begin{environment}{quiz*} +% This environment is more latexy, \texttt{quiz*} environment is for quizzes with forms. Equivalent +% to \verb!\begin{quiz}*...\end{quiz}!/ +% \begin{macrocode} +\newenvironment{quiz*}{\goodbreak\gdef\qstar{*}\@quiz*f}{\aeb@endquiz} +% \end{macrocode} +% \end{environment} +% +% \subsection{Begin/End Quiz with Link or Buttons} +% +% Redefine this macro to \cmd{\eq@BeginQuizButton} to get a form button +% for the \texttt{quiz} environment. Pressing on the link or button +% initializes the quiz. The default is `link': \cmd{\eq@BeginQuizLink}. +% \begin{macrocode} +\newcommand\eq@beginQuiz{\eq@BeginQuizLink} +% \end{macrocode} +% Redefine this macro to |\eq@EndQuizButton| to get a form button +% for the \texttt{quiz} environment. Pressing on the link or button +% will score the quiz. The default is `link': |\eq@EndQuizLink|. +% \begin{macrocode} +\newcommand\eq@endQuiz{\eq@EndQuizLink} +% \end{macrocode} +% \begin{macro}{\useBeginQuizButton} +% Use a button instead of a link for begin quiz +% \begin{macrocode} +\newcommand\useBeginQuizButton[1][] + {\renewcommand\eq@beginQuiz{\eq@BeginQuizButton[#1]}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\useEndQuizButton} +% Use a button instead of a link for end quiz +% \begin{macrocode} +\newcommand\useEndQuizButton[1][] + {\renewcommand\eq@endQuiz{\eq@EndQuizButton[#1]}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\useBeginQuizLink} +% Use a link begin quiz (the default) +% \begin{macrocode} +\newcommand\useBeginQuizLink + {\renewcommand\eq@beginQuiz{\eq@BeginQuizLink}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\useEndQuizLink} +% Use a link end quiz (the default) +% \begin{macrocode} +\newcommand\useEndQuizLink + {\renewcommand\eq@endQuiz{\eq@EndQuizLink}} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\def\listOfQuizzes{} +\def\listOfSubmitQuizzes{} +\def\initializeAllSubmitQuizzes{} +% \end{macrocode} +% \begin{macro}{\@initQuiz} +% \begin{macro}{\priorInitQuiz} +% \begin{macro}{\postInitQuiz} +% \cs{@initQuiz} is executed when you click on `Begin Quiz'. Included here are some +% macro hooks for insert code prior to, and after the quiz initialization. This +% command appears in the commands \cs{eq@@BeginQuizLinkActions} and \cs{eq@@BeginQuizButtonActions} below. +%\changes{v7.0}{2014/11/05}{Added some JS: lstOfQuizzes is an associative array +% listing all quizzes in the document, the value is the quiz object. We add properties +% isSubmitted and initializeWith to the quiz object.} +% \begin{macrocode} +\newcommand\@initQuiz{% + var \curr@quiz=new Object();\jsR + lstOfQuizzes["\curr@quiz"]=\curr@quiz;\jsR + \curr@quiz.oAlertCheck={bAfterValue:false};\jsR + \curr@quiz.Grp={}; + \ifx\defaultColorJSLoc\@empty\else\jsR + \oField.DefaultColorJSLoc=\defaultColorJSLoc;\fi + \ifx\rghtColorJSLoc\@empty\else\jsR + \oField.RightColorJSLoc=\rghtColorJSLoc;\fi + \ifx\wrngColorJSLoc\@empty\else\jsR + \oField.WrongColorJSLoc=\wrngColorJSLoc;\fi + \ifx\partialColorJSLoc\@empty\else\r + \oField.PartialColorJSLoc=\partialColorJSLoc;\fi + \ifx\rghtAnsSymbJSLoc\@empty\else\jsR + \oField.RightAnsSymbJSLoc=\rghtAnsSymbJSLoc;\fi + \ifx\wrngAnsSymbJSLoc\@empty\else\jsR + \oField.WrongAnsSymbJSLoc=\wrngAnsSymbJSLoc;\fi + \ifx\corrAnsSymbJSLoc\@empty\else\jsR + \oField.CorrAnsSymbJSLoc=\corrAnsSymbJSLoc;\fi + \ifx\eqGradeScaleLoc\@empty\else\jsR + \oField.GradeScaleLoc=new Array(\eqGradeScaleLoc);\fi + \ifx\priorInitQuiz\@empty\else\jsR\priorInitQuiz\fi\jsR + InitializeQuiz("\curr@quiz",\ifnocorrections0\else1\fi); + \ifx\eq@CGI\@empty\jsR\curr@quiz.isSubmitted=false;\else + \jsR\curr@quiz.isSubmitted=true;\fi + \jsR\curr@quiz.initializeWith=% +'InitializeQuiz("\curr@quiz",\ifnocorrections0\else1\fi);' + \ifx\postInitQuiz\@empty\else\jsR\postInitQuiz\fi +} +% \end{macrocode} +% \cs{priorInitQuiz} and \cs{postInitQuiz} are hooks that allow a document author to +% execute JavaScript just prior to initializing the quiz and just after. These appear in +% \cs{eq@@BeginQuizLinkActions} and \cs{eq@@BeginQuizButtonActions} below. +% \begin{macrocode} +\newcommand{\priorInitQuiz}{} +\newcommand{\postInitQuiz}{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% Here are a couple of macros used with `End Quiz', and are used for +% submitting quiz results to a web server. +% \begin{macrocode} +\let\eq@submitURL\@empty +\let\eq@insertHiddenFields\@empty +% \end{macrocode} +% +% \subsubsection{With Links} +% +% \begin{macro}{\eq@BeginQuizLink} +% Begin quiz with links +% \begin{macrocode} +\def\eq@@BeginQuizLinkActions +{% + \A{\JS{% +% \ifx\priorInitQuiz\@empty\else\priorInitQuiz\jsR\fi + \@initQuiz +% \ifx\postInitQuiz\@empty\else\jsR\postInitQuiz\fi + }}% +} +\def\eq@BeginQuizLinkDefaults{\Border{0 0 0}} +\let\bqlabelFmt\@empty +\def\eq@BeginQuizLink +{% + \set@@Link{}{}{}{\color{\@linkcolor}\bqlabelFmt\bqlabel}{}% + {\eq@setWidgetProps\setLink@driver}% + {\eq@BeginQuizLinkDefaults\eq@@BeginQuizLinkActions\every@Link}% + \space\ignorespaces +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\eq@EndQuizLink} +% Code the the link version of `End Quiz'. +% \begin{macrocode} +\newcommand\priorSubmitQuiz{} +\newcommand\postSubmitQuiz{} +\def\eq@@EndQuizLinkActions +{% + \A{\JS{% + if (!isQuizInitialized("\curr@quiz"))\jsR\jsT + eqAppAlert(InitMsg("\bqlabelISO"),3);\jsR + else {\jsR\jsT + if (\minQuizResp(\thequestionno)) {\jsR\jsT\jsT + \curr@quiz.PtValues=new % +Array(\pointValuesArray);\jsR\jsT\jsT + ProbType = [\ptypeArray];\jsR\jsT\jsT +\if@inclkey + \curr@quiz.CorrAns=(new % +Array(\corrAnsArray));\jsR\jsT\jsT +\fi + DisplayQuizResults("\curr@quiz",\theeqpointvalue,% +\thequestionno);\jsR\jsT\jsT +% \priorSubmitQuiz + \eq@submitURL + \postSubmitQuiz + resetQuiz("\curr@quiz");\jsR\jsT + }\jsR + }}}% +} +\def\eq@EndQuizLinkDefaults{\Border{0 0 0}} +\let\eqlabelFmt\@empty +\def\eq@EndQuizLink +{% + \ifx\eq@CGI\@empty + \let\eq@submitURL\@empty + \let\eq@insertHiddenFields\@empty + \fi + \set@@Link{}{}{}{\color{\@linkcolor}\eqlabelFmt\eqlabel}{}% + {\eq@setWidgetProps\setLink@driver}% + {\eq@EndQuizLinkDefaults\eq@@EndQuizLinkActions\every@Link}% + \makebox[0pt][r]{\textField[\BC{}\autoCenter{n}]% + {htxtfld.\curr@quiz}{0bp}{0bp}}% + \makebox[0pt][r]{\eq@insertHiddenFields}\global\let\eq@CGI\@empty + \ignorespaces +} +% \end{macrocode} +% \end{macro} +% +% \subsubsection{With Buttons} +% +% \begin{macro}{\eq@BeginQuizButton} +% This is the button when the user wants button rather than link for the +% \texttt{quiz} environment. +% \begin{macrocode} +\def\BeginQuizButtonDefaults +{% + \CA{\bqlabel}\H{P}\F{\FPrint} + \BC{1 0 0}\BG{.7529 .7529 .7529}\W{1}\S{B} +} +\def\eq@@BeginQuizButtonActions +{% + \A{\JS{% +% \ifx\priorInitQuiz\@empty\else\priorInitQuiz\r\fi + \@initQuiz +% \ifx\postInitQuiz\@empty\else\r\postInitQuiz\fi + }}% +} +\newcommand\eq@BeginQuizButton[1][] +{% + \mbox{\push@@Button{#1}{beginQuiz.\curr@quiz}{}% + {\DefaultHeightOfWidget}{\eq@protect\A}% + {\eq@setButtonProps\eq@Button@driver}% + {\BeginQuizButtonDefaults\eq@@BeginQuizButtonActions + \every@ButtonField\every@BeginQuizButton}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\eq@EndQuizButton} +% The `End Quiz' code for Links +% \begin{macrocode} +\def\EndQuizButtonDefaults +{% + \CA{\eqlabel}\F{\FPrint}\BC{1 0 0} + \BG{.7529 .7529 .7529}\W{1}\S{B}\H{P} +} +\def\eq@@EndQuizButtonActions +{% + \A{\JS + {if (!isQuizInitialized("\curr@quiz"))\jsR\jsT + eqAppAlert(InitMsg("\bqlabelISO"),3);\jsR + else {\jsR\jsT + if (\minQuizResp(\thequestionno)&&_ModalNotOn){\jsR\jsT\jsT + \curr@quiz.PtValues=(new % +Array(\pointValuesArray));\jsR\jsT\jsT + ProbType=[\ptypeArray];\jsR\jsT\jsT +\if@inclkey + \curr@quiz.CorrAns=(new % +Array(\corrAnsArray));\jsR\jsT\jsT +\fi + DisplayQuizResults("\curr@quiz",\theeqpointvalue,% +\thequestionno);\jsR\jsT\jsT + \eq@submitURL + \postSubmitQuiz + resetQuiz("\curr@quiz");\jsR\jsT + }\jsR + }}% + } +} +\newcommand\eq@EndQuizButton[1][] +{% + \ifx\eq@CGI\@empty + \let\eq@submitURL\@empty + \let\eq@insertHiddenFields\@empty + \fi + \mbox{\push@@Button{#1}{endQuiz.\curr@quiz}{}% + {\DefaultHeightOfWidget}{\eq@protect\A}% + {\eq@setButtonProps\eq@Button@driver}% + {\EndQuizButtonDefaults\eq@@EndQuizButtonActions + \every@ButtonField\every@EndQuizButton}}% + \makebox[0pt][r]{\eq@insertHiddenFields}\global\let\eq@CGI\@empty +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\databaseName} +% \begin{macro}{\tableName} +% \begin{macro}{\eqCGI} +% \begin{macro}{\eqSubmit} +% These four commands give general support for submitting quiz data +% to a web server for storage in a database. Use in my \textsf{eq2db} Package +% which I have not completed yet. (2014/09/14) Sanitized first argument of \cs{eqSubmit}. +% \begin{macrocode} +\newcommand\databaseName[1]{\gdef\db@Name{#1}}\def\db@Name{} +\newcommand\tableName[1]{\gdef\db@Table{#1}}\def\db@Table{} +\newcommand\eqCGI{\definePath{\eq@CGI}}\def\eq@CGI{} +\newcommand\eqSubmit{\hyper@normalise\eqSubmiti} +\def\eqSubmiti#1{\xdef\eq@CGI{"#1"}\eqSubmitii} +\def\eqSubmitii#1#2{\databaseName{#1}\tableName{#2}} +\providecommand{\rtnURL}{\definePath{\thisRtnURL}} +\let\thisRtnURL\@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% The next two commands are used in the \textsf{eq2db} package. We make the +% definitions here so that they can be used even if the package is not loaded. +% In this way, a self-contained quiz can be submitted just by loading the +% package. +% \begin{macrocode} +\newcommand\addHiddenTextField[3][]{} +\newcommand\populateHiddenField[2]{} +% \end{macrocode} +% \subsection{Correcting the Quiz} +% +% \begin{macro}{\eqButton} +% Use this button to correct the quiz. Can be customize with +% optional arguments. +% section. +%\begin{verbatim} +% #1 = optional attributes of button +% #2 = title of textfield that contains the score. +%\end{verbatim} +% \begin{macrocode} +\def\eqButtonDefaults +{% + \CA{\eq@local@CA}\AC{}\H{P}\W{1}\S{B} + \BC{1 0 0}\BG{.7529 .7529 .7529} +} +\def\@@eqButtonActions +{% + \A{\JS{if (isEndQuizPushed("\eqBaseName")){\jsR\jsT% + correctQuiz("\eqBaseName",\thequestionno);% + \ifusesumrytbls\jsR\jsT\else\jsR\fi +% \end{macrocode} +% (06/13/10) Added the quiz summary table, and the function +% \texttt{correctSumryTbl}. If a summary table is not present +% the function does nothing. +% \begin{macrocode} + if (typeof correctSumryTbl == "function")\jsR\jsT\jsT + correctSumryTbl("\eqBaseName",\thequestionno);\jsR + } + }}% +} +\newcommand\eqButton[2][] +{% +% \end{macrocode} +% If nocorrections is true, then this button does not appear. +% \begin{macrocode} + \ifnocorrections\else + \def\eqBaseName{#2}% + \mbox{\push@@Button{#1}{correct.#2}{}{\DefaultHeightOfWidget}% + {\eq@protect\A}{\eq@setButtonProps\eq@Button@driver}% + {\eqButtonDefaults\@@eqButtonActions\every@ButtonField + \every@eqButton}}% + \fi +} +% \end{macrocode} +% \changes{v6.7n}{2013/09/17}{\cs{CorrButton} is now an alias for \cs{eqButton}} +% \DescribeMacro{\CorrButton} is a name better suited for the task of this button +% than the \cs{eqButton} name. +% \begin{macrocode} +\def\CorrButton{\eqButton} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\rbMarkup} +% An optional element for quizzes. Place just after a response box (perhaps, before the +% \cs{CorrAnsButton}. When the correct button is pressed, this check box will show a +% green check or a red cross (by default). +% \begin{macrocode} +\def\rbMarkup@Defaults +{% + \BC{}\F{\FHidden}\Ff{\FfReadOnly}\textSize{12} + \textColor{0 g}\symbolchoice{check}\W{} +} +\newcommand\rbMarkup[1][]{% + \ifx\grpquestions\eq@One + \def\Fld@name{% + \oField.\thequestionno.\thegrpquestionno}\else + \def\Fld@name{\oField.\thequestionno}\fi + \mbox{\check@@Box{#1\V{Yes}\DV{Yes}}% + {rbmarkup.\Fld@name}% +% {rbmarkup.\curr@quiz.\thequestionno}% + {\RadioFieldSize}{\RadioFieldSize}{Yes}{}% + {\eq@setWidgetProps\eq@RadioCheck@driver}% + {\rbMarkup@Defaults\every@CheckBox\every@rbMarkup}}}% +% \end{macrocode} +% \end{macro} +% +% \subsection{Measuring Quiz Results} +% +% \begin{macro}{\minQuizResp} +% Define the threshold level. The two permissible values are \texttt{lowTreshold} +% and \texttt{highThreshold}. These are names of DLJS. New threshold functions +% can be defined and specified. +% \begin{macrocode} +\newcommand\minQuizResp{lowThreshold} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\PTs} +% Use this macro to assign weights to the quiz questions. Use only within +% the \texttt{questions} environment, just after an \cmd{\item}. If +% \cmd{\PTs} does not appear, then a weight of $1$ is assumed. +%\par\noindent|#1 = number of points for the current question.| +% The star-form records the points but does not display the points. +% \begin{macrocode} +\newcommand\PTs{\@ifstar{\def\eq@star{*}\@PTs}{\def\eq@star{x}\@PTs}} +\def\@PTs#1{\gdef\eq@PTs{#1}\ifx\eq@PTs\@empty\gdef\eq@PTs{1}\fi + \global\let\eqPTs\eq@PTs\global\let\eq@PTs\@empty + \if\eq@star*\else\PTs@Hook\fi} +\def\eq@PTs{0} % initialize this variable +% \end{macrocode} +% \begin{macro}{\QT} +% \cs{QT} is used for entering the ``question type'' for the question (optional). +% This question type is entered into the ``\texttt{tagged}'' data, and is meant to be +% used for classifying and in tracking the problem types. Example: \verb+\QT{limits}+. +% \begin{macrocode} +\newcommand\QT[1] +{% + \gdef\eq@qT{#1}\ifx\eq@qT\@empty\global\let\eq@qT\eq@na\fi +% \end{macrocode} +% \cs{eqQT} saves the value, then we put \cs{eq@qT} back to its default. +% \begin{macrocode} + \global\let\eqQT\eq@qT\global\let\eq@qT\eq@na +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\def\eq@na{na} % not applicable +\let\eq@qT\eq@na +% \end{macrocode} +% \end{macro} +% \begin{macro}{\PTsHook} +% Used to typeset the number of points. +% \begin{macrocode} +\newcommand\PTsHook[1]{\def\PTs@Hook{#1}} +\let\PTs@Hook\@empty +\let\eq@PTs\@empty +% \end{macrocode} +% \end{macro} +% \begin{macro}{\eqGradeScale} +% This is an array of letter grades and grade ranges. This macro is use as the argument +% of the JS function \texttt{GetGrade}. +% \begin{macrocode} +\newcommand\eqGradeScale{% + "A",[90, 100],"B",[80,90],"C",[70,80],"D",[60,70],"F",[0,60]} +\let\eqGradeScaleLoc\@empty +\newcommand{\resetGradeScaleLoc}{\global\let\eqGradeScaleLoc\@empty} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\DefaultHeightOfWidget} +% \begin{macro}{\RBW} +% \begin{macro}{\SFW} +% \begin{macro}{\GFW} +% \begin{macro}{\PtW} +% \begin{macro}{\PcW} +% \cmd{\DefaultHeightOfWidget} is the default height of all form +% fields (except radio fields and checkboxes). \cmd{\RBW} is the +% default width of the \cmd{\RespBox}; and \cmd{\SFW} is the +% default width of the \cmd{\ScoreField}. \cs{GFW} is the default +% width of a grade field button; \cs{PtFW} is the default width +% of a points field button; and \cs{PcFW} is the default width +% of the percent field button. +% \begin{macrocode} +\def\tallywidth#1{\def\TBW{#1}} +\def\TBW{15bp} +\def\DefaultHeightOfWidget{11bp} +\def\RadioFieldSize{11bp} +\def\RBW{2in} % Response Box width (math,txt, txtpc, answer field) +\def\SFW{1.5in} % Score Field Width +\def\GFW{20pt} % Grade Field Width +\def\PtFW{1.5in} % Point Field Width +\def\PcFW{1.5in} % Percent Field Width +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\ScoreField} +% This text field will receive the scores +% of a quiz. The command \cmd{\eqScore} was defined +% in Section~\ref{ss:ldm}. This command takes an optional +% argument and a required argument. +%\begin{verbatim} +%#1 = one or more commands that will customize the design of the +% field. See the manual for examples. +%#2 = Base name of the quiz +%\end{verbatim} +% \begin{macrocode} +\def\ScoreFieldDefaults +{% + \Ff{\FfReadOnly}\BC{1 0 0}\BG{}\S{S} + \DV{\eqScore}\V{\eqScore}\W{1} +} +\newcommand\ScoreField[2][] +{% + \mbox{\text@@Field{#1}{ScoreField.#2}{\SFW}% + {\DefaultHeightOfWidget}{}{\eq@setWidgetProps\eq@TextField}% + {\ScoreFieldDefaults\every@eqTextField\every@ScoreField}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\GradeField} +% This command creates a text field that shows the letter grade of the user's +% effort on the current quiz. +% \begin{macrocode} +\def\GradeFieldDefaults +{% + \textColor{0 0 1 rg}\BC{1 0 0}\BG{1 1 1}\S{S} + \Ff{\FfReadOnly}\Q{1}\W{1} +} +\newcommand\GradeField[2][] +{% + \mbox{\text@@Field{#1}{GradeField.#2}{\GFW}% + {\DefaultHeightOfWidget}{}{\eq@setWidgetProps\eq@TextField}% + {\GradeFieldDefaults\every@eqTextField\every@GradeField}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\AnswerField} +% This command creates a text field to receive the answers to the +% fill-in questions. +% \begin{macro}{\resetAnsFieldOnClose} +% When expanded, the \cs{AnswerField}s will be reset whenever the user changes pages. +% \begin{macro}{\noResetAnsFieldOnClose} +% When expanded, the \cs{AnswerField}s will not be reset, this is the default behavior. +% \begin{macrocode} +\def\AnswerFieldDefaults +{% + \BC{0 0 0}\S{S}\Ff{\FfReadOnly}\W{1}% + \presets{\eq@resetAnsFieldOnClose}% +} +\let\eq@resetAnsFieldOnClose\@empty +\newcommand{\noResetAnsFieldOnClose}{% + \global\let\eq@resetAnsFieldOnClose\@empty} +\newcommand{\resetAnsFieldOnClose}{% + \gdef\eq@resetAnsFieldOnClose{% + \AApageclose{this.resetForm(["\Fld@name"]);}}} +\newcommand\AnswerField[2][] +{% + \mbox{\text@@Field{#1}{Ans.#2}{\RBW}{\DefaultHeightOfWidget}% + {}{\eq@setWidgetProps\eq@TextField}% + {\AnswerFieldDefaults\every@eqTextField\every@AnswerField}}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\autoAnswerField} +% An attempt at putting \cs{AnswerField} in the left running footer on each page where there +% is a response box. +% \begin{macrocode} +% +\newcommand\autoAnswerField{% + \@ifundefined{lfooter}{\def\eq@next{\eq@autoAnswerFieldgobble}% + \PackageError{exerquiz}{The \string\autoAnswerField\space + command\MessageBreak requires the web package}{Use web package} + }{% + \PackageInfo{exerquiz}{% + For this auto answer field feature to run\MessageBreak + the webheadings pagestyle of the web package\MessageBreak + is required}\def\eq@next{\eq@autoAnswerField}% + \ifx\web@lfoot\@empty\else + \PackageWarning{exerquiz}{The left running footer already in + use\MessageBreak Will overwrite what is there now. + Better fix it.}\fi + }% + \eq@next +} +\newcommand\eq@autoAnswerFieldgobble[1][]{\relax} +\newcommand\autoAnsFldRaiseBox[1]{\def\ef@aAFRB{#1}} +\autoAnsFldRaiseBox{0pt} +\let\autoAFOpts\@empty +\newcommand\eq@autoAnswerField[1][]{\gdef\autoAFOpts{#1}% + \def\eq@insertAnswerField{\AnswerField[#1]{\currQuiz}}% + \eq@@autoAnswerField +} +\newcommand\eq@@autoAnswerField{\lfooter{\ifIsRespBox + \raisebox{\ef@aAFRB}{\eq@insertAnswerField}% + \global\IsRespBoxfalse\fi}% +} +\newcommand\manualAnswerField[1][\autoAFOpts]{% + \expandafter\AnswerField\expandafter[#1]{\currQuiz}} +% \end{macrocode} +% \end{macro} +% Now let's define some additional text fields for the quiz environment. +% \begin{macro}{\PointsField} +% This command creates a text field which displays the number of points in the +% quiz scored by the user of the \texttt{quiz}. +% \begin{macrocode} +\def\PointsFieldDefaults +{% + \rawPDF{}\BC{1 0 0}\BG{}\W{1}\S{S}\Ff{\FfReadOnly} + } +\newcommand\PointsField[2][] +{% + \mbox{\text@@Field{#1}{PointsField.#2}{\PtFW}% + {\DefaultHeightOfWidget}{}{\eq@setWidgetProps\eq@TextField}% + {\PointsFieldDefaults\every@eqTextField\every@PointsField}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\PercentField} +% This command creates a text field which displays user's score in percent +% form. +% \begin{macrocode} +\def\PercentFieldDefaults +{% + \rawPDF{}\BC{1 0 0}\BG{}\W{1}\S{S}\Ff{\FfReadOnly}% +} +\newcommand\PercentField[2][] +{% + \mbox{\text@@Field{#1}{PercentField.#2}{\PcFW}% + {\DefaultHeightOfWidget}{}{\eq@setWidgetProps\eq@TextField}% + {\PercentFieldDefaults\every@eqTextField\every@PercentField}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\RestoreScoreField} +% Reset the score field to its default, in case some author +% changed things. +% \begin{macrocode} +\newcommand\RestoreScoreField +{% + \global\let\eqScore\eq@Score + \global\let\eqOutOf\eq@OutOf +} +% \end{macrocode} +% \end{macro} +% \subsection{Floating and Docking a Quiz} +% +% \begin{macro}{\DeclareQuiz} +% A convenience macro for setting the name of the quiz. This command defines the +% text macro \cs{currQuiz} which contains the quiz name. Can be used in conjunction +% with \cs{floatQuiz} and \cs{startQuizHere}. +% \changes{v6.05c}{2006/05/19} +% { +% Added a convenience macro for setting the name of the quiz. This command defines the +% text macro \cs{currQuiz} which contains the quiz name. Can be used in conjunction +% with \cs{floatQuiz} and \cs{startQuizHere}. +% } +% \begin{macrocode} +\def\DeclareQuiz#1{% + \edef\thisQuiz{#1}% + \edef\curr@quiz{#1}% + \edef\currQuiz{#1}% + \edef\curr@quiz{#1}% +} +\let\Quiz\DeclareQuiz +% \end{macrocode} +% \end{macro} +% \begin{macro}{\floatQuiz} +% \begin{macro}{\dockQuiz} +% Use \cs{floatQuiz} to create commands \cs{startQuizHere} and \cs{endQuizHere}. These commands expand to the +% `Begin Quiz' button or link (`End Quiz' button or link). But these commands can be placed anywhere before the +% \texttt{quiz} environment (after the \texttt{quiz} environment). Use \cs{dockQuiz} to return to the default behavior of the +% \texttt{quiz} environment. +% \changes{v6.05c}{2006/05/19} +% { +% Added \cs{floatQuiz}, \cs{dockQuiz} and \cs{startQuizHere} to start a quiz in an +% arbitrary place prior to the beginning of the quiz. +% } +%\par\medskip\noindent Usage: +%\begin{verbatim} +%\Quiz{myQuiz} +%\floatQuiz +%........ +%\begin{center} +%\startQuizHere +%\end{center} +%.... +%\begin{quiz*}{\thisQuiz} +%.... +%\end{quiz*} +%.... +%\endQuizHere +% ... +%\docQuiz +%\begin{quiz}{anotherQuiz} +%.... +%\end{verbatim} +% \begin{macrocode} +\def\aeb@noindgobble{\noindent\@gobbletwo} +\let\startQuizHere\relax +\let\endQuizHere\relax +\let\dockQuiz\relax +\newcommand\floatQuiz{% + \global\let\eq@beginQuiz@saved\eq@beginQuiz + \global\let\eq@endQuiz@saved\eq@endQuiz + \global\let\startQuizHere\eq@beginQuiz + \global\let\endQuizHere\eq@endQuiz + \global\let\eq@beginQuiz\aeb@noindgobble + \global\let\eq@endQuiz\@empty + \global\let\dockQuiz\eq@dockQuiz +} +\newcommand\eq@dockQuiz{% + \global\let\eq@beginQuiz\eq@beginQuiz@saved + \global\let\eq@endQuiz\eq@endQuiz@saved + \global\let\startQuizHere\relax + \global\let\endQuizHere\relax + \global\let\eq@beginQuiz@saved\relax + \global\let\eq@endQuiz@saved + \global\let\dockQuiz\relax +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{\texorpdfstring{\protect\cs{titleQuiz} and \protect\cs{fancyQuizHeaders}} +% {\textbackslash{titleQuiz} and \textbackslash{fancyQuizHeaders}}} +% +% \begin{macro}{\fancyQuizHeaders} +% \begin{macro}{\restoreDefaultQuizHeaders} +% \begin{macro}{\dfltFncyQHdrsFmt} +% \begin{macro}{\dclrFncyQzHdrsFmt} +% \begin{macro}{\dclrFncySqHdrsFmt} +% The commands for \cs{fancyQuizHeaders}: \cs{restoreDefaultQuizHeaders} restores +% solution headers to the old style; \cs{eq@fancyQuizHeadersfmt} determines the +% formatting for quizzes; and \cs{eq@fancyShrtQuizHeadersfmt} does the same for +% short quizzes. +% \begin{macrocode} +\def\fancyQuizHeaders{% + \global\let\eq@sqsllabel@fancy@save\eq@sqsllabel + \gdef\eq@sqsllabel{\eq@fancyQuizHeaders}} +\def\eq@fancyQuizHeaders{% + \if\eqQuizType\isQZ\expandafter\eq@fancyQuizHeadersfmt\else + \expandafter\eq@fancyShrtQuizHeadersfmt\fi +} +\let\eq@sqsllabel@fancy@save\@empty +% \end{macrocode} +% We set \cs{eq@sqsllabel} back to its value when \cs{fancyQuizHeaders} was last +% invoked. +% \begin{macrocode} +\def\restoreDefaultQuizHeaders{% + \global\let\eq@sqsllabel\eq@sqsllabel@fancy@save} +% \end{macrocode} +% Here is the definition of the format for quizzes. This can be redefined, a few +% suggestions are made in the documentation. \DescribeMacro{\dfltFncyQHdrsFmt} +% \cmd{\dfltFncyQHdrsFmt} is the common format for both \texttt{quiz} and \texttt{shortquiz}. +% \begin{macrocode} +\newcommand\fncyQHdrsColor{blue} +% \end{macrocode} +% (2016/12/21) Localized some text strings in \cs{dfltFncyHdrsFmt}. +% \changes{v7.8c}{2016/12/21}{Localized some text strings in \string\cs{dfltFncyHdrsFmt}} +% \begin{macrocode} +\newcommand\FncyHdrsFmtNoTitleQuiz{Solution to Quiz:} +\newcommand\FncyHdrsFmtQuestion{Question} +\newcommand\dfltFncyQHdrsFmt{% + \protect\bfseries\protect\color{\fncyQHdrsColor}% + \ifx\aebTitleQuiz\@empty + \ifnum\@eqquestiondepth>0\relax\FncyHdrsFmtNoTitleQuiz\fi + \else\aebTitleQuiz:\ifnum\@eqquestiondepth=0\else\protect\ % + \FncyHdrsFmtQuestion\fi\fi\ifcase\@eqquestiondepth + \ifx\aebTitleQuiz\@empty\FncyHdrsFmtNoTitleQuiz\fi + \or\space\arabic{eqquestionnoi}.% + \or\space\arabic{eqquestionnoi}(\alph{eqquestionnoii})% + \or\space\arabic{eqquestionnoi}(\alph{eqquestionnoii})% + (\roman{eqquestionnoiii})\fi +} +% \end{macrocode} +% \DescribeMacro{\dclrFncyQzHdrsFmt}\cmd{\dclrFncyQzHdrsFmt} is used to declare the formatting for quizzes. +% \begin{macrocode} +\newcommand\dclrFncyQzHdrsFmt[1]{% + \def\eq@fancyQuizHeadersfmt{{#1}}% +} +\dclrFncyQzHdrsFmt{\dfltFncyQHdrsFmt} +% \end{macrocode} +% \DescribeMacro{\dclrFncySqHdrsFmt}\cmd{\dclrFncySqHdrsFmt} is for short quizzes, we make the formatting the same as that for quizzes. +% re-defined. +% \begin{macrocode} +\newcommand\dclrFncySqHdrsFmt[1]{% + \def\eq@fancyShrtQuizHeadersfmt{{#1}}% +} +\dclrFncySqHdrsFmt{\dfltFncyQHdrsFmt} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\titleQuiz} +% \begin{macro}{\titleQuizfmt} +% \begin{macro}{\ifQuizType} +% \begin{macro}{\ifstaroption} +% \begin{macro}{\eq@ifstaroption} +% The \cs{titleQuiz} command adds a title to the quiz or short quiz, using +% a format, as defined in \cs{titleQuizfmt}. The switches \cs{ifQuizType} +% and \cs{eq@ifstaroption} allows you to distinguish between quizzes and +% short quizzes, a \texttt{*} option or non-\texttt{*} option. +% +%\cs{titleQuiz} takes two parameters: an optional \texttt{*} and the +%text for the title of the quiz. When \texttt{*} is used---for short +%quizzes only---the title of the quiz is used for the definition of +%\cs{sqlabel}. Note that \cs{makeatletter} is invoked before the +% parameters are read. +% \changes{v6.7o}{2013/11/25}{Changed \cs{aeb@@titleQuzi} to \cs{aebTitleQuiz}} +% \changes{v6.7p}{2013/12/11}{Added optional parameter to \cs{titleQuiz} +% to execute a command, such as incrementing a counter.} +% \begin{macrocode} +\let\tqhspace\space +\newcommand\titleQuiz[1][]{#1\@titleQuizi} +\def\@titleQuizi{\makeatletter + \@ifstar{\def\eq@tq@star{*}\eq@titleQuiz}% +{\def\eq@tq@star{x}\eq@titleQuiz}} +\def\eq@titleQuiz#1{% + \gdef\aebTitleQuiz{#1}\def\@currentlabelname{#1}% + \gdef\aeb@@titleQuiz{#1}% + \gdef\aebtitleQuiz{\mbox{\titleQuizfmt{#1}}\tqhspace}% +\makeatother} +%</package> +%<package|eqexam>\let\aebtitleQuiz\@empty +%<package|eqexam>\let\aebTitleQuiz\@empty +%<*package> +% \end{macrocode} +% The command to format the \cs{titleQuiz}. +% \begin{macrocode} +\newcommand\titleQuizfmt{\bfseries} +% \end{macrocode} +% A user interface to distinguish between quizzes and short quizzes. +% \begin{macrocode} +\def\ifQuizType#1#2{\if\eqQuizType\isQZ\def\qt@next{#1}% + \else\def\qt@next{#2}\fi\qt@next} +% \end{macrocode} +% Used to distinguish between whether \cs{titleQuiz} was invoked with +% the \texttt{*} option. In the short quiz environment, this command +% is let equal to \cs{ifstaroption}, which is the user-access to this command. +% Outside the \texttt{shortquiz} environment, \cs{ifstaroption} is \cs{@gobbletwo} +% \begin{macrocode} +\def\eq@ifstaroption#1#2{\if\eq@tq@star*\def\sq@next{#1}% + \else\def\sq@next{#2}\fi\sq@next} +\let\eq@tq@star\relax +\def\ifstaroption{\PackageWarning{exerquiz} + {\protect\ifstaroption\space is only defined within the\MessageBreak + shortquiz environment. Gobbling up its two\MessageBreak + arguments, sorry. This occurred}% + \@gobbletwo +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Showing Partial Credit Markup} +% +% \begin{macro}{\aeb@creditmarkup} +% \begin{macro}{\aeb@creditmarkupfmt} +% \begin{macro}{\ptsLabel} +% \begin{macro}{\ptLabel} +% \begin{macro}{\multipartquestion} +% \begin{macro}{\hideCreditMarkup} +% \begin{macro}{\showCreditMarkup} +% \cs{showCreditMarkup} will show points assigned to individual questions in a quiz. +% \cs{showCreditMarkup} turns off this feature. Should be placed before the next quiz, +% not within a quiz. The command \cs{multipartquestion} is placed just prior to a question +% that introduces a problem with sub-parts. See the demo file \texttt{pc\_test.tex} for examples. +% The other two commands \cs{aeb@creditmarkup} and \cs{aeb@creditmarkupfmt} can be redefined +% to suite your tastes. +% +%\changes{v6.2c}{2007/11/14} +%{ +% Added the commands \cs{showCreditMarkup} and \cs{hideCreditMarkup} to show partial credit markup +%} +%\changes{v6.3k}{2008/01/09} +%{ +% Added \cs{ptsLabel} and \cs{ptLabel} to localize the markup in the margin of a quiz +%} +% \begin{macrocode} +\newcounter{qMarkCnt} +\def\multipartquestion{\global\let\aeb@multipart\eq@One} +% \end{macrocode} +% The labeling for the partial credit markup. These two commands are +% are defined (identically) in the \textsf{eqexam} package, hence the +% use of \cs{providecommand}. +% \begin{macrocode} +\providecommand{\ptsLabel}[1]{\def\eqptsLabel{#1}}\ptsLabel{pts} +\providecommand{\ptLabel}[1]{\def\eqptLabel{#1}}\ptLabel{pt} +\let\aeb@multipart\eq@Zero +% \end{macrocode} +% \DescribeMacro{\pcMarkupColor} is the named color in RGB color space to +% use for the color of the partial credit markup. (2013/09/14). +% \begin{macrocode} +\newcommand\pcMarkupColor{red} +% \end{macrocode} +% \cs{aeb@creditmarkup} creates a small text fields that holds the partial +% credit markup. The command may be redefined, perhaps to changes the dimensions +% of the rectangular bounding box, set at \texttt{12bp} by \texttt{8bp}. +% +% We supply basic controls for the text field, width (\DescribeMacro{\markupWidth}\cmd\markupWidth), +% height (\DescribeMacro{\markupHeight}\cmd{\markupHeight}), and text size +% (\DescribeMacro{\markupTextSize}\cmd{\markupTextSize}) +% \begin{macrocode} +\def\markupWidth{12bp}\def\markupHeight{8bp}\def\markupTextSize{0} +% \end{macrocode} +% \cmd\aeb@creditmarkup creates the text field that appears in the margins. +% \begin{macrocode} +\newcommand{\aeb@creditmarkup}{% + \textField[\Ff\FfReadOnly\BC{}\F\FHidden + \textColor{\pcMarkupColor}\textSize{\markupTextSize}\autoCenter{n}% + \DV{0 \eqptsLabel}\V{0 \eqptsLabel}]% + {qMark.\currQuiz.\thequestionno.\arabic{qMarkCnt}}% + {\markupWidth}{\markupHeight}% +} +% \end{macrocode} +% The \cs{showCreditMarkup} command defines \cs{qMark} and \cs{qMark@Hook}. +% \begin{macrocode} +\def\showCreditMarkup{% +% \end{macrocode} +% \cs{qMark} makes the decision whether to place a mark or not. If +% the command \cs{multipartquestion} has been expanded, \cs{aeb@multipart} is one, otherwise +% it is zero. If zero we do place the markup, otherwise, no. +% \begin{macrocode} + \def\qMark{\if\aeb@multipart\eq@Zero\aeb@creditmarkup + \stepcounter{qMarkCnt}\else\global\let\aeb@multipart\eq@Zero\fi}% +% \end{macrocode} +% \cs{qMark@Hook} is a hook that is normally \cs{@empty}. The hook is strategically +% placed at the beginning of each question \cs{item}. Here we define it to be +% \cs{aeb@creditmarkupfmt}. +% \begin{macrocode} + \def\qMark@Hook{\aeb@creditmarkupfmt}% +} +% \end{macrocode} +% Turn off partial credit markup by putting \cs{qMark@Hook} back to its default. +% \begin{macrocode} +\def\hideCreditMarkup{\global\let\qMark@Hook\@empty} +% \end{macrocode} +% A simple command to place the \cs{qMark} in a \cs{makebox[0pt][r]}, with +% a little adjustment to please the eye. +% \begin{macrocode} +\newcommand{\aeb@creditmarkupfmt}{\makebox[0pt][r]{\qMark\hspace{-2bp}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +%\subsection{Filtering solutions to quizzes} +% The \cs{eqQt} and \cs{eqSQt} commands have one argument designed to be used to filter +% solutions to quizzes. The demo document is \texttt{filter\_quizzes.tex}, +% but basically, we can include the solutions several times, once for each set filtered set. +% \begin{macrocode} +\long\def\gobbleToEndQt#1\endeqQt{\ifeqforpaper\expandafter\@gobble\fi} +\long\def\gobbleToEndSQt#1\endeqSQt{% + \ifeqforpaper\expandafter\@gobble\fi} +% \end{macrocode} +% The \DescribeMacro{\inclQtFilter}\cmd{\inclQtFilter} operates on the quizzes. If the argument \texttt{\#1} +% matches the optional argument of \cs{filterFor}, we include, otherwise, we gobble +% up everything to the end of the quiz, including the token that follows +% \cmd{\gobbleToEndQt}. +% \begin{macrocode} +\newcommand\inclQtFilter[1]{\def\eqarg{#1}\ifx\eqarg\eqFilterArg + \else\expandafter\gobbleToEndQt\fi} +% \end{macrocode} +% The \DescribeMacro{\exclQt}\cmd{\exclQt} command exclude all quiz solutions. +% \begin{macrocode} +\newcommand{\exclQt}[1]{\gobbleToEndQt} +% \end{macrocode} +% The \DescribeMacro{\useQtFilter}\cmd{\useQtFilter} command \cs{let}s \cs{eqQt} to +% \cs{inclQtFilter}, and it also \cs{let}s \cs{eqSQt} to +% \cs{exclSQt}. +% \begin{macrocode} +\newcommand{\useQtFilter}{% + \let\eqQt\inclQtFilter\let\eqSQt\exclSQt +} +% \end{macrocode} +% Now we repeat the same sequence of construct for short quizzes. +% The command \DescribeMacro{\inclSQtFilter}\cmd{\inclSQtFilter} includes a short quiz +% solution if it meets the filter criteria. +% \begin{macrocode} +\newcommand\inclSQtFilter[1]{\def\eqarg{#1}\ifx\eqarg\eqFilterArg + \else\expandafter\gobbleToEndSQt\fi} +% \end{macrocode} +% The \DescribeMacro{\exclSQt}\cmd{\exclSQt} command excludes all short quiz solutions. +% \begin{macrocode} +\newcommand{\exclSQt}[1]{\gobbleToEndSQt} +% \end{macrocode} +% The \DescribeMacro{\useSQtFilter}\cmd{\useSQtFilter} \cs{let}s \cs{eqSQt} to +% \cs{inclSQtFilter}. +% \begin{macrocode} +\newcommand{\useSQtFilter}{\let\eqSQt\inclSQtFilter\let\eqQt\exclQt} +% \end{macrocode} +% +%\section{Bookmarking the Quizzes} +% +% \begin{macro}{\sqbookmarkfmt} +% \begin{macro}{\qzbookmarkfmt} +% \begin{macro}{\quizpdfbookmark} +% Support for bookmarking the quizzes and shortquizzes. Unlike the bookmarking +% of the exercises, there is no support for bookmarking individual questions +% within a quiz. +%\changes{v6.2a}{2007/11/10} +%{ +% Added \cs{quizpdfbookmark} to bookmark quizzes. +%} +% \begin{macrocode} +\newcommand{\sqbookmarkfmt}{Short Quiz \@shortquizCnt.\space} +\newcommand{\qzbookmarkfmt}{Quiz \@quizCnt.\space} +\newcommand{\quizpdfbookmark}[1]{\relax\def\argi{#1}% + \if\eqQuizType\isSQZ\edef\aeb@bmmrkdest{sqbm.\@shortquizCnt}% + \def\aeb@thisbkmrkfmt{\sqbookmarkfmt}\else + \edef\aeb@bmmrkdest{qzbm.\@quizCnt}% + \def\aeb@thisbkmrkfmt{\qzbookmarkfmt}\fi + \def\quizpdfbookmarktitle{#1}% + \def\eqex@next{\belowpdfbookmark{\aeb@thisbkmrkfmt#1}% + {\aeb@bmmrkdest}}% + \ifx\aebTitleQuiz\@empty\else\ifx\argi\@empty + \def\quizpdfbookmarktitle{\aebTitleQuiz}% + \def\eqex@next{\belowpdfbookmark{\aebTitleQuiz}% + {\aeb@bmmrkdest}}\fi\fi + \eqex@next\ignorespaces +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \section{Multiple Choice Alternatives} +% \subsection{For \texttt{shortquiz}} +% \subsubsection{The \texttt{answers} Environment} +% \begin{macro}{answers} +% The alternatives of a multiple choice question are enclosed in +% the \texttt{answers} environment. +% This environment takes an optional argument, and one +% required argument. The required parameter is the number of +% columns to construct in the underlying \texttt{tabular} +% environment; the presence of the optional argument means the author +% wants to include the solution to this quiz question. The value of +% the optional parameter is the named destination of the solution. +% The optional parameter for the named destination can also be a +% `\texttt*', in which case a name of \texttt{\string\curr@quiz.\string\thequestionno} +% is assigned. +% \begin{macrocode} +%</package> +%<*package|eqexam> +\def\pushEnvir{\xdef\eq@currenvir{\@currenvir}\endgroup} +\def\popEnvir{\begingroup\@endpefalse + \edef\@currenvir{\eq@currenvir}% + \edef\@currenvline{\on@line}% +} +\def\answers@sq{\parindent0pt +% \end{macrocode} +% The \texttt{answers} environment needs to go into horizontal mode for the +% \cs{linelength} to be correct when using \cs{leadinitem}. +% \begin{macrocode} + \ifx\solutionparshape\@empty\else +% ?? remove the \par, why is it there to begin with? + \pushEnvir\par\noindent\expandafter\popEnvir\fi +% \pushEnvir\par\noindent\expandafter\popEnvir\fi + \stepcounter{questionno}% + \if\sqstar*\relax + \if\aeb@FLOverride\eq@l + \let\@Ans\Ans@sq@l\else + \let\@Ans\Ans@sq@f\fi + \else + \if\aeb@FLOverride\eq@f + \let\@Ans\Ans@sq@f\else + \let\@Ans\Ans@sq@l\fi + \fi + \def\aeb@answerType{r}\@ifnextchar[{\answers@@sq}% + {\@ifstar{\answers@@sq[\curr@quiz.\thequestionno]}{\answers@@sq[]}}} +\def\manswers@sq{\parindent0pt +% \end{macrocode} +% \cs{ifuserectforms} is defined in \textsf{eqexam}, +% \begin{macrocode} + \@ifundefined{ifuserectforms}{} + {\if\aeb@FLOverride\eq@f\ifuserectforms + \useRectForMC\else\useCircForMC\fi\fi}% + \ifx\solutionparshape\@empty\else + \pushEnvir\par\noindent\expandafter\popEnvir\fi + \stepcounter{questionno}% + \if\sqstar*\relax + \if\aeb@FLOverride\eq@l + \let\@Ans\Ans@ck@sq@l\else + \let\@Ans\Ans@ck@sq@f\fi +% \if\aeb@FLOverride l\let\@Ans\Ans@ck@sq@f\fi + \else + \if\aeb@FLOverride\eq@f + \let\@Ans\Ans@ck@sq@f\else + \let\@Ans\Ans@ck@sq@l\fi + \fi + \def\aeb@answerType{c}\@ifnextchar[{\answers@@sq}% + {\@ifstar{\answers@@sq[\curr@quiz.\thequestionno]}{\answers@@sq[]}}} +% \end{macrocode} +% \end{macro} +%\begin{verbatim} +% #1 = named destination to be associated with solution +% #2 = number of columns in the tabular environment +%\end{verbatim} +% If the number of columns specified, then we use a list environment. +% \begin{macrocode} +\let\sq@hwdest\@empty % hard-wired destination +\def\answers@@sq[#1]#2{% + \xdef\aeb@numCols{#2}% + \ifx\sq@hwdest\@empty + \xdef\@qzsolndest{#1}\else + \gdef\@qzsolndest{\sq@hwdest}\fi + \if\aeb@numCols1\gdef\eq@listType{1}\expandafter\answers@sq@list + \else + \gdef\eq@listType{0}\expandafter\answers@@sq@tabular + \fi{\aeb@numCols}% +} +% \end{macrocode} +% \begin{macro}{\setMClabelsep} +% \changes{v6.05e}{2006/18/06 v6.05e} +% { +% Added control over the separation between the MC label and subsequent text: +% \cs{setMClabelsep} and \cs{resetMClabelsep}. +% } +% \begin{macro}{\resetMClabelsep} +% \begin{macro}{\eq@hspanner} +% \begin{macro}{\eq@hspanner@default} +% Some convenience macros for computing the width of labels. The command \cs{setMClabelsep} +% can be used to set the separation between the MC label and the beginning of text. The +% argument for this command is anything that takes up horizontal space. The command sets +% the value of \cs{eq@hspanner}. The default value % of the separation is given by \cs{eq@hspanner@default}. +% The default value can be restored by executing \cs{resetMClabelsep}. +% \begin{macrocode} +\def\setMClabelsepDefault#1{\def\eq@hspanner@default{#1}} +\def\setMClabelsep#1{\def\eq@hspanner{#1}} +\setMClabelsep{\ }\setMClabelsepDefault{\ } +\def\resetMClabelsep{\expandafter\setMClabelsep\expandafter + {\eq@hspanner@default}} +\def\eq@lw@l{\eq@l@l\eq@hspanner} +% \end{macrocode} +% For the link-style MC question, the default width, \cs{eq@l@l}, of the label is the normalsize width of +% `(d)'. For a form checkbox or radiobutton bux, the default width, cs{eq@lw@f}, is \cs{RadioFieldSize}, +% normally defined as \texttt{11bp}. +% \begin{macrocode} +\def\eq@l@l{\normalsize\normalfont(d)} +\def\eq@lw@f{\kern\RadioFieldSize\eq@hspanner} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% This macro will pick up the arguments of the \cs{Ans} command. +%\begin{verbatim} +% [#1] = points to be awarded if problem is false (partial credit) +% #2 = 1 (for true) or 0 (for false) +%\end{verbatim} +% In a list, each time the \cs{item} is executed, \cs{@Ans} +% is executed as the default label. +% +% These parameters are saved in the commands \cs{eq@pPTs} and +% \cs{Ans@choice}. +% \begin{macrocode} +\@ifundefined{ifwithsoldoc}{\newif\ifwithsoldoc\withsoldocfalse}{} +\let\eq@ansChoiceArray\@empty +\def\eq@recordAnsChoice{% + \ifx\eq@ansChoiceArray\@empty + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\eq@ansChoiceArray{"\alph{quizno}"}}\else + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\eq@ansChoiceArray{,"\alph{quizno}"}}\fi + \tmp@exp +} +\newcommand\Ans@list[2][0]{\gdef\eq@pPTs{#1}% + \xdef\Ans@choice{#2}\item\relax\noindent\if\eq@listType\eq@One + \addtocounter{quizno}{-1}\@ifundefined{ifwithsoldoc} + {\refstepcounter{quizno}}{\ifwithsoldoc\stepcounter{quizno}\else + \refstepcounter{quizno}\fi}\fi + \ignorespaces} +% \end{macrocode} +% Answers environment for a list environment. +% \begin{macrocode} +\newenvironment{answers@sq@list}[1] +{% + \ifx\aeb@answerType\eq@r + \let\endanswers\endanswers@sq@list\else + \let\endmanswers\endanswers@sq@list\fi + \list{\strut\@Ans}{% + \if\sqstar*\relax + \settowidth{\labelwidth}{\eq@lw@f}\else + \settowidth{\labelwidth}{\eq@lw@l}\fi +% \end{macrocode} +% (2013/05/17) Incorporated \cs{aboveanswersSkip} into \cs{topsep} +% \begin{macrocode} + \setlength{\topsep}{-\parskip+\aboveanswersSkip}% + \setlength{\parsep}{0pt}\setlength{\itemindent}{0pt}% +% \end{macrocode} +% (2014/04/05) Added a specification for \cs{itemsep} so that the +% \cs{rowsep} acts identically for tabular and list. +% \begin{macrocode} + \setlength{\itemsep}{0pt}\setlength{\partopsep}{0pt}% + \setlength{\listparindent}{\parindent}% +% \end{macrocode} +% (2013/05/17) When inside the parts environment in tabular-mode, +% we need to add in \cs{eqemargin}. For \textsf{exerquiz} defaults +% to 0pt; when \textsf{eqexam} is used, it has a nonzero value. +% \begin{macrocode} + \ifnum\exerwparts@cols>1\relax + \ifx\itsExerParts\eq@YES % dps17 + \setlength{\leftmargin}{\labelwidth}\else + \setlength{\leftmargin}{\labelwidth+\eqemargin}\fi + \else +% \end{macrocode} +% (2013/05/17) Some adjustments depending on whether \cs{solutionparshape} +% is empty or not. If empty, \cs{leftmargin} is its usual value; otherwise +% we add in \cs{eqemargin} (0pt in \textsf{exerquiz}, nonzero in \textsf{eqexam}). +% \begin{macrocode} + \ifx\solutionparshape\@empty + \setlength{\leftmargin}{\labelwidth}\else + \setlength{\leftmargin}{\labelwidth+\eqemargin}\fi\fi +% \end{macrocode} +% (2013/10/10) I'm changing the \cs{labelsep}, one definition for \texttt{eqexam} +% another for \texttt{exerquiz}. +% to the following. +% \begin{macrocode} +%</package|eqexam> +%<package> \setlength{\labelsep}{0pt}% +%<package>% \settowidth{\labelsep}{\eq@hspanner}% +%<eqexam> \setlength{\labelsep}{0pt}% +%<*package|eqexam> + \def\Ans{\Ans@list}% + }% +}% +{\endlist\setcounter{quizno}{0}\eq@answersEndHook} +% \end{macrocode} +% Answers environment for a tabular environment. This command picks +% up the arguments of \cs{Ans}, then passes on the \cs{@Ans} +%\begin{verbatim} +% [#1] = points to be awarded if problem is false (partial credit) +% #2 = 1 (for true) or 0 (for false) +%\end{verbatim} +% These parameters are saved in the commands \cs{eq@pPTs} and +% \cs{Ans@choice}. +% \begin{macrocode} +\newcommand\Ans@tabular[2][0]{\gdef\eq@pPTs{#1}% + \xdef\Ans@choice{#2}\leavevmode\@Ans +} +% \end{macrocode} +% (2013/05/17) \DescribeMacro{\sqtabsep} sets the \cs{tabsep} between columns. +% \DescribeMacro{\sqTabPos} \cs{sqTabPos} allows you to set the positioning +% optional parameter (t,c,b) on the tabular env. The default is no optional parameter. +% \begin{macrocode} +\newcommand\sqtabsep[1]{\def\eq@argi{#1}\ifx\eq@argi\@empty + \def\sq@tabsep{1.5pt}\else\def\sq@tabsep{#1}\fi} +\sqtabsep{1.5pt} +\def\sqTabPos#1{\def\sq@TabPos{[#1]}}\sqTabPos{} +\def\answers@@sq@tabular#1{% +% \ifinner\else\par\vskip-\parskip\vspace{\aboveanswersSkip}\fi + \ifinner % dps17 + \ifx\itsExerParts\eq@YES\par\removelastskip + \removelastparskip\vskip\aboveanswersSkip\fi + \else\par\removelastskip\removelastparskip + \vskip\aboveanswersSkip\fi +% \end{macrocode} +% (2013/05/17) If within a parts environment in tabular mode, the tab env +% needs to be shifted over by an amount of \cs{eqemargin}, for +% \textsf{exerquiz} this is 0pt, nonzero for \textsf{eqexam}. +% \begin{macrocode} + \noindent\ifnum\exerwparts@cols>1\relax\parshape=0\fi + \tabcolsep=0pt +% \end{macrocode} +%\begin{verbatim} +% n=#1 +% width=(\linewidth-2*(n-1)*\tabcolsep)/n +%\end{verbatim} +% In the next line, we adjust \cs{linewidth}, \cs{eqemargin} is \texttt{0pt} +% in \textsf{exerquiz} and nonzero otherwise. +% \begin{macrocode} +% \setlength{\linewidth}{\linewidth-\eqemargin}% + \eq@tmpdima=\linewidth + \@tempcnta#1\relax +% n-1 + \advance\@tempcnta-1\relax +% 2(n-1) + \multiply\@tempcnta by2 + \@tempdima\sq@tabsep\relax +% 2*(n-1)*\eq@partstabcolsep + \multiply\@tempdima\@tempcnta +% \linewidth-(n-1)*\sq@tabsep + \advance\eq@tmpdima-\@tempdima +% (\linewidth-(n-1)*\sq@tabsep)/n + \divide\eq@tmpdima by#1 + \def\Ans{\Ans@tabular}% + \tabcolsep\sq@tabsep\relax +% \end{macrocode} +% (2013/05/17) We allow the position argument (t,b,c). It changed +% through \cs{sqTabPos} defined above. +% \begin{macrocode} + \expandafter\tabular\sq@TabPos{@{}*{#1}{p{\eq@tmpdima}}@{}}}% +% \end{macrocode} +% \changes{v7.4}{2015/03/23}{added \cmd{\reset@doendpe}} +% \DescribeMacro{\reset@doendpe} attempts to restore the \cs{parshape} +% following a list environment. It appears in several locations, includeing +% \cs{endanswers}, \cs{endmanswers}, and \cs{setTabulrSolnEnv}. +% \par\medskip\noindent We begin by saving the core definition of \cs{@doendpe}, +% it is restored after each usage of \cs{reset@doendpe}. +% \begin{macrocode} +\let\eq@save@doendpe\@doendpe +% \end{macrocode} +% The argument \texttt{\#1} consists of the \cs{parshape} parameters to be restored +% following the closing of any environment that uses \cs{doendpe} +% \begin{macrocode} +\def\reset@doendpe#1{\global\eq@scratchtoks=\expandafter{#1}% + \gdef\@doendpe{\par\@endpetrue\global\let\@doendpe\eq@save@doendpe + \def\par{\@restorepar + \expandafter\everypar + \expandafter{\the\eq@scratchtoks}\par\@endpefalse}% + \everypar{{\setbox\z@\lastbox}% + \everypar{}\@endpefalse}\the\eq@scratchtoks + }% +} +% \end{macrocode} +% +% \begin{macro}{\endanswers} +% Close off \texttt{tabular} environment, and reinitialize the +% \texttt{quizno} counter. Added \cs{answersEndHook}. +% \begin{macrocode} +\newcommand\answersEndHook[1]{\def\eq@answersEndHook{#1}} +\let\eq@answersEndHook\@empty +\def\endanswers@sq{\endtabular\setcounter{quizno}{0}% + \eq@answersEndHook\reset@doendpe{\the\everypar}% + \ifinner\else%\par + \removelastskip +% \removelastparskip + \vspace{\aboveanswersSkip}\@endpetrue\fi +} +\def\endmanswers@sq{\endtabular\setcounter{quizno}{0}% + \eq@answersEndHook\reset@doendpe{\the\everypar}% + \ifinner\else%\par + \removelastskip +% \removelastparskip + \vspace{\aboveanswersSkip}\@endpetrue\fi +} +\def\popiiictm{\special{CTM: pop pop pop}} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \subsubsection{Link Style} +% \begin{macro}{\Ans@sq@l} +% For the link multiple choice type question. The driver independent stuff starts +% here, then goes to |\Ans@sq@l@driver| the rest of the code that depends on the +% driver. +% \begin{macrocode} +\def\sqWrongRespJS{OnBlurRespBox( false, "\oField" );} +\def\sqRightRespJS{OnBlurRespBox( true, "\oField" );} +\def\Ans@sq@l@Actions +{% + \A{\if\Ans@choice1 + \JS{\sqRightRespJS} + \ifx\@qzsolndest\@empty\else + \ifeq@solutionsafter\else + /Next <</S/GoTo/D(\@qzsolndest)>> + \fi + \fi + \else + \JS{\sqWrongRespJS\jsR + \ifx\oField\@empty\else + updateTally("\oField.\thequestionno"); + \fi}% + \fi + }% +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\def\linkContentFormat{\alph{quizno}} +\def\aebChoiceAltFmt{\noexpand\ifaebshowgrayletters + \Alph{quizno}\noexpand\else\linkContentFormat\noexpand\fi} +%</package> +%<*eqexam> +\def\aebChoiceAltFmt{\noexpand\ifaebshowgrayletters + \Alph{quizno}\noexpand\else\linkContentFormat\noexpand\fi} +\def\linkContentFormat{% + \if\probstar*\Alph{quizno}\else\alph{quizno}\fi} +%</eqexam> +%<*package|eqexam> +\def\linkContentWrapper{(\hfil\linkContentFormat\hfil)}% +\def\Ans@sq@l{% + \leavevmode\if\eq@listType\eq@One\stepcounter{quizno}\else + \@ifundefined{ifwithsoldoc}{\refstepcounter{quizno}} + {\ifwithsoldoc\stepcounter{quizno}\else + \refstepcounter{quizno}\fi}\fi\PBS\raggedright + \settowidth{\eq@tmplength}{\eq@lw@l}\sbox{\eq@tmpbox}{\eq@l@l}% + \eq@tmpdima=\wd\eq@tmpbox + \def\link@@Content{\linkContentWrapper}% + \hangindent=\eq@tmplength\hangafter=1\relax +%</package|eqexam> +%<*eqexam> + \Ans@sq@l@driver +%</eqexam> +%<*package> + \set@@Link{}{}{}% + {\makebox[\eq@tmpdima]{\color{\@linkcolor}\link@@Content}} + {\eq@protect\A}{\eq@setWidgetProps\setLink@driver}% + {\set@LinkTextDefaults\Ans@sq@l@Actions\every@Link}% + \Ans@proofing{\eq@tmpdima}% +%</package> +%<*package|eqexam> +\eq@hspanner\ignorespaces} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \begin{macro}{\Ans@ck@sq@l} +% Created in support of eqExam to give multiple selection for the +% online and email options. Otherwise, it defaults to a radio button field. +% \begin{macrocode} +\def\Ans@ck@sq@l{\Ans@ck@sq@f} +%</package> +%<*eqexam> +% dps 4/16/05 +\let\Ans@ck@sq@l\Ans@sq@l +%</eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \subsubsection{Form Style} +% \begin{macro}{\Ans@sq@f} +% For the link multiple choice type question. The driver independent stuff starts +% here, then goes to |\Ans@sq@f@driver| the rest of the code that depends on the +% driver. +% \changes{v7.7d}{2015/11/15}{Changed mc.\cs{oFields} so it is printable} +% \begin{macrocode} +\def\@@Ans@sq@f@Defaults +{% + \BC{0 0 0}\Ff{\FfNoToggleToOff}\W{1} + \F{\FPrint}\textSize{12}\textColor{0 g} +} +% \end{macrocode} +% For short quizzes, refine the type of responses: turn off the alert +% message (the default is on); or have a (red) `\texttt{x}' make an +% incorrect answer, and a (green) check mark a correct answer. +% \begin{macrocode} +\def\sqTurnOffAlerts{\let\@sqTurnOffAlerts\eq@Zero} +\def\sqTurnOnAlerts{\let\@sqTurnOffAlerts\eq@One} +\sqTurnOnAlerts +% \end{macrocode} +% This feature was discontinued sometime between version 5.x and 6.x. +% \begin{macrocode} +\def\sqNoCorrections{\let\@sqAlertsOnly\eq@One} +\def\sqCorrections{\let\@sqAlertsOnly\eq@Zero} +\sqNoCorrections +% \end{macrocode} +% The actions for the form version of a multiple choice question of a \texttt{shortquiz}. +% \begin{macrocode} +\def\Ans@sq@f@Actions +{% + \A{\if\Ans@choice\eq@One + \JS{% +% \end{macrocode} +%\changes{v6.7d}{2013/05/27}{removed JS control of checks and color, they +% are hardwired instead.} +% \begin{macrocode} + \if\@sqTurnOffAlerts1OnBlurRespBox(true,"\oField");\jsR\fi + \ifx\@qzsolndest\@empty\else + \ifeq@solutionsafter\else + jmpToNamedDest("\oField","\@qzsolndest",% +\if\@sqTurnOffAlerts00\else1\fi);\fi + \fi}% + \else + \JS{% + \if\@sqTurnOffAlerts1OnBlurRespBox( false, % +"\oField" );\jsR\fi + \ifx\oField\@empty\else + updateTally("\oField.\thequestionno"); + \fi}% + \fi% + }% + \AA{\AAMouseDown{\JS{% + updateTally.downState=!!event.target.isBoxChecked% +(\arabic{quizno}-1);}}}% +} +\def\Ans@proofing +#1{% + \ifeq@proofing\if\Ans@choice1\relax + \llap{\@proofingsymbol\,\hskip#1\relax}% + \fi\fi +} +% \end{macrocode} +%\DescribeMacro{\sqRghtSymbChoice}\DescribeMacro{\sqRghtSymbColor} for the \texttt{shortquiz} +% environment, these first two commands assign the right symbol (default check) and +% color (default webgreen). The second two\DescribeMacro{\sqWrngSymbChoice}\DescribeMacro{\sqWrngSymbColor} +% does the same thing for the wrong answer. +% \begin{macrocode} +\def\sqRghtSymbChoice#1{\chooseJSsymbol*{#1}% + \ifx\eq@retnStyle\@empty + \edef\sq@corrsymch{\sqRghtSymbChoiceDef}\else + \edef\sq@corrsymch{#1}\fi} +\def\sqRghtSymbColor#1{\edef\eq@arg{#1}\ifx\eq@arg\@empty + \edef\sq@corrsymcol{\sqRghtSymbColorDef}\else + \edef\sq@corrsymcol{#1}\fi} +\def\sqWrngSymbChoice#1{\chooseJSsymbol*{#1}% + \ifx\eq@retnStyle\@empty + \edef\sq@wrgsymch{\sqWrngSymbChoiceDef}\else + \edef\sq@wrgsymch{#1}\fi} +\def\sqWrngSymbColor#1{\edef\eq@arg{#1}\ifx\eq@arg\@empty + \edef\sq@wrgsymcol{\sqWrngSymbColorDef}\else + \edef\sq@wrgsymcol{#1}\fi} +\def\sqRghtSymbChoiceDef{check} +\def\sqRghtSymbColorDef{0 .6 0 rg} +\def\sqWrngSymbChoiceDef{cross} +\def\sqWrngSymbColorDef{1 0 0 rg} +\edef\sq@corrsymch{\sqRghtSymbChoiceDef} +\edef\sq@corrsymcol{\sqRghtSymbColorDef} +\edef\sq@wrgsymch{\sqWrngSymbChoiceDef} +\edef\sq@wrgsymcol{\sqWrngSymbColorDef} +\def\sqResetSymbToDef{% + \sqRghtSymbChoice{}\sqRghtSymbColor{}% + \sqWrngSymbChoice{}\sqWrngSymbColor{}% +} +% \end{macrocode} +%\DescribeMacro{\qChoiceSymb}\DescribeMacro{\qChoiceColor} for the \texttt{quiz} +% environment, these two commands assign the selection symbol (default check) and the +% color (default webgreen). +% \begin{macrocode} +\def\qChoiceSymb#1{\chooseJSsymbol*{#1}% + \ifx\eq@retnStyle\@empty + \edef\qz@chksymb{\qChoiceSymbDef}\else + \edef\qz@chksymb{#1}\fi} +\def\qChoiceColor#1{\edef\eq@arg{#1}\ifx\eq@arg\@empty + \edef\qz@chksymbcol{\qChoiceColorDef}\else + \edef\qz@chksymbcol{#1}\fi} +\def\qChoiceSymbDef{check} +\def\qChoiceColorDef{0 0 0 rg} +\edef\qz@chksymb{\qChoiceSymbDef} +\edef\qz@chksymbcol{\qChoiceColorDef} +%</package> +%<*package|eqexam> +\let\rbf@Opts\@empty +\def\Ans@sq@f{% + \if\eq@listType\eq@One\stepcounter{quizno}\else + \@ifundefined{ifwithsoldoc}{\refstepcounter{quizno}} + {\ifwithsoldoc\stepcounter{quizno}\else + \refstepcounter{quizno}\fi}\fi\PBS\raggedright +%</package|eqexam> +% \end{macrocode} +%\changes{v6.7d}{2013/05/27}{added \cs{rbf@Opts} to hardwire choices.} +% \begin{macrocode} +%<*package> + \if\Ans@choice\eq@One + \def\rbf@Opts{\symbolchoice{\sq@corrsymch}% + \textColor{\sq@corrsymcol}}\else + \def\rbf@Opts{\symbolchoice{\sq@wrgsymch}% + \textColor{\sq@wrgsymcol}}\fi +%</package> +%<*package|eqexam> + \settowidth{\eq@tmplength}{\eq@lw@f}% + \eq@tmpdima=\wd\eq@tmpbox% + \hangindent=\eq@tmplength\hangafter=1\relax + \insertGrayLetters % 6.3d +%</package|eqexam> +%<*eqexam> + \Ans@sq@f@driver +%</eqexam> +%<*package> +% \end{macrocode} +%\changes{v6.7d}{2013/05/27}{new \cs{rbf@Opts} option.} +% \begin{macrocode} + \mbox{\expandafter\radio@@Button\expandafter{\rbf@Opts}% + {mc.\oField.\thequestionno}% + {\RadioFieldSize}% 11/16/05 changed from \oField to mc.\oField + {\RadioFieldSize}{\Ans@choice\alph{quizno}}{\eq@protect\A}% + {\eq@setWidgetProps\eq@RadioCheck@driver}% + {\@@Ans@sq@f@Defaults\Ans@sq@f@Actions\every@RadioButton + \every@sqRadioButton}}% + \Ans@proofing{\RadioFieldSize}% +%</package> +%<*package|eqexam> +\eq@hspanner\ignorespaces} +%</package|eqexam> +%<*package> +% \end{macrocode} +% \end{macro} +% \begin{macro}{\Ans@ck@sq@f} +% Created in support of \textsf{eqExam} to give multiple selection for the +% online and email options. Otherwise, it defaults to a radio button field. +% \begin{macrocode} +% +%</package> +%<*eqexam> +% dps 4/16/05 +\let\Ans@ck@sq@f\Ans@sq@f +%</eqexam> +%<*package> +\def\@@Ans@ck@sq@f@Defaults +{% + \BC{0 0 0}\Ff{\FfNoToggleToOff} + \F{\FPrint}\textSize{12}\textColor{0 g}\W{1} +} +\begingroup +\catcode`\&=12 +\gdef\eq@AND{&&} +\endgroup +\def\Ans@ck@sq@f@Actions +{% + \A{\if\Ans@choice1% + \JS{% +var fName=event.target.name;\jsR +var g=this.getField("mc.\oField.\thequestionno");\jsR +var a=g.getArray();\jsR +for (var i=0; i<a.length; i++)\jsR\jsT + if ( a[i].isBoxChecked(0) \eq@AND\space +a[i].value.charAt(0)==0)\jsR\jsT\jsT + a[i].checkThisBox(0,false);\jsR + \if\@sqTurnOffAlerts1OnBlurRespBox( % + true, "\oField" );\jsR\fi + \ifx\@qzsolndest\@empty\else + \ifeq@solutionsafter\else +% if all correct answers are check, jump to solution +for (var i=0; i<a.length; i++){\jsR\jsT + if ( a[i].exportValues[0].charAt(0)==1 \eq@AND\space +!a[i].isBoxChecked(0) )\jsR\jsT\jsT + break;\jsR +}\jsR + if (i>=a.length) jmpToNamedDest("\oField","\@qzsolndest",% + \if\@sqTurnOffAlerts00\else1\fi); + \fi + \fi}% + \else% + \JS{% +var fName=event.target.name;\jsR +var g=this.getField("mc.\oField.\thequestionno");\jsR +var a=g.getArray();\jsR +for (var i=0; i<a.length; i++)\jsR +{\jsR\jsT + if (a[i].value.charAt(0)==0) {\jsR\jsT\jsT + if ( fName != a[i].name )\jsR\jsT\jsT\jsT + a[i].checkThisBox(0,false);\jsR\jsT + }\jsR +}\jsR + \if\@sqTurnOffAlerts1OnBlurRespBox( false, "\oField" );\fi% + \ifx\oField\@empty\else% + updateTally("\oField.\thequestionno"); + \fi}% + \fi% + }% + \AA{\AAMouseDown{% +\JS{updateTally.downState=!!event.target.isBoxChecked(0);}}} +} +\def\Ans@ck@sq@f{% + \if\eq@listType\eq@One\stepcounter{quizno}\else + \@ifundefined{ifwithsoldoc}{\refstepcounter{quizno}} + {\ifwithsoldoc\stepcounter{quizno}\else + \refstepcounter{quizno}\fi}\fi\PBS\raggedright + \if\Ans@choice1% + \def\rbf@Opts{\symbolchoice{\sq@corrsymch}% + \textColor{\sq@corrsymcol}}\else + \def\rbf@Opts{\symbolchoice{\sq@wrgsymch}% + \textColor{\sq@wrgsymcol}}\fi + \settowidth{\eq@tmplength}{\eq@lw@f}% + \eq@tmpdima=\wd\eq@tmpbox% + \hangindent=\eq@tmplength\hangafter=1\relax + \insertGrayLetters % 6.3d + \mbox{\expandafter\check@@Box\expandafter{\rbf@Opts}% + {mc.\oField.\thequestionno.\arabic{quizno}}% + {\RadioFieldSize}{\RadioFieldSize} + {\Ans@choice\alph{quizno}}{\eq@protect\A}% + {\eq@setWidgetProps\eq@RadioCheck@driver}% + {\@@Ans@ck@sq@f@Defaults\Ans@ck@sq@f@Actions\every@CheckBox + \every@sqCheckBox}}% + \Ans@proofing{\RadioFieldSize}% +\eq@hspanner\ignorespaces} +% \end{macrocode} +% \end{macro} +% \subsection{For \texttt{quiz}} +% \subsubsection{The \texttt{answers} and \texttt{manswers} Environment} +% \begin{macro}{answers} +% This is the answers environment for the \texttt{quiz} +% environment. The \texttt{quiz} environment states +% \verb+\let\answers=\answers@q+. This is to avoid a conflict +% with \texttt{shortquiz}, which also as an \texttt{answers} +% environment. +% +% The following parameters are recognized: +%\begin{verbatim} +% [#1]|* = named destination to be associated with solution; +% with *, the destination is automatically generated +% #2 = number of columns in the tabular environment +%\end{verbatim} +% If the number of columns is $1$, then we use a list environment, +% else, we use a tabular environment. +% \begin{macrocode} +%</package> +%<*package|eqexam> +\newskip\aboveanswersSkip +\setlength\aboveanswersSkip{3pt} +%</package|eqexam> +%<*package> +\let\q@hwdest\@empty % hard-wired destination +\let\pointValuesArray\@empty +\newif\ifeqshowmarkup\eqshowmarkupfalse +\newif\ifeqshowOutOf \eqshowOutOffalse +\def\showOutOfinSmryTbl{false} +\def\eq@recordThesePTs{% + \ifx\pointValuesArray\@empty + \edef\ptsValue{\showOutOfinSmryTbl,\eqPTs}\else + \edef\ptsValue{,\eqPTs}\fi + \expandafter\g@addto@macro\expandafter\pointValuesArray + \expandafter{\ptsValue}} +% \end{macrocode} +% \changes{v7.7m}{2016/07/04}{Added \string\texttt{ptypeArray} to track problem types better} +% \begin{macrocode} +\let\ptypeArray\@empty +\def\eq@recordProbType{% + \ifx\ptypeArray\@empty + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\ptypeArray{null,"\eqQT"}}\else + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\ptypeArray{,"\eqQT"}}\fi + \tmp@exp +} +\let\corrAnsArray\@empty +\def\eq@recordCorrAns#1{% + \ifx\corrAnsArray\@empty + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\corrAnsArray{null,#1}}\else + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\corrAnsArray{,#1}}\fi + \tmp@exp +} +\def\aeb@answerType@r{r} +\def\aeb@answerType@c{c} +\newcommand\answers@q{% + \eq@AddProbToQzQuesList + \def\aeb@answerType{r}\setdefault@Ans\eq@recordThesePTs + \eq@recordProbType + \addtocounter{eqpointvalue}{\eqPTs}\stepcounter{questionno}% + \def\aeb@thisType{"mc"}\@ifnextchar[{\answers@@q}% + {\@ifstar{\answers@@q[\curr@quiz.\thequestionno]}{\answers@@q[]}}% +} +\def\answers@@q[#1]#2{\global\let\eq@ansChoiceArray\@empty + \xdef\aeb@numCols{#2}\edef\eqtmp{\aPointType}% + \xdef\aPointType{\eqtmp,[\eqPTs,\aeb@thisType]}% + \ifx\q@hwdest\@empty + \xdef\@qzsolndest{#1}\else + \gdef\@qzsolndest{\q@hwdest}\fi + \ifnum\aeb@numCols=1 + \gdef\eq@listType{1}\expandafter\answers@q@list\else + \gdef\eq@listType{0}\expandafter\answers@q@tabular\fi{\aeb@numCols}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{manswers} +% The \texttt{manswers} environment is used for multiple selection questions for the quiz +% environment only. Within this environment, the \cs{Ans} command (\cs{@Ans} actually) is let equal to +% \cs{Ans@ck@f} or \cs{Ans@ck@l} for forms or links respectively. These commands are defined +% in the sections that follow. +% \changes{v6.2}{2007/11/08 } +%{ +% Added the \texttt{manswers} environment, and supporting elements, both {\LaTeX} +% and JavaScript. This \texttt{manswers} environment is for the \texttt{quiz} environment +% only. There is a \texttt{manswers} environment for the \texttt{shortquiz} environment, but +% this is used by \textsf{eqExam} only. +%} +% +% The following parameters are recognized +%\begin{verbatim} +% [#1]|* = named destination to be associated with solution; +% with *, the destination is automatically generated +% #2 = number of columns in the tabular environment +%\end{verbatim} +% \begin{macrocode} +\newcommand\manswers@q +{% + \eq@AddProbToQzQuesList + \def\aeb@answerType{c}\@setFormLinkType + \global\expandafter\let\expandafter\@Ans + \expandafter=\csname Ans@ck@\@@quiztype\endcsname + \eq@recordThesePTs\eq@recordProbType + \addtocounter{eqpointvalue}{\eqPTs}\stepcounter{questionno}% + \def\aeb@thisType{"ms"}\@ifnextchar[{\answers@@q}% + {\@ifstar{\answers@@q[\curr@quiz.\thequestionno]}{\answers@@q[]}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\newenvironment{answers@q@list}[1]{% + \ifx\aeb@answerType\eq@r + \let\endanswers\endanswers@q@list\else + \let\endmanswers\endanswers@q@list\fi + \list{\strut\@Ans}{% + \if\qstar*\relax + \if\aeb@FLOverride\eq@l + \settowidth{\labelwidth}{\eq@lw@l}\else + \settowidth{\labelwidth}{\eq@lw@f}\fi + \else + \if\aeb@FLOverride\eq@f + \settowidth{\labelwidth}{\eq@lw@f}\else + \settowidth{\labelwidth}{\eq@lw@l}\fi + \fi + \setlength{\topsep}{-\parskip+\aboveanswersSkip}% + \setlength{\parsep}{0pt}\setlength{\itemindent}{0pt}% + \setlength{\listparindent}{\parindent}% + \setlength{\leftmargin}{\labelwidth}% + \setlength{\labelsep}{0pt}% + \def\Ans{\Ans@list}% + }% +}{\endlist\setcounter{quizno}{0}% + \eq@answersEndHook + \setdefault@Ans + \ifx\aeb@answerType\aeb@answerType@r +% \end{macrocode} +% If this is a MC question, we record the author's correct answer +% \begin{macrocode} + \eq@recordCorrAns{\eq@ansChoiceArray}\ifwithinMCFI +% \end{macrocode} +% If within a \cs{bMCFI}/\cs{eMCFI} command pair, we also record +% the author's correct answer. +% \begin{macrocode} + \eq@recordCorrAns{\s@veCorrAnsMCFI}\fi\else +% \end{macrocode} +% If this is a MS question, we record the author's correct answer as an array +% \begin{macrocode} + \eq@recordCorrAns{[\eq@ansChoiceArray]}\fi + \global\let\eqlimselTo\@empty +} +% \end{macrocode} +% \begin{macrocode} +\newcommand\qztabsep[1]{\def\eq@argi{#1}\ifx\eq@argi\@empty + \def\qz@tabsep{1.5pt}\else\def\qz@tabsep{#1}\fi} +\qztabsep{1.5pt} +\def\qzTabPos#1{\def\qz@TabPos{[#1]}}\qzTabPos{} +\def\answers@q@tabular#1{% + \ifinner\else\par\removelastparskip\vspace{\aboveanswersSkip}\fi + \eq@tmpdima=\linewidth + \@tempcnta#1\relax +% n-1 + \advance\@tempcnta-1\relax +% 2(n-1) + \multiply\@tempcnta by2 + \@tempdima\qz@tabsep\relax +% 2*(n-1)*\qz@tabsep + \multiply\@tempdima\@tempcnta +% \linewidth-(n-1)*\qz@tabsep + \advance\eq@tmpdima-\@tempdima +% (\linewidth-(n-1)*\qz@tabsep)/n + \divide\eq@tmpdima by#1 +% \begin{macrocode} + \tabcolsep\qz@tabsep\relax + \def\Ans{\Ans@tabular}% + \ifx\aeb@answerType\eq@r + \let\endanswers\endanswers@q@tabular\else + \let\endmanswers\endanswers@q@tabular\fi + \noindent\expandafter + \tabular\qz@TabPos{@{}*{#1}{p{\eq@tmpdima}}@{}}% +} +% \end{macrocode} +% \begin{macro}{\endanswers} +% Again, we put \verb+\let\endanswers=\endanswers@q+. +% \begin{macrocode} +\def\endanswers@q@tabular +{% + \endtabular\setcounter{quizno}{0}% + \eq@answersEndHook + \setdefault@Ans + \ifx\aeb@answerType\aeb@answerType@r +% \end{macrocode} +% If this is a MC question, we record the author's correct answer +% \begin{macrocode} + \eq@recordCorrAns{\eq@ansChoiceArray}\ifwithinMCFI +% \end{macrocode} +% If within the MCFI command pair, we record the author's fill-in as well. +% \begin{macrocode} + \eq@recordCorrAns{\s@veCorrAnsMCFI}\fi\else +% \end{macrocode} +% If this is a MS question, we record the author's correct answer as an array +% \begin{macrocode} + \eq@recordCorrAns{[\eq@ansChoiceArray]}\fi + \global\let\eqlimselTo\@empty +} +% \end{macrocode} +% \end{macro} +% \subsubsection{Link Style} +% \begin{macro}{\Ans@l} +% For the forms version of the \texttt{quiz} environment. +% dps 12/19/03 removed the notify because we are not embedding a radio button field +% \begin{macrocode} +\let\qRadionActionsHook\@empty +\def\Ans@@l@Actions{\A{\JS{% + this.getField("mc.\curr@quiz.\thequestionno").value + = "\Ans@choice\alph{quizno}";\jsR + RecordPointValue([0,\eqPTs,\eq@pPTs],\thequestionno);\jsR + RecordProblemType("\eqQT",\thequestionno);\jsR + ProcessQuestion(\Ans@choice,"\alph{quizno}",\thequestionno,% +\arabic{quizno},"\curr@quiz",0,\ifnocorrections0\else1\fi,% +"\bqlabelISO"\if\eqQuizType\isQZ\ifx\eq@online\eq@YES +\ifeq@noquizsolutions\else,1\fi\fi\fi);\qRadionActionsHook}}% +} +\def\Ans@r@l@Defaults +{% + \BC{}\S{S}\W{1}\Ff{\FfNoToggleToOff}\F{\FPrint} + \textSize{12}\textColor{0 g}\Ff{\FfReadOnly} +} +\def\Ans@l{\leavevmode\if\eq@listType1\stepcounter{quizno}% + \else\refstepcounter{quizno}\fi\PBS\raggedright + \settowidth{\eq@tmplength}{\eq@lw@l}\sbox{\eq@tmpbox}{\eq@l@l}% + \hangindent=\eq@tmplength\hangafter=1\relax + \eq@tmpdima=\wd\eq@tmpbox + \def\link@@Content{(\hfil\linkContentFormat\hfil)}% +% begin dps changes 12/19/03 +% \end{macrocode} +% (2013/10/24) Imperative that radio button has no boundary line. +% \begin{macrocode} + \def\late@options{\BC{}}% +\if\Ans@choice1\relax\eq@recordAnsChoice\fi + \makebox[0pt][l]{\radio@@Button{}{mc.\curr@quiz.\thequestionno}% + {\eq@tmpdima}{\RadioFieldSize}{\Ans@choice\alph{quizno}}% + {\eq@protect\A}{\eq@setWidgetProps\eq@l@check@driver}% + {\Ans@r@l@Defaults\every@RadioButton + \every@qRadioButton\late@options}}% +% end dps changes 12/19/03 + \set@@Link{}{}{}% + {\makebox[\eq@tmpdima]{\color{\@linkcolor}\link@@Content}}% + {\eq@protect\A}{\eq@setWidgetProps\setLink@driver}% + {\set@LinkTextDefaults\Ans@@l@Actions\every@Link}% + \ifnocorrections\else + \if\Ans@choice1\relax + \edef\Ans@c@l@Choice{\noexpand\DV{Yes}% + \ifx\@qzsolndest\@empty + \noexpand\Ff{\FfReadOnly}% + \else % there is a solution + \ifeq@noquizsolutions + \noexpand\Ff{\FfReadOnly}% + \else + \noexpand\A{\noexpand\quiz@SolutionActionHook}% + \fi + \fi + }% + \else + \def\Ans@c@l@Choice{\Ff{\FfReadOnly}\BC{}}% + \fi + \def\late@options{\BC{}}% + \if\Ans@choice1\relax + \ifx\@qzsolndest\@empty\else + \ifeq@noquizsolutions\else + \edef\late@options{\noexpand\BC{\solution@Color}}% + \fi + \fi + \fi + \makebox[0pt][r]{\check@@Box{}% + {mcq.\curr@quiz.\thequestionno.\arabic{quizno}}% + {\eq@tmpdima}{0pt}{Yes}{}% \@tempdimb + {\eq@setWidgetProps\eq@l@check@driver}% + {\Ans@c@f@Defaults\Ans@c@l@Choice\every@RadioButton + \every@qRadioButton\late@options}}% + \fi + \Ans@proofing{\eq@tmpdima}% +\eq@hspanner\ignorespaces} +% \end{macrocode} +% \end{macro} +% Now for the code to support the \texttt{manswers} environment for link style. +% \begin{macro}{\Ans@ck@l} +% Below is \cs{Ans@ck@l} and its supporting default appearances and actions. The command \cs{Ans@ck@l} defines +% a checkbox, on top of that a link (that the user interacts with) and on top another check box. +% \begin{macrocode} +\def\Ans@ck@@l@Actions{\A{\JS{% + var ckfName="mck.\curr@quiz.\thequestionno.\arabic{quizno}";\jsR + var ckf = this.getField(ckfName);\jsR + ckf.checkThisBox(0,!ckf.isBoxChecked(0));\jsR + var _bOK=true;\jsR +\ifx\eqlimselTo\@empty\else _bOK = LimitSelection(\eqlimselTo,% +"mck.\curr@quiz.\thequestionno","\arabic{quizno}");\jsR\fi +if (_bOK) {\jsR\jsT + var aPMSretn=ProcessMultiSelection(\Ans@choice,"\alph{quizno}",% +\thequestionno,\arabic{quizno},"\curr@quiz",\eqPTs,\eq@pPTs);\jsR\jsT + RecordProblemType("\eqQT",\thequestionno);\jsR\jsT + ProcessQuestion(aPMSretn[0],aPMSretn[1],\thequestionno,% +\arabic{quizno},"\curr@quiz",0,\ifnocorrections0\else1\fi,% +"\bqlabelISO"\if\eqQuizType\isQZ\ifx\eq@online\eq@YES +\ifeq@noquizsolutions\else,1\fi\fi\fi);\jsR +} + }} +} +\def\Ans@ck@l@Defaults +{% + \BC{}\S{S}\W{1}\H{N}\Ff{\FfNoToggleToOff} + \textSize{12}\textColor{0 g}\Ff{\FfReadOnly} +} +\def\Ans@ck@l{% + \leavevmode\if\eq@listType1\stepcounter{quizno}% + \else\refstepcounter{quizno}\fi + \if\Ans@choice1\eq@recordAnsChoice\fi\PBS\raggedright + \settowidth{\eq@tmplength}{\eq@lw@l}\sbox{\eq@tmpbox}{\eq@l@l}% + \hangindent=\eq@tmplength\hangafter=1\relax + \eq@tmpdima=\wd\eq@tmpbox + \def\link@@Content{(\hfil\linkContentFormat\hfil)}% +% begin dps changes 12/19/03 + \makebox[0pt][l]{% + \check@@Box{}{mck.\curr@quiz.\thequestionno.\arabic{quizno}}% + {\eq@tmpdima}{\RadioFieldSize}{\Ans@choice\alph{quizno}}% + {\eq@protect\A}{\eq@setWidgetProps\eq@l@check@driver}% + {\Ans@ck@l@Defaults\every@RadioButton + \every@qckCheckbox}}% +% end dps changes 12/19/03 + \set@@Link{}{}{}% + {\makebox[\eq@tmpdima]{\color{\@linkcolor}\link@@Content}}% + {\eq@protect\A}{\eq@setWidgetProps\setLink@driver}% + {\set@LinkTextDefaults\Ans@ck@@l@Actions\every@Link}% + \ifnocorrections\else + \if\Ans@choice1\relax + \edef\Ans@c@l@Choice{\noexpand\DV{Yes}% + \ifx\@qzsolndest\@empty\noexpand\BC{}% + \noexpand\Ff{\FfReadOnly}% + \else % there is a solution + \ifeq@noquizsolutions + \noexpand\BC{}\noexpand\Ff{\FfReadOnly}% + \else + \noexpand\BC{\solution@Color}% + \noexpand\A{\noexpand\quiz@SolutionActionHook}% + \fi + \fi + }% + \else + \def\Ans@c@l@Choice{\Ff{\FfReadOnly}\BC{}}% + \fi + \makebox[0pt][r]{\check@@Box{}% + {mcq.\curr@quiz.\thequestionno.\arabic{quizno}}% + {\eq@tmpdima}{0pt}{Yes}{}% + {\eq@setWidgetProps\eq@l@check@driver}% + {\Ans@c@f@Defaults\Ans@c@l@Choice\every@RadioButton + \every@qRadioButton}}% + \fi + \Ans@proofing{\eq@tmpdima}% +\eq@hspanner\ignorespaces} +% \end{macrocode} +% \end{macro} +% \subsubsection{Form Style} +% \begin{macro}{\Ans@f} +% For the form button multiple choice type question. The driver independent stuff starts +% here, then goes to |\Ans@f@driver| the rest of the code that depends on the +% driver. +% \begin{macrocode} +\def\Ans@f{\leavevmode\if\eq@listType1\stepcounter{quizno}% + \else\refstepcounter{quizno}\fi + \PBS\raggedright\Ans@@f} +\def\Ans@r@f@Defaults +{% + \BC{0 0 0}\S{S}\W{1}\Ff{\FfNoToggleToOff} + \F{\FPrint}\textSize{12}\textColor{0 g} +} +% Action of the radio button field +\def\Ans@r@f@Actions{\A{\JS{% + RecordPointValue([0,\eqPTs,\eq@pPTs],\thequestionno);\jsR + RecordProblemType("\eqQT",\thequestionno);\jsR + ProcessQuestion(\Ans@choice,"\alph{quizno}",\thequestionno,% + \arabic{quizno},"\curr@quiz",0,\ifnocorrections0\else1\fi,% + "\bqlabelISO"\if\eqQuizType\isQZ\ifx\eq@online\eq@YES + \ifeq@noquizsolutions\else,1\fi\fi\fi);\qRadionActionsHook}} +} +% Action of the check box underlying the radio button field +\def\quiz@SolutionActionHook{% + /S/GoTo/D(\@qzsolndest)/Next<<\JS{this.resetForm(% + ["mcq.\curr@quiz.\thequestionno.\arabic{quizno}"]);}>> +} +\def\Ans@c@f@Defaults +{% + \BC{0 0 0}\S{S}\W{1}\F{\FHidden}\textSize{12} + \textColor{0 g}\symbolchoice{circle} +} +% \end{macrocode} +% \changes{v6.05d}{2007/04/14} +% { +% Added the command \cs{insertGrayLetters}. This can be defined to place symbols under +% the multiple choice form boxes. The command \cs{bottomOfAnsfStack} is there as a +% hook for whatever purposes are desired. +% } +% \begin{macrocode} +\let\bottomOfAnsfStack\relax +%</package> +%<*package|eqexam> +% \end{macrocode} +% \changes{v7.7}{2015/06/04}{Added \cs{graylettersColor}} +% \DescribeMacro\graylettersColor sets the color of the gray letters, the default is +% \texttt{gray}. +% \begin{macrocode} +\providecommand\graylettersColor{gray} +\def\insertGrayLetters{\ifaebshowgrayletters + \rlap{\makebox[\RadioFieldSize]% + {\textcolor{\graylettersColor}{\Alph{quizno}}}}\else\relax\fi} +%</package|eqexam> +%<*package> +\def\Ans@@f +{% + \settowidth{\eq@tmplength}{\eq@lw@f}% + \hangindent=\eq@tmplength\hangafter=1 + \bottomOfAnsfStack\insertGrayLetters +% dps add + \edef\rbf@Opts{\ifaeb@usecircles\else + \noexpand\symbolchoice{\qz@chksymb}\fi + \noexpand\textColor{\qz@chksymbcol}}% + \if\Ans@choice1\eq@recordAnsChoice\fi + \mbox{\expandafter\radio@@Button\expandafter{\rbf@Opts}% + {mc.\curr@quiz.\thequestionno}% + {\RadioFieldSize}{\RadioFieldSize}{\Ans@choice\alph{quizno}}% + {\eq@protect\A}{\eq@setWidgetProps\eq@RadioCheck@driver}% + {\Ans@r@f@Defaults\Ans@r@f@Actions\every@RadioButton + \every@qRadioButton\insert@circlesymbol}}% + \let\late@options\@empty + \ifnocorrections\else + \if\Ans@choice1\relax + \edef\Ans@c@f@Choice{\noexpand\DV{Yes}% + \ifx\@qzsolndest\@empty\noexpand\Ff{\FfReadOnly}% + \else + \ifeq@noquizsolutions + \noexpand\Ff{\FfReadOnly}% + \else + \noexpand\A{\noexpand\quiz@SolutionActionHook}% + \fi + \fi + }% + \else + \def\Ans@c@f@Choice{\Ff{\FfReadOnly}}% + \fi +% \end{macrocode} +% \changes{v6.7h}{2013/08/19}{When the \cs{useMCCircles} is used, the boundary +% color is transparent. We try a fix for this to show the colored solution +% boundary. The fix uses the \cs{late@options} commands.} +% \begin{macrocode} + \ifaeb@usecircles\def\late@options{\BC{}}\fi + \if\Ans@choice1\relax + \ifx\@qzsolndest\@empty\else + \ifeq@noquizsolutions\else + \edef\late@options{\noexpand\BC{\solution@Color}}% + \fi + \fi + \fi + \makebox[0pt][r]{\check@@Box{}% + {mcq.\curr@quiz.\thequestionno.\arabic{quizno}}% + {\RadioFieldSize}{\RadioFieldSize}{Yes}{}% + {\eq@setWidgetProps\eq@RadioCheck@driver}% + {\Ans@c@f@Defaults\Ans@c@f@Choice\every@CheckBox + \every@qCheckBox\late@options}}% + \fi + \Ans@proofing{\RadioFieldSize}% +\eq@hspanner\ignorespaces} +% \end{macrocode} +% \DescribeMacro{\limitSelectionTo} limits the selection to the number specified +% by its argument for multiple selection questions. +% \begin{macrocode} +\def\limitSelectionTo#1{\def\eqlimselTo{#1}} +\let\eqlimselTo\@empty +% \end{macrocode} +% \begin{macro}{\Ans@ck@f} +% The support for multiple selection answers within the \texttt{manswers} environment. +% \begin{macrocode} +\def\Ans@ck@f{\leavevmode\if\eq@listType1\stepcounter{quizno}% + \else\refstepcounter{quizno}\fi + \if\Ans@choice1\eq@recordAnsChoice\fi + \PBS\raggedright\Ans@@ck@f} +\def\Ans@ck@f@Defaults +{% + \BC{0 0 0}\S{S}\W{1}\Ff{\FfNoToggleToOff} + \textSize{12}\textColor{0 g} +} +% Action of the radio button field +\def\Ans@ck@f@Actions +{% + \A{\JS{% +% \end{macrocode} +% Here is limit the number of selections. If \cs{eqlimselTo} is nonempty, +% we call \texttt{LimitSelection()} to count the number of checks in this +% current field. If too many, we uncheck the current effort and inform the +% user. +% \begin{macrocode} + var _bOK=true;\jsR +\ifx\eqlimselTo\@empty\else _bOK = LimitSelection(\eqlimselTo,% +"mck.\curr@quiz.\thequestionno","\arabic{quizno}");\jsR\fi +% \end{macrocode} +% As a result of the previous changes, we make this a condition: +% if the JavaScript function \texttt{LimitSelection()} returns false, we do not execute. The default +% value is \texttt{\_bOK=true}. +% \begin{macrocode} +if (_bOK) {\jsR\jsT + var aPMSretn=ProcessMultiSelection(\Ans@choice,"\alph{quizno}",% +\thequestionno,\arabic{quizno},"\curr@quiz",\eqPTs,\eq@pPTs);\jsR\jsT + RecordProblemType("\eqQT",\thequestionno);\jsR\jsT + ProcessQuestion(aPMSretn[0],aPMSretn[1],\thequestionno,% +\arabic{quizno},"\curr@quiz",0,\ifnocorrections0\else1\fi,% +"\bqlabelISO"\if\eqQuizType\isQZ\ifx\eq@online\eq@YES +\ifeq@noquizsolutions\else,1\fi\fi\fi);\jsR +}}}% +} +% Action of the check box underlying the radio button field +\def\quiz@SolutionActionHook{% + /S/GoTo/D(\@qzsolndest)/Next<<\JS{this.resetForm(% +["mcq.\curr@quiz.\thequestionno.\arabic{quizno}"]);}>> +} +% \end{macrocode} +% \cs{Ans@@ck@f} is the definition of the \cs{Ans} command within the +% \texttt{manswers} environment. +% \begin{macrocode} +\def\Ans@@ck@f +{% + \settowidth{\eq@tmplength}{\eq@lw@f}% + \hangindent=\eq@tmplength\hangafter=1 + \bottomOfAnsfStack\insertGrayLetters +% \end{macrocode} +% The bottom most checkbox +% \begin{macrocode} + \bottomOfAnsfStack\insertGrayLetters +% dps add +\def\cbf@Opts{\symbolchoice{\qz@chksymb}% + \textColor{\qz@chksymbcol}}% + \mbox{\expandafter\check@@Box\expandafter{\cbf@Opts}% + {mck.\curr@quiz.\thequestionno.\arabic{quizno}}% + {\RadioFieldSize}{\RadioFieldSize}{\Ans@choice\alph{quizno}}% + {\eq@protect\A}{\eq@setWidgetProps\eq@RadioCheck@driver}% + {\Ans@ck@f@Defaults\Ans@ck@f@Actions\every@RadioButton + \every@qckCheckbox}}% + \ifnocorrections\else + \if\Ans@choice1\relax + \edef\Ans@c@f@Choice{\noexpand\DV{Yes}% + \ifx\@qzsolndest\@empty\noexpand\Ff{\FfReadOnly}% + \else + \ifeq@noquizsolutions + \noexpand\Ff{\FfReadOnly}% + \else + \noexpand\A{\noexpand\quiz@SolutionActionHook}% + \fi + \fi + }% + \else + \def\Ans@c@f@Choice{\Ff{\FfReadOnly}}% + \fi + \let\late@options\@empty + \if\Ans@choice1\relax + \ifx\@qzsolndest\@empty\else + \ifeq@noquizsolutions\else + \edef\late@options{\noexpand\BC{\solution@Color}}% + \fi + \fi + \fi +% \end{macrocode} +% The top most checkbox +% \begin{macrocode} + \makebox[0pt][r]{\check@@Box{}% + {mcq.\curr@quiz.\thequestionno.\arabic{quizno}}% + {\RadioFieldSize}{\RadioFieldSize}{Yes}{}% + {\eq@setWidgetProps\eq@RadioCheck@driver}% + {\Ans@c@f@Defaults\Ans@c@f@Choice\every@CheckBox +% \end{macrocode} +% (2012/12/22) Replace \cs{every@qRadioButton} with \cs{every@qCheckBox}. +% \begin{macrocode} + \every@qCheckBox\late@options}}% + \fi + \Ans@proofing{\RadioFieldSize}% +\eq@hspanner\ignorespaces} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +%</package> +%<*package|eqexam> +% \end{macrocode} +%\subsection{The \texorpdfstring{\protect\cs{bChoices}/\protect\cs{eChoices}} +% {\textbackslash{bChoices}/\textbackslash{eChoices}} Pair} +% (2/15/05) This pair of macros is not really an environment, the +% \cs{eChoices} really does nothing other than to act as an ending marker. The idea +%behind this pair of macros twofold: (1) To provide a convenient way of listing +%alternate choices for a multiple choice questions, the ``environment'' makes it +%easy to change the number of columns, or to change from tabular to list (or visa-versa); +%(2) Laying out the alternatives in a list style, makes it easy to develop techniques +%of randomizing the alternatives. Here is an example of usage: +%\begin{verbatim} +%\begin{answers}{4} +%\bChoices[2] +% \Ans0 a choice\eAns +% \Ans1 another choice\eAns +% \Ans0 still another choice\eAns +% \Ans0 another\eAns +% \Ans0 incoming\eAns +% \Ans0 more choices\eAns +% \Ans0 another still\eAns +% \Ans0 too many\eAns +% \Ans0 choices\eAns +%\eChoices +%\end{answers} +%\end{verbatim} +%\noindent The argument of the \texttt{answers} environment is $4$ which means we are +%going to use the tabular environment with $4$ columns. Now within those $4$ we are going +%to only use the first $2$ columns ( this is the optional argument of \cs{bChoices}. +% +% If the optional argument is removed from \cs{bChoices}, the choices are typeset +% in the with $4$ columns. If the argument of \cs{answers} is changed to $1$, then the +% optional argument of \cs{bChoices} is ignored, and the alternatives are typeset in a +% one column list environment. +% +% By changing the two parameters (one for \cs{answers} and one for \cs{bChoices}) +% you can easily modify how the alternatives are typeset. +%\par\medskip\noindent +% This counter tracts the column number we are in. +% \begin{macrocode} +\newcount\eq@tabColCnt +% \end{macrocode} +% \begin{macro}{\bChoices} +% This command has one optional argument, the number of columns to use. +% +% When the answer environment sets the number of columns, the answers are set in +% tabular form. If you say \verb!\begin{answers}[4]!, four columns are used. +% If you then say \IndexKey{nCols}\verb!\Choices[nCols=2]!, only the first two columns are used. +% To maintain backward compatibility, you can also say \verb!\Choices[2]! +% \begin{macrocode} +\define@key{bchoice}{nCols}{\def\bChoiceNumCols{#1}} +\@for\eqi:=1,2,3,4,5,6,7,8,9,10 \do{\edef\temp@expand@def{% + \noexpand\define@key{bchoice}{\eqi}[\eqi]{% + \noexpand\def\noexpand\bChoiceNumCols{\eqi}}% + }\temp@expand@def +} +% \end{macrocode} +% The number of columns specified in the answers environment is saved as the value +% of \cs{aeb@numCols}. This the default value of \cs{bChoiceNumCols}. +% \begin{macrocode} +\def\bChoiceNumCols{\aeb@numCols} +% \end{macrocode} +% This is the definition of the random key\IndexKey{random}, a boolean. +% \begin{macrocode} +\define@key{bchoice}{random}[true]{% + \csname if#1\endcsname\eq@randomizeChoicestrue + \else\eq@randomizeChoicesfalse\fi +} +% \end{macrocode} +% \changes{v6.3x}{2011/04/05}{% +% Added \texttt{label} parameter to \cs{bChoices}. +%} +% A new key, \IndexKey{label}\texttt{label}, if this label is specified, then we keep track of all the +% correct alternatives, put them into a commands to make them accessible by the user. +% \begin{macrocode} +\define@key{bchoice}{label}[]{\xdef\bChoiceLabel{#1}} +% \end{macrocode} +% The \cs{bChoices} command is now processed by the \texttt{keyval} package. There +% are two keys: \texttt{nCols} and \texttt{random}. The first key +% sets the number of columns we are limited to; the second one obviously declares +% that this list of choices should be randomized, a boolean. The \texttt{random} +% key is ignored unless the document author has use the \texttt{allowrandomize} option. +% \begin{macrocode} +\def\bChoices{\@ifnextchar[{\@ansChoices}{\@ansChoices[\aeb@numCols]}} +% \end{macrocode} +% If \cs{numCols} is $1$, we use a list environment, otherwise, a tabular is used. +% \begin{macrocode} +\def\@ansChoices[#1]% +{% +% \end{macrocode} +% We initialize some variables that the new label option uses. +% \begin{macrocode} + \global\let\@tempholdSaveAns\@empty %4/5 + \global\let\@tempholdSaveChoice\@empty %4/5 + \global\let\bChoiceLabel\@empty %4/5 + \setkeys{bchoice}{#1}% + \global\eq@tabColCnt=0 + \ifnum\aeb@numCols=1 % list mode + \def\eq@next{\@layoutListAns}\else % tabular mode + \def\eq@next{\@layoutTabularAns{\bChoiceNumCols}}\fi + \eq@next +} +\let\eChoices\relax +% \end{macrocode} +% \end{macro} +% If the next token is \cs{Ans} we grab its all stuff between +% \cs{Ans} and \cs{eAns} and typeset it. We continue until the +% next token is not \cs{Ans}. (This last token +% should be \cs{eChoices}.) +% \begin{macrocode} +\def\@layoutListAns{\@ifnextchar\Ans{\@getListAns}% + {\@lookforendansChoices{\@layoutListAns}}% +} +% \end{macrocode} +% \changes{v6.3x}{2011/04/05}{% +% Supporting commands that use the value of the \texttt{label} parameter +% of \cs{bChoices}: \cs{eq@saveAns}, \cs{eq@displayAns}, \cs{eq@displayAlts}, etc. +%} +% \texttt{4/5} We begin an experimental series of commands. The idea is to be able to +% conveniently reference a multiple choice problem when the +% \texttt{vspacewithsolns} option is in effect (\textsf{eqexam}). +% +% \cs{eq@saveAns} is an internal macro, it gathers up the first two +% arguments of \cs{Ans}, if the second arg is a 1, it passes the flow +% to \cs{@@@SaveAns}; otherwise, it gobbles all leftovers. +% \begin{macrocode} +\newcommand{\eq@saveAns}[2][]{% + \let\eq@next\@@@SaveAnsGobbleAns + \ifx\bChoiceLabel\@empty\else + \def\eq@savedAnsOpt{#1}\def\eq@savedAnsZO{#2}% + \if\eq@savedAnsZO1 \let\eq@next\@@@SaveAns\fi + \fi\eq@next +} +% \end{macrocode} +% \cs{@@@SaveAns} collects the answer to the problem, and placed +% it in the holding command \cs{@tempholdSaveAns}, it also saves +% the alternative letter as well in \cs{@tempholdSaveChoice}. +% \begin{macrocode} +\long\def\@@@SaveAns#1\eAns{% 4/5 + \g@addto@macro\@tempholdSaveAns{\\{\ignorespaces#1}}% +% \end{macrocode} +% This code is expanded before the \cs{Ans} command is, so we'll simulate +% incrementing the \texttt{quizno} counter, \dots +% \begin{macrocode} + \addtocounter{quizno}{1}% + \edef\temp@expand{\noexpand\g@addto@macro\noexpand + \@tempholdSaveChoice{% + \noexpand\\{\ifx\sqstar\@empty\aebChoiceAltFmt\else + \ifaebshowgrayletters\Alph{quizno}\else + \linkContentFormat\fi\fi}}}\temp@expand +% \end{macrocode} +% and decrement when we are finished adding to the token list. +% \begin{macrocode} + \addtocounter{quizno}{-1}% +} +% \end{macrocode} +% \cs{eq@displayAns} is \cs{let} to \verb!\\!. Definition and name may change. +% \cs{useSaveAns} is a simple interface to accessing the list of all correct +% answers. Probably this definition will change. +% +% \cs{eq@insertComma} is a simple way of delimiting the list. We put a comma +% before each expression, except for the first one. +% +% (2016/11/21) The \DescribeMacro{\oxfordCommaOn}\cs{oxfordCommaOn} is on by default, while +% \DescribeMacro{\oxfordCommaOn}\cs{oxfordCommaOff} turns off the Oxford comma. The +% Oxford comma comes into play only with the star-forms of \cs{useSavedAns}, +% \cs{useSavedAlts}, and \cs{useSavedAltsAns}. +% \changes{v7.8}{2016/11/21}{Added star option to each of the \string\cs{useSaved...} commands} +% \begin{macrocode} +\newif\ifoxfordcomma \oxfordcommatrue +\def\oxfordCommaOn{\oxfordcommatrue} +\def\oxfordCommaOff{\oxfordcommafalse} +\def\eq@insertComma{% + \ifx\eq@comma\@empty + \ifnum\@nameuse{NumAns\eq@namearg}>2\relax + \def\eq@comma{,}\fi + \else\ifx\eq@insertAnd\@empty\eq@comma\space + \else\ifnum\@tempcnta=\@nameuse{NumAns\eq@namearg}% + \ifoxfordcomma\eq@comma\fi\else\eq@comma\fi\space + \fi + \fi +} +\newcommand\eqAnd{and}\def\eq@insertAnd{% + \ifnum\@nameuse{NumAns\eq@namearg}<2\relax\else + \ifnum\@nameuse{NumAns\eq@namearg}>2\relax + \else\leavevmode\space\fi\eqAnd\space\fi} +\long\def\eq@displayAns#1{\advance\@tempcnta1\relax + \eq@insertComma + \ifnum\@tempcnta=\@nameuse{NumAns\eq@namearg}\eq@insertAnd\fi#1} +\def\eq@displayAlts#1{\advance\@tempcnta1 + \eq@insertComma + \ifnum\@tempcnta=\@nameuse{NumAns\eq@namearg}\eq@insertAnd\fi + \savedAltFmt{#1}} +\def\eq@displayAltsAns#1{\advance\@tempcnta1\relax + \eq@insertComma + \ifnum\@tempcnta=\@nameuse{NumAns\eq@namearg}\eq@insertAnd\fi#1} +% \end{macrocode} +% \begin{macro}{\useSavedAns} +% \begin{macro}{\useSavedAlts} +% \begin{macro}{\useSavedAltsAns} +% \begin{macro}{\useSavedNumAns} +% \changes{v6.3x}{2011/04/05}{% +% Added \cs{useSavedAns}, \cs{useSavedAlts}, and \cs{useSavedAltsAns}. +%} +% These three commands hold the correct alternatives and answers to a multiple choice +% or multiple selection problem. The optional first argument allows you to display +% a particular result, the second argument is the value of the \texttt{label} key-value, +% given in the enclosing \cs{bChoices}/\cs{eChoices} ``environment.'' +% \begin{macrocode} +\newcommand{\savedAltFmt}[1]{(#1)} +\newcommand{\useSavedAns}{\bgroup\@ifstar{\useSavedAns@i} + {\let\eq@insertAnd\@empty\useSavedAns@i}} +\newcommand{\useSavedAns@i}[2][]{\@tempcnta=0\relax + \def\eq@namearg{#2}\let\label\@gobble + \def\eq@argi{#1}\ifx\eq@argi\@empty + \let\eq@comma\@empty + \let\\\eq@displayAns\@nameuse{SavedAns#2}\else + \@nameuse{SavedAns#2-Idx#1}\fi + \egroup +} +\newcommand{\useSavedAlts}{\bgroup\@ifstar{\useSavedAlts@i} + {\let\eq@insertAnd\@empty\useSavedAlts@i}} +\newcommand{\useSavedAlts@i}[2][]{\@tempcnta=0\relax + \def\eq@namearg{#2}\@nameuse{caseFor#2}% + \def\eq@argi{#1}\ifx\eq@argi\@empty + \let\eq@comma\@empty + \let\\\eq@displayAlts\@nameuse{SavedAlts#2}\else + \savedAltFmt{\@nameuse{SavedAlts#2-Idx#1}}\fi + \egroup +} +\newcommand{\useSavedAltsAns}{\bgroup\@ifstar{\useSavedAltsAns@i} + {\let\eq@insertAnd\@empty\useSavedAltsAns@i}} +\newcommand{\useSavedAltsAns@i}[2][]{\@tempcnta=0\relax + \def\eq@namearg{#2}\@nameuse{caseFor#2}\let\label\@gobble + \def\eq@argi{#1}\ifx\eq@argi\@empty + \let\eq@comma\@empty + \let\\\eq@displayAltsAns\@nameuse{SavedAltsAns#2}\else + \savedAltFmt{\@nameuse{SavedAlts#2-Idx#1}} + \@nameuse{SavedAns#2-Idx#1}\fi + \egroup +} +\newcommand{\useSavedNumAns}[1]{\@nameuse{NumAns#1}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\long\def\@@@SaveAnsGobbleAns#1\eAns{} % 4/5 +% \end{macrocode} +% This command gets, and sets the list of alternatives +% \begin{macrocode} +\long\def\@getListAns\Ans#1\eAns{%\@@par %start new paragraph +% \end{macrocode} +% We record the list as we process each item. +% \begin{macrocode} + \eq@saveAns#1\eAns % 4/5 + \Ans#1\vspace{\@rowskip}% + \@layoutListAns +} +\long\def\@lookforendansChoices#1{% + \@ifnextchar\eChoices{\rowsep{\rowsep@default}% + \expandafter\@findendans\@gobble}{\expandafter#1\@gobble}% +} +% \end{macrocode} +% The argument is the number of columns to typeset, this number +% is forced to be \texttt{<=} to the number of columns specified in the \texttt{answers} +% environment. +% \begin{macrocode} +\def\@layoutTabularAns#1{% + \let\eq@tabSep\@empty + \xdef\numShortCols{#1}% + \ifnum#1>\aeb@numCols \xdef\numShortCols{\aeb@numCols}\fi + \@@layoutTabularAns +} +% \end{macrocode} +% If the next token is \cs{Ans} we grab its all stuff between +% \cs{Ans} and \cs{eAns} and typeset it and insert the appropriate +% token, either \texttt{\&} or \texttt{\string\cr}. +% We continue until the next token is not \cs{Ans}. (This last token +% should be \cs{eChoices}.) +% \begin{macrocode} +\def\@@layoutTabularAns{% + \@ifnextchar\Ans{\@getTabAns}% + {\@lookforendansChoices{\@@layoutTabularAns}}% +} +\def\rowsep#1{\gdef\@rowsep{[#1]}\gdef\@rowskip{#1}}% +\rowsep{\rowsep@default} +\def\rowsepDefault#1{\def\rowsep@default{#1}} +\def\rowsep@default{0pt} +\long\def\@getTabAns\Ans#1\eAns{% + \eq@saveAns#1\eAns + \global\advance\eq@tabColCnt1 + \let\@save@tabSep=\eq@tabSep + \ifnum\eq@tabColCnt=\numShortCols + \global\eq@tabColCnt=0 + \xdef\eq@tabSep{\noexpand\\\noalign{\kern\@rowskip\relax}}% + \else + \gdef\eq@tabSep{&}% + \fi + \@ifnextchar\eChoices{\@save@tabSep\Ans#1\rowsep{\rowsep@default} + \expandafter\@findendans\@gobble}% + {\@save@tabSep\Ans#1\@@layoutTabularAns}% +} +% \end{macrocode} +% This command, I think, is executed after we've found the \cs{eChoices}. +% \begin{macrocode} +\def\@findendans{\@ifnextchar\end{% 4/5 +% \end{macrocode} +% If there is a \cs{bChoiceLabel} we process the alternatives. +% \begin{macrocode} + \ifx\bChoiceLabel\@empty\else + \processLabeledAns\fi + }{\expandafter\@findendans\@gobble}}% +% \end{macrocode} +% The command that processes the alternatives. +% \changes{v6.7g}{2013/08/09}{Changed \texttt{\#1} to \cs{the}\cs{@temptokena} Fixing +% a nasty bug. Reported by Christopher C.} +% \begin{macrocode} +\def\defineEachAns#1{\advance\count0by1\relax + \@temptokena={#1}\csarg\xdef + {SavedAns\bChoiceLabel-Idx\the\count0}{\the\@temptokena}% + \ifsolutionsonly\else + {\let\\\relax\eq@IWDefs{\string + \csarg\string\gdef{SavedAns\bChoiceLabel-Idx\the\count0}% + {\the\@temptokena}}}\fi +} +\def\defineEachChoice#1{\advance\count0by1\relax + \@temptokena={#1}\csarg\xdef + {SavedAlts\bChoiceLabel-Idx\the\count0}% + {\the\@temptokena}\ifsolutionsonly\else + {\let\\\relax\eq@IWDefs{\string + \csarg\string\gdef{SavedAlts\bChoiceLabel-Idx\the\count0}% + {\the\@temptokena}}}\fi +} +\def\processLabeledAns{% + \bgroup + \let\label\@gobble +% \end{macrocode} +% \changes{v7.7c}{2015/10/08}{Added memory for the case} +% \begin{macrocode} +\if\aeb@FLOverride\eq@l + \global\@namedef{caseFor\bChoiceLabel}{\graylettersOff}\else + \ifaebshowgrayletters + \global\@namedef{caseFor\bChoiceLabel}{\graylettersOn}\else + \global\@namedef{caseFor\bChoiceLabel}{\graylettersOff}\fi +\fi + \toks@=\expandafter{\@tempholdSaveAns}\csarg + \xdef{SavedAns\bChoiceLabel}{\the\toks@}% + \ifsolutionsonly\else{\let\\\relax\eq@IWDefs{\string + \csarg\string\gdef{SavedAns\bChoiceLabel}{\the\toks@}}}\fi + \count0=0\relax\let\\\defineEachAns\the\toks@ + \xdef\@currNCntAns{\the\count0 }\csarg + \xdef{NumAns\bChoiceLabel}{\@currNCntAns}% + \ifsolutionsonly\else{\eq@IWDefs{\string + \csarg\string\gdef{NumAns\bChoiceLabel}{\the\count0 }}}\fi + \toks@=\expandafter{\@tempholdSaveChoice}\csarg + \xdef{SavedAlts\bChoiceLabel}{\the\toks@}% + \ifsolutionsonly\else{\let\\\relax\eq@IWDefs{\string + \csarg\string\gdef{SavedAlts\bChoiceLabel}{\the\toks@}}}\fi + \count0=0\relax\let\\\defineEachChoice\the\toks@ + \count0=1\relax\toks@={}%{\ignorespaces\@gobble}% + \loop + \edef\temp@exp{\the\toks@\noexpand\\{% + \noexpand\useSavedAlts[\the\count0]{\bChoiceLabel} + \noexpand\useSavedAns[\the\count0]{\bChoiceLabel}}}% + \toks@=\expandafter{\temp@exp}% + \ifnum\count0<\@currNCntAns + \advance\count0by1 + \repeat + \csarg\xdef{SavedAltsAns\bChoiceLabel}{\the\toks@}% + \ifsolutionsonly\else{\let\\\relax\eq@IWDefs{\string + \csarg\string\gdef{SavedAltsAns\bChoiceLabel}{\the\toks@}}}\fi + \egroup +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +%</package|eqexam> +% \end{macrocode} +% \begin{macrocode} +%<*randomize> +% \end{macrocode} +% +% \subsection{Randomizing the Order of the Multiple Choices}\label{randomize} +% +% When the author wants to randomize the multiple choices, we require the \texttt{keyval} +% package and the \texttt{random.tex} macro file. This works only when using \cs{bChoices} +% and \cs{eChoices}. The use of \cs{bChoices} and \cs{eChoices} is limited to non-verbatim +% items. +% +% \changes{v6.7f}{2013/08/03}{Added conditional input of random.tex} +% The \texttt{random.tex}, by Donald Arseneau, provides the random number support. +% \begin{macrocode} +\@ifundefined{nextrandom}{\input{random.tex}}{} +% \end{macrocode} +% We redefine \cs{nextrandom} from \texttt{random.tex} to save the initializing seed. +% \begin{macrocode} +\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 +% \end{macrocode} +% Save the initial seed value to \cs{eqInitSeedValue}. +% \changes{v6.7f}{2013/08/03}{Save the initial seed value to \cs{eqInitSeedValue}.} +% \begin{macrocode} + \xdef\InitSeedValue{\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 +} +% \end{macrocode} +% The \cs{bChoices} command is now processed by the \texttt{keyval} package. There +% are two keys: \texttt{nCols} and \texttt{random}. The first key +% sets the number of columns we are limited to; the second one obviously declares +% that this list of choices should be randomized, a boolean. +% +% We redefine \cs{@ansChoices} above to take key-value optional arguments. +% We allow for a global override of the random key. If random is true, we +% call \cs{@@bChoices}, which begins the process of randomization; otherwise +% we call \cs{@@ansChoices} which is roughly equal to the earlier +% \cs{@ansChoices}. +% \changes{v6.1}{2007/10/28} +% {% +% Added support for randomizing the multiple choices, requires the use of \cs{bChoices} +% and \cs{eChoices}. +% } +% \begin{macrocode} +\def\@ansChoices[#1]% +{% + \global\let\@tempholdSaveAns\@empty % 5/24 + \global\let\@tempholdSaveChoice\@empty % 5/24 + \global\let\bChoiceLabel\@empty % 5/24 + \ifeq@randomizeallChoices + \setkeys{bchoice}{#1,random=true}\else + \setkeys{bchoice}{#1}\fi + \global\eq@tabColCnt=0 + \ifeq@randomizeChoices\expandafter\@@bChoices + \else\expandafter\@@ansChoices\fi +} +% \end{macrocode} +% This is actually the old \cs{@ansChoices} only slightly modified. +% \begin{macrocode} +\def\@@ansChoices{% + \ifnum\aeb@numCols=1 % list mode + \def\eq@next{\@layoutListAns}% + \else % tabular mode + \edef\eq@next{\noexpand\@layoutTabularAns{\bChoiceNumCols}}% + \fi + \eq@next +} +% \end{macrocode} +% The following are some registers to hold integers and tokens. +% \begin{macrocode} +\newcount\aeb@numChoices +\newcount\aeb@ranChoice +\newtoks\aeb@hold\aeb@hold={} +% \end{macrocode} +% This is the command that begins the randomization of the alternatives. +% First we initialize some scratch macros to hold the choices, then +% we look for the next token, if it is \cs{Ans} we then execute \cs{@getAns} +% otherwise, we're finished. +% \begin{macrocode} +\def\@@bChoices{\gdef\@temphold{}\gdef\@tempholdrandom{}% + \gdef\@tempholdfreeze{}\aeb@searchfortoken{\@getAns}% +} +\def\aeb@searchfortoken#1{% + \@ifnextchar\Ans{\advance\aeb@numChoices1\relax#1} + {\@ifnextchar\eFreeze{\expandafter\@getFreezeAns\@gobble} + {\@ifnextchar\par{\def\@@temp{\aeb@searchfortoken{#1}}% + \expandafter\@@temp\@gobble}{\@eChoices}}}% +} +% \end{macrocode} +% The non-frozen questions will be held in the macro \cs{@temphold}. +% We keep track of the number of choices using the counter \cs{aeb@numChoices}. +% \begin{macrocode} +\long\def\@getAns\Ans#1\eAns{% + \g@addto@macro\@temphold{{\Ans#1\eAns}}% + \aeb@searchfortoken{\@getAns}% +} +% \end{macrocode} +% We've encountered \cs{eFreeze}, if the next token is \cs{Ans}, go get the +% choices, otherwise, we are finished. +% \begin{macrocode} +\def\@getFreezeAns{\aeb@searchfortoken{\@@getFreezeAns}} +% \end{macrocode} +% Get the frozen choice, then look for another. Hold these frozen choices +% in the macro \cs{@tempholdfreeze}. +% \begin{macrocode} +\long\def\@@getFreezeAns\Ans#1\eAns{% + \g@addto@macro\@tempholdfreeze{\Ans#1\eAns}% + \aeb@searchfortoken{\@@getFreezeAns}% +} +% \end{macrocode} +% When we are finished finding all the choices, we come here to randomize the choices. +% \begin{macrocode} +\long\def\@eChoices#1\eChoices{% + \aeb@randomizeChoices{\the\aeb@numChoices}% +} +% \end{macrocode} +% The routine that randomizes the choices. Basically, we use \texttt{random.tex} to get +% a random number between one and \cs{aeb@numChoices}, inclusive. Then we search through +% the list of choices (\cs{@temphold}, moved to \cs{aeb@hold}). The one selected at random +% is moved to \cs{@tempholdrandom}, and the rest of the choices are moved to \cs{@temphold}, +% here \cs{aeb@hold} is used as a scratch token register. +% \begin{macrocode} +\def\aeb@randomizeChoices#1{% + \setrannum{\aeb@ranChoice}{1}{#1} + \count0=0 \aeb@hold=\expandafter{\@temphold}\def\@temphold{}% + \expandafter\@tfor\expandafter + \@temp\expandafter:\expandafter=\the\aeb@hold \do {% + \advance\count0by1 + \ifnum\count0=\aeb@ranChoice + \aeb@hold=\expandafter\expandafter\expandafter + {\expandafter\@tempholdrandom\@temp}% + \edef\@tempholdrandom{\the\aeb@hold}% + \else + \aeb@hold=\expandafter\expandafter\expandafter + {\expandafter\@temphold\expandafter{\@temp}}% + \edef\@temphold{\the\aeb@hold}% + \fi + }% +% \end{macrocode} +% We repeat this process a total of \cs{aeb@numChoices}, the original count of the number +% of choices. Once finished, we go to \cs{aeb@finishedRandomizing} to lay out the +% randomized choices for typesetting. +% \begin{macrocode} + \aeb@numChoices=#1 + \advance\aeb@numChoices-1 + \ifnum\aeb@numChoices=0\relax + \def\aeb@next{\aeb@finishedRandomizing}\else + \def\aeb@next{\aeb@randomizeChoices{\the\aeb@numChoices}}\fi + \aeb@next +} +% \end{macrocode} +% This command assembles the questions held in random order in the command \cs{@tempholdrandom} and +% the frozen ones held in \cs{@tempholdfreeze}, and lays out the choices for typesetting. +% \begin{macrocode} +\def\aeb@finishedRandomizing{% + \aeb@hold=\expandafter\expandafter\expandafter + {\expandafter\@tempholdrandom\@tempholdfreeze}% + \gdef\@temphold{}\gdef\@tempholdrandom{}\gdef\@tempholdfreeze{}% + \edef\finished@Randomizing{% + \noexpand\@@ansChoices + \the\aeb@hold + \noexpand\eChoices}% + \finished@Randomizing +} +% \end{macrocode} +% \begin{macro}{\saveRandomSeed} +% \begin{macro}{\inputRandomSeed} +% \begin{macro}{\useRandomSeed} +% +% \cs{saveRandomSeed} causes \texttt{exerquiz/eqexam} to save the last random seed used. +% +% When you have labels, as we might have in a list of multiple choices, the save feature +% needs to be turned off for several runs of latex until the label reference +% becomes up to date. +% +% \cs{inputRandomSeed} causes \texttt{exerquiz/eqexam} to input the last random seed used, if +% one exists, to re-seed the randomization so a new random sequence +% will be generated. This allows you to get a new sequence every time +% you latex. +% +% (2013/09/17) Made a number of changes so that the randomization of \cs{bChoices} +% and \cs{eChoices} works well with the \textsf{ran\_toks}. There is a lot of common +% code, and commands with the same name. I've also change from using the aux file +% \cs{jobname\_ran.sav} to \cs{jobname\_rt.sav}, the latter being the aux file used +% by \textsf{ran\_toks}. Now, there share a common aux file and common initial and final +% seeds. +% \begin{macrocode} +%\def\saveRandomSeed{\AtEndDocument{\eq@writeRandomData}} +\def\saveRandomSeed{\PackageInfo{exerquiz} + {The command \string\saveRandomSeed\space + is deprecated.\MessageBreak Seed automatically saved}} +% \end{macrocode} +% I \cs{let} the commands in this file to the companion commands in \textsf{ran\_toks} file. +% The user can use either set of commands \cs{inputRandomSeed} or \cs{useLastSeed} as one +% pair and \cs{useRandomSeed} and \cs{useThisSeed} as the other pair. +% \begin{macrocode} +\@ifpackageloaded{ran_toks}{% + \let\inputRandomSeed\useLastAsSeed + \let\useRandomSeed\useThisSeed +}{% + \def\inputRandomSeed{\eq@readRandomData}% + \def\useRandomSeed#1{\saveseedfalse\randomi=#1}% +} +\def\InitSeedValue{\the\randomi} % dps +\@ifundefined{ifsaveseed}{\newif\ifsaveseed\saveseedtrue}{} % dps +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\def\eq@writeRandomData +{% + \ifsaveseed + \@ifundefined{saveseedinfo}{\newwrite\saveseedinfo}{} + \immediate\openout \saveseedinfo \jobname_rt.sav + \let\verbatim@out\saveseedinfo + \def\eqrt@msgi{initializing seed value}% + \def\eqrt@msgii{last random number used}% + \uccode`c=`\%\uppercase{% + \immediate\write\verbatim@out + {\InitSeedValue\space c \eqrt@msgi}% + \immediate\write\verbatim@out + {\the\randomi\space c \eqrt@msgii}% + }\immediate\closeout\saveseedinfo + \fi +} +\AtEndDocument{\eq@writeRandomData} +% \end{macrocode} +% Save the data to the file \cs{jobname\_ran.sav}. +% \begin{macrocode} +\def\eq@readRandomData{\IfFileExists{\jobname_rt.sav}{% + \PackageInfo{exerquiz}{Inputting \jobname_rt.sav}% + \@ifundefined{readsavfile}{\newread\readsavfile}{}% + \openin\readsavfile=\jobname_rt.sav + \read\readsavfile to \InitSeedValue + \read\readsavfile to \eqlastRandomNum + \closein\readsavfile + \randomi=\eqlastRandomNum + \xdef\InitSeedValue{\the\randomi}% + \immediate\closeout\readsavfile +}{% + \PackageInfo{exerquiz}{\jobname_rt.sav cannot + be found, \MessageBreak + using the random initializer}% +}} +% \end{macrocode} +% \begin{macrocode} +%</randomize> +% \end{macrocode} +%\subsection{In Support of showgrayletters} +% +% This is a hack to reference multiple choice questions when the +% \texttt{showgrayletters} option is in effect. We define \cs{REF} to +% return the uppercase version of the letters. +% \begin{macrocode} +%<*package|eqexam> +% \end{macrocode} +% \begin{macro}{\graylettersOn} +% \begin{macro}{\graylettersOff} +% Convenience commands for turning on or off the gray letter feature +% \begin{macrocode} +\def\graylettersOn{\aebshowgrayletterstrue} +\def\graylettersOff{\aebshowgraylettersfalse} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macrocode} +\def\aeb@exiii{\expandafter\expandafter\expandafter} +% \end{macrocode} +% \begin{macro}{\REF} +% Same syntax as \cs{ref}, including a \texttt{*} option. the +% \texttt{*} version does not create a link. If +% \texttt{showgrayletters} is not in effect, then \cs{REF} is +% equivalent to \cs{ref}. +%\changes{v6.06c}{2007/04/26} +%{ +% Added \cs{REF} in support of the \texttt{showgrayletters} option. +%} +%\changes{v6.4d}{2011/07/14}{% +% Correct \cs{REF} so that a link is created. +%} +% \begin{macrocode} +\def\REF{\@ifstar{\let\isREFstar\eq@One\aeb@REFstar} + {\let\isREFstar\eq@Zero\aeb@REF}} +\def\aeb@REFstar#1{\@ifundefined{r@#1}{\hbox{\reset@font\bfseries ??}} + {\ifaebshowgrayletters\aeb@buildUpperCaseRef{#1}% + \else\ref*{#1}\fi}% +} +\def\aeb@REF#1{\@ifundefined{r@#1}{\hbox{\reset@font\bfseries ??}} + {\ifaebshowgrayletters\aeb@buildUpperCaseRef{#1}% + \else\ref{#1}\fi}% +} +%</package|eqexam> +%<*eqexam> +\def\aeb@buildUpperCaseRef#1{% + \xdef\tmp@expand{\aeb@exiii\@firstoftwo\csname r@#1\endcsname}% + \xdef\tmp@expand{\uppercase{\tmp@expand}}\tmp@expand +} +%</eqexam> +%<*package> +\def\aeb@buildUpperCaseRef#1{% + \xdef\tmp@expand{\aeb@exiii\@firstoffive\csname r@#1\endcsname}% + \xdef\tmp@expand{\uppercase{\tmp@expand}}% + \if\isREFstar\eq@One\tmp@expand\else\hyperref[#1]{\tmp@expand}\fi +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Circles instead of Rectangles} +% +% For quizzes only, there is now an way to use circles for the radio button +% fields for multiple choice questions (not for multiple selection questions, however). +% +% \begin{macro}{\useMCCircles} +% Execute this command prior to the quiz you want to use circular radio buttons. The command +% saves the values of \cs{every@qRadioButton} and \cs{every@qCheckBox}, then uses the +% every mechanism to set the all radio buttons created in a quiz to a circle symbol, we also +% set all check boxes used in multiple choice question to a transparent border. +% +%\changes{v6.3j}{2008/12/08} +%{ +% Added \cs{useMCCircles} and \cs{useMCCRects}. +%} +% \par\medskip\noindent We use a switch to keep track of ``circle mode.'' If the +% document author invokes \cs{useMCCircles} when we are already in circle mode, +% \cs{useMCCircles} does nothing. +% \begin{macrocode} +\newif\ifaeb@usecircles\aeb@usecirclesfalse +% \end{macrocode} +% \begin{macrocode} +\let\insert@circlesymbol\@empty +\def\useMCCircles{\useForms + \ifaeb@usecircles\else + \global\aeb@usecirclestrue + \gdef\insert@circlesymbol{\symbolchoice{circle}}% + \fi +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\useMCRects} +% We can restore the default behavior by executing \cs{useMCRects} prior to the next quiz. +% The command restores the state of \cs{every@qRadioButton} and \cs{every@qCheckBox} +% to their values prior to the last invocation of \cs{useMCCircles}. +% \begin{macrocode} +\def\useMCRects{\useForms + \ifaeb@usecircles\global\aeb@usecirclesfalse + \global\let\insert@circlesymbol\@empty + \fi +} +\let\useMCCRects\useMCRects +% \end{macrocode} +% \end{macro} +% +% \section{Objective Style Questions} +% +% The code for objective style questions is very simple. The +% evaluation of the user's response is done by JavaScript. The +% JavaScript is inserted into the PDF file through DLJS. For +% authors using \textsf{pdftex} or \textsf{dvipdfm}, this process +% is automatic; for authors using the distiller (hence, would use +% the \texttt{dvips} or \texttt{dvipsone} option), the solution is +% also automatic if you use \textbf{Acrobat 5.0}. If you do not have +% the latest version of Acrobat, the DLJS must be inserted +% manually using the \texttt{Document > Insert Pages} menu item. See +% paragraphs below for a little more detail, or see the manual. +% +% There are two kinds of questions that can be posed (actually only one type): +% (1) a question that has a numerical answer; +% (2) a question that has a symbolic answer in one variable, +% $x$. The symbolic answer must reduce, however, to a numerical value when +% $x$ is given a numerical value. Thus, only questions whose answers can +% be reduced to numerical values can be posed. +% +% If the author has Acrobat 5.0, the \textsf{exerquiz} package should be +% built using the \texttt{Acrobatv} option in the +% \textsf{exerquiz.ins} file. In this case, Document level +% Javascript will be input when the newly distilled file is +% first opened in the Acrobat Viewer. If the function ``CkBalP'' is +% undefined, the we input the FDF file contained the Doc Level JS. +% The file needs to be saved (Save As) for the Doc Level JS to +% remain in the PDF file. +% +% In the case of the author using Acrobat 4.0, he/she needs to load +% manually insert the \texttt{eq\_DLJS.pdf} file. If only exercises +% are used, this insertion is not needed. +% \begin{macrocode} +%</package> +% \end{macrocode} +% \begin{macrocode} +%<*package> +% \end{macrocode} +% \begin{environment}{oQuestion} +% This was my first attempt and I have not deleted it from the package yet. +% Useful for posing a single question only. The argument is the (unique) name +% of this question. This name is used to define the macro \cmd{\oField} which is used +% by support macros. The \texttt{shortquiz} environment can also be used for +% single/multiple questions as well. +% \begin{macrocode} +\let\oqpriorhook\@empty +\newenvironment{oQuestion}[1]{% +% \end{macrocode} +% (06/08/10) The next two lines initialize the macros for registering the +% question label, i.e., \texttt{2(a)(ii)}. These two lines are repeated for +% the \texttt{shortquiz} and \texttt{quiz} environments. +% \begin{macrocode} + \let\@currentQues\@empty + \xdef\eq@pageThisQ{\the\c@page}% + \global\let\eqQzQuesList\@empty + \xdef\oField{#1}\xdef\curr@quiz{#1}\xdef\currQuiz{#1}% + \let\@qzsolndest\@empty + \stepcounter{questionno}% + \let\eqQuizType\isSQZ\gdef\eqPTs{1}\global\let\eqQT\eq@na + \let\answers\answers@sq + \let\endanswers\endanswers@sq + \let\manswers\manswers@sq + \let\endmanswers\endmanswers@sq + \let\solution\solution@sq + \let\endsolution\endsolution@sq + \noindent\oqpriorhook\sq@IDTxtField\ifx\aebTitleQuiz\@empty + \else\aebtitleQuiz\fi\ignorespaces +}{% + \global\let\aebtitleQuiz\@empty + \global\let\aebTitleQuiz\@empty + \global\let\eq@tq@star\relax +} +\def\oSolution#1{\edef\@qzsolndest{#1}} +% \end{macrocode} +% \end{environment} +% \begin{macro}{\replaceExclPt} +% When processing a mathematical expression, replace \texttt{n!} or \texttt{(n)!} with +% \texttt{fact(n)}. Used with the \texttt{combinatorics} option of \textsf{dljslib} package. +% \begin{macrocode} +\def\replaceExclPt#1{\def\replaceexclaim{#1}} +\replaceExclPt{false} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\negPointsAllowed} +% Used with the \texttt{ProcessMultiSelection} when processing \texttt{manswers} environments. +% The default is not to allow the score to go below 0. By executing \cs{negPointsAllowed} +% in the preamble, we allow the score to go below zero. +%\changes{v6.3i}{2008/10/22} +%{ +% Added \cs{negPointsAllowed} to allow negative scores on quizzes. This is only relevant +% when the quiz has a \texttt{manswers} environment. +%} +% \begin{macrocode} +\def\negPointsAllowed{\def\negpointsallowed{true}} +\@onlypreamble{\negPointsAllowed} +\def\negpointsallowed{false} +\def\negPointsMarkupAllowed{\def\negpointsmarkupallowed{true}} +\def\negpointsmarkupallowed{false} +\@onlypreamble{\negPointsMarkupAllowed} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\requireAlertBox} +% Turn off the ``Do not show this message again'' checkbox for objective questions +% and multiple choice questions. +%\changes{v6.3m}{2010/01/27} +%{ +% Added \cs{requireAlertBox} to turn off the ``Do not show this message again'' checkbox for objective questions. +%} +%The alert box displays the message \cs{doNotShowAgainMsg} which by default is +%``Do not show this message again'' +% \begin{macrocode} +\def\requireAlertBox{\def\bcheckboxused{false}} +\def\allowNoAlertBox{\def\bcheckboxused{true}} +\allowNoAlertBox +% \end{macrocode} +% \end{macro} +% \subsection{Math Fill-In Questions} +% \begin{macro}{\RespBox} +% \begin{macro}{\RespBoxMath} +% \begin{macro}{\RespBoxNT} +% \cmd{\RespBox} and \cmd{\RespBoxNT} lay out a text box, into which the +% user enters his/her response to the question. \cmd{\RespBox} expects the presence +% of \cmd{\sqTallyBox}, whereas \cmd{\RespBoxNT} does not (NT = No Tally ). +%\par\medskip +% Usage: |\RespBox[#1]#2(#3)[#4]#5#6#7#8[#9]*#10| +% \begin{description} +% \item[\ttfamily\#1 :] Optional parameter used to modify the appearance of the +% text field. +% \item[\ttfamily\#2 :] The correct answer to the question. +% This must be a numerical value, or a function of one variable. +% JavaScript Note: +% In JavaScript, functions such as \texttt{sin(x)} and \texttt{cos(x)} are +% methods of the \texttt{Math} object. It is not necessary, however, to +% type \texttt{Math.sin(x)} or \texttt{Math.cos(x)}; this is done by inserting +% the expression into a \texttt{with(Math)} group. +% \item[\ttfamily\#3 :] An optional parameter, \textit{delimited by parentheses}, +% that defines the independent variable; \texttt{x}, is the default value. Note +% that this parameter is set off by parentheses. For a multivariate question, just +% list the variables in juxtaposition, \texttt{(xyz)}. An alternate method is to +% delimit with commas \texttt{(x,y,n)} and include the type of the variables +% \texttt{(r:x,r:y,i:n)}, where \texttt{"r"} means a real variable and \texttt{"i"} +% means an integer variable. The variables must be either of the old style (no commas, no typing) +% or the new style. Do not mix the styles. +% \item[\ttfamily\#4 :] Optional, a named destination to the solution to the +% question. If this parameter appears, then a solution must follow the +% question, enclosed in a \texttt{solution} environment. +% Alternately, the fourth parameter can be a `\texttt*', in which case, we have +% automatic naming of the destination, namely, \texttt{[\string\curr@quiz.\string\thequestionno]} +% \item[\ttfamily\#5 :] The number of samples points to be used, usually $3$ or $4$ is +% sufficient. +% \item[\ttfamily\#6 :] Precision required, the $\epsilon$ value, if you will. +% \item[\ttfamily\#7 :] Parameters \#7 and \#8 are used to define the interval from +% which to draw the sample points. There are two forms: (1) \#7 is the left-hand endpoint +% of the interval and \#8 is the right-hand endpoint (the use of \#7 and \#8 in this form +% is deprecated); (2) the interval is defined by standard interval notation, \texttt{[a,b]}. +% For a multivariate question---one where parameter \#2 lists more than one variable, +% separate the intervals for each variable by a `x', \texttt{[0,2]x[1,2]x[3,4]}. +% \item[\ttfamily\#8 :] (1) \#8 is the right-hand endpoint of the interval (the use of this +% parameter is deprecated); (2) in the second +% case, \#8 is not used. +% \item[\ttfamily\#9 :] This optional parameter is either the name of a customized +% comparison function \textit{or} a JavaScript object with at most two properties: +% \texttt{priorParse} and \texttt{comp}. See the demo file \texttt{integer\_tst.tex} for +% examples of usage. +% \item[\ttfamily\#10:] (Only detected if following an asterisk, `\texttt*') +% The name of a JavaScript function that is to be used to process the user input. +% \end{description} +% Example: +%\begin{flushleft}\footnotesize +%|\RespBoxMath{<exp(t), 2*t, sin(t)>}(t)[soln]{3}{.0001}{[0,1]}[compare]*{ProcVec}| +%\end{flushleft} +% or (the deprecated form) +%\begin{flushleft}\footnotesize +%|\RespBoxMath{<exp(t), 2*t, sin(t)>}(t)[soln]{3}{.0001}{0}{1}[compare]*{ProcVec}| +%\end{flushleft} +% \begin{macrocode} +\newcommand\RespBoxNT{\def\rbFlag{0}\@RespBox} +\newcommand\RespBox{\def\rbFlag{0}\@RespBox} +\newcommand\RespBoxMath{\def\rbFlag{0}\@RespBox} +% \end{macrocode} +% These commands can be used define the default appearance of the \cs{RespBoxMath}, +% \cs{RespBoxTxt} et al. This first set controls all standard text fields. +% \begin{macrocode} +% \end{macrocode} +% Get any changes in the appearance of the text box +% \changes{v6.4c}{2011/07/01}{\cs{RespBoxMath} now records its lists of +% independent variables under the global variable \texttt{\_mathVars}.} +% \begin{macrocode} +\begin{defineJS}[% + \catcode`\%=14\relax\catcode`\@=0\relax]{\AAKqRespBoxMath} +if(event.willCommit){ + RecordPointValue(@eqPTs,@thequestionno@ifx@grpquestions1,% +@thegrpquestionno,@grpPointValue,@grpTotalWeight,% +"@grpEvalFunction"@fi); + RecordProblemType("@eqQT",@thequestionno); + _mathVars=@indepVar; + var retn = @processJSfunc(@rbArgs,@compareJSfunc); + ProcUserResp(retn,event.value,@thequestionno,% +0@ifx@grpquestions1,@thegrpquestionno@fi); +} +if (!isQuizInitialized("@currQuiz")) { + @eqObjAlert@space eqAppAlert(InitMsg("@bqlabelISO"),3); + event.rc = false; +} +\end{defineJS} +\def\RespBoxMathDefaults +{% + \BC{0 0 0}\S{S}\textColor{0 g}\F{\FPrint}\W{1} +} +\def\moreRespBoxMathDefaults +{% + \edef\@moreRespBoxMathDefaults{% + \if\eqQuizType\isQZ\ifx\eq@online\eq@YES + \ifeq@noquizsolutions + \else\noexpand\Ff{\FfReadOnly}\fi\fi\fi + }% +} +\let\eqFormatArg\@empty +\def\@@RespBoxMathActions +{% + \AA{\if\eqQuizType\isQZ + \AAKeystroke{\AAKqRespBoxMath\eqAAKeystrokeArg} + \AAFormat{\eqFormatArg} + \else + \AAKeystroke{if(event.willCommit) {\r\t + _mathVars=\indepVar;\r\t + retn=\processJSfunc(\rbArgs,\compareJSfunc);\r +\if\@sqTurnOffAlerts1 + \t OnBlurRespBox(% + \if\@sqTurnOffAlerts1retn\else null\fi,"\curr@quiz"); + \eqAAKeystrokeArg\r +\fi + }% + } + \AAFormat{\eqFormatArg}% + \AAOnFocus{\JS{var retn = null;}}% + \AAOnBlur{\JS{OnBlurRespBox(null,"\curr@quiz");}}% + \fi + } +} +\newcommand\@RespBox[1][] +{% + \eq@AddProbToQzQuesList + \smallskip\ifx\grpquestions\eq@Zero + \addtocounter{eqpointvalue}{\eqPTs}\fi + \if\eqQuizType\isQZ + \def\rbFlag{1}\global\IsRespBoxtrue + \ifx\grpquestions\eq@One + \stepcounter{grpquestionno}% + \def\Fld@name{% + grpobj.\curr@quiz.\thequestionno.\thegrpquestionno}% + \else + \eq@recordThesePTs\eq@recordProbType + \edef\eqtmp{\aPointType}% + \xdef\aPointType{\eqtmp,[\eqPTs,"math"]}% + \stepcounter{questionno}% + \def\Fld@name{obj.\curr@quiz.\thequestionno}% + \fi + \else % shortquiz + \ifx\grpquestions\eq@One + \stepcounter{grpquestionno}% + \def\Fld@name{% + grpobj.\oField.\thequestionno.\thegrpquestionno}% + \else + \stepcounter{questionno}% + \def\Fld@name{% + obj.\oField.\thequestionno}% + \fi + \fi +% \end{macrocode} +% Changed (v6.3f, 2008/10/08) the command \cs{array} to \cs{Array} to avoid clashing with the +% array command defined in \texttt{amsmath}. +% \begin{macrocode} + \let\Array\aeb@array + \moreRespBoxMathDefaults +% \end{macrocode} +% (2014/01/23) This is tricky, I'm enclosing \cs{text@@Field} in an \cs{mbox}, beginning here +% \begin{macrocode} + \leavevmode\hbox\bgroup\text@@Field{#1}{\Fld@name}% + {\RBW}{\DefaultHeightOfWidget}% + {\eq@protect\AA}{\eq@setWidgetProps\eq@RespBox}% + {\RespBoxMathDefaults\@moreRespBoxMathDefaults + \@@RespBoxMathActions\every@eqTextField\every@RespBoxMath}% +} +% \end{macrocode} +% Get the second parameter, which is the correct answer to the question, and +% test to see if there is a specification for the optional third parameter, +% which is the variable list, `\texttt x' is the default. +% \begin{macrocode} +\def\eq@RespBox#1{\gdef\eqCorrectAns{#1}\if\grpquestions\eq@Zero +% \end{macrocode} +% If not within a \texttt{mathGrp} environment, if within a MCFI command pair we save the author's +% answer as \cs{s@veCorrAnsMCFI}; otherwise, we record the author's answer. If within +% \texttt{mathGrp} environment, we record is as part of the group array to be use later. +% \begin{macrocode} + \ifwithinMCFI\gdef\s@veCorrAnsMCFI{"#1"}\else +% \eq@recordCorrAns{"#1"} +\fi\else\eq@recordGrpAnsArray{"#1"}\fi + \@ifnextchar({\@eq@RespBox{#1}}{\@eq@RespBox{#1}(x)}} +% \end{macrocode} +% Pick up the optional third parameter, then test whether the optional fourth parameter is there. +% There are two forms: the [mydest] an explicit destination for the solution to the problem, or +% a `\texttt*', in which case, we have automatic naming, the name is +% \texttt{[\string\curr@quiz.\string\thequestionno]}. +% \begin{macrocode} +\def\@eq@RespBox#1(#2){\@ifnextchar[{\@eq@RespB@x{#1}(#2)}% + {\@ifstar{\@eq@RespB@x{#1}(#2)[\curr@quiz.\thequestionno]}% + {\@eq@RespB@x{#1}(#2)[]}}} +% \end{macrocode} +% Now get the next three parameters: the number of samples, the precision, and the first of the +% two interval parameters. +% \begin{macrocode} +\def\eq@ZERO{0} +\def\defaultRDPrecision#1{\def\eq@defaultRDPrecision{#1}} +\defaultRDPrecision{1E-14} +% \end{macrocode} +% dps/change 02/23/07 Here we try to implement a suggest of Bruce Wagner. If the tolerance +% is set to zero, then use \texttt{reldiffCompare} as the default compare, and set the tolerance +% to some small value. Here, the small value is the value of the command +% \cs{eq@defaultRDPrecision} which can be set by \cs{defaultRDPrecision}. The default definition +% is \verb!\defaultRDPrecision{1E-14}!. +% \begin{macrocode} +\def\@eq@RespB@x#1(#2)[#3]#4#5#6{\xdef\@qzsolndest{#3}% + \def\indepVar{"#2"}\def\eq@precision{#5}% + \ifx\eq@precision\eq@ZERO + \def\eq@defaultCompare{reldiffCompare}% +% \end{macrocode} +% (2017/01/11) Replace \texttt{\#1} by \cs{eqCorrectAns} to delay expansion +% \changes{v7.8d}{2017/01/11}{Replace \string\texttt{\#1} by \string\cs{eqCorrectAns} to delay expansion} +% \begin{macrocode} + \def\rbArgstmp{% + \rbFlag,"\eqCorrectAns",#4,\eq@defaultRDPrecision}\else + \def\eq@defaultCompare{diffCompare}% + \def\rbArgstmp{\rbFlag,"\eqCorrectAns",#4,#5}\fi +% \end{macrocode} +% We have arrived at the first of possibly two parameters that define the interval(s) +% from which to sample random points. There are two forms, the old style (deprecated) +% and the new style. We must detect which form this is. +% \par\medskip\noindent +% (10/10/11) To support \cs{viidna}, we expand \texttt{\#6} first before passing it +% to the command \cs{@checkforInterval}. +% \begin{macrocode} + \edef\eq@ixparam{#6}% + \expandafter\@checkforInterval\eq@ixparam\\% +} +% \end{macrocode} +% \DescribeMacro{\viidna} is used with the \texttt{satisfyEq} for the seventh parameter, +% these routines do not use the ninth, but there needs to be something that does not +% stop compilation. +% \begin{macrocode} +\def\viidna{[]} +% \end{macrocode} +% If the next token is a `\texttt[', then that signals the beginning of an interval +% such as \texttt{[a,b]}, must be the new style. The second parameter is not +% needed, and not expected in this case. It would be a mistake to include it. +% \begin{macrocode} +\def\@checkforInterval{% + \@ifnextchar[{\@checkforIntervali}{\@checkforIntervalii}} +% \end{macrocode} +% This is the case of the new style of defining the interval. We insert it into the +% arguments list, and continue on to the next stage. +% +% I have detected a problem when the ninth parameters is a JavaScript object and the left brace +% is next to the left bracket. Somehow, the left brace and right brace get absorbed. We do a +% work around, and insert a space after the left bracket. +% \begin{macrocode} +\def\@checkforIntervali#1\\{% + \def\rbArgs{\rbArgstmp,"#1",\indepVar}% + \@ifnextchar[{\@eq@@RespBox[ \expandafter\@gobble}% + {\@eq@@RespBox[\eq@defaultCompare]}% +} +% \end{macrocode} +% This is assumed to be the old style for defining the interval. In this case, the next +% token is the right-hand endpoint of the interval, we need it. It would be a mistake +% \texttt{not} to include it. We also test for the presence of the optional +% of a customized comparison function, parameter \texttt{\#9} +% \begin{macrocode} +\def\@checkforIntervalii#1\\#2{% + \def\rbArgs{\rbArgstmp,"[#1,#2]",\indepVar}% + \@ifnextchar[{\@eq@@RespBox}{\@eq@@RespBox[\eq@defaultCompare]}% +} +% \end{macrocode} +% Finally, we see if there will be a 10th parameter by seeing if `\texttt*' comes +% next. We change the catcodes here, so we can have a left and right brace in the +% optional argument \#9. Hope it works. dps 12/30/03 +%\changes{v6.4g}{2011/07/21}{% +% Changing the definition of \cs{@eq@@RespBox}, removing the change +% in \cs{catcode}s. If this causes problems, can restore the +% old definition. +%} +% \begin{macrocode} +%\def\@eq@@RespBox{\begingroup\catcode`\<=1\relax\catcode`\>=2\relax +% \catcode`\{=12\relax\catcode`\}=12\relax\@eq@@@RespBox} +%\def\@eq@@@RespBox[#1]{\endgroup\@ifstar{\jsRespBox[#1]}% +% {\jsRespBox[#1]{ProcResp}}} +% \end{macrocode} +% Below is an alternate (and obvious) definition for \cs{@eq@@RespBox}. Whatever +% reason I had to change the catcodes, I don't remember, and things seem to work +% without it. But, will keep things as they are. +% \begin{macrocode} +\def\@eq@@RespBox{\@eq@@@RespBox} +\def\@eq@@@RespBox[#1]{\@ifstar{\jsRespBox[#1]}% + {\jsRespBox[#1]{ProcResp}}} +\def\eq@ProcRespIntervals{ProcRespIntervals} +\def\jsRespBox[#1]#2{\def\compareJSfunc{#1}% + \def\processJSfunc{#2}\gdef\g@processJSfunc{#2}% 01/11 +% \end{macrocode} +% (2017/01/11) Run answer through \cs{pdfstringdef} if +% \texttt{ProcRespIntervals} is used to avoid unbalanced parentheses. +% \changes{v7.8d}{2017/01/11}{Run answer through \string\cs{pdfstringdef} if +% \string\texttt{ProcRespIntervals} is used.} +% \begin{macrocode} + \ifx\eq@ProcRespIntervals\g@processJSfunc +% \end{macrocode} +% When the response function is \texttt{ProcRespIntervals} there is no `real' math, no subscripts, +% no superscripts. We turn of the math mode warning before \cs{pdfstringdef}. +% \begin{macrocode} + \let\@inmathwarn@SAVE\@inmathwarn\let\@inmathwarn\@gobble +% \end{macrocode} +% When the response function is \texttt{ProcRespIntervals}, there may be unbalanced parentheses, we'll +% pass \cs{eqCorrectAns} through \cs{pdfstringdef} to escape them. +% \begin{macrocode} + \pdfstringdef{\eqCorrectAns}{\eqCorrectAns}% + \let\@inmathwarn\@inmathwarn@SAVE\fi + \eq@recordCorrAns{"\eqCorrectAns"}% 01/11 + \ifeq@proofing\makebox[0pt][l]{\space\math@correctAnswer}\fi + \eq@TextField % send to the driver-dependent macro +% \end{macrocode} +% (2014/01/23) Closing the \cs{hbox} here, begun at the opening of \cs{text@@Field} above. +% \begin{macrocode} + \egroup +} +% \end{macrocode} +% The primitive \cs{meaning} is used to get a typeset version of the answer for the \texttt{proofing} +% option. I found it a difficult problem because once the answer is scanned, it has catcodes attached. +% Once that is done, it is impossible to use standard methods to make a typeset the answer in +% verbatim mode. This trick appears in the \TeX book. \cs{meaning} inserts additional spaces on occasion, +% for example, following a period (`.'). Oh, well. +% \begin{macrocode} +\def\gobbleMacro#1>{} +\gdef\math@correctAnswer{% + \ttfamily\color{\@proofingsymbolColor}\spaceskip=2pt\xspaceskip=2pt% + \expandafter\gobbleMacro\meaning\eqCorrectAns +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +%\subsection{Text Fill-In} +% \begin{macro}{\RespBoxTxt} +% \begin{macro}{\RespBoxTxtNT} +% These two macros process open-ended questions that require a text response. +% There are several ways to customize these macros; as described below. +% \par\medskip +% \noindent Usage: |\RespBoxTxt[#1]#2#3[#4]#5<plus listing of alternatives>| +% \begin{description} +% \item[\ttfamily\#1 :] Optional parameter used to modify the appearance of the +% text field. +% \item[\ttfamily\#2 :] This required parameter is a number that indicates +% the filtering method to be used. Permissible values of this parameter are +% \begin{description} +% \item[\ttfamily -1: ] (The default) The author's and user's answers are not filtered +% in any way. (Spaces, case, and punctuation are preserved.) +% \item[\ttfamily 0: ] The author's and user's answers are converted to +% lower case, any white space and non-word characters are removed. +% \item[\ttfamily 1: ] The author's and user's answers are converted to +% lower case, any white space is removed. +% \item[\ttfamily 2: ] The author's and user's answers are stripped of any +% white space. +% \end{description} +% \item[\ttfamily\#3 :] This parameter a number that indicates the compare +% method to be used. Permissible values of this parameter are +% \begin{description} +% \item[\ttfamily 0: ] (The default) The author's and user's answers are +% compared for an exact match. (These answers are filtered before they are +% compared.) +% \item[\ttfamily 1: ] The user's response is searched in an attempt to +% get a substring match with the author's alternatives. Additional comparison +% methods may be added. +% \end{description} +% \item[\ttfamily\#4 :] Optional, a named destination to the solution to the +% question. If this parameter appears, then a solution must follow the +% question, enclosed in a \texttt{solution} environment. +% \item[\ttfamily\#5 :] This required parameter is the number of alternative +% answers that are acceptable. The alternative answers are listed +% immediately after this parameter. (The example above specified +% that $4$ alternatives follow.) +% \end{description} +% \begin{macrocode} +\newcommand\RespBoxTxtNT{\def\rbFlag{0}\@RespBoxTxt} +\newcommand\RespBoxTxt{\def\rbFlag{0}\@RespBoxTxt} +% \end{macrocode} +% Pick up any parameters that would modify the appearance of this text field. +% \begin{macrocode} +\def\RespBoxTxtOnBlur{OnBlurRespBox(% + \if\@sqTurnOffAlerts1retn\else null\fi,"\curr@quiz");} +\def\eqObjAlert{% + \ifx\eqQuizType\isQZ\ifx\eq@online\eq@YES\ifeq@noquizsolutions + \else if (false)\fi\fi\fi} +\begin{defineJS}[% + \catcode`\@=0\relax\catcode`\%=14\relax]{\AAKqRespBoxTxt} +if(event.willCommit){ + RecordPointValue(@eqPTs,@thequestionno@ifx@grpquestions1,% +@thegrpquestionno,@grpPointValue,@grpTotalWeight,% +"@grpEvalFunction"@fi); + RecordProblemType("@eqQT",@thequestionno); + var retn = ProcRespTxt(@rbTxtAlt); + ProcUserResp(retn,event.value,@thequestionno,% +0@ifx@grpquestions1,@thegrpquestionno@fi); +} +if (!isQuizInitialized("@currQuiz")) { + @eqObjAlert@space eqAppAlert(InitMsg("@bqlabelISO"),3); + event.rc = false; +} +\end{defineJS} +\def\RespBoxTxtDefaults +{% + \BC{0 0 0}\W{1}\S{S}\textColor{0 g}\F{\FPrint}% +} +\def\moreRespBoxTxtDefaults +{% + \edef\@moreRespBoxTxtDefaults{% + \if\eqQuizType\isQZ\ifx\eq@online\eq@YES + \ifeq@noquizsolutions\else + \noexpand\Ff{\FfReadOnly}\fi\fi\fi + }% +} +\def\@@RespBoxTxtActions +{% + \AA{\if\eqQuizType\isQZ + \AAKeystroke{\AAKqRespBoxTxt} + \else + \AAKeystroke{% + if(event.willCommit) {\r\t + retn = ProcRespTxt(\rbTxtAlt);\r +\if\@sqTurnOffAlerts1 + \t\RespBoxTxtOnBlur\r +\fi + }% + } + \AAOnFocus{\JS{var retn = null;}} +% \end{macrocode} +% dps 2/12/05 A fix for Acro7.0, a change in the blur event, must +% move this event to keystroke so behavior is the same as in previous +% versions. +% \begin{macrocode} +\if\@sqTurnOffAlerts0 + \AAOnBlur{\JS{\RespBoxTxtOnBlur}}% +\fi + \fi + } +} +\newcommand\@RespBoxTxt[1][] +{% + \eq@AddProbToQzQuesList +% \smallskip + \ifx\grpquestions\eq@Zero\addtocounter{eqpointvalue}{\eqPTs}\fi + \if\eqQuizType\isQZ + \def\rbFlag{1}\global\IsRespBoxtrue + \ifx\grpquestions\eq@One + \stepcounter{grpquestionno}% + \def\Fld@name{% + grpobj.\curr@quiz.\thequestionno.\thegrpquestionno}% + \else + \eq@recordThesePTs\eq@recordProbType + \edef\eqtmp{\aPointType}% + \xdef\aPointType{\eqtmp,[\eqPTs,"text"]}% + \stepcounter{questionno}% + \def\Fld@name{obj.\curr@quiz.\thequestionno}% + \fi + \else + \stepcounter{questionno}% + \def\Fld@name{obj.\oField.\thequestionno}% + \fi + \moreRespBoxTxtDefaults + \leavevmode\hbox\bgroup\text@@Field{#1}{\Fld@name}% + {\RBW}{\DefaultHeightOfWidget}% + {\eq@protect\AA}{\eq@setWidgetProps\@@RespBoxTxt}% + {\RespBoxTxtDefaults\@moreRespBoxTxtDefaults + \@@RespBoxTxtActions\every@eqTextField\every@RespBoxTxt}% +} +% \end{macrocode} +% Now get the next two required parameters. Also, see if there is going to be a solution. +% This can be specified in two ways: (1) By inserting an explicit named destination \texttt{[mydest]} +% or (2) by specifying a `\texttt*', in which case, automatic naming is performed. The name is +% \texttt{\string\curr@quiz.\string\thequestionno}, \texttt{[\string\curr@quiz.\string\thequestionno]]} is inserted +% as the parameter. +% \medskip\noindent +% |#1 = filter|, |#2 = comp| +% \begin{macrocode} +\def\@@RespBoxTxt#1#2{% + \@ifnextchar[{\@@@RespBoxTxt{#1}{#2}} + {\@ifstar{\@@@RespBoxTxt{#1}{#2}[\curr@quiz.\thequestionno]}% + {\@@@RespBoxTxt{#1}{#2}[]}}} +% \end{macrocode} +% |#1 = filter|, |#2 = comp|, |#3 = dest|, |#4 = num_alts| +% \begin{macrocode} +\def\eq@ZERO{0}\def\eq@ONE{1}\def\eq@TWO{2} +\def\@@@RespBoxTxt#1#2[#3]#4{% + \xdef\@qzsolndest{#3}% + \def\eq@argi{#1}\ifx\eq@argi\eq@ZERO\else + \ifx\eq@argi\eq@ONE\else\ifx\eq@argi\eq@TWO\else + \def\eq@argi{-1}\fi\fi\fi + \def\eq@argii{#2}\ifx\eq@argii\eq@ONE\else\def\eq@argii{0}\fi + \begingroup + \ifnum\eq@argii=1\relax +% \end{macrocode} +% local definitions: \DescribeMacro{\rexpStr}\cs{rexpStr}, +% \DescribeMacro{\\<RegEXP>}|\\|, and \DescribeMacro{\word}\cs{word}. +% \begin{macrocode} + \def\rexpStr##1{\eqbs\eqbs\eqbs\eqbs##1}% + \def\\##1{\eqbs\eqbs\eqbs\eqbs##1}% + \def\word##1{\\b##1\\b}\def\any{@any@}\fi + \xdef\rbTxtAlt{\rbFlag,\eq@argi,\eq@argii}% + \global\let\txtAltList\@empty + \count0=#4 \ifnum\count0 > 0 \expandafter\@argRead\else + \PackageError{exerquiz}{% + The fourth required parameter of \string\RespBoxTxt\MessageBreak + is required to be a positive integer. You entered\MessageBreak + #4\space instead}{Enter a positive integer.}\fi +} +\def\@argRead#1{\xdef\jsTempArgs{\txtAltList}% + \ifx\txtAltList\@empty\xdef\txtAltList{"#1"}\else + \xdef\txtAltList{\jsTempArgs,"#1"}\fi\@@argRead} +\def\@@argRead{\advance\count0 by-1\relax + \ifnum\count0=0\relax + \def\eq@next{\endgroup + \xdef\rbTxtAlt{\rbTxtAlt,\txtAltList}% + \if\grpquestions\eq@Zero + \ifwithinMCFI + \xdef\s@veCorrAnsMCFI{[\txtAltList]}\else + \eq@recordCorrAns{[\txtAltList]}\fi + \else +% \end{macrocode} +% \changes{v7.8a}{2016/11/18}{Fixed a typo, \string\texttt{...AnsArrayi} should be +% \string\texttt{...AnsGrpAnsArray}} +% Fixed typo, changed \cs{eq@recordGrpAnsArrayi} to \cs{eq@recordGrpAnsArray}. +% \begin{macrocode} + \eq@recordGrpAnsArray{[\txtAltList]}% + \fi + \eq@@RespBoxTxt + }% + \else + \def\eq@next{\@argRead}% + \fi\eq@next +} +\def\eq@@RespBoxTxt{% + \ifeq@proofing\makebox[0pt][l]{\space\txt@correctAnswer}\fi + \eq@TextField +% \end{macrocode} +% Closing of the \cs{hbox} begun above. +% \begin{macrocode} + \egroup +} +% \end{macrocode} +% If the \texttt{proofing} option is specified, then we type out the author's list of +% acceptable answers. Again, we use \cs{meaning}, probably not needed here. +% \begin{macrocode} +\def\gobbleTxt#1>#2,#3,#4,{} +\gdef\txt@correctAnswer{\ttfamily\color{\@proofingsymbolColor}% + \spaceskip=2pt\xspaceskip=2pt + \expandafter\gobbleTxt\meaning\rbTxtAlt +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\RespBoxTxtPC} +% This is pretty much a copy of \cs{RespBoxTxt}, with slight modifications. Here, +% we attempt to award partial credit for words that appear in the answer. +% This is a feature request of Kate of Kenya. +% \par\medskip +% \noindent Usage: +%\begin{verbatim} +% \RespBoxTxt[#1]#2[#3]#4[<num1>]{<word1>}...[<num_n>]{<word_n>} +%\end{verbatim} +% \begin{description} +% \item[\ttfamily\#1 :] Optional parameter used to modify the appearance of the +% text field. +% \item[\ttfamily\#2 :] This required parameter is a number that indicates +% the filtering method to be used. Permissible values of this parameter are +% \begin{description} +% \item[\ttfamily -1: ] (The default) The author's and user's answers are not filtered +% in any way. (Spaces, case, and punctuation are preserved.) +% \item[\ttfamily 0: ] The author's and user's answers are converted to +% lower case, any white space and non-word characters are removed. +% \item[\ttfamily 1: ] The author's and user's answers are converted to +% lower case, any white space is removed. +% \item[\ttfamily 2: ] The author's and user's answers are stripped of any +% white space. +% \item[\ttfamily 3: ] The author's and user's answers are converted to +% lower case only. \emph{This is the recommended value for this function.} +% \end{description} +% \item[\ttfamily\#3 :] Optional, a named destination to the solution to the +% question. If this parameter appears, then a solution must follow the +% question, enclosed in a \texttt{solution} environment. +% \item[\ttfamily\#4 :] This required parameter is the number of alternative +% answers that are acceptable. The alternative answers are listed +% immediately after this parameter. (The example above specified +% that $4$ alternatives follow.) +% \end{description} +% \begin{macrocode} +\begin{defineJS}[% + \catcode`\@=0\relax\catcode`\%=14\relax]{\AAKqRespBoxTxtPC} +if(event.willCommit){ + RecordPointValue(@eqPTs,@thequestionno@ifx@grpquestions1,% +@thegrpquestionno,@grpPointValue,@grpTotalWeight,% +"@grpEvalFunction"@fi); + RecordProblemType("@eqQT",@thequestionno); + var retn = ProcRespTxtPC(@rbTxtAlt); +@ifx@grpquestions1% + ProbValue[@thequestionno][3+@thegrpquestionno]% +=ProcRespTxtPC.txtPCpCr;@else% + ProbValue[@thequestionno]=ProcRespTxtPC.txtPCpCr;@fi + ProcUserResp(retn,event.value,@thequestionno,0% +@ifx@grpquestions1,@thegrpquestionno@fi); +} +if (!isQuizInitialized("@currQuiz")) { + @eqObjAlert@space eqAppAlert(InitMsg("@bqlabelISO"),3); + event.rc = false; +} +\end{defineJS} +\def\@@RespBoxTxtPCActions +{% + \AA{\if\eqQuizType\isQZ + \AAKeystroke{\AAKqRespBoxTxtPC} + \else + \AAKeystroke{% + if(event.willCommit) {\r\t + retn = ProcRespTxtPC(\rbTxtAlt);\r +\if\@sqTurnOffAlerts1% + \t\RespBoxTxtOnBlur\r +\fi + }% + } + \AAOnFocus{\JS{var retn = null;}} +\if\@sqTurnOffAlerts0% + \AAOnBlur{\JS{\RespBoxTxtOnBlur}}% +\fi + \fi + } +} +% \end{macrocode} +% Here is the beginning of \cs{RespBoxTxtPC}. +% \begin{macrocode} +\newcommand{\RespBoxTxtPC}{\def\rbFlag{0}\@RespBoxTxtPC} +\newcommand\@RespBoxTxtPC[1][] +{% + \eq@AddProbToQzQuesList + \smallskip\ifx\grpquestions\eq@Zero + \addtocounter{eqpointvalue}{\eqPTs}\fi + \if\eqQuizType\isQZ\def\rbFlag{1}\global\IsRespBoxtrue + \ifx\grpquestions\eq@One + \stepcounter{grpquestionno}% + \def\Fld@name{% + grpobj.\curr@quiz.\thequestionno.\thegrpquestionno}% + \else + \eq@recordThesePTs\eq@recordProbType + \edef\eqtmp{\aPointType}% + \xdef\aPointType{\eqtmp,[\eqPTs,"text"]}% + \stepcounter{questionno}% + \def\Fld@name{obj.\curr@quiz.\thequestionno}% + \fi + \else + \stepcounter{questionno}% + \def\Fld@name{obj.\oField.\thequestionno}% + \fi + \moreRespBoxTxtDefaults + \leavevmode\hbox\bgroup\text@@Field{#1}{\Fld@name}% + {\RBW}{\DefaultHeightOfWidget}% + {\eq@protect\AA}{\eq@setWidgetProps\@@RespBoxTxtPC}% + {\RespBoxTxtDefaults\@moreRespBoxTxtDefaults + \@@RespBoxTxtPCActions\every@eqTextField\every@RespBoxTxt}% +} +\def\@@RespBoxTxtPC#1{\@ifnextchar[{\@@@RespBoxTxtPC{#1}} + {\@ifstar{\@@@RespBoxTxtPC{#1}[\curr@quiz.\thequestionno]}% + {\@@@RespBoxTxtPC{#1}[]}}} +\def\@@@RespBoxTxtPC#1[#2]#3{\xdef\@qzsolndest{#2}% + \begingroup +% \end{macrocode} +% We make special definitions for retrieving the parameters. +% \begin{macrocode} + \def\rexpStr##1{\eqbs\eqbs\eqbs\eqbs##1}% + \def\\##1{\eqbs\eqbs\eqbs\eqbs##1}% + \def\word##1{\\b##1\\b}\def\any{@any@} + \gdef\rbTxtAlt{\rbFlag,#1,1}% force sub-string match + \global\let\txtAltList\@empty + \count0=#3 \ifnum\count0>0 \expandafter\@argReadPC\else + \PackageError{exerquiz}{% + The third required parameter of + \string\RespBoxTxtPC\MessageBreak + is required to be a positive integer. + You entered\MessageBreak #3\space instead} + {Enter a positive integer.}\fi +} +% \end{macrocode} +% \texttt{\#1=<num>}, partial credit for this answer, \texttt{\#2=word}. +% \begin{macrocode} +\newcommand\@argReadPC[2][0]{\xdef\jsTempArgs{\txtAltList}% + \ifx\txtAltList\@empty\xdef\txtAltList{["#2",#1]}\else + \xdef\txtAltList{\jsTempArgs,["#2",#1]}\fi\@@argReadPC} +\def\@@argReadPC{\advance\count0 by-1\relax + \ifnum\count0=0\relax + \def\eq@next{\endgroup + \xdef\rbTxtAlt{\rbTxtAlt,\txtAltList}% + \if\grpquestions\eq@Zero + \ifwithinMCFI + \xdef\s@veCorrAnsFCFI{[\txtAltList]}\else + \eq@recordCorrAns{[\txtAltList]}\fi + \else + \eq@recordGrpAnsArray{[\txtAltList]}% + \fi + \eq@@RespBoxTxtPC + }% + \else + \def\eq@next{\@argReadPC}% + \fi\eq@next +} +\def\eq@@RespBoxTxtPC{% + \ifeq@proofing\makebox[0pt][l]{\space\txt@correctAnswer}\fi + \eq@TextField +% \end{macrocode} +% Closing of the \cs{hbox} begun above. +% \begin{macrocode} + \egroup +} +% \end{macrocode} +% \end{macro} +%\subsection{Essay Fill-In} +% \begin{macro}{\RespBoxEssay} +% Here is a simple text field with a multi-line attribute for entering +% essay-type questions. This question will not be graded by JavaScript, +% of course; ideally, the response will be submitted to a CGI for storage +% in a database. The instructor can later bring up the student's response +% and assign a grade. +% \begin{macrocode} +\def\RespBoxEssayDefaults +{% + \BC{0 0 0}\W{1}\S{S}\Ff{\FfMultiline}\rawPDF{}% +} +\def\@@RespBoxEssayActions +{% + \AA{\if\eqQuizType\isQZ + \AAKeystroke{% + if(event.willCommit){\jsR\jsT + RecordPointValue(\eqPTs,\thequestionno);\jsR\jsT + RecordProblemType("\eqQT",\thequestionno);\jsR\jsT + }\jsR + if (!isQuizInitialized("\curr@quiz")) {\jsR\jsT + @eqObjAlert\space eqAppAlert(% + InitMsg("\bqlabelISO"),3);\jsR\jsT + event.rc = false;\jsR + }% + }% + \fi + } +} +\newcommand\RespBoxEssay[3][] +{% + \smallskip\addtocounter{eqpointvalue}{\eqPTs}% + \stepcounter{questionno}% + \mbox{\text@@Field{#1}{essay.\curr@quiz.\thequestionno}{#2}{#3}% + \edef\eqtmp{\aPointType}\xdef\aPointType{\eqtmp,[\eqPTs,"essay"]}% + {\eq@protect\AA}{\eq@setWidgetProps\@@RespBoxEssayActions + \eq@TextField}{\RespBoxEssayDefaults\every@eqTextField}}% +} +% \end{macrocode} +% \end{macro} +%\subsection{Fields that Support the Fill-Ins} +% \begin{macro}{\sqTallyBox} +% The \cmd{\sqTallyBox} holds the number of incorrect responses to the +% question. This box is not required to appear. If it does not +% appear, use \cmd{\RespBoxNT} to prevent the doc level JavaScript +% from trying to write a nonexistent text field. +% \begin{macrocode} +\let\@@sqTallyBoxActions\@empty +\@ifundefined{calcOrder}{% +\ifpdf\def\@@sqTallyBoxActions{% + \AA{\AAValidate{getTotalTally("\oField");}}}\fi}{} +\def\sqTallyBoxDefaults +{% + \BC{0 0 0}\W{1}\textColor{1 0 0 rg}\S{I}\Q{2}\Ff{\FfReadOnly} +} +\ifpdf\def\@@sqTallyBoxActions{% + \AA{\AAValidate{getTotalTally("\oField");}}}\else + \let\@@sqTallyBoxActions\@empty +\fi +\newcommand\sqTallyBox[1][] +{% + \mbox{\text@@Field{#1}{tally.\oField.\thequestionno}% + {\TBW}{\DefaultHeightOfWidget}% + {}{\eq@setWidgetProps\eq@TextField}% + {\sqTallyBoxDefaults\@@sqTallyBoxActions\every@eqTextField + \every@sqTallyBox}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\sqTallyTotal} +% This text field stores the tally total. Only used within the +% \texttt{shortquiz} environment. Takes on optional parameter; this +% parameter can be used to modify the appearance of the fields. +% \begin{macrocode} +\def\sqTallyTotalDefaults +{% + \rawPDF{}\W{1}\BC{0 0 0}\S{I}\textColor{1 0 0 rg}% + \Q{2}\Ff{\FfReadOnly}% +} +\def\@@sqTallyTotalActions +{% + \AA{% + \AAKeystroke{AFNumber_Keystroke(0,0,0,0,"",true);} + \AAFormat{AFNumber_Format(0,0,0,0,"",true);} + \AACalculate{% + AFSimple_Calculate("SUM",new Array("tally.\oField")); + }} +} +\newcommand\sqTallyTotal[1][] +{% + \mbox{\text@@Field{#1}{tallytotal.\oField}{\TBW}% + {\DefaultHeightOfWidget}{\eq@protect\AA}% +% {\eq@setWidgetProps\eq@calcTextField}% + {\eq@setWidgetProps\eq@TextField}% + {\sqTallyTotalDefaults\@@sqTallyTotalActions\every@eqTextField + \every@sqTallyTotal}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\CorrAnsButton} +% The \cmd{\CorrAnsButton} is a button macro which, when pressed, will +% display the correct answer for the user. This button is again +% optional. This macro takes one parameter and one optional parameter +%\begin{verbatim} +%#1 : the correct answer as the user should enter it. +%\end{verbatim} +% The value if \texttt{\#1} may be different from the parameter +% \texttt{\#2} in \cmd{\RespBox}; for example, if the answer is +% $x^2$, then \texttt{\#2} of \cmd{\RespBox} would be +% \texttt{pow(x,2)}; but the user would enter |x^2|. +% +% The optional parameter is specified by a star * followed by a +% name of a JavaScript function. The arguments of this JS function +% is the same as that of DisplayAnswer. For example, +%\begin{verbatim} +%\CorrAnsButton{convertFrac('#1','#2')}*{EvalCorrAnsButton}} +%\end{verbatim} +% The JavaScript function might be +%\begin{verbatim} +%function EvalCorrAnsButton(fieldname,theanswer) +%{ +% theanswer = eval(theanswer); +% DisplayAnswer(fieldname,theanswer); +%} +%\end{verbatim} +% Here, we call a function to evaluate the answer for us. +% \begin{macrocode} +\def\CorrAnsButtonDefaults +{% + \CA{\eq@local@CorrAnsButton}\W{1}\S{S} + \BC{0 0 0}\BG{.7529 .7529 .7529}\H{P} +} +\def\normalCABtnBC{0 0 0} + \def\qCorrAnsButtonActionHook + {% + \JS{% + \ifx\@qzsolndest\@empty\else + if (event.shift)\jsR\jsT + this.gotoNamedDest("\@qzsolndest");\jsR + else\jsR\jsT + \fi + \processJSfunc("Ans.\curr@quiz","\CorrectAns",\currQuiz); + }% + } + \def\sqCorrAnsButtonActionHook + {% + \JS{% +% \end{macrocode} +% Allow local definition the reset color for response boxes. The reset color +% is normally black (\cs{eqDefaultColor}). Now if \cs{sqCorrAnsResetBC} is none +% empty, we put it in as a property of the \cs{oField} object. +% \begin{macrocode} + \ifx\@qzsolndest\@empty\else + if (event.shift)\jsR\jsT + this.gotoNamedDest("\@qzsolndest");\jsR + else\jsR\jsT + \fi + \processJSfunc("obj.\oField.\thequestionno","\CorrectAns",% +\currQuiz); + }% + } +\newcommand\CorrAnsButton[1][]{\eq@@CorrAnsButton{#1}} +\def\eq@@CorrAnsButton#1#2{\bgroup\makeJSspecials % 1/12 + \@ifstar{\eq@@@CorrAnsButton{#1}{#2}}{% + \eq@@@CorrAnsButton{#1}{#2}{DisplayAnswer}}% +} +\def\eq@@@CorrAnsButton#1#2#3{\gdef\CorrectAns{#2}% + \def\processJSfunc{#3}% + \ifx\eq@ProcRespIntervals\g@processJSfunc % 01/11 + \let\@inmathwarn@SAVE\@inmathwarn\let\@inmathwarn\@gobble +% \end{macrocode} +% When the response function is \texttt{ProcRespIntervals}, there may be unbalanced parentheses, we'll +% pass \cs{CorrectAns} through \cs{pdfstringdef} to escape them. +% \begin{macrocode} + \pdfstringdef{\CorrectAns}{\CorrectAns}% + \let\@inmathwarn\@inmathwarn@SAVE\fi + \if\eqQuizType\isQZ\def\Fld@name{corr.\curr@quiz.\thequestionno}% + \else\def\Fld@name{corr.\oField.\thequestionno}\fi + \if\eqQuizType\isQZ + \edef\@@CorrAnsButtonActions{\noexpand\F{\FHidden}% + \ifx\@qzsolndest\@empty%\noexpand\BC{\normalCABtnBC}% + \else\noexpand\BC{\solution@Color}\fi + \noexpand\A{\noexpand\qCorrAnsButtonActionHook}}% + \ifeq@noquizsolutions\else + \mbox{\push@@Button{#1}{\Fld@name}{}{\DefaultHeightOfWidget}% + {\eq@protect\A}{\eq@setButtonProps\eq@Button@driver}% + {\CorrAnsButtonDefaults\@@CorrAnsButtonActions + \every@ButtonField\every@CorrAnsButton}}% + \fi + \else + \edef\@@CorrAnsButtonActions{% + \ifx\@qzsolndest\@empty%\noexpand\BC{\normalCABtnBC} + \else\noexpand\BC{\solution@Color}\fi + \noexpand\A{\noexpand\sqCorrAnsButtonActionHook}}% + \mbox{\push@@Button{#1}{\Fld@name}{}{\DefaultHeightOfWidget}% + {\eq@protect\A}{\eq@setButtonProps\eq@Button@driver}% + {\CorrAnsButtonDefaults\@@CorrAnsButtonActions + \every@ButtonField\every@CorrAnsButton}}% + \fi + \egroup +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\sqClearButton} +% This button will clear the tallyfields and change the color of +% the \cmd{\RespBox} back to \cmd{\defaultColorJS}. The button clears the fields +% based on the current value of \cmd{\oField}. This text macro is +% given its value when the optional parameter in the +% \texttt{shortquiz} environment is specified. +%\changes{v6.3g}{2008/10/13 } +%{% +% Fixed a problem with the clear button not setting the boundary color +% back to the default. I must have changed the name of an objective field, +% now, we say \texttt{this.getField("obj.\cs{oField}")}. +%} +% \begin{macrocode} +\def\sqClearButtonDefaults +{% + \CA{\eq@local@sqClearButton}\textColor{0 g}\F{\FPrint} + \BC{0 0 0}\BG{.7529 .7529 .7529}\W{1}\S{B}\Ff{\FfNoExport} +} +% \end{macrocode} +% In an attempt to supply some custom colors for the shortquiz, we +% define \cmd{\sqRespBoxResetColor}. It determines the clear +% \begin{macrocode} +\def\@@sqClearButtonActions +{% + \A{\JS{ProcessIt = false;\jsR + if ( typeof \oField\space== "undefined" )\jsR\jsT + \oField\space= new Object;\jsR + if (typeof appAlerts["\oField"] == "undefined")\jsR\jsT + appAlerts["\oField"] = new Object;\jsR + this.resetForm(new Array("mc.\oField","obj.\oField",% + "tally.\oField","grpobj.\oField"));\jsR + var f = this.getField("obj.\oField");\jsR +% \end{macrocode} +% Here, we give the user an opportunity to designate the color +% of the response boxes when they are reset by the \cs{sqClearButton}. +% The default is to use \cs{eqDefaultColor}. +% \begin{macrocode} + if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty +\defaultColorJS\else\defaultColorJSLoc\fi;\jsR + f = this.getField("grpobj.\oField");\jsR + if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty +\defaultColorJS\else\defaultColorJSLoc\fi;\jsR + f = this.getField("rbmarkup.\oField");\jsR + if ( f != null ) f.display=display.hidden;\jsR + \oField.Grp = {};\jsR + appAlerts["\oField"].bAfterValue=false;\jsR + ProcessIt=true;}% + } +} +\newcommand\sqClearButton[1][] +{% + \mbox{\push@@Button{#1}{clear.\oField}{}{\DefaultHeightOfWidget}% + {\eq@protect\A}{\eq@setButtonProps\eq@Button@driver}% + {\sqClearButtonDefaults\@@sqClearButtonActions\every@ButtonField + \every@sqClearButton}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\@PromptButton} +% The \cs{@PromptButton} is used to create a ``progressive-style'' question (for math fill-in). +% Some series of questions build on one another. You can use this button to show the solution +% for one problem, so the student can try the next problem. On clicking on the prompt button, +% the student cannot enter another answer in the text field, and the input that is already +% there will be the one that is counted has the student's response. +% \begin{macrocode} +\def\PromptButtonDefaults +{% + \CA{\eq@local@CorrAnsButton}\W{1}\S{S}\BC{0 0 0} + \BG{.7529 .7529 .7529}\H{P} +} +\newcommand{\promptButtonMsg}{% + "Would you like to see the correct answer at this time? "\r\t\t + + "Your current answer will be the one that will be scored. "\r\t\t + + "If you click on \\"Yes\\", + you will not be able to change your answer." +} +\newcommand{\AnsPromptBtnStr}{Answer:\space} +\def\PromptButtonActionHook +{% + \JS{% + if (!isQuizInitialized("\currQuiz")) {\r\t + eqAppAlert(InitMsg("\bqlabelISO"),3);\r\t + event.rc=false;\r + } else {\r\t + if ( !\currQuiz.oAlertCheck.bAfterValue ) {\r\t + var resp=eqAppAlert({\r\t\t + cMsg:\promptButtonMsg,\r\t\t + nIcon: 2, nType: 2,\r\t\t + cTitle: ("AcroTeX Prompt Message"),\r\t\t + oCheckbox: \currQuiz.oAlertCheck\r\t + });\r\t + }\r +% \end{macrocode} +% Correction to the if condition below +% \changes{v7.8d}{2017/01/11}{Correction to the if condition in \string\cs{PromptButtonActionHook}} +% \begin{macrocode} + if ( promptQuiz.oAlertCheck.bAfterValue || resp==4 )\r\t + {\r\t\t + var field=this.getField(% + "obj.\currQuiz.\thequestionno");\r\t\t + field.readonly=true;\r\t\t + field=this.getField("Ans.\currQuiz");\r\t\t + if (field!=null) + field.value = "\AnsPromptBtnStr\PromptAns";\r\t + }\r + } + }% +} +% \end{macrocode} +% This button takes the standard two arguments +% \begin{flushleft} +% \texttt{\#1}: Optional parameters to change the appearance of the field\\ +% \texttt{\#2}: Prompt answer +% \end{flushleft} +% \begin{macrocode} +\newcommand\@PromptButton[2][] +{% + \def\PromptAns{#2}\if\eqQuizType\isQZ + \def\Fld@name{promptButton.\curr@quiz.\thequestionno}% + \else\def\Fld@name{promptButton.\oField.\thequestionno}\fi + \if\eqQuizType\isQZ + \def\@@PromptButtonActions{% + \A{\PromptButtonActionHook}}% + \mbox{\push@@Button{#1}{\Fld@name}{}% + {\DefaultHeightOfWidget}{\eq@protect\A}% + {\eq@setButtonProps\eq@Button@driver}% + {\PromptButtonDefaults\@@PromptButtonActions + \every@ButtonField\every@CorrAnsButton}}% + \else\PackageWarning{exerquiz}{The \string\PromptButton + is for quiz questions only.} + \fi +} +% \end{macrocode} +% \end{macro} +% \DescribeMacro{\PromptButton} is the default definition of the \cs{PromptButton}, +% it can be redefined. The \cs{CorrectAns} command is defined in the +% \cs{CorrAnsButton} as the answer provided by the author. +% \begin{macrocode} +\newcommand{\PromptButton}{\makebox[0pt][r] % assumes xcolor + {\@PromptButton[\textColor{1 0 0 rg}]{\CorrectAns}}} +% \end{macrocode} +% \begin{environment}{mathGrp} +% An environment for enclosing a collection of math/text fill-ins that are to be grouped +% together. This grouping should not cross a begin or end of another environment, or include more +% an \cs{item}. This environment has two optional arguments: +%\begin{description} +% \item[\texttt{[\#1]}] : total weight (needed when sum of weight is greater than total number of points +% \item[\texttt{[\#2]}] : evaluation function, a JavaScript function to evaluate the user's responses. +% The default evaluation function is \texttt{groupEval}. +%\end{description} +% The way the parsing of the parameters works out, to specify \texttt{\#1}, you must specify +%\texttt{\#2}. +% \begin{macrocode} +\let\eq@ansGrpArray\@empty +\def\eq@recordGrpAnsArray#1{% + \ifx\eq@ansGrpArray\@empty + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\eq@ansGrpArray{#1}}\else + \edef\tmp@exp{\noexpand\g@addto@macro + \noexpand\eq@ansGrpArray{,#1}}\fi + \tmp@exp +} +\let\grpquestions\eq@Zero +\def\mathGrp{\global\let\eq@ansGrpArray\@empty + \@ifnextchar[{\@imathGrp}{\@imathGrp[groupEval]}} +\def\@imathGrp[#1]{\def\argi{#1}% + \@ifnextchar[{\@iimathGrp}{\@iimathGrp[]}} +\def\@iimathGrp[#1]{\def\argii{#1}% + \eq@AddProbToQzQuesList + \global\let\grpquestions\eq@One + \setcounter{grpquestionno}{0}% + \stepcounter{questionno}% + \xdef\beginGrp{\thequestionno}% + \xdef\grpPointValue{\eqPTs}% + \eq@recordThesePTs\eq@recordProbType + \if\eqQuizType\isQZ + \edef\eqtmp{\aPointType}% + \xdef\aPointType{\eqtmp,[\eqPTs,"grp"]}\fi + \addtocounter{eqpointvalue}{\eqPTs}% + \ifx\argii\@empty + \xdef\grpTotalWeight{\eqPTs}% + \xdef\grpEvalFunction{\argi}% + \else + \xdef\grpTotalWeight{\argi}% + \xdef\grpEvalFunction{\argii}% + \fi +} +\def\endmathGrp{\global\let\grpquestions\eq@Zero + \eq@recordCorrAns{[\eq@ansGrpArray]}% + \xdef\endGrp{\thequestionno}} +% \end{macrocode} +% \end{environment} +% \begin{macro}{\CorrAnsButtonGrp} +% The correct answer button for grouped questions. +% \begin{macrocode} +\def\CorrAnsButtonGrpDefaults +{% + \CA{\eq@local@CorrAnsButton}\W{1}\S{S}\BC{0 0 0} + \BG{.7529 .7529 .7529}\H{P} +} +\def\CorrAnsButtonGrpActionHook{\JS{% +\ifx\@qzsolndest\@empty\else + if (event.shift)\jsR\jsT + this.gotoNamedDest("\@qzsolndest");\jsR + else\jsR +\fi + {\jsR\jsT + var aCorrectAns=\CorrectAns;\jsR\jsT + var beginGrp = 1;\jsR\jsT + grpOffset = beginGrp;\jsR\jsT +% if ( typeof \currQuiz == "undefined" ) {\jsR\jsT\jsT +% \currQuiz = new Object;\jsR\jsT\jsT +% \currQuiz.Grp = {};\jsR\jsT +% }\jsR\jsT + if ( \currQuiz.Grp==null ) \currQuiz.Grp = {};\jsR\jsT + if (typeof \currQuiz.Grp["\thequestionno"]=="undefined")\jsR\jsT + {\jsR\jsT\jsT + \currQuiz.Grp["\thequestionno"] = {offset: 0};\jsR\jsT\jsT + var f = this.getField(% + "grpobj.\curr@quiz.\thequestionno." + + grpOffset)\jsR\jsT\jsT +% \end{macrocode} +% When the field is readonly, then we cannot set the focus. We'll remove the readonly, set focus, then +% reset readonly to true again; however, we must wait a little for \texttt{setFocus} to finish. +% \begin{macrocode} + if ( f.readonly ) {\jsR\jsT\jsT + f.readonly = false;\jsR\jsT\jsT + f.setFocus();\jsR\jsT\jsT + eqDelay = app.setTimeOut(% + "f.readonly = true; + app.clearTimeOut(eqDelay);",10);\jsR\jsT + } else f.setFocus();\jsR\jsT + }\jsR\jsT + else \jsR\jsT + {\jsR\jsT\jsT + \currQuiz.Grp["\thequestionno"].offset = + ++\currQuiz.Grp["\thequestionno"].offset + \% aCorrectAns.length;\jsR\jsT\jsT + grpOffset = beginGrp + + \currQuiz.Grp["\thequestionno"].offset;\jsR\jsT\jsT + var f = this.getField("grpobj.\curr@quiz.\thequestionno." + + grpOffset);\jsR\jsT\jsT + if ( f.readonly ) {\jsR\jsT\jsT + f.readonly = false;\jsR\jsT\jsT + f.setFocus();\jsR\jsT\jsT + eqDelay = app.setTimeOut("f.readonly = true; + app.clearTimeOut(eqDelay);",10);\jsR\jsT + } else f.setFocus();\jsR\jsT + }\jsR\jsT +\if\eqQuizType\isQZ + DisplayAnswer("Ans.\curr@quiz", + aCorrectAns[\currQuiz.Grp["\thequestionno"].offset],% +\currQuiz); +%\ifx\sqCorrAnsResetBC\@empty\else,\currQuiz\fi);\jsR +\else +% \end{macrocode} +% Allow local definition the reset color for response boxes. The reset color +% is normally black (\cs{eqDefaultColor}). Now if \cs{sqCorrAnsResetBC} is none +% empty, we put it in as a property of the \cs{oField} object. +% \begin{macrocode} +%\ifx\sqCorrAnsResetBC\@empty\else +% if ( typeof \oField=="undefined")\jsR\jsT\jsT +% var \oField = new Object;\jsR\jsT +% \oField.CorrAnsResetBC=\sqCorrAnsResetBC;\jsR\jsT +%\fi + DisplayAnswer("grpobj.\oField.\thequestionno."+ grpOffset, + aCorrectAns[\currQuiz.Grp["\thequestionno"].offset],% +\oField);\jsR +\fi + } +}} +\newcommand\CorrAnsButtonGrp[2][] +{% + \makeStringArray{#2}% + \edef\CorrectAns{\stringArray}% + \if\eqQuizType\isQZ\def\Fld@name{corr.\curr@quiz.\thequestionno}% + \else\edef\currQuiz{\oField}% + \def\Fld@name{corr.\oField.\thequestionno}\fi + \if\eqQuizType\isQZ + \edef\@@CorrAnsButtonGrpActions{\noexpand\F{\FHidden}% + \ifx\@qzsolndest\@empty%\noexpand\BC{\normalCABtnBC} + \else\noexpand\BC{\solution@Color}\fi + \noexpand\A{\noexpand\CorrAnsButtonGrpActionHook}}% + \ifeq@noquizsolutions\else + \mbox{\push@@Button{#1}{\Fld@name}{}{\DefaultHeightOfWidget}% + {\eq@protect\A}{\eq@setButtonProps\eq@Button@driver}% + {\CorrAnsButtonGrpDefaults\@@CorrAnsButtonGrpActions + \every@ButtonField\every@CorrAnsButton}}% + \fi + \else + \edef\@@CorrAnsButtonGrpActions{% + \ifx\@qzsolndest\@empty%\noexpand\BC{\normalCABtnBC} + \else\noexpand\BC{\solution@Color}\fi + \noexpand\A{\noexpand\CorrAnsButtonGrpActionHook}}% + \mbox{\push@@Button{#1}{\Fld@name}{}{\DefaultHeightOfWidget}% + {\eq@protect\A}{\eq@setButtonProps\eq@Button@driver}% + {\CorrAnsButtonGrpDefaults\@@CorrAnsButtonGrpActions + \every@ButtonField\every@CorrAnsButton}}% + \fi +} +\def\makeStringArray#1{\def\stringArray{[}\@makeStringArray#1,\@nil} +\def\@makeStringArray#1,#2\@nil{% + \edef\eq@temp{\stringArray}\def\argii{#2}% + \ifx\argii\@empty + \edef\stringArray{\eq@temp"#1"]}% + \def\eq@next{}% + \else + \edef\stringArray{\eq@temp"#1",}% + \def\eq@next{\@makeStringArray#2\@nil}% + \fi + \eq@next +} +% \end{macrocode} +% \end{macro} +% +% \section{Quiz Summary Tables} +% +% This code is designed for use with a \texttt{quiz}, as opposed to a +% \texttt{shortquiz}. Insert the command \cs{displaySumryTbl} after the +% end of the quiz, but before \verb!\end{quiz}!. The expansion of +% \cs{displaySumryTbl} is a table summarizing the user's effort on the +% quiz, indicating which questions had responses, and which did not. +%\par\medskip\noindent +% (06/08/10) We define \cs{eq@AddProbToQzQuesList}, which adds the current question label to +% the list \cs{eqQzQuesList}. The command \cs{@eqListExp} is initially defined +% to be \cs{relax} and is redefined just before \cs{eqQzQuesList} is expanded. +% \begin{macrocode} +\let\@eqListExp\relax +\let\@currentQues\@empty +\let\eqQzQuesList\@empty +\def\eq@AddProbToQzQuesList{% + \edef\eq@tmpExp{\noexpand\g@addto@macro% + \noexpand\eqQzQuesList{% + \noexpand\@eqListExp{\@currentQues}{\thepage}}}% +% \end{macrocode} +% We add to the list only if we are not within a \texttt{mathGrp} environment. +% \begin{macrocode} + \ifx\grpquestions\eq@Zero\eq@tmpExp\fi +} +% \end{macrocode} +% \begin{macrocode} +%</package> +%<*sumrytbls> +% \end{macrocode} +% The command below is convenience command to concatenate the current quiz with +% another string. The reason the parameter is enclosed in parenthesis is that +% the command is (sometimes) executed in a limited verbatim environment were the +% catcodes of our friendly braces have been changed. +% \begin{macrocode} +\def\ccatCurrQzWith(#1){\currQuiz#1} +% \end{macrocode} +% This is the JavaScript action for the push button \cs{pbPopulateSumTable}. +% The code is activated when the page becomes visible. The code reads through +% the Responses array and determines which questions were answered, and checks +% the appropriate box. (Version 6 or greater) +% \begin{macrocode} +% \end{macrocode} +% This zero width/height push button is hidden at the top of the table. When +% the page that contains the button, the JS is executes. +% \begin{macrocode} +\def\pbPopulateSumTable{\pushButton[\W0\BG{}\BC{}\S{S}\autoCenter{n} + \TU{\thequestionno}\Ff{\FfReadOnly} + \AA{\AAPageVisible{try{popVisitsTbl("\currQuiz",\thequestionno)}% + catch(e){}}}]{\currQuiz activateSC}{0pt}{0pt}} +% \end{macrocode} +% (2013/12/29) Here are some ideas to think about. Each change in the response to a question +% can execute the following code. I've put the needed information in the tooltip +% above, the code below extracts this information and calls \texttt{popVisitsTbl} +% in this way, the summary need to be required to appear on separate page. +%\begin{verbatim} +%f=this.getField("\currQuiz activateSC"); +%v=f.userName +%v=v.split(",") +%popVisitsTbl.apply(null,v) +%\end{verbatim} +% \begin{macrocode} +\def\pbDoNoCorrectSumryTbl{\makebox[0pt][l]{\pushButton[\F{\FHidden}]% + {\currQuiz NoCorrections}{0pt}{0pt}}} +% \end{macrocode} +% A scratch counter to count the number of row entries we have created. +% \begin{macrocode} +\newcount\eq@rowcnt +% \end{macrocode} +% \begin{macro}{\sumryTblQ} +% \begin{macro}{\sumryTblR} +% \begin{macro}{\sumryTblP} +% Through these commands, the author can change the title headings of the summary table. +% \begin{macrocode} +\newcommand{\sumryTblQ}{Question} +\newcommand{\sumryTblR}{Responded} +\newcommand{\sumryTblP}{Page} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\displaySumryTbl} +% Place this command between the end of the quiz \textbf{on a new page} (after the closing of the +% last \texttt{questions} environment and before \verb!\end{quiz}!. +% +% The \cs{displaySumryTbl} takes two parameters, one optional and one required. +%\begin{description} +% \item[{[\texttt{\#1}]}] is optional and takes key-value pairs +% \begin{itemize} +% \item \texttt{ntables}\IndexKey{ntables} is a key that has a value of 1, 2, or 3, the default is determined by +% \cs{smrytbl@ntables}, which is set to 2 in this package. If +% \texttt{ntables=1} only one table is created, and if \texttt{ntables=2} +% two tables are created, each containing half the information. +% \item \texttt{showmarkup}\IndexKey{showmarkup}: If this switch is true, then markup fields are +% created that will hold the number of points the student received for +% each problem. The default is there is no markup. Entering +% \texttt{showmarkup} in the option list will generate the markup fields. +% \item \texttt{nocorrections}\IndexKey{nocorrections}: If this switch is true, corrections will not +% be shown when the user presses the `End Quiz' button. +% \item \texttt{showOutOf}\IndexKey{showOutOf}: if taken the point and total points for the problem are displayed. +% For example, `2 of 5 pts'. +% \item \texttt{setDimens}\IndexKey{setDimen} is a key to pass its value within group created by +% the command \cs{displaySumryTbl}. Use it to use the conditional switches to set the +% dimensions of the markup text fields, color declarations, font declarations, etc. +% None of it should take up space of any kind. +% \end{itemize} +% \item[\texttt{\#2}] is the quiz this table represents, usually this is \cs{currQuiz}. +%\end{description} +% \begin{macrocode} +\define@key{smrytbl}{ntables}{% + \@tempcntb=#1 + \ifnum\@tempcntb<1 \@tempcntb=1 \fi + \ifnum\@tempcntb>3 \@tempcntb=3 \fi + \edef\smrytbl@ntables{\the\@tempcntb}% +} +\def\smrytbl@ntables{2} +\define@key{smrytbl}{showmarkup}[true]{% + \csname if#1\endcsname\eqshowmarkuptrue + \else\eqshowmarkupfalse\fi +} +\newif\ifsmrytbl@corrections\smrytbl@correctionstrue +\define@key{smrytbl}{nocorrections}[true]{% + \csname if#1\endcsname\smrytbl@correctionsfalse + \else\smrytbl@correctionstrue\fi +} +\define@key{smrytbl}{showOutOf}[true]{% + \csname if#1\endcsname\eqshowOutOftrue\def\stfmtType{OO}% + \gdef\showOutOfinSmryTbl{true}\let\stmarkupbox\relax + \else + \eqshowOutOffalse\let\stfmtType\@empty + \gdef\showOutOfinSmryTbl{false}% + \fi +} +\let\stfmtType\@empty +\define@key{smrytbl}{setDimens}[]{#1} +\def\showOutOfinSmryTbl{false} +\def\stmarkupbox{\makebox[0pt][l]} +% \end{macrocode} +% Finally we come to the definition of \cs{displaySumryTbl}. +% \begin{macrocode} +\newcommand{\displaySumryTbl}[2][]{% + \begingroup\edef\currQuiz{#2}\edef\oField{#2}\edef\curr@quiz{#2}% + \setkeys{smrytbl}{#1}% + \count0=\smrytbl@ntables +% \end{macrocode} +% We accept only 1 or 2 as an argument, we put it in \cs{count0}, +% if not an integer, we'll stop the compile. If the argument is not 1, +% we force a value of 2. +% \begin{macrocode} +% \ifnum\count0=1\relax\else\count0=2\relax\fi + \eq@rowcnt=0\relax\@tempcntb=\value{questionno}% +% \end{macrocode} +% We calculate the number of rows in the first column, in case +% of a two column table. When the number of questions is odd, +% the the left-hand table will have one more entry than the right-hand +% column. +% \begin{macrocode} + \ifnum\count\z@=2\relax + \divide\@tempcntb2\relax + \advance\@tempcntb\ifodd\value{questionno}2\else1\fi + \xdef\@beginSecCol{\the\@tempcntb}% + \advance\@tempcntb-1\relax + \fi +% \end{macrocode} +% Three table support +% \begin{macrocode} + \ifnum\count\z@=3 + \edef\eq@n{\the\@tempcntb}% + \divide\@tempcntb\count\z@ + \edef\eq@q{\the\@tempcntb}% + \@tempcnta=\@tempcntb\multiply\@tempcnta3 + \edef\eq@p{\the\@tempcnta}% + \@tempcnta=\eq@n + \advance\@tempcnta-\eq@p\relax + \ifnum\@tempcnta=0 + \@tempcntb=\eq@q \advance\@tempcntb1 + \xdef\@beginSecCol{\the\@tempcntb}% + \advance\@tempcntb\eq@q\relax + \xdef\@beginThrdCol{\the\@tempcntb}% + \else\ifnum\@tempcnta=1 + \@tempcntb=\eq@q \advance\@tempcntb1 + \edef\nB@lCols{\the\@tempcntb}% + \advance\@tempcntb1\relax + \xdef\@beginSecCol{\the\@tempcntb}% + \advance\@tempcntb\eq@q\relax + \xdef\@beginThrdCol{\the\@tempcntb}% + \else\ifnum\@tempcnta=2 + \@tempcntb=\eq@q \advance\@tempcntb1 + \edef\nB@lCols{\the\@tempcntb}% + \advance\@tempcntb1 + \xdef\@beginSecCol{\the\@tempcntb}% + \advance\@tempcntb\nB@lCols + \xdef\@beginThrdCol{\the\@tempcntb}% + \fi\fi\fi + \@tempcntb=\eq@n + \fi +% \end{macrocode} +% We \cs{let} \cs{@eqListExp} to \cs{@@eqListExp}, defined below. +% \begin{macrocode} + \let\@eqListExp\@@eqListExp +% \end{macrocode} +% \dots and expand the token list \cs{eqQzQuesList}. +% \begin{macrocode} + \eqQzQuesList + \endgroup +} +% \end{macrocode} +% \end{macro} +% \paragraph*{Construction of the table.} The construction is performed by \cs{@eqListExp}. +% This is a definition of \cs{@eqListExp}. It appears in the +% token list \cs{eqQzQuesList}. A typical entry in \cs{eqQzQuesList} is +% of the form +%\begin{verbatim} +% \@eqListExp{<question_label>}{\thepage} +%\end{verbatim} +% We use the two arguments to construct a table of three columns: Question (consisting +% of the question label); Responded (a checkbox that is checked if that question was answered); +% and Page (a hypertext link to the page containing he question). The command may be redefined +% to as needed.\medskip\par\noindent +% \textbf{Column headings} are defined by \cmd{\eq@begintab}. +% This can be redefined. We begin a \texttt{tabular} with +% headings (may be redefined). +% \begin{macrocode} +\def\eq@begintab{% + \begin{tabular}[t]{lcc}\sumryTblQ&\sumryTblR&\sumryTblP\\\sthline + {\Large\strut}% +} +% \end{macrocode} +% \DescribeMacro{\sthline}\cmd{\sthline} +% is a user hook to change the appearance of the horizontal line, such +% as adding color. +% \begin{macrocode} +\def\sthline{\hline} +% \end{macrocode} +% End of the \texttt{tabular}. +% \begin{macrocode} +\def\eq@endtab{\end{tabular}} +% \end{macrocode} +% \cs{@@eqListExp} is \cs{let} to \cs{@eqListExp} in \cs{displaySumryTbl}. +% \begin{macrocode} +\def\sumrytblCkMUsep{\kern3bp} +\def\sumrytbllinkHook#1{#1} +% \end{macrocode} +% \textbf{First Column.} \DescribeMacro{\sumryTblProbFmt}\cmd{\sumryTblProbFmt} +% sets the {\LaTeX} formatting for the problem numbers that appear in the +% first column of the table. +% \begin{macrocode} +\newcommand{\sumryTblProbFmt}[1]{\textbf{\textcolor{blue}{#1}}} +% \end{macrocode} +% A macro to set the separation between the tables. +% \begin{macrocode} +\newcommand{\sumrytablesep}{\space} +% \end{macrocode} +% We supply basic controls for the text field, width (\DescribeMacro{\stmarkupWidth}\cmd{\stmarkupWidth}), +% height (\DescribeMacro{\stmarkupHeight}\cmd{\stmarkupHeight}), and text size +% (\DescribeMacro{\stmarkupTextSize}\cmd{\stmarkupTextSize}) +% \begin{macrocode} +\def\stmarkupWidth{12bp}\def\stmarkupHeight{9bp}\def\stmarkupTextSize{0} +% \end{macrocode} +% \textbf{Second column.} The second column of the table consisting of a checkbox +% and stMarkup text field. +% \begin{macrocode} +\def\st@scndclmn{% + \checkBox[\Ff{\FfReadOnly}]% + {\ccatCurrQzWith(SanityCheck).\the\eq@rowcnt}% + {\markupHeight}{\markupHeight}{Yes}\ifeqshowmarkup + \stmarkupbox{\sumrytblCkMUsep\textField[% + \Ff\FfReadOnly\BC{}\textColor{\pcMarkupColor}% + \textSize{\stmarkupTextSize}\autoCenter{n}% +% \end{macrocode} +% Key to being able to have duplicated summary fields with different \texttt{showOutOf} +% options is the naming of the text field. If \texttt{showOutOf=false}, the default, +% the field name is \cs{currQuizSanityCheckPts}, but if \texttt{showOutOf=true}, the +% text field is named \cs{currQuizSanityCheckOOPts}. When the Correct button is pressed, +% the JavaScript function \texttt{correctSumryTbl()} checks for the existence of each of +% these two fields, and populates them properly formatted. The command \cs{stfmtType} is +% either \cs{empty} or \cs{OO}. +% \begin{macrocode} + ]{\ccatCurrQzWith(SanityCheck\stfmtType Pts).\the\eq@rowcnt}% + {\stmarkupWidth}{\stmarkupHeight}}\fi +} +% \end{macrocode} +% \textbf{Third column.} The third column of the table consisting of a link to the +% page that contains the question. +% \begin{macrocode} +\def\st@thrdclmn#1{% + \setLink[\linktxtcolor{\@linkcolor} + \A{\JS{this.pageNum=(#1-1)}}]{\sumrytbllinkHook{#1}}} +% \end{macrocode} +% Now for the definition of \cs{@@eqListExp} which does the work in the table. +% \begin{macrocode} +\def\@@eqListExp#1#2{\global\advance\eq@rowcnt1\relax +% \end{macrocode} +% If it is the first row, we insert the push button that will activate +% when the page becomes visible, and we expand \cs{eq@begintab}, which +% is a \texttt{tabular} environment. +% \begin{macrocode} + \ifnum\eq@rowcnt=1\relax + \pbPopulateSumTable\ifsmrytbl@corrections\else + \pbDoNoCorrectSumryTbl\fi\expandafter\eq@begintab\fi +% \end{macrocode} +% If it is the two table solution, and the row number equals the calculated +% value of the first row of the second table, we emit another +% \cs{eq@begintab}. +% \begin{macrocode} + \ifnum\count0>1 \ifnum\eq@rowcnt=\@beginSecCol\relax + \eq@endtab\expandafter\sumrytablesep\expandafter\eq@begintab + \fi\fi + \ifnum\count0=3 \ifnum\eq@rowcnt=\@beginThrdCol\relax + \eq@endtab\expandafter\sumrytablesep\expandafter\eq@begintab + \fi\fi +% \end{macrocode} +% We layout a row of the table, problem label, checkbox, and page. +% \begin{macrocode} + \sumryTblProbFmt{#1}&\st@scndclmn&\st@thrdclmn{#2}\\[1bp] +% \end{macrocode} +% We set the \cs{eq@endtab} at the bottom of the first table, +% and at the bottom of the second table. +% \begin{macrocode} +% \ifnum\count0=2 \ifnum\eq@rowcnt=\@tempcntb +% \expandafter\eq@endtab\fi\fi + \ifnum\eq@rowcnt=\thequestionno\relax\expandafter\eq@endtab\fi +} +% \end{macrocode} +% +% \subsection{Duplicating the Summary Table elsewhere} +% +% \begin{macro}{\writeProListAux} +% This command writes the information essential to the creation of +% the quiz summary table (\cs{displaySumryTbl}), and should be +% placed after the final question, and before the `End Quiz'. The purpose +% is to write the info to the auxiliary file so the table can be +% constructed elsewhere, for example, at the beginning of the quiz, or +% wherever desired. The command writes two macros to the aux file, +% \verb!\csname \currQuiz QzQuesList\endcsname! that contains the token +% list of problems using by the table, and +% \verb!\csname \currQuiz nQuestions\endcsname! that contains the +% total number of questions. +% \begin{macrocode} +\def\writeProListAux{% + \eq@IWAuxOut{\string\expandafter\string\gdef + \string\csname\space\currQuiz QzQuesList\string\endcsname + {\eqQzQuesList}}% + \eq@IWAuxOut{\string\expandafter\string\gdef + \string\csname\space\currQuiz nQuestions\string\endcsname + {\thequestionno}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +\def\setParamSumryTblAux{% + \edef\eqQzQuesList{\@nameuse{\currQuiz QzQuesList}}% + \@ifundefined{\currQuiz nQuestions}{}{% + \value{questionno}=\@nameuse{\currQuiz nQuestions}}% +} +% \end{macrocode} +% \begin{environment}{sumryTblAux} +% Normally, we use \cs{displaySumryTbl} right after the last question, and before +% the `End Quiz.' It is possible to display a summary table elsewhere, perhaps at the beginning +% of the quiz, on the first page, wherever. Assuming \cs{writeProListAux} jas beem +% inserted after the last question and before `End Quiz', you can then use the +% \texttt{sumryTblAux} environment to place the same table in another location. For example, +%\begin{verbatim} +% \begin{sumryTblAux}{demoQuiz} +% \begin{center} +% {\normalsize\sffamily\bfseries Quiz Summary Table}\\[3pt] +% \displaySumryTbl[showmarkup]{\currQuiz} +% \end{center} +% \end{sumryTblAux} +%\end{verbatim} +% The environment takes one parameter, the quiz name that this table +% represents. It uses \cs{setParamSumryTblAux} to set the appropriate +% variables that \cs{displaySumryTbl} uses. +% +% This environment \emph{is required} if the table appears outside the scope of the +% quiz. +% \begin{macrocode} +\newenvironment{sumryTblAux}[1]{% + \DeclareQuiz{#1}\setParamSumryTblAux}{}% +% \end{macrocode} +% \end{environment} +% \begin{macrocode} +%</sumrytbls> +% \end{macrocde} +% \subsection{Posing MC/math fill-in questions} +% \begin{macrocode} +%<*mcfi> +\def\bMCFI{% + \withinMCFItrue + \ifx\qRadionActionsHook\@empty + \let\qRadionActionsHook@SAVE\@empty + \def\qRadionActionsHook{\jsR + qRadioButtonMCFI(\Ans@choice,"\currQuiz",\thequestionno);}\else + \let\qRadionActionsHook@SAVE\qRadionActionsHook + \def\qRadionActionsHook{\qRadionActionsHook@SAVE\jsR + qRadioButtonMCFI(\Ans@choice,"\currQuiz",\thequestionno);}\fi + \ifx\every@RespBoxMath\@empty + \let\every@RespBoxMath@SAVE\@empty + \def\every@RespBoxMath{% + \AddAAKeystroke{mcfiKeyStroke("\currQuiz",\thequestionno);}}% + \else + \let\every@RespBoxMath@SAVE\every@RespBoxMath + \expandafter\def\expandafter\every@RespBoxMath\expandafter{% + \every@RespBoxMath@SAVE + \AddAAKeystroke{mcfiKeyStroke("\currQuiz",\thequestionno);}}% + \fi +} +\def\eMCFI{% + \ifx\qRadionActionsHook@SAVE\@empty + \let\qRadionActionsHook\@empty\else + \let\qRadionActionsHook\qRadionActionsHook@SAVE\fi + \ifx\every@RespBoxMath@SAVE\@empty + \let\every@RespBoxMath\@empty\else + \let\every@RespBoxMath\every@RespBoxMath@SAVE\fi + \withinMCFIfalse +} +\def\eqNA{-43252452452} +\@ifundefined{text}{\let\MCFIMarkup@BOX\mbox}{\let\MCFIMarkup@BOX\text} +\newcommand\mcfiMarkupfmt{\cgBdry + ${}^{\MCFIMarkup@BOX{\aeb@creditmarkup}}$} +\def\mcfiMarkup{\addtocounter{questionno}{-1}\mcfiMarkupfmt + \stepcounter{questionno}} +%</mcfi> +%<*package> +% \end{macrocode} +% \section{Input Language definitions and JS} +% Here is were we make the redefinitions of the above commands if +% a language option is specified. +% \begin{macrocode} +\LangRedefinitions +% \end{macrocode} +% We introduce the document-level JavaScript for exerquiz at this point. +% \begin{macrocode} +\input{aebjs.def} +% \end{macrocode} +% If the \texttt{usesumrytbls} option is taken, we input the code. +% \begin{macrocode} +\inputSumryTblCode +% \end{macrocode} +% If the \texttt{usemcfi} option is taken, we input the code. +% \begin{macrocode} +\inputMCFICode +% \end{macrocode} +% \begin{macrocode} +%</package> +% \end{macrocode} +% \section{eForms Support} +% \begin{macrocode} +%<*package> +% \end{macrocode} +% \begin{macro}{\solutionColor} +% This color is introduced at the pdfmark/rawPDF level. Define +% the color without commas. For example |\solutionColor{0 .6 0}| +% \begin{macrocode} +\newcommand{\solutionColor}[1]{\def\eq@argi{#1}\ifx\eq@argi\@empty + \def\solution@Color{\solutionColorDef}\else + \def\solution@Color{#1}\fi} +\newcommand{\solutionColorDef}{0 .6 0} +\solutionColor{\solutionColorDef} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +%<*eqcolor> +% \end{macrocode} +% +% \subsection{Color support} +% +% \begin{macrocode} +\def\eq@getCmdName#1#2{\edef#1{\expandafter\@gobble\string#2}} +\def\eq@getfirst#1#2\@nil{\def\eq@argi{#1}} +\def\eq@checkValidityModel#1{% + \if#1g\else\if#1r\else\if#1c\else + \PackageError{exerquiz} + {JavaScript does not support this model} + {Use a named color from one of the models gray, rgb, or cmyk.} + \fi\fi\fi +} +\def\eq@jsSetColorMsg#1#2{\PackageWarning{exerquiz} + {The argument `#2' of \string#1\MessageBreak + is not of the right form.\MessageBreak Using the default}} +\def\eqModelInfo#1#2{% + \uppercase{\def\eq@ucmodel{#1}}\def\eq@modelspec{#2}% + \eq@getfirst#1\@nil\eq@ResetModelForGray{\eq@argi}% + \eq@checkValidityModel{\eq@argi}% +} +\def\eq@ResetModelForGray#1{\if#1g\def\eq@ucmodel{G}\fi} +% \end{macrocode} +% We test for raw JS color in two ways, look for \texttt{["} or look for \texttt{co} +% as the first two tokens. +% \begin{macrocode} +\def\eq@checkRawJSColor#1{% + \edef\eq@argi{#1}\ifx\eq@argi\@empty + \def\eq@next{\let\eq@rawJSCol\eq@YES}\else + \def\eq@next{\expandafter\eq@@checkRawJSColor#1\@nil}\fi\eq@next +} +\def\eq@@checkRawJSColor#1#2#3\@nil{\let\eq@rawJSCol\eq@NO + \let\eqpredefineJSCol\eq@NO + \if[#1\if#2"\let\eq@rawJSCol\eq@YES\fi\fi + \ifx\eq@rawJSCol\eq@NO\if#1c\if#2o\let\eq@rawJSCol\eq@YES + \let\eqpredefineJSCol\eq@YES\fi\fi\fi +} +\def\eq@jsColorWXColori#1#2{\edef\eq@colorDefn{#2}% + \ifx\eq@colorDefn\@empty + \ifx\is@Defined\eq@YES + \edef\eq@colorDefn{\csname\cmdName Def\endcsname}\else + \PackageError{exerquiz}{JS color \string#1 has an + empty definition}{}\fi + \fi + \eq@checkRawJSColor{\eq@colorDefn}% + \ifx\eq@rawJSCol\eq@NO + \extractcolorspec{\eq@colorDefn}{\eq@tmp@color}% + \expandafter\eqModelInfo\eq@tmp@color + \edef#1{["\eq@ucmodel",\eq@modelspec]}% + \else\edef#1{\eq@colorDefn}\fi +} +\def\eq@jsColorWOXColori#1#2{\def\eq@colorDefn{#2}% + \ifx\eq@colorDefn\@empty + \ifx\is@Defined\eq@YES + \edef\eq@colorDefn{\csname cmdName Def\endcsname}\else + \PackageError{exerquiz}{JS color \string#1 has an + empty definition}{}\fi + \fi + \eq@checkRawJSColor{\eq@colorDefn}% + \ifx\eq@rawJSCol\eq@YES\edef#1{\eq@colorDefn}\else + \eq@jsSetColorMsg{#1}{#2}\fi +} +% \end{macrocode} +% \DescribeMacro{\jsColor} General command for defining a JavaScript Color, and support commands for +% \textsf{xcolor} and w/o \textsf{xcolor}. When \textsf{xcolor} is used, colors +% can be specified using the usual {\LaTeX} color methods: +%\begin{verbatim} +% \jsColor{\rghtColorJS}{blue} +% \jsColor{\rghtColorJS}{[cmyk]{0,1,0,0}} +%\end{verbatim} +% or the \emph{JavaScript format} can be used: +%\begin{verbatim} +% \jsColor{\rghtColorJS}{["RGB",0,0,1]} +% \jsColor{\rghtColorJS}{["CMYK",0,1,0,0} +%\end{verbatim} +% When \textsf{xcolor} is not used, only the JavaScript format is allowed. +% \begin{macrocode} +\def\jsColor#1#2{\eq@getCmdName{\cmdName}{#1}% + \let\is@Defined\eq@YES + \expandafter\ifx\csname\cmdName\endcsname\relax + \PackageWarning{exerquiz}{\string#1 is not a command used by + exerquiz.\MessageBreak Will define it anyway}% + \let\is@Defined\eq@NO\fi + \HyColor@IfXcolor{\eq@jsColorWXColori{#1}{#2}}% + {\eq@jsColorWOXColori{#1}{#2}}% +} +% \end{macrocode} +% \begin{macrocode} +%</eqcolor> +%<*package> +% \end{macrocode} +% Now input \texttt{eqcolor.def}. +% \changes{v7.8f}{2017/02/29}{Separated the color stuff into its own segment +% (\string\texttt{eqcolor})} +% \begin{macrocode} +\@ifundefined{jsColor}{% + \InputIfFileExists{eqcolor.def}{\PackageInfo{exerquiz} + {Inputting eqcolor.def}} + {\PackageError{exerquiz}{cannot find eqcolor.def} + {Refresh your file name database and try again.}} +}{} +% \end{macrocode} +% +% \subsection{Default Colors for Checks, Crosses, and Borders} +% +% These commands are used to define the colors for the checks, +% crosses and correct symbols. These are controlled by JavaScript, +% so use the correct syntax for defining colors here. +% +% The default colors for the above defined color declaration commands, the +% the default definitions of the color commands. The commands appear in pairs +% and are used in the second and third arguments of \cs{eq@jsColor}. +% \begin{macrocode} +\newcommand\rghtColorJSDef{["RGB", 0, .6, 0]} +\newcommand\rghtColorJS{\rghtColorJSDef} +\newcommand\wrngColorJSDef{color.red} +\newcommand\wrngColorJS{\wrngColorJSDef} +\newcommand\partialColorJSDef{color.blue} +\newcommand\partialColorJS{\partialColorJSDef} +\newcommand\defaultColorJSDef{color.black} +\newcommand\defaultColorJS{\defaultColorJSDef} +% \end{macrocode} +% The next command is special, it is used in the quiz environments to allow a localization +% of the color. Unlike the ones above, this can be specified within the body of the document. +% \begin{macrocode} +\let\defaultColorJSLoc\@empty +\let\defaultColorJSLocDef\@empty +\let\rghtColorJSLoc\@empty +\let\rghtColorJSLocDef\@empty +\let\wrngColorJSLoc\@empty +\let\wrngColorJSLocDef\@empty +\let\partialColorJSLoc\@empty +\let\partialColorJSLocDef\@empty +% \end{macrocode} +% \paragraph*{Symbol choice.} This is in support for changing check styles for quizzes +% These must be declared in the preamble. +% \begin{macrocode} +\def\chooseJSsymbol{\@ifstar{\let\eq@isstar\eq@YES\chooseJSsymboli} + {\let\eq@isstar\eq@NO\chooseJSsymboli}} +\def\chooseJSsymboli#1{\lowercase{\edef\eq@arg{#1}}% + \def\eq@carg{check}\ifx\eq@arg\eq@carg + \def\eq@retnStyle{style.ch}\else + \def\eq@carg{cross}\ifx\eq@arg\eq@carg + \def\eq@retnStyle{style.cr}\else + \def\eq@carg{diamond}\ifx\eq@arg\eq@carg + \def\eq@retnStyle{style.di}\else + \def\eq@carg{circle}\ifx\eq@arg\eq@carg + \def\eq@retnStyle{style.ci}\else + \def\eq@carg{star}\ifx\eq@arg\eq@carg + \def\eq@retnStyle{style.st}\else + \def\eq@carg{square}\ifx\eq@arg\eq@carg + \def\eq@retnStyle{style.sq}\else + \let\eq@retnStyle\@empty + \ifx\eq@isstar\eq@NO\PackageWarning{exerquiz} + {Argument `#1' not recognized.\MessageBreak + Permissible values are check, cross, diamond,\MessageBreak + circle, star, square. Will use the default}\fi + \fi\fi\fi\fi\fi\fi +} +% \end{macrocode} +% \begin{macro}{\setRightAnsSymb} +% The check style when the user is correct. (def: \texttt{style.ch}) +% \begin{macro}{\setCorrAnsSymb} +% The check style when the user is wrong but you are marking which response is correct. +% (def: \texttt{style.ci}) +% \begin{macro}{\setWrongAnsSymb} +% The check style when the use chooses the incorrect answer. +% (def: \texttt{style.cr}) +% \begin{macrocode} +%\def\defineAnsStyle#1#2{% +% \eq@getCmdName{\cmdName}{#1}\let\is@Defined\eq@YES +%} +\newcommand\setRghtAnsSymb[1]{\chooseJSsymbol{#1}% + \ifx\eq@retnStyle\@empty\else + \edef\rghtAnsSymbJS{\eq@retnStyle}% + \edef\rghtAnsSymb{\eq@carg}\fi} +\def\rghtAnsSymbJS{style.ch} +\def\rghtAnsSymb{check} +\newcommand\setCorrAnsSymb[1]{\chooseJSsymbol{#1}% + \ifx\eq@retnStyle\@empty\else + \edef\corrAnsSymbJS{\eq@retnStyle}% + \edef\corrAnsSymb{\eq@carg}\fi} +\def\corrAnsSymbJS{style.ci} +\def\corrAnsSymb{circle} +\newcommand\setWrngAnsSymb[1]{\chooseJSsymbol{#1}% + \ifx\eq@retnStyle\@empty\else + \edef\wrngAnsSymbJS{\eq@retnStyle}% + \edef\wrngAnsSymb{\eq@carg}\fi} +\def\wrngAnsSymbJS{style.cr} +\def\wrngAnsSymb{cross} +\def\setRghtAnsSymbLoc#1{\chooseJSsymbol*{#1}% + \ifx\eq@retnStyle\@empty + \let\rghtAnsSymbJSLoc\@empty\else + \edef\rghtAnsSymbJSLoc{\eq@retnStyle}\fi +} +\def\setCorrAnsSymbLoc#1{\chooseJSsymbol*{#1}% + \ifx\eq@retnStyle\@empty + \let\corrAnsSymbJSLoc\@empty\else + \edef\corrAnsSymbJSLoc{\eq@retnStyle}\fi +} +\def\setWrngAnsSymbLoc#1{\chooseJSsymbol*{#1}% + \ifx\eq@retnStyle\@empty + \let\wrngAnsSymbJSLoc\@empty\else + \edef\wrngAnsSymbJSLoc{\eq@retnStyle}\fi +} +\let\rghtAnsSymbJSLoc\@empty +\let\rghtAnsSymbJSLocDef\@empty +\let\corrAnsSymbJSLoc\@empty +\let\corrAnsSymbJSLocDef\@empty +\let\wrngAnsSymbJSLoc\@empty +\let\wrngAnsSymbJSLocDef\@empty +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \subsection{``Every'' Definitions} +% \begin{macrocode} +\newcommand\everyeqTextField[1]{\def\every@eqTextField{#1}} +\def\every@eqTextField{} +\newcommand\everyRespBoxMath[1]{\def\every@RespBoxMath{#1}} +\def\every@RespBoxMath{} +\newcommand\everyRespBoxTxt[1]{\def\every@RespBoxTxt{#1}} +\def\every@RespBoxTxt{} +\newcommand\everyrbMarkup[1]{\def\every@rbMarkup{#1}} +\def\every@rbMarkup{} +\newcommand\everysqTallyBox[1]{\def\every@sqTallyBox{#1}} +\def\every@sqTallyBox{} +\newcommand\everysqTallyTotal[1]{\def\every@sqTallyTotal{#1}} +\def\every@sqTallyTotal{} +\newcommand\everyScoreField[1]{\def\every@ScoreField{#1}} +\def\every@ScoreField{} +\newcommand\everyAnswerField[1]{\def\every@AnswerField{#1}} +\def\every@AnswerField{} +\newcommand\everyPointsField[1]{\def\every@PointsField{#1}} +\def\every@PointsField{} +\newcommand\everyPercentField[1]{\def\every@PercentField{#1}} +\def\every@PercentField{} +\newcommand\everyGradeField[1]{\def\every@GradeField{#1}} +\def\every@GradeField{} +% \end{macrocode} +% \begin{macro}{\AddAAFormat} +% Here is the definition of \cs{AddAAFormat}. This macro can be used +% in \cs{RespBoxMath} to add in formatting of the answer. This macro is +% necessary because the \cs{AA} actions for the \textsf{exerquiz} quiz macros +% are ``protected''; the document author cannot accidentally overwrite my +% JavaScript for processing the user's answer. +% \begin{flushleft} +% Example: In the preamble +%\begin{verbatim} +%\begin{defineJS}{\formatAsSet} +%if (event.value.replace(/\\s/g,"") != "") +% event.value = "{ " + event.value + " }"; +%\end{defineJS} +%\end{verbatim} +% and in the body of a \texttt{quiz} environment, +%\begin{verbatim} +%$x^2 - 3x + 2 = 0$, $S = \RespBoxMath[\AddAAFormat{\formatAsSet} +% \rectW{.75in}\textSize{0}]{1,2}{1}{.0001}{[0,1]}*{ProcRespSetNum}$ +%\end{verbatim} +%\end{flushleft} +% \begin{macrocode} +\def\@eqAddAAFormat#1{\def\eqFormatArg{#1}} +\def\eq@AddAAFormat{} +\def\formatAsSet{try{formatAsSet()}catch(e){}} +\def\formatAsVector{try{formatAsVector()}catch(e){}} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\AddAAKeystroke} +% The value of this key is JS code that executes after the input box has been processed. +% Created to use with AcroFleX for showing graphs after the user enters a response. +% +%\changes{v6.3b}{2008/06/29} +%{ +% Added the \cs{AddAAKeystroke} to the recognizable set of keys. This will be obeyed +% within the optional arguments of \cs{RespBoxMath}. +%} +% \begin{macrocode} +\def\@eqAddAAKeystroke#1{\def\argi{#1}\ifx\argi\@empty + \def\eqAAKeystrokeArg{}\else\def\eqAAKeystrokeArg{\r #1}\fi} +\def\eqAAKeystrokeArg{} +% \end{macrocode} +% \end{macro} +% \begin{macro}{\everysqRadioButton} +% \begin{macro}{\everyqRadioButton} +% Here, you can control the appearance of all the standard checkboxes, also +% effects radio fields of \texttt{shortquiz} and \texttt{quiz}. +% \begin{macro}{\everyqckCheckBox} +% (2010/07/30) Added \cs{everyqckCheckBox} to control the appearance +% of the underlying checkbox for \texttt{manswers} environments. +% Previously \cs{everyqRadioButton} was used, but this is the same as used by +% multiple choice. To get control over \texttt{manswers} when \cs{useMCCircles} +% and \cs{useMCCRects} \texttt{manswers} needs it one ``every'' command. +% \begin{macrocode} +\newcommand{\everysqRadioButton}[1]{\def\every@sqRadioButton{#1}} +\def\every@sqRadioButton{} +\newcommand{\everyqRadioButton}[1]{\def\every@qRadioButton{#1}} +\def\every@qRadioButton{} +\newcommand{\everyqckCheckBox}[1]{\def\every@qckCheckbox{#1}} +\def\every@qckCheckbox{} +% \end{macrocode} +% \begin{macro}{\everyqCheckBox} +% (12/08/2008) Added \cs{everyqCheckBox}, this is used only for the check boxes +% that hold the answer of a multiple choice question, not a multiple selection +% problem. This change is needed to create a circle radio button, in this case +% we need to make the boundary of the check box to 0 width. +% \begin{macrocode} +\newcommand{\everyqCheckBox}[1]{\def\every@qCheckBox{#1}} +\def\every@qCheckBox{} +\newcommand{\everysqCheckBox}[1]{\def\every@sqCheckBox{#1}} +\def\every@sqCheckBox{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% Here, you can control the appearance of all the standard buttons. +% \begin{macrocode} +\let\everyeqButtonField\everyButtonField +\newcommand\everyCorrAnsButton[1]{\def\every@CorrAnsButton{#1}} +\def\every@CorrAnsButton{} +\newcommand\everysqClearButton[1]{\def\every@sqClearButton{#1}} +\def\every@sqClearButton{} +\newcommand\everyeqButton[1]{\def\every@eqButton{#1}} +\newcommand\everyCorrButton{\everyeqButton} +\def\every@eqButton{} +\newcommand\everyBeginQuizButton[1]{\def\every@BeginQuizButton{#1}} +\def\every@BeginQuizButton{} +\newcommand\everyEndQuizButton[1]{\def\every@EndQuizButton{#1}} +\def\every@EndQuizButton{} +% Replace everyeqGenButten with everyPushButton +\let\everyeqGenButton\everyPushButton +\let\every@eqGenButton\every@PushButton +\newcommand\everyeqIcon[1]{\def\every@eqIcon{#1}} +\def\every@eqIcon{} +% dps new +\let\eqGenButton\pushButton +% \end{macrocode} +% \begin{macro}{\eqIcon} +% Create a push button for displaying an icon. I've set this on read only, this +% can be removed by saying \verb+\Ff{-\FfReadOnly}+/ +%\begin{verbatim} +% #1 = optional, used to enter any modification of the appearance/actions +% #2 = the title of the button field +% #3 = the width of the bounding rectangle +% #4 = the height of the bounding rectangle +%\end{verbatim} +% \begin{macrocode} +\def\eqIconDefaults +{% + \rawPDF{}\S{}\mkIns{/TP 1}\W{} + \CA{}\RC{}\AC{}\BC{}\BG{}\H{N} + \textColor{0 g}\Ff{\FfReadOnly} +} +\newcommand\eqIcon[4][] +{% + \mbox{\push@@Button{#1}{#2}{#3}{#4}{}{\eq@setButtonProps + \eq@Button@driver}{\eqIconDefaults\every@ButtonField + \every@eqIcon}}% +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \section{Document Level JavaScripts} +% +% The \texttt{insDLJS} package is used to insert the JavaScript at +% the document level. This package makes all necessary +% driver-dependent conversions, we just write the JavaScript code, +% which is hard enough. +% +% \begin{macrocode} +%<*aebjs> +% \end{macrocode} +% \begin{macrocode} +\def\aeb@array{new Array} +% \end{macrocode} +% The following definitions are associated with \texttt{requireForm()}, the JS function +% defined below. +% \begin{macrocode} +%\newcommand{\defaultReqFormMsg}{% +% "The expression is not in the expected form."} +% \end{macrocode} +% (07/16/11) Some definitions that may be used by \texttt{requireForm}, a \cs{RespMathBox} filter +% \begin{macrocode} +%\def\refac(#1){\\(#1\\)}\def\regrp(#1){(#1)}\def\rechrclass(#1){[#1]} +\def\refac#1{\\(#1\\)}\def\regrp#1{(#1)}\def\rechrclass#1{[#1]} +\def\redm{\\.}\def\remul{\\*}\def\rediv{\\/}\def\repow{\\^} +\def\redigit{\\d}\def\reany{.}\def\rebstr{\string^}\def\reestr{\string$} +% \end{macrocode} +% \begin{macro}{\preDenyForm} +% \begin{macro}{\preReqForm} +% \begin{macro}{\postDenyForm} +% (10/07/11) Some convenience commands to simplifying the use of the \texttt{priorParse} +% and \texttt{postParse} filters. +% \begin{macrocode} +%\def\preDenyForm(#1){\Array(denyForm,#1)} +%\def\preReqForm(#1){\Array(requireForm,#1)} +%\def\postDenyForm(#1){\Array(requireFormNot,#1)} +\def\preReqForm{\Array(requireForm,\@gobble} +\def\preDenyForm{\Array(denyForm,\@gobble} +\def\postDenyForm{\Array(requireFormNot,\@gobble} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \DescribeMacro{\noPeekArgs}\cmd{\noPeekArgs} is used to modify the arguments +% of the no peeking alert box. +% \begin{macrocode} +\newcommand{\noPeekArgs}[1]{% + \def\NoPeekAlert{eqAppAlert(#1)}}\def\newNoPeekArgs{} +\def\NoPeekAlert{eqAppAlert(\noPeekMsg,3)} +% \end{macrocode} +% \begin{macrocode} +\newcommand{\dlLibSpecRespJS}{"none","undefined","empty"} +\begin{insDLJS*}[exerquizLoaded]{exerquiz} +% \end{macrocode} +% \subsection{Global Data} +% Global data and some miscellaneous definitions +% \begin{macrocode} +\begin{newsegment}{AeB: AcroTeX eDucation Bundle} +/* + Document Level JavaScript + AcroTeX eDucation Bundle + D. P. Story copyright 2000-\the\year +*/ +var exerquizLoaded = true; +this.disclosed = true; +app.runtimeHighlight=false; +\end{newsegment} +\begin{newsegment}{Eq: Global Data} +var ok2Continue = true; +% \end{macrocode} +% The global variable \texttt{ProcessIt} is really used only once. In the +% function \texttt{DisplayAnswer()}. The function is called by the correct +% answer button. It sets \texttt{ProcessIt = false}, then it inserts the correct +% answer into the text field. A \texttt{false} value of \texttt{ProcessIt} +% prevents the \texttt{ProcResp} (and others) from from processing the answer. +% +% The arrays \texttt{RightWrong}, \texttt{ProbValue}, \texttt{ProbDist} and \texttt{ProbType} maintain quiz information +% for a quiz. The following are typical values of these arrays. This is a quiz taken +% from the manswer.tex demo file. Question 1 is a multiple selection question; Question 2 +% is a multiple choice question; Question 3 is a math fill-in question; and Question 4 +% is a grouped question. (The \texttt{undefined} entries indicate an empty or a not used entry.) +%\begin{verbatim} +%RightWrong.toSource() +%[undefined, [0, 1, [undefined, undefined, 0, 1, 1, 0, 1]], 1, 1, +% [undefined, 1, 1, 1, 0]] +% +%Responses.toSource() +%[undefined, [undefined, undefined, "b", "c", "d", "e", "f"], "a", "cos(x)", +% [undefined, "0", "4", "1", "9"]] +% +%ProbValue.toSource() +%[undefined, [3, 5, [undefined, undefined, -2, 3, 3, -2, 3]], [0, 3, 0], 3, +% [1, "groupEval", 4, 4, 1, 1, 1, 1]] +% +%ProbDist.toSource() +%[undefined, 5, 3, 3, 3] +% +%ProbType.toSource() +%[undefined, "na", "na", "na", "na"] +% +%aPointType.toSource() +% [undefined, [2, "mc"], [4, "ms"], [2, "text"], [4, "math"], [4, "grp"]] +%\end{verbatim} +% \begin{macrocode} +var ProcessIt = true; +var retn; +var Score=0; +var ptScore=0; +var pcScore=0; +var quizGrade="C"; +var e = Math.E; +var pi = Math.PI; +var replaceExclaim = \replaceexclaim; +var negPointsAllowed = \negpointsallowed; +var negPointsMarkupAllowed = \negpointsmarkupallowed; +var aQuizControl = new Array(); +var RightWrong=new Array(); +var ProbValue = new Array(); +var ProbDist = new Array(); +var ProbType = new Array(); +var Responses=new Array(); +var appAlerts = new Object; +var _mathVars="x"; +var _ModalNotOn=true; +var GradeScaleDefault=new Array(\eqGradeScale); +var aDlLibSpecResp=new Array(\dlLibSpecRespJS); +% \end{macrocode} +% JSf is an array of supported mathematical functions. +%\changes{v6.06}{2007/02/23} +%{ +% Separated the \texttt{JSf} array into \texttt{JSfBuiltIn} and \texttt{JSfCustom}. This +% allows us to identify the built-in JavaScript functions. I concatenate these two +% into \texttt{JSf}. +%} +% \begin{macrocode} +var JSfBuiltIn = new Array + ( "abs","acos","asin","atan","ceil", "floor","cos","exp", + "log","max","min","pow","random","round","sin", + "sqrt","tan"); +% \end{macrocode} +%\changes{v6.3c}{2008/07/03} +%{ +% Added the hyperbolic functions and inverse hyperbolic functions +%} +% Additional function recognized by exerquiz. Note to self, when adding +% functions, if one function is a substring of another, list the function +% with the longer name first. Searching is done in the order the functions +% are listed in this array. +%\changes{v6.3o}{2010/05/24} +%{ +% Modification of the array structure for supported JS functions, due to +% Robert Marik. He writes, ``arcsin(x), arccos(x) and arctan(x) are not +% recognized properly when implmulti from dljslib is active. I think that +% the problem is caused by the fact that arcsin(x) follows sin(x) in the +% field of known functions and converted into arc*sin(x) and then into +% a*r*c*sin(x). I enclose the patch for the exerquiz.dtx file which in my +% opinion solves the problem.'' +%} +% \begin{macrocode} +var JSfCustomEarly = new Array ("arctan", "arcsin", "arccos") +var JSfCustomLate = new Array + ( "logc", "ln","sec","csc","cot", + "asinh", "acosh","atanh","acoth","asech","acsch", + "sinh", "cosh","tanh","coth","sech","csch","sgn", + "C","P","fact","pi"); +var JSf = new Array().concat(JSfCustomEarly, JSfBuiltIn, JSfCustomLate); +var JSfCustom = new Array().concat(JSfCustomEarly, JSfCustomLate); +var JSc = new Array("PI","E") +% \end{macrocode} +% Additional functions that I've defined. +% \begin{macrocode} +function ln(x) { return Math.log(x); } +function sec(x) { return 1/Math.cos(x); } +function csc(x) { return 1/Math.sin(x);} +function cot(x) { return Math.cos(x)/Math.sin(x); } +function arctan(x) { return Math.atan(x); } +function arcsin(x) { return Math.asin(x); } +function arccos(x) { return Math.acos(x); } +function logc(x) { return Math.LOG10E * Math.log(x); } +function C(x,y) {return ch(x,y);} +function P(x,y) {return perm(x,y);} +% \end{macrocode} +% Additional functions that I've defined. (07/03/08) +% \begin{macrocode} +function sinh(x) { return ( Math.exp(x) - Math.exp(-x) )/2; } +function cosh(x) { return ( Math.exp(x) + Math.exp(-x) )/2; } +function tanh(x) { + return (Math.exp(x)-Math.exp(-x))/(Math.exp(x)+Math.exp(-x)); } +function coth(x) { + return ( Math.exp(x)+Math.exp(-x))/(Math.exp(x)-Math.exp(-x)); } +function sech(x) { return 2/( Math.exp(x) + Math.exp(-x) )/2; } +function csch(x) { return 2/( Math.exp(x) - Math.exp(-x) )/2; } +function asinh(x) { return Math.log (x+Math.sqrt(Math.pow(x,2)+1)); } +function acosh(x) { + return Math.log (x+Math.sqrt(Math.pow(x,2)-1)); } // x ge 1 +function atanh(x) { return .5*Math.log ((1+x)/(1-x)); } // -1 < x < 1 +function acoth(x) { return atanh(1/x); } // |x| > 1 +function asech(x) { return acosh(1/x); } // 0 < x le 1 +function asch(x) { return asinh(1/x); } // x ne 0 +function acsch(x) { return asinh(1/x); } // x ne 0 +function sgn(x) { return (x==0?0:(x<0?-1:1)) }; +% \end{macrocode} +% The aGroup array lists left and right grouping delimiters. This array is +% used by ParseInput() to call CkBalP(). +% \begin{macrocode} +var aGroup = new Array + ( ["\(","\)",\eqParens], + ["[","]",\eqBrackets], + ["{","}",\eqBraces] + ); +\end{newsegment} +% \end{macrocode} +% \subsection{Math Fill-in} +% This section of the code is primarily dedicated to processing the math fill-in questions. +% \begin{macrocode} +\begin{newsegment}{Eq: Support for Math Fill-in} +% \end{macrocode} +% A custom alert box that uses \texttt{\_ModalNotOn} to alert when the modal alert +% box is displayed. When \texttt{!\_ModalNotOn} is true, there is an alert box being +% displayed. +%\changes{v6.9}{2014/10/05}{Added eqAppAlert} +% \begin{macrocode} +var _mto; +function eqAppAlert(args) { + _ModalNotOn = false; + var retn=app.alert(args); + _mto= app.setTimeOut("_ModalNotOn = true", 100); +% \end{macrocode} +% Add a return to eqAppAlert, needed for the prompt button +% \changes{v7.8d}{2017/01/11}{Add a return to eqAppAlert} +% \begin{macrocode} + return retn; +} +% \end{macrocode} +% Description: Checks for balanced grouping delimiters. +% Arguments: +%\begin{enumerate} +% \item \texttt{UserInput}: A string +% \item \texttt{lDelimiter}: left delimiter +% \item \texttt{rDelimiter}: right delimiter +%\end{enumerate} +% Returns: \texttt{true} (if balanced); \texttt{false} (if not) +% \begin{macrocode} +function CkBalP(UserInput,lDelimiter,rDelimiter) +{ + var Lcount=0, Rcount=0; + for (var k=0; k < UserInput.length; k++) + { + if (UserInput.charAt(k) == lDelimiter) Lcount++; + else if (UserInput.charAt(k) == rDelimiter) Rcount++; + } + return (Lcount==Rcount); +} +% \end{macrocode} +% Description: This function simply determines if there are an even number of +% `\verb+|+' chars. Used for parsing absolute value. +% \verb=| x+2 | --> abs(x+2)=.\\ +% Arguments:\\ +% \texttt{UserInput}: a string\\ +% Returns: \texttt{true} (if even); \texttt{false} (if odd) +% \begin{macrocode} +function CkBalVert(UserInput) +{ + var Lcount=0; + for (var k=0; k < UserInput.length; k++) + if (UserInput.charAt(k)=="|") Lcount++; + return (Lcount \% 2 == 0); +} +% \end{macrocode} +% Description: This function searches for alpha words and matches them against supported +% mathematical functions.\\ +% Arguments:\\ +% \texttt{UserInput}: a string\\ +% Returns: 1 (if there is a match); 0 (if no match) +% also sets the global variable \texttt{ok2Continue} to \texttt{false}. +% \changes{v6.4c}{2011/07/01}{Ckfunc now uses a global variable \texttt{\_mathVars} which +% holds the variables of the current \cs{RespBoxMath} being processed. We search +% all substrings containing 2 or more letters; if it consists only of the variables +% that substring is OK.} +% \begin{macrocode} +function Ckfuncs(UserInput) +{ + var re, rei, reii; + re = /[a-zA-Z]{2,}/g; + reii=/r:|i:|,/g +% \end{macrocode} +% Get \texttt{\_mathVars}, and remove special formatting, new variable \texttt{\_v}. +% \begin{macrocode} + var _v=_mathVars.replace(reii,""); +% \end{macrocode} +% Define a regular expression that will return null if the string +% contains only letters from the variable list \texttt{\_v}. +% \begin{macrocode} + rei=new RegExp("[^"+_v+"]", "g"); + aF = UserInput.match(re); + if ( aF == null ) return true; + for (var i=0; i < aF.length; i++) + { +% \end{macrocode} +% If the current string contains only variables, move on to the next string +% \begin{macrocode} + if ( rei.exec(aF[i]) == null ) continue; + for(var j=0; j < JSf.length; j++) + if ( aF[i].indexOf(JSf[j]) != -1 ) break; + if (j < JSf.length) continue; + for(var j=0; j < JSc.length; j++) + if ( aF[i].indexOf(JSc[j]) != -1 ) break; + if(j==JSc.length) + { + eqAppAlert(\eqerrBadMathFunc,3); +% \end{macrocode} +% 09/07/09 added the next line, this could change behavior. We try to signal +% that an alert box has already been displayed, don't display another one. +% \begin{macrocode} + ok2Continue=false; + return false; + } + } + return true; +} +% \end{macrocode} +% This function displays the answer. +% \begin{macrocode} +function DisplayAnswer(fieldname,theanswer) +{ + ProcessIt = false; + var oDefault; + if (arguments.length > 2 ) + var oQName = arguments[2]; + else var oQName = oDefault; + if (typeof oQName=="undefined") + var oQName = new Object; + var defaultColor=(typeof oQName.DefaultColorJSLoc=="undefined")% +?\defaultColorJS:oQName.DefaultColorJSLoc; + try { + this.getField(fieldname).value=(theanswer); +% this.getField(fieldname).strokeColor = defaultColor; + } catch(e) {} + ProcessIt = true; +} +function EvalCorrAnsButton(fieldname,theanswer) +{ + theanswer = eval(theanswer); + DisplayAnswer(fieldname,theanswer); +} +% \end{macrocode} +% Finds and returns the position of the matching parentheses. +% \begin{macrocode} +function FindBalP(UserInput,Poff,Forward) +{ + var j,depth; + if (Forward) + { + for (depth=-1, j=Poff+1; depth !=0; j++) + { + if ( j > UserInput.length) return null; + if (UserInput.charAt(j)=="\(") depth--; + else if (UserInput.charAt(j)=="\)") depth++; + } + j-- + } + else + { + for (depth=-1, j=Poff-1; depth !=0; j--) + { + if ( j < 1 ) return null; + if (UserInput.charAt(j)=="\)") depth--; + else if (UserInput.charAt(j)=="\(") depth++; + } + j++ + } + return j; +} +% \end{macrocode} +% Remove white spaces from \texttt{UserInput}. +% \begin{macrocode} +function stripWhiteSpace (UserInput) +{ + UserInput = UserInput.replace(/\s/g,""); + if(UserInput==null || UserInput.length==0) + { + ok2Continue = false; + return false; + } else return UserInput; +} +function stripOutMuli (UserInput) +{ + UserInput = UserInput.replace(/\*/g,""); + return UserInput; +} +% \end{macrocode} +% This function takes its argument, and adds in the suffix of \texttt{Math.} +% in front of every recognizable JS built-in functions. +% \begin{macrocode} +function addMathObject(UserInput) +{ + for ( var i=0; i < JSfBuiltIn.length; i++) { + var re = new RegExp("\\b("+JSfBuiltIn[i]+")\\b","g"); + UserInput = UserInput.replace(re,"Math.$1"); + } + re = /\b(PI)\b/g; + UserInput = UserInput.replace(re,"Math.$1"); + return UserInput; +} +% \end{macrocode} +% +% \paragraph{ParseInput.} +% +% This is the very heart of parsing the user's input. This function takes the +% \texttt{UserInput} and works it over and places it in a proper JavaScript expression +% for the JavaScript interpreter to evaluate. +% +% First get rid of all whitespace. Then +% check for balanced parentheses followed by checking for known +% or unknown math functions. +% +% The power function is \texttt{pow}; thus, |x^2| is \texttt{pow(x,2)}. Rather than +% make students write \texttt{pow(x,2)} we try to code things so they can enter +% |x^2| instead, much easier for them. Now we must scan through for different +% patterns. The patterns are: |x^n|, |(expr)^n|, |x^(expr)| and |(expr1)^(expr1)|. We +% search through looking for these patterns and replace them appropriately: +% |pow(x,n)|, |pow(expr,n)|, |pow(x,expr)| and |pow (expr1,expr2)|. To do this, we +% must find balanced parentheses. +% +% For those who have Acrobat 5.0, you can call this function from the console, something +% I do quite a lot when developing new scripts. From the console, enter, for example, +% \verb+ParseInput("xycos(xy^3)")+, and the return value of this function will be +% displayed in the console. An author can check the syntax of his/her answer. +% +% \begin{macrocode} +function ParseInput(UserInput) +{ + var re, repi; + UserInput = stripWhiteSpace (UserInput); + if (!ok2Continue) return null; +% \end{macrocode} +% See if there are matching `\texttt{[]}', `\texttt{\{\}}' and `\texttt{()}'. +% \begin{macrocode} + for(var i=0; i< aGroup.length; i++) + { + if(!CkBalP(UserInput, aGroup[i][0], aGroup[i][1])) + { + eqAppAlert(\eqerrDelimNotBal,3); + ok2Continue = false; + return false; + } + } +% \end{macrocode} +% Replace `\texttt{[]}' and `\texttt{\{\}}' with `\texttt{()}'; only parentheses +% are used in JavaScript for grouping. +% \begin{macrocode} + UserInput = ChngAllGrpsToParens(UserInput); +% UserInput = UserInput.replace(/\[|\{/g, "\("); +% UserInput = UserInput.replace(/\]|\}/g, "\)"); +% \end{macrocode} +% If the \texttt{fact} function is defined, we attempt to replace user's input of the form +% \texttt{<number>!} with \texttt{fact(<number>)}. +% \begin{macrocode} + if ( replaceExclaim &&(typeof fact == "function") ) + UserInput = UserInput.replace(% +/(?=\()?(\d+)(?=\))?!/g,"fact($1)"); +% \end{macrocode} +% Check to see if there are an even number of absolute value symbols, `\verb+|+'. +% \begin{macrocode} + if (!CkBalVert(UserInput)) + { + eqAppAlert(\eqerrABS,3); + ok2Continue = false; + return false; + } +% \end{macrocode} +% 07/07/08 Before we go further, find all occurrences of the JavaScript function, +% and enclose each in parentheses. This helps with some of the exponential parsing +% later. Things of the form \verb!sin^2(x)! will not be enclosed, but will be +% if the \texttt{ImplMulti} option is used. +% \begin{macrocode} + UserInput=groupJSf(UserInput); +% \end{macrocode} +% (01/09/10) We try to identify an expression of the form \verb!e^!, when preceded by a +% letter or number, in this case we assume multiplication. We also look for +% the letter \texttt{e} when it is not in the middle of \texttt{sec}, this interpreted +% as a numerical constant, it is converted to \verb!(e^1)!. +% \begin{macrocode} + re=/(\w)(e)(\^)/g; + repi=/(\w)(pi)/g; +% \end{macrocode} +% If its a word followed by e, followed by the exponent symbol (\verb!^!), it is +% multiplication. +% \begin{macrocode} + UserInput=UserInput.replace(re, "$1*$2$3"); + UserInput=UserInput.replace(repi, "$1*$2"); +% UserInput=UserInput.replace(repE, "$1*$2"); +% \end{macrocode} +% We mark \texttt{sec} so we don't get a hit on the next search. +% \begin{macrocode} + UserInput=UserInput.replace(/(sec)/g, "s@e@c"); + re=/(\w)(e)([^\^])?/g; +% \end{macrocode} +% If its a word, followed by e, followed by something other than \verb!^! +% then e must be used in the sense of a constant, so we replace it by +% \verb!(e^1)!, so subsequence searches within this function will ultimately +% convert it to \texttt{pow(e,1)}. +% multiplication. +% \begin{macrocode} + UserInput=UserInput.replace(re,"$1($2\^1)$3"); + UserInput=UserInput.replace(/(s@e@c)/g, "sec"); +% \end{macrocode} +% (07/16/11) In support of scientific notation. It is desirable to support E4, for example. +% So we search for any occurrence of \texttt{E\cs{d}} and replace with \texttt{E+\cs{d}}. +% Note: the letters \texttt{E} and \texttt{e} are used in JS to represent floating point numbers. +% In this package \texttt{e} will be used for the natural number. Another problem, +% JavaScript does not compute something like \texttt{1*E+2}, so we must remove any \texttt{*} between +% the digit previous to \texttt{E} and \texttt{E}. +% \begin{macrocode} + re=/E(\d)/g; + UserInput=UserInput.replace(re,"E+$1"); + re=/(\d)\*E/g; + UserInput=UserInput.replace(re,"$1E"); +% \end{macrocode} +% We make a rough check of the user input, if it has alpha-words of size two or greater +% that do not match up against a recognizable function, it must be an error. +% +% (09/07/09) Comment this out so we check for function in both cases, get same alert message +% \begin{macrocode} +% if (typeof(Ck4Exponents) == "undefined") + if(!Ckfuncs(UserInput)) return false; +% \end{macrocode} +% Now try to insert the multiplication operator where applicable. +% \begin{macrocode} + if (typeof(Ck4Exponents) != "undefined") + UserInput = Ck4Exponents(UserInput); + if (typeof(Ck4Products) != "undefined" ) + UserInput = Ck4Products(UserInput); + ok2Continue = true; +% \end{macrocode} +% Convert any occurrence of log to log10 (known internally as logc). We are now (12/22/06) going to use log for +% common log even though log in JS is natural log. This may break a few things. +% \changes{v6.05f}{2006/12/22 } +% { +% Added support for common logarithms. log is now common logs, and ln is +% natural logs. +% } +% \begin{macrocode} + re = /\b(log)\b/g; + UserInput = UserInput.replace(re, "logc"); +% \end{macrocode} +% Search for occurrences of \verb!|<exp>|! and replace with \texttt{abs(<exp>)}. +% \begin{macrocode} + while (/\|/.test(UserInput)&&(ok2Continue)) + { + re = /(\|)([^\|]*)(\|)([-\+\/\*\^\)\|])/; + if (re.test(UserInput)) + if (re.exec(UserInput)[4] == '^') + UserInput = UserInput.replace(re, "(abs($2))$4"); + else + UserInput = UserInput.replace(re, "abs($2)$4"); + else + { + re = /(\|)([^\|]*)(\|$)/; + if (re.test(UserInput)) + UserInput = UserInput.replace(re, "abs($2)"); + } + } +% \end{macrocode} +% Replace every instance of \texttt{pi} with \texttt{(pi)} so things like +% \verb!pi^2! are parsed correctly. +% \begin{macrocode} + re=/\b(pi)\b/g; + UserInput=UserInput.replace(re,"($1)") +% \end{macrocode} +% We now begin our search for exponents, we search the UserInput from left to right +% for any of the four strings \texttt{"\string^"},\texttt{")\string^"}, \texttt{"\string^("}, and +% \texttt{")\string^("}, using the regular expression \texttt{reTstExp}. (07/07/08) I've rewritten +% this part of the parser to accommodate nested exponents of the form \verb!x^2^3!, which should +% be interpreted as \verb!(x^2)^2!, something like \verb!2^sin(x)! and \verb!sin(x)^2! work, the latter +% is interpreted as \verb!(sin(x))^2!. This is why earlier we executed \texttt{groupJSf} to enclose +% all JS function and their arguments in parentheses; by the time \verb!sin(x)^2! reaches this parser +% it has already been changed to \verb!(sin(x))^2!, which is correct syntax. +% +% These is another change to the parser here. We pass through \texttt{Ck4OddRoots}, which tries, +% in a crude way, to determine if this exponent is of the form \texttt{a/b}, and if so, whether +% \texttt{b}, the denominator, is an odd root. If so, we change the calculation of \texttt{Math.pow} +% to avoid a calculation bug by that JavaScript function. +% \begin{macrocode} + var reTstExp = /(\))?\^(\()?/g; + while ( ((aResults=reTstExp.exec(UserInput))!=null)&&(ok2Continue) ) + { + var firstGroup = Number(Boolean(aResults[1])); // 0 or 1 + var secondGroup = 2*Number(Boolean(aResults[2])); // 0 or 2 + var caseStudy = firstGroup+secondGroup; // 0,1,2,3 + switch(caseStudy) { + case 0: + re=/([a-zA-Z]|\d*\.?\d*)\^([a-zA-Z]|[\+-]?\d+\.?\d*|% +[\+-]?\d*\.?\d+)/; + if (re.test(UserInput)) + UserInput=Ck4OddRoots(UserInput,re); + else ok2Continue=false; + break; + case 1: + aP =/\)\^/.exec(UserInput); + LeftP=FindBalP(UserInput,aP.index,0); + re = new RegExp("\\((.{"+eval(aP.index-LeftP-1) + +"})\\)\\^([a-zA-Z]|[\+-]?\\d+\\.?\\d*|% +[\+-]?\\d*\\.?\\d+)"); + if (re.test(UserInput)) + UserInput=Ck4OddRoots(UserInput,re); + else ok2Continue=false; + break; + case 2: + aP = /\^\(/.exec(UserInput); + RightP=FindBalP(UserInput,aP.index+1,1); + re = new RegExp("([a-zA-Z]|\\d*\\.?\\d*)\\^\\((.{" + +eval(RightP-aP.index-2)+"})\\)"); + if (re.test(UserInput)) + UserInput=Ck4OddRoots(UserInput,re); + else ok2Continue=false; + break; + case 3: + aP = /\)\^\(/.exec(UserInput); + LeftP=FindBalP(UserInput,aP.index,0); + RightP=FindBalP(UserInput,aP.index+2,1); + re = new RegExp("\\((.{"+eval(aP.index-LeftP-1) + +"})\\)\\^\\((.{"+eval(RightP-aP.index-3)+"})\\)"); + if (re.test(UserInput)) + UserInput=Ck4OddRoots(UserInput,re); + else ok2Continue=false; + break; + default: + ok2Continue=false; + } +% console.println("working.."+UserInput); + } + if (!ok2Continue) + { + eqAppAlert(\eqerrBadExp,3); + return false; + } + else { +% \end{macrocode} +%\changes{v6.06}{2007/02/23} +%{ +% Now, just before we return the parsed expression, we append all built-in +% JavaScript functions and constants with \texttt{Math.}, this is to avoid +% having to use the \texttt{with(Math)} construct. These changes are in support +% of using scientific notation. +%} +% \begin{macrocode} + UserInput=addMathObject(UserInput); + return UserInput; + } +} +% \end{macrocode} +% \DescribeMacro{ChngAllGrpsToParens}(2011/10/04) Separated out the routine to replace `\texttt{[}' and `\verb!{!' with +% `\texttt{(}'. +% \begin{macrocode} +function ChngAllGrpsToParens(UserInput) +{ + UserInput = UserInput.replace(/\[|\{/g, "\("); + UserInput = UserInput.replace(/\]|\}/g, "\)"); + return UserInput; +} +% \end{macrocode} +% \DescribeMacro{Ck4OddRoots}The \texttt{Ck4OddRoots} function looks for exponents of the form \texttt{a/b}, +% it checks whether \texttt{b} is an odd integer, if yes, instead of returning +% the usual of \verb!"(pow($1,$2))"!, it returns something like +% \verb!(sgn(<base>)^a*(abs(<base>)^a)^(1/b))!. This gives a base that evaluates +% to a negative number a change of being evaluated, and avoid a bug in the \texttt{Math.pow} +% function. +% \begin{macrocode} +function Ck4OddRoots(UserInput,re) { + var a=re.exec(UserInput); +% \end{macrocode} +% \texttt{a[2]} should be the exponent +% try to remove extraneous parentheses +% \begin{macrocode} + while ( a[2].charAt(0)=="\(") { + var RightP=FindBalP(a[2],0,1); // forward search + if (RightP == a[2].length-1) + a[2]=a[2].substring(1,a[2].length-1); + else break; + } + var b=a[2].split("/"); +% \end{macrocode} +% We are looking for an exponent of the form a/b, if we can't find it +% we process this power in the usual way. \texttt{b[0]} is our possible numerator +% and \texttt{b[1]} is our possible denominator. +% \begin{macrocode} + if ( b.length==2 ) { + try { _m=eval(b[1]) +% \end{macrocode} +% We try to evaluate the denominator \texttt{b[1]}. If there are unbalanced +% parentheses, JavaScript will throw an exception, if \texttt{\_m} is either +% undefined or not a number, we throw an exception. The expression will be +% processed in the usual way. +% \begin{macrocode} + if ( _m == undefined || isNaN(_m) ) throw new Error(); +% \end{macrocode} +% The denominator appears to be numerical, so we'll continue +% \begin{macrocode} + var d = b[1]; +% \end{macrocode} +% Check for the presence of enclosing parentheses +% \begin{macrocode} + var isEnclosed=(d.charAt(0) == "\(" && d.charAt(d.length-1)=="\)"); +% \end{macrocode} +% if not enclosed look for arithmetic operations +% \begin{macrocode} + if (!isEnclosed) +% \end{macrocode} +% if arithmetic operations of add/sub found, exit. In this case, perhaps the user had an +% exponent of the form \texttt{x/2 + 3}, and so \texttt{d = 2 + 3}, which is not the desired denominator. +% We'll throw an exception, and process as usual. +% \begin{macrocode} + if (/.+[\+\-].+/.test(d)) throw new Error(); +% \end{macrocode} +% remove enclosing parentheses +% \begin{macrocode} + if (isEnclosed) d = s.substring(1,d.length-1); +% \end{macrocode} +% now need to do the same thing for the numerator +% \begin{macrocode} + var n = b[0]; + isEnclosed=(n.charAt(0) == "\(" && n.charAt(d.length-1)=="\)"); + if (!isEnclosed) +% \end{macrocode} +% if arithmetic operations of add/sub found, exit. If numerator was not enclosed +% in parentheses, and there is either addition or subtraction, we are looking +% at an exponent of the form \texttt{1 + x/d,} and \texttt{n = 1 + x}. The numerator is not \texttt{1+x}, we +% process in the usual way. +% \begin{macrocode} + if (/.+[\+\-].+/.test(n)) throw new Error(); +% \end{macrocode} +% I don't think we need to remove the enclosing parentheses +% as we did for the denominator. +% +% Now check if the denominator, \texttt{d}, is an integer, for that we'll use \texttt{parseInt}, +% If it is an integer, we see if it is odd or even using \verb!d % 2!, which yields +% a nonzero remainder if d is odd. If \texttt{d} passes all tests, we write +% \verb!<base>^(n/d)! as \verb!(sgn(<base>))^n! \verb!(abs(<base>)^(n/d))!. +% \begin{macrocode} + if ( d == parseInt(d) && ( Boolean(d \% 2) ) ) { + UserInput=UserInput.replace(re, + "(pow(sgn($1),"+n+")*(pow(abs($1),$2)))"); +% \end{macrocode} +% We we have an odd integer as a denominator, we return our result here +% \begin{macrocode} + return UserInput; + } +% \end{macrocode} +% All exceptions come here, then continue on to the lines that follow. +% \begin{macrocode} + } catch(e) {} + } +% \end{macrocode} +% If we don't have an odd integer as a denominator, we return here +% \begin{macrocode} + UserInput=UserInput.replace(re,"(pow($1,$2))"); + return UserInput; +} +% \end{macrocode} +% \DescribeMacro{groupJSf}We enclose all recognizable functions in parentheses. This makes it easier for doing +% exponents, and avoids parsing errors. We look for functions of the form \texttt{fname(..)}, +% replace that with \texttt{fname@(..)} to avoid an infinite loop, as we search for the function +% name followed by a left parenthesis. Once finished, we remove the \texttt@ character. +% \begin{macrocode} +function groupJSf(UserInput) +{ + var re, regexp, aP, RightP; + for (var i=0; (i<JSf.length) && (ok2Continue); i++) + { + re = new RegExp(JSf[i]+"\\\("); + while ( re.test(UserInput) && (ok2Continue) ) + { + regexp = new RegExp(JSf[i]+"\\\(", "g"); + if ( (aP = regexp.exec(UserInput)) != null ) + { + RightP=FindBalP(UserInput,regexp.lastIndex-1,1); + offsetArg = RightP - regexp.lastIndex; + regexp = new RegExp(% +"("+JSf[i]+")\\((.{"+offsetArg+"})\\)"); + regexp.lastIndex=0; + if (regexp.test(UserInput)) + UserInput=UserInput.replace(regexp,"($1@($2))"); + else ok2Continue=false; + continue; + } + } + } +% \end{macrocode} +% Remove the \texttt@ marker, and return. +% \begin{macrocode} + UserInput=UserInput.replace(/@/g,""); + return UserInput; +} +% \end{macrocode} +% Process the user's response. Here, we randomly choose, $n$, +% points from the selected interval $[a,b]$. The correct answer (as +% supplied by the author of the document and the answer provided by +% the user are evaluated at each of the $n$ points. If any of the +% evaluations differs by more than \texttt{epsilon}, the answer is +% considered wrong. +% +% The idea for evaluating user input in this way comes from Drs.\ +% Wlodzimierz Bryc and Stephan Pelikan of The University of +% Cincinnati. These two have developed an \texttt{html} based +% \textbf{Online Exercise System} which can evaluate objective +% type questions. This evaluation, however, takes place on the +% \emph{server-side}. This implementation is on \emph{the client-side}. +% +% \begin{macro}{TypeParameters} +% The argument \texttt{v} is either a comma delimited list of variables \texttt{"x,y,z"} or just a list \texttt{"xyz"}. +% This function types each untyped variable that is not typed. Currently, there +% are only two data types: \texttt{"r"} and \texttt{"i"}. \texttt{"r:x"} means \texttt{"x"} is a real variable, +% \texttt{"i:x"} means \texttt{"x"} is an integer variable. +% \begin{macrocode} +function TypeParameters(v) +{ + var aV; +% \end{macrocode} +% If \texttt{v} has a colon in it, we take that as a signal that the variables are comma +% delimited. +% \begin{macrocode} + aV = ( (v.indexOf(":") == -1) && (v.indexOf(",") == -1) ) ? + v.split("") : v.split(","); + for ( var i=0; i < aV.length; i++) + if ( aV[i].indexOf(":") == -1 ) aV[i] = "r:"+aV[i]; + return aV.join(",") +} +% \end{macrocode} +% \end{macro} +% \begin{macro}{ProcResp} +% This function handles numerical answers or function of a single variable, x, +% that evaluate to a number. +% \begin{macrocode} +function ProcResp(flag,CorrAns,n,epsilon,domain,indepVar,oComp) +{ + if (!ProcessIt) return null; + var fieldname = event.target.name; + var UserAns = event.value; + var success = _ProcResp(flag,CorrAns,UserAns,% +n,epsilon,domain,indepVar,oComp); +% \end{macrocode} +% 09/07/09 Added next line to avoid double alert boxes +% \begin{macrocode} + if ( success == -1 || !ok2Continue ) return null; + if ( success == null ) { return syntaxError(), null; } + return notifyField(success, flag, fieldname); +} +// changed name of var comp -> oComp +function _ProcResp(flag,CorrAns,UserAns,n,epsilon,domain,indepVar,oComp) +{ + ok2Continue = true; +% \end{macrocode} +% by preprocessing. +% \begin{macrocode} + CorrAns = ParseInput(CorrAns); + if (!ok2Continue) { + eqAppAlert("Syntax error in author's answer! Check console.",3); + return null; + } +% \end{macrocode} +% If \texttt{oComp} is an object, then see if it has a \texttt{comp} property +% \begin{macrocode} + var comp = ( typeof oComp == "object" ) ? + ((typeof oComp.comp == "undefined" ) ? + diffCompare : oComp.comp ) : oComp; +% \end{macrocode} +% \paragraph*{priorParse} The \texttt{comp} parameter, which has been changed to \texttt{oComp}, can now be +% an object. One property of this object is \texttt{comp}, handled above. Another +% property is \texttt{priorParse}, this is a function that returns \texttt{null} +% or \texttt{true}. This \texttt{priorParse} function allows for additional +% filtering of the \texttt{UserAns} before parsing. If it returns \texttt{true}, +% we are ok to continue, if \texttt{null}, we don't like something the user has entered, +% and ask him/her to change it. +% \begin{macrocode} + if ( (typeof(oComp)=="object") % +&& (typeof(oComp.priorParse)!="undefined") ) { + var retn=processSpecialParse(oComp.priorParse,UserAns); + if (retn==null) return -1; + } +% \end{macrocode} +% (2014/01/22) Before we solve Bruce's problem with the commas, we need to allow for the use of +% the combinatorics functions \texttt{C(x,y)} and \texttt{P(x,y)}. +% \begin{macrocode} + var reCP=/((C|P)\(.+?)(,)(.+?\))/g +% str="P(12,4)" +% reCP.exec(str) + UserAns=UserAns.replace(reCP,"$1@c@$4"); +% \end{macrocode} +% (2012/04/13) Bruce Wagner reports a problem with the user enters an answer containing +% a comma \texttt{"3,2"}, if the correct answer is 2, exerquiz marks the response as correct +% even though the user has also entered a 3. The comma operator in JS, evaluates its operands +% one to the left, one to the right, and returns the value of the one on the right. To fix +% this problem, we scan the \texttt{UserAns} for a comma (,) and set an alert if one is found. +% +% For vector- and list-valued answers, the \texttt{ProcResp<name>} procedure should parse +% the comma-delimited answers and call \texttt{\_ProcResp} once for each answer in the list +% so there should be no problem with commas in that regard. +% \changes{v6.4r}{2012/04/13}{Added a warning about commas in an answer.} +% \begin{macrocode} + var reComma=/,/; + if ( reComma.test(UserAns) ) { + eqAppAlert(\eqSyntaxErrorComma,3); + return -1; + } +% \end{macrocode} +% \begin{macrocode} + var reRlCommaSubst=/@c@/g; + UserAns=UserAns.replace(reRlCommaSubst,","); +% \end{macrocode} +% Parse the user's input. +% \begin{macrocode} + UserAns = ParseInput(UserAns); +% \end{macrocode} +% Originally, the value of \texttt{indepVar} is a string of variables \texttt{"xyz"}. You can +% now have variables of the form \texttt{"r:x,i:n,r:y"}. Where the identifier \texttt{"r:"} indicates a +% real variable and \texttt{"i:"} indicates an integer variable. \texttt{indepVar} must be either +% of the old style, or the new style, not a mixture of both, e.g. \texttt{"xyi:n"}. +% \begin{macrocode} + indepVar = TypeParameters(indepVar); + if (!ok2Continue) return null; + var success=randomPointCompare(n,domain,indepVar,% +epsilon,CorrAns,UserAns,comp); +% \end{macrocode} +% \paragraph*{postParse} (2011/10/05) The beginning of an idea, \texttt{postParse}. After it is determined +% whether the answer is right or wrong, post-process it here. For example, +% if the problem is to extract all roots of $\sqrt{72}$, the correct answer +% is $6\sqrt{2}$, whereas $3\sqrt{8}$ is not correct though it is equal to +% $\sqrt{72}$ +% \begin{macrocode} + if ( success && (typeof(oComp)=="object") % +&& (typeof(oComp.postParse)!="undefined") ) + success=processSpecialParse(oComp.postParse,UserAns); + return success; +} +% \end{macrocode} +% \end{macro} +% \begin{macrocode} +function processSpecialParse(oParse,UserAns) { + var retn, f, _o + if ( typeof(oParse) == "object" ) { + for ( var i=0; i < oParse.length; i++) { + _o=oParse[i]; + if (typeof(_o)=="function") { +% \end{macrocode} +% If \texttt{oParse} is an object (it should be an array), and the first entry is a function +% then we have: \texttt{priorParse: [myfunction, optional arguments]}. The function is +% evaluated with the args \texttt{(UserAns, optional args)}. In the code below, we remove +% the name of the function at the beginning of the array, and insert the \texttt{UserAns} +% in its place. Various syntax variations supported. +%\begin{verbatim} +% priorParse: nodec, +% priorParse: [nodec,noBinFac], +% priorParse: [nodec,noBinFac,[myFunc,arg1, arg2,..]], +%\end{verbatim} +% \begin{macrocode} +% _o=oParse.shift(); +% oParse.unshift(UserAns); + retn=_o(UserAns); +% retn = _o.apply(null,oParse); + if (retn==null) return retn; +% \end{macrocode} +% In this case, we break out of the loop, we don't expect any more properties +% for \texttt{priorParse} or \texttt{postParse}. +% \begin{macrocode} +% break; + } else { +% \end{macrocode} +% If \texttt{oComp.priorParse[i]} is not a function, it is required to be an array. The first +% element of the array is the function, the rest of the entries are the additional arguments +% (in addition to \texttt{UserAns}). +% \begin{macrocode} +% f=_o.shift(); +% _o.unshift(UserAns); +% retn=f.apply(null,_o); + retn=_o[0].apply(null, [ UserAns ].concat(_o.slice(1))); + if (retn==null) return null; + } + } + } else { +% \end{macrocode} +% The case where \texttt{preParse: myfunction} or \texttt{postParse: myfunction}. +% Such a function is evaluated with the \texttt{UserAns} argument. +% \begin{macrocode} + retn = oParse(UserAns); + } + return retn; +} +% \end{macrocode} +% This function randomly selects points from the interval [a,b] +% and calls the 'comp' function to compare results. +% Returns: null if the expression is bad, no penalty. +% true if the error of the random comparison is less than epsilon +% false if the error of the random comparison is greater than epsilon +% \begin{macrocode} +function randomPointCompare (n,domain,indepVar,epsilon,% +CorrAns,userAns,comp) +{ + var error, i, j, k; + var aXY = new Array(); + domain = domain.replace(/[\[\]\s]/g, ""); + var aIntervals = domain.split("&"); + for (k=0; k < aIntervals.length; k++) + { + var aInterval = aIntervals[k].split("x"); + nI = aInterval.length; + with (Math) { + for (j=0; j < n; j++) + { + for (i=0; i < nI; i++) + { + var endpoints = aInterval[i].split(","); + aXY[i] = eval(endpoints[0])-0+(eval(endpoints[1])% +-eval(endpoints[0]))*Math.random(); + } + var cXY = aXY.toString(); + error = comp(domain,cXY,indepVar,CorrAns,userAns); + if (error == null) return null; + if ( (error == -1) || (error > epsilon) ) {j=-1; break;} + } + } + if (j!=n) return false; + } + return true; +} +% \end{macrocode} +% \texttt{diffCompare}: A simple comparison function, we evaluate the two input function `\texttt{\_F}' +% and `\texttt{\_G}' and the point `\texttt{\_c}' and return the absolute difference. +% +% Returns: Absolute difference between `\texttt{\_F}' and `\texttt{\_G}' +% null if expression was not valid +% -1 if expression is not a number +% \begin{macrocode} +function diffCompare(_a,_c,_v,_F,_G) { + var aXY = _c.split(","); + var _V = _v.split(","); // e.g. _V[0] = "i:x" + var _n = aXY.length; +% \end{macrocode} +% For each of the independent variables, we set them equal to a randomly chosen value +% from the specified interval. +% \begin{macrocode} + for (var _i=0; _i < _n; _i++) + { + if (_V[_i].charAt(0) == "r" ) + eval ("var "+_V[_i].charAt(2)+"="+aXY[_i]+";"); + else // assume type "i" + eval ("var "+_V[_i].charAt(2)+"="+Math.ceil(aXY[_i])+";"); + } +% \end{macrocode} +% The \texttt{\_F} is the author's answer, we assume this is well formed JavaScript +% and do not test it for possible errors. The author can correct before s/he distributes +% the document. +% \begin{macrocode} + _F = eval(_F); +% \end{macrocode} +% Now we try to protect our code from bad input. We use \texttt{try/catch} to try and +% thrown exceptions. However, \texttt{try/catch} is not valid in any version of the +% Acrobat Reader prior to version 5. +% \begin{macrocode} + if ( app.viewerVersion >= 5) + { +% \end{macrocode} +% This code, which uses \texttt{eval()} and \texttt{try/catch} is an attempt to write +% code that both works for Acro5 (or higher) and Acro4.05/4.0. In Acro4.x, \texttt{try/catch} +% are reserved words, so we can't use them even in a conditional. However, within a string +% the JavaScript interpreter does not see them. The other complication is that Acro5 objects +% to having a \texttt{return} within an \texttt{eval()}, so we work around that with a +% \texttt{rtnCode}. The returns are executed outside the \texttt{eval()}. +% \begin{macrocode} + var rtnCode = 0; + eval("try {if(isNaN(_G = eval(_G))) rtnCode=-1; }" + +"catch (e) { rtnCode=1; }"); + switch(rtnCode) + { + case 0: break; + case 1: return null; + case -1: return -1; + } + } + else +% \end{macrocode} +% For Acro4/4.05, all we can do is detect whether \texttt{\_G} is a number or not. If the user +% enters an undefined symbol, for example, we cannot catch this as we can with Acro5. Oh, well. +% \begin{macrocode} + if(isNaN(_G = eval(_G))) return -1; +% \end{macrocode} +% +% The function \texttt{G} is the user's input expression. There may be syntax errors +% that prevent the successful numerical evaluation of the expression. We try to +% prevent problems. +% +% If the user enters a function such as \texttt{sqrt( 1 - x )}, and this function is +% evaluated at a x = 2, for example, we are outside the domain of the function. The \texttt{isNaN} +% function will catch this type of error. A return of \texttt{-1} signals an error +% at this of this type. This is considered to be an error by the user, and will be scored as an +% incorrect answer. +% +% The error described above does not throw an exception. What will throw an exception +% is if the users function has some undefined variables in it. For example, suppose +% we are expecting a response that is a function of \texttt{x} and the user enters a +% function of \texttt{t} instead. This will throw an exception as \texttt{t} is undefined. +% In this case, we do not treat this as an error, and expect the user to correct the +% input. This kind of error is signaled by returning a \texttt{null}. +% +% \begin{macrocode} + return Math.abs ( _F - _G ); +} +% \end{macrocode} +% This function is the same as above, but returns the relative absolute error. +% \begin{macrocode} +function reldiffCompare(_a,_c,_v,_F,_G) { + var aXY = _c.split(","); + var _V = _v.split(","); // e.g. _V[0] = "i:x" + var _n = aXY.length + for (var _i=0; _i < _n; _i++) + { + if (_V[_i].charAt(0) == "r" ) + eval ("var "+_V[_i].charAt(2)+"="+aXY[_i]+";"); + else // assume type "i" + eval ("var "+_V[_i].charAt(2)+"="+Math.ceil(aXY[_i])+";"); + } + _F = eval(_F); + if ( app.viewerVersion >= 5) + { + var rtnCode = 0; + eval("try { if(isNaN(_G = eval(_G))) rtnCode=-1; }" + +"catch (e) { rtnCode=1; }"); + switch(rtnCode) + { + case 0: break; + case 1: return null; + case -1: return -1; + } + } + else + if(isNaN(_G = eval(_G))) return -1; + return Math.abs ( (_F - _G)/_G ); +} +% \end{macrocode} +% \DescribeMacro{requireForm}(07/16/11) The JS function \texttt{requireForm} is an example of a filter function. It is +% of such a general nature we put it in the \textsf{exerquiz} code, rather than the \textsf{dljslib} code. +% The function takes two or three arguments, the second one is an regular expression or an array +% of regular expressions to test \texttt{UserAns} against. The third, optional argument is a text message to +% be displayed if the \texttt{UserAns} is not of the required form. +%\changes{v6.4f}{2011/07/16}{Added \texttt{requireForm} filtering function} +%\par\medskip\noindent Usage: Factor: $-36z^5 - 96z^4 - 64z^3.$ +%\begin{verbatim} +%\RespBoxMath{-4z^3(3z+4)^2}(z)*{3}{.0001}{[0,1]}[ { priorParse: +% \Array( \Array( requireForm, \Array(% +% /.*(\refac\repow|\refac\refac)/,% +% /.*\refac\refac\repow\redigit+/,% +% /.*\refac\repow\redigit+\refac/,% +% /.*\refac\refac\refac/% +% ), \myCustomMsg ) ) } +% ]\CorrAnsButton{-4z^3(3z+4)^2} +%\end{verbatim} +% where \cs{refac}, \cs{repow}, \cs{redigit}, and \cs{rediv} are convenience macros defined +% earlier in \texttt{exerquiz.dtx}. The regular expression describe the form of the answer +% acceptable. +% +% There seems to be a redundancy in the usage of \cs{Array}, but this is by design. +% The first \cs{Array} is there so the function \texttt{\_ProcResp} does not misinterpret +% the second \cs{Array}. +% \begin{macrocode} +function requireForm(UserAns, regexpr) { + var msg=\defaultReqFormMsg; + UserAns = stripWhiteSpace (UserAns); + if (!ok2Continue) return null; +% UserAns = stripOutMuli(UserAns); + UserAns = ChngAllGrpsToParens(UserAns); + if (arguments.length>2) msg=arguments[2]; + if (typeof(regexpr.length)=="undefined") { + if (regexpr.test(UserAns)) return true; + else { eqAppAlert(msg,3); return null; } +% \end{macrocode} +% \texttt{regexpr} is an array of regular expressions. +% \begin{macrocode} + } else { + for (var i=0; i<regexpr.length; i++) + if (regexpr[i].test(UserAns)) break; + if ( i < regexpr.length ) return true; + else { eqAppAlert(msg,3); return null; } + } +} +% \end{macrocode} +% \DescribeMacro{denyForm}Same type of function as \texttt{requireForm}. +% If the regular expression is found, we return \texttt{null} +% and emit an alert. +% \begin{macrocode} +function denyForm(UserAns, regexpr) { + var msg=\defaultReqFormMsg; + UserAns = stripWhiteSpace (UserAns); + if (!ok2Continue) return null; +% UserAns = stripOutMuli(UserAns); + UserAns = ChngAllGrpsToParens(UserAns); + if (arguments.length>2) msg=arguments[2]; + if (typeof(regexpr.length)=="undefined") { + if (regexpr.test(UserAns)) { eqAppAlert(msg,3); return null; } + else return true; +% \end{macrocode} +% \texttt{regexpr} is an array of regular expressions. +% \begin{macrocode} + } else { + for (var i=0; i<regexpr.length; i++) + if (regexpr[i].test(UserAns)) break; + if ( i < regexpr.length ) { eqAppAlert(msg,3); return null; } + else return true; + } +} +% \end{macrocode} +% \DescribeMacro{requireFormNot} does the opposite of +% \texttt{requireForm}. If the regular expression is found, +% we return \texttt{false}. \texttt{postParse} does not emit any messages. +% \begin{macrocode} +function requireFormNot(UserAns, regexpr) { + UserAns = stripWhiteSpace (UserAns); + if (!ok2Continue) return null; + UserAns = stripOutMuli(UserAns); + UserAns = ChngAllGrpsToParens(UserAns); + if (typeof(regexpr.length)=="undefined") { +% \end{macrocode} +% If the regular expression is found, we return false +% this is opposite to what \texttt{requireForm} returns +% \begin{macrocode} + if (regexpr.test(UserAns)) return false; + else return true; +% \end{macrocode} +% \texttt{regexpr} is an array of regular expressions. +% \begin{macrocode} + } else { + for (var i=0; i<regexpr.length; i++) + if (regexpr[i].test(UserAns)) break; + if ( i < regexpr.length ) return false; + else return true; + } +} +\end{newsegment} +% \end{macrocode} +% \subsection{Text Fill-in} +% Now the JS functions that process text fill-in questions. +% \begin{macrocode} +\begin{newsegment}{Eq: Support Text Fill-in} +% \end{macrocode} +% This function processes fill-in problems that require only a text +% response. It takes a variable number of arguments, which are retrieved +% using the \texttt{arguments[]} array +% \begin{macrocode} +function ProcRespTxt() { + var i, success, authorAnswer, userAnswer = event.value; + var fieldname=event.target.name; + var flag = arguments[0]; + var filterMethod = arguments[1]; + var compareMethod = arguments[2]; + if ( !ProcessIt || userAnswer == "" ) return null; + for (i = 3; i < arguments.length; i++) + if ( success = compareTxt(userAnswer,arguments[i],% +filterMethod, compareMethod)) break; + return notifyField(success, flag, fieldname); +} +% \end{macrocode} +% This is for text fill-in problems with partial credit. It takes a variable +% number of arguments. \texttt{arguments[i]=["<word>", part\_credit]}. This +% function has a property attached to it \texttt{ProcRespTxtPC.txtPCpCr} +% is the credit received for this problem. This function is called by +% \cs{RespBoxTxtPC}. +% \begin{macrocode} +function ProcRespTxtPC() { + var i, success, authorAnswer, userAnswer = event.value; + ProcRespTxtPC.txtPCpCr=0; + var fieldname=event.target.name; + var flag = arguments[0]; + var filterMethod = arguments[1]; + var compareMethod = arguments[2]; + if ( !ProcessIt || userAnswer == "" ) return null; +% \end{macrocode} +% Unlike \texttt{ProcRespTxt}, we do not break at our first success. We go through +% all \texttt{<words>}, each having partial credit associated with it. For each +% success returned by \texttt{compareTxt}, we add in the credit to the total. +% \begin{macrocode} + for (i=3;i<arguments.length;i++) + if(compareTxt(userAnswer,arguments[i][0],% +filterMethod,compareMethod)) + ProcRespTxtPC.txtPCpCr+=(arguments[i][1]); +% \end{macrocode} +% success if at least one of the words were used, partial credit awarded. +% \begin{macrocode} + success=(ProcRespTxtPC.txtPCpCr>0); + return notifyField(success,flag,fieldname); +} +% \end{macrocode} +% +% \texttt{compareTxt} actually compares the \texttt{userAnswer} with the \texttt{authorAnswer}. +% there are options for various types of comparisons. +% Returns true or false. +% \begin{macrocode} +function compareTxt(userAnswer,authorAnswer,filterMethod,compareMethod) +{ + var caseSensitive = ( compareMethod==3 ) ? "" : "i"; + var reSwitches = "g"+caseSensitive; + userAnswer = new String(userAnswer).filter(filterMethod); + switch(compareMethod) { + case 1: + var AuthorAnswer; + var aAuthorAnswer = authorAnswer.split(/\s+/); + for (var j=0; j < aAuthorAnswer.length; j++) { + AuthorAnswer = new String(% +aAuthorAnswer[j]).filter(filterMethod); +% \end{macrocode} +% When using \cs{RespBoxTxtPC}, if the author wants to use the +% character class . (period, meaning match anything newline or another unicode line terminator) +% we define in \cs{RespBoxTxtPC} a local command \cs{any} which expands to \texttt{@any@}. +% After we replace any occurrence of . (period) with \verb!\\.!, we then replace \texttt{@any@} +% with \texttt{.}. +% \begin{macrocode} + AuthorAnswer = AuthorAnswer.replace(/\./g,"\\."); + AuthorAnswer = AuthorAnswer.replace(/@any@/g,"."); + var re = new RegExp(AuthorAnswer, reSwitches); + if (!re.test(userAnswer)) return false; + } + return true; + default: + authorAnswer=new String(authorAnswer).filter(filterMethod); + return (userAnswer == authorAnswer) ? true : false; + } +} +% \end{macrocode} +% Various string prototypes. This function is called by compareTxt. +% The function returns the 'filtered' string. +% \begin{macrocode} +String.prototype.filter = eqFilter; +function eqFilter(filterMethod) { + switch (filterMethod) { + case 0: + var re = /\W/g; + return this.replace(re,"").toLowerCase(); + case 1: + var re = /\s/g; + return this.replace(re,"").toLowerCase(); + case 2: + var re = /\s/g; + return this.replace(re,""); +% \end{macrocode} +% If filter method 3 is used, a case-insensitive search is used in the +% \texttt{compareTxt} method. Added 04/21/09. +% \begin{macrocode} + case 3: + default: +% \end{macrocode} +%\changes{v6.4k}{2011/08/17}{Within the function eqFilter, changed \texttt{this} to +% \texttt{this.toString()}. The comparisons were returning false when they shouldn't +% this is because in this case, we were comparing objects to objects} +% \begin{macrocode} + return this.toString(); + } +} +\end{newsegment} +% \end{macrocode} +% \subsection{Multiple Choice Questions} +% These are the routines for processing multiple choice questions. +% \begin{macrocode} +\begin{newsegment}{Eq: Quiz Management} +function InitMsg(msg) { return (\eqInitQuizMsg) } +function syntaxError() { eqAppAlert(\eqSyntaxErrorUndefVar,3); } +% \end{macrocode} +% \begin{macrocode} +var lstOfQuizzes=new Array(); +% \end{macrocode} +% There are four required parameters, if there is a fifth, that means +% we have a grouped question, parameter 5 will be the group sub-problem number. +% \begin{macrocode} +var reExtractBaseName=/^.+?\.(.+?)\..+$/; +function ProcUserResp(key,userresp,probno,notify) +{ + if (key==null) { + ProcUserNoResp.apply(null,arguments); + return; + } + if ( arguments.length > 4 ) { + if ( typeof RightWrong[probno] == "undefined" ) { + RightWrong[probno] = new Array(); + RightWrong[probno][0] = "grp"; + Responses[probno] = new Array(); + } + RightWrong[probno][arguments[4]] = (!!key) ? 1 : 0; + Responses[probno][arguments[4]] = userresp; + } else { +% \end{macrocode} +% If key is an array, we are processing a multiple selection problem. The +% actual key is the first entry. The second entry, not used here, is 1 +% if user has selected at least one correct answer, zero otherwise. +% \begin{macrocode} + if ( typeof key == "object" ) { + RightWrong[probno][0] = key[0]; + RightWrong[probno][1] = key[1]; + Responses[probno] = userresp; + if (Responses[probno].length==0) + Responses[probno]=undefined; + } else { + RightWrong[probno] = (!!key)?1:0; + Responses[probno] = userresp; + } + } +% \end{macrocode} +% \texttt{ProcUserResp()} is also called by a link, so we'll skip this code. +% \texttt{fieldPopTbl()} is executed later in \texttt{ProcessQuestions()} +% \begin{macrocode} + if ( (typeof fieldPopTbl == "function")&&(event.type != "Link") ) { + var a=reExtractBaseName.exec(event.target.name); + fieldPopTbl(a[1]); + } +} +function ProcUserNoResp(key,userresp,probno,notify) +{ + if ( arguments.length > 4 ) { + RightWrong[probno][arguments[4]] = undefined; + Responses[probno][arguments[4]] = undefined; + var bVoidArray=true; + for (var i=0; i<Responses[probno].length; i++) { + if ( typeof Responses[probno][i] != "undefined") { + bVoidArray=false; + break; + } + } + if (bVoidArray) { + Responses[probno]=undefined; + RightWrong[probno]=undefined; + ProbValue[probno]=undefined; + } + } else { + RightWrong[probno] = undefined; + Responses[probno] = undefined; + } + if ( typeof fieldPopTbl == "function" ) { + var a=reExtractBaseName.exec(event.target.name); + fieldPopTbl(a[1]); + } +} +function InitializeQuiz(qtfield,mark) { + var oQName=eval(qtfield); + Score=0; + retn = null; + if (!isQuizInitialized(qtfield)&&!isAQuizUnfinished()) return null; + neutralizeQuizzes(); + ProcessIt = false; + aQuizControl[qtfield] = 1; + this.resetForm(["ScoreField." + qtfield,"mc."+qtfield, + "obj."+qtfield,"mck."+qtfield,"Ans."+qtfield, + "PointsField."+qtfield,"PercentField."+qtfield, + "essay."+qtfield,"GradeField."+qtfield, + "grpobj."+qtfield,"qMark."+qtfield, qtfield+"SanityCheck", + qtfield+"SanityCheckPts",qtfield+"SanityCheckOOPts", + "rbmarkup."+qtfield]); + ProcessIt = true; + var f = this.getField("qMark."+qtfield); + if ( f != null ) f.display = display.hidden; + f = this.getField("promptButton."+qtfield); + if (f != null) f.display=display.visible; +% \end{macrocode} +% We create a special parameter for Oa.Sys. Then the arguments.length is +% 3 (or greater) we do not set the objective text fields to readonly=false. +% Oa.Sys already creates a readonly field for the solutions, we don't want +% to mess with that. +% \begin{macrocode} + if (arguments.length<3) { + f = this.getField("obj." + qtfield); + if ( f != null ) f.readonly = false; + } + RightWrong=new Array(); + Responses=new Array(); + ProbValue=new Array(); + ProbDist=new Array(); + ProbType=new Array(); + if (mark==1) + { +% \end{macrocode} +% The next few lines support local symbol and color assignment. +% \begin{macrocode} + var defaultColor=(typeof oQName.DefaultColorJSLoc=="undefined")% +?\defaultColorJS:oQName.DefaultColorJSLoc; + var rightColor=(typeof oQName.RightColorJSLoc=="undefined")% +?\rghtColorJS:oQName.RightColorJSLoc; + var corrAnsSymb=(typeof oQName.CorrAnsSymbJSLoc=="undefined")% +?\corrAnsSymbJS:oQName.CorrAnsSymbJSLoc; + var f = this.getField("mcq." + qtfield); + if (f != null) { + f.delay=true; + f.display=display.hidden; + this.resetForm([f.name]); +% \end{macrocode} +% (2013/10/27) Removed legacy code for version prior to 4.0 +% \begin{macrocode} + f.textColor = rightColor; + var a = f.getArray(); + for (var i=0; i<a.length; i++) a[i].style=corrAnsSymb; + f.delay=false; + } + f = this.getField("obj." + qtfield); + if ( f != null ) f.strokeColor = defaultColor; + f = this.getField("grpobj." + qtfield); + if ( f != null ) f.strokeColor = defaultColor; + f = this.getField("corr." + qtfield); + if ( f != null ) f.display = display.hidden; + f = this.getField(qtfield+"SanityCheck"); + if ( f != null ) f.strokeColor=defaultColor; + f = this.getField("rbmarkup."+qtfield); + if ( f != null ) f.display = display.hidden; + } + return null; +} +function neutralizeQuizzes() +{ + for ( var qtfield in aQuizControl ) aQuizControl[qtfield] = 0; +} +isAQuizUnfinished.check=true; +function isAQuizUnfinished() +{ + if (!isAQuizUnfinished.check) return true; + for ( var qtfield in aQuizControl ) + if ( aQuizControl[qtfield] == 1 ) + { + eqAppAlert(\eqerrUnfinishQuiz, 3); + return false; + } + return true; +} +function isQuizInitialized(qtfield) +{ + if (typeof (aQuizControl[qtfield]) == "undefined") + return false; + else + return (aQuizControl[qtfield] == 1); +} +function isEndQuizPushed(qtfield) +{ + if (typeof (aQuizControl[qtfield]) == "undefined") + return false; + else + return (aQuizControl[qtfield] == -1); +} +function resetQuiz(qtfield) +{ + aQuizControl[qtfield] = -1; +} +% \end{macrocode} +% The function RecordPointValue has two required parameters. For a grouped question, +% there are three more parameters, they are, in order (2) grpquestionno (3) grpPointValue +% (4) total weight (5) grpEvalFunction, a JS function that evaluates the group. +% The elements of the ProbValue array are as follows: +%\begin{enumerate} +% \item If multiple choice, then the entry is \texttt{[0, point value, partial credit]} +% \item If objective type question that is not part of a group, the entry is a number \texttt{point value} +% \item total weight of the group, significant only if greater than point value +% \item If objective grouped-type question, the entry is\\ +% \texttt{[1, EvalJS, grpPointValue, <list of points for each part>]} +%\end{enumerate} +% \begin{macrocode} +function RecordPointValue(ptvalue,probno) +{ + if (arguments.length > 2) { + if ( typeof ProbValue[probno] == "undefined" ) { + ProbValue[probno]=[1,arguments[5],arguments[3],arguments[4]]; + ProbValue[probno][3+arguments[2]] = ptvalue; + } else ProbValue[probno][3+arguments[2]] = ptvalue; + } + else { + ProbValue[probno]=ptvalue; + } +} +function RecordProblemType(qType,probno) +{ + ProbType[probno]=qType; +} +function GrpRight( a, nProb, qtfield ) +{ + var f = this.getField("grpobj."+qtfield+"."+nProb); + var l = f.getArray().length + var prod = 1; + for ( var i=1; i <= l; i++) prod *= !!a[i]; + return prod; + +} +function DisplayQuizResults(qtfield,nPointTotal,nQuestions) +{ + Score = 0; ptScore = 0; + for (var i=1; i < RightWrong.length; i++) + { + if ( (typeof RightWrong[i] == "object" ) % + && ( RightWrong[i][0] == "grp" ) ) { + // grouped question + Score += GrpRight(RightWrong[i], i, qtfield); + var aWeights = ProbValue[i].slice(2); + var evalGrpJS = eval(ProbValue[i][1]); + var evalGrpJSValue = evalGrpJS(this,qtfield,i, + RightWrong[i],aWeights); + ProbDist[i] = evalGrpJSValue; + ptScore = ptScore + evalGrpJSValue; + } else { + if (typeof RightWrong[i] == "object") { + if ( RightWrong[i][0] == 1 ) { + Score++; + ProbDist[i]=(typeof ProbValue[i] == "object") ? + 1*ProbValue[i][1] : 1*ProbValue[i]; + ptScore += (1*ProbDist[i]); + } else { + if (RightWrong[i][1] == 1) + ProbDist[i]=(typeof ProbValue[i]=="object") ? + 1*ProbValue[i][1] : 1*ProbValue[i]; + else + ProbDist[i]=(typeof ProbValue[i] == "object") ? + 1*ProbValue[i][1] : 0; + ptScore += (1*ProbDist[i]); + } + } else { + if (RightWrong[i]==1) { + Score++; + ProbDist[i] = ( typeof ProbValue[i] == "object") ? + 1*ProbValue[i][1] : 1*ProbValue[i]; + ptScore += (1*ProbDist[i]); + } + else { + ProbDist[i] = ( typeof ProbValue[i] == "object") ? + 1*ProbValue[i][2] : 0; + ptScore += (1*ProbDist[i]); + } + } + } + } +if ( !negPointsAllowed && (ptScore < 0) ) ptScore = 0; + if (ptScore == nPointTotal) pcScore = 100; + else pcScore = util.printf("\%.1f", (100 * ptScore) / nPointTotal); + var oQName=eval(qtfield); + var gradeScale=% +(typeof oQName.GradeScaleLoc=="undefined")% +?GradeScaleDefault:oQName.GradeScaleLoc; + quizGrade = GetGrade.apply(null,gradeScale); +% quizGrade = GetGrade(\eqGradeScale); + var f = this.getField("ScoreField."+qtfield); + if ( f != null ) f.value=(\eqQuizTotalMsg); + f = this.getField("PointsField."+qtfield); + if ( f != null) f.value=(\eqQuizPointsMsg); + f = this.getField("PercentField."+qtfield); + if ( f != null) f.value=(\eqQuizPercentMsg); + f = this.getField("GradeField."+qtfield); + if ( f != null) f.value=(\eqQuizGradeMsg); +} +function GetGrade() +{ + var cGrade, aRange; + var l = arguments.length/2; + if (pcScore >=100) return arguments[0]; + if (pcScore < 0 ) return arguments[arguments.length-2]; + for (var i=0; i < l; i++) + { + cGrade = arguments[2*i]; + aRange = arguments[2*i+1]; + if ( (pcScore >= arguments[2*i+1][0]) + && (pcScore < arguments[2*i+1][1])) return cGrade; + } + return null; +} +function ProcessQuestion (key,letterresp,probno, + quizno,qtfield,notify,mark,msg) { + var silent = ( arguments.length > 8 ) ? true : false; + if (!isQuizInitialized(qtfield)) + { + if (!silent) eqAppAlert(InitMsg(msg),3); + this.resetForm(["mc."+qtfield+"."+probno, + "mck."+qtfield+"."+probno]); + } + else + { + ProcUserResp(key,letterresp,probno,notify); + if (mark==1) + { + var oQName=eval(qtfield); + var defaultColor=% +(typeof oQName.DefaultColorJSLoc=="undefined")% +?\defaultColorJS:oQName.DefaultColorJSLoc; + var rightColor=% +(typeof oQName.RightColorJSLoc== "undefined")% +?\rghtColorJS:oQName.RightColorJSLoc; + var wrongColor=% +(typeof oQName.WrongColorJSLoc=="undefined")% +?\wrngColorJS:oQName.WrongColorJSLoc; + var rightAnsSymb=% +(typeof oQName.RightAnsSymbJSLoc=="undefined")% +?\rghtAnsSymbJS:oQName.RightAnsSymbJSLoc; + var wrongAnsSymb=% +(typeof oQName.WrongAnsSymbJSLoc=="undefined")% +?\wrngAnsSymbJS:oQName.WrongAnsSymbJSLoc; + var corrAnsSymb=% +(typeof oQName.CorrAnsSymbJSLoc=="undefined")% +?\corrAnsSymbJS:oQName.CorrAnsSymbJSLoc; +% \end{macrocode} +% MC or MS questions +% \begin{macrocode} + var f = this.getField("mcq."+qtfield+"."+probno); + var fck = this.getField("mck."+qtfield+"."+probno); + var bMultiSelect = ( fck != null ) ? true : false; + f.delay=true; + this.resetForm([f.name]); + var a = f.getArray(); + var l = a.length; + if ( bMultiSelect ) { + var ack = fck.getArray(); + for ( var i=0; i<l; i++) { + if ( ack[i].isBoxChecked(0) ) { + a[i].style = ( a[i].isDefaultChecked(0) ) ? + rightAnsSymb : wrongAnsSymb; + a[i].textColor = ( a[i].isDefaultChecked(0) ) ? + rightColor : wrongColor; + a[i].value = "Yes"; + } else { + a[i].style = ( a[i].isDefaultChecked(0) ) ? + corrAnsSymb : wrongAnsSymb; + a[i].textColor = ( a[i].isDefaultChecked(0) ) ? + rightColor : wrongColor; + a[i].value = ( a[i].isDefaultChecked(0) ) ? + "Yes" : "Off"; + } + } + } else { + for (var i=0; i < a.length; i++) + if (a[i].style == rightAnsSymb) + { + a[i].style = corrAnsSymb; + a[i].textColor = rightColor; + } + var qr=this.getField(% +"mcq."+qtfield+"."+probno+"."+quizno); +% \end{macrocode} +% (2013/10/27) removed legacy code for versions prior to 4.0. +% \begin{macrocode} + qr.textColor = key ? rightColor :wrongColor; + qr.style = key ? rightAnsSymb : wrongAnsSymb; + qr.value="Yes"; // gr.checkThisBox(0); // ver 5.0 + } + this.getField("mcq."+qtfield+"."+probno).delay=false; + } + } + if ( typeof fieldPopTbl == "function" ) fieldPopTbl(qtfield); +} +% \end{macrocode} +% Dependencies: \texttt{RightWrong}, \texttt{ProbDist} (if \texttt{qMark} is present). +% \begin{macrocode} +function correctQuiz(qtfield,nQuestions) +{ + var oQName=eval(qtfield); + var defaultColor=(typeof oQName.DefaultColorJSLoc=="undefined")% +?\defaultColorJS:oQName.DefaultColorJSLoc; + var rightColor=(typeof oQName.RightColorJSLoc=="undefined")% +?\rghtColorJS:oQName.RightColorJSLoc; + var wrongColor=(typeof oQName.WrongColorJSLoc=="undefined")% +?\wrngColorJS:oQName.WrongColorJSLoc; + var rightAnsSymb=(typeof oQName.RightAnsSymbJSLoc=="undefined")% +?\rghtAnsSymbJS:oQName.RightAnsSymbJSLoc; + var wrongAnsSymb=(typeof oQName.WrongAnsSymbJSLoc=="undefined")% +?\wrngAnsSymbJS:oQName.WrongAnsSymbJSLoc; +% \end{macrocode} +% MC or MS questions +% \begin{macrocode} + var f = this.getField("mcq." + qtfield); + if ( f != null) f.display = display.visible; + f = this.getField("obj." + qtfield); + if ( f != null ) { + var a = f.getArray(); + var re=/^obj\./; + for (var i = 0; i < a.length; i++) { + var probno = a[i].name.replace(/.*\./g,""); + var rbmuname = a[i].name.replace(re,"rbmarkup\."); + var oRBMarkup = this.getField(rbmuname); + var bRBMU = ( oRBMarkup != null ); + if ( RightWrong[probno] == 1 ) { + a[i].strokeColor = rightColor; + if (bRBMU) { + oRBMarkup.textColor=rightColor; + oRBMarkup.style=rightAnsSymb; + } + } else { + a[i].strokeColor = wrongColor; + if (bRBMU) { + oRBMarkup.textColor=wrongColor; + oRBMarkup.style=wrongAnsSymb; + } + } + } + } + f = this.getField("grpobj." + qtfield); + var re=/^grpobj\./; + if ( f != null ) { + var a = f.getArray(); + for ( var i = 0; i < a.length; i++) { + var rbmuname = a[i].name.replace(re,"rbmarkup\."); + var oRBMarkup = this.getField(rbmuname); + var bRBMU = ( oRBMarkup != null ); + var aX = a[i].name.split("."); + var probno = 1*aX[aX.length-2]; + var grpProbno = 1*aX[aX.length-1]; + if ( ( RightWrong[probno] != undefined ) % +&& ( RightWrong[probno][grpProbno] == 1 ) ) { + a[i].strokeColor = rightColor; + if (bRBMU) { + oRBMarkup.textColor=rightColor; + oRBMarkup.style=rightAnsSymb; + } + } else { + a[i].strokeColor = wrongColor; + if (bRBMU) { + oRBMarkup.textColor=wrongColor; + oRBMarkup.style=wrongAnsSymb; + } + } + } + } + f=this.getField("rbmarkup."+qtfield); + if ( f != null ) f.display = display.visible; +% f = this.getField("Ans." + qtfield); + % if ( f != null ) f.strokeColor = defaultColor; + f = this.getField("promptButton." + qtfield) + if ( f != null ) f.display = display.hidden; + f = this.getField("corr." + qtfield); + if ( f != null ) f.display = display.noPrint; +% \end{macrocode} +% dps (01/01/04) If there are qMark fields, then write marks for each question +% to them. +% \begin{macrocode} + f = this.getField("qMark."+qtfield); + if ( f != null ) + { +% console.println("ProbDist = " + ProbDist.toSource() ); + for ( var i = 1; i <= nQuestions; i++) + { + if ( ProbValue[i] == undefined ) ProbValue[i]=0 + f = this.getField("qMark."+qtfield+"."+(i-1)); + if ( f != null ) + { +% \end{macrocode} +% (3/22/04) This is code to account for grouping +% \begin{macrocode} + // find the next non-null field + for ( var j=i; j <= nQuestions; j++) + { + var h = this.getField("qMark."+qtfield+"."+j); + if ( h != null ) break; + } + var g = f.getArray(); + var qpts=(ProbDist[i]==undefined) ? 0 : ProbDist[i]; + if ( !negPointsMarkupAllowed && (qpts < 0) ) qpts=0; + g[0].value = qpts + (( qpts == 1 ) ? " \eqptLabel\space" + : " \eqptsLabel"); + } + } + this.getField("qMark."+qtfield).display = display.visible; + } +} +% \end{macrocode} +% When pdftex is used, the total tally box does not work because pdftex does not support +% the calculate key in AcroForms. We try to simulate this. +% \begin{macrocode} +function getTotalTally(basename) { + var sqtotal=0; + var f=this.getField("tally."+basename); + var g = f.getArray(); + for (var i=0; i<g.length; i++) { + if ( g[i] == event.target ) sqtotal += (1*event.value); + else sqtotal += (1*g[i].value); + } +% console.println("sqtotal="+sqtotal); + if ( ( f=this.getField("tallytotal."+basename) ) != null ) + f.value = sqtotal; +} +function clearAllSubQuizzes() { + isAQuizUnfinished.check=false; + for ( var o in lstOfQuizzes) { + if (lstOfQuizzes[o].isSubmitted) + eval ( lstOfQuizzes[o].initializeWith ); + } + isAQuizUnfinished.check=true; +} +\end{newsegment} +% \end{macrocode} +% \subsection{Support for Multiple Selection Questions} +% This function +% \begin{macrocode} +\begin{newsegment}{Eq: Support for Multi-Selection} +function ProcessMultiSelection(key,letterresp,probno,% +quizno,qtfield,pts,ppts) { + var f = this.getField("mck."+qtfield+"."+probno); +% \end{macrocode} +% For the multiple selection problem, the formats for the \texttt{RightWrong} and \texttt{ProbValue} +% arrays are as follows: +%\begin{verbatim} +% RightWrong[probno] +% [0, 1, [undefined, undefined, 0, 1, 1, 0, 1]] +%\end{verbatim} +% The first entry records whether the user answered the question totally correctly, +% the second entry is for awarding points, 1 if the user selected at least one correct +% answer. The third entry is an array of right/wrong responses to the user's responses. +%\begin{verbatim} +% ProbValue[probno] +% [3, 5, [undefined, undefined, -2, 3, 3, -2, 3]] +%\end{verbatim} +% First entry is the number of correct answers for this problem, the second entry is the +% number of points the student has earned for this problem, the third entry is an array of points obtained +% based on the user's responses. +%\changes{v6.3h}{2008/10/17 } +%{% +% For the manswers environment, we were not determining if the user had answered the question +% correctly. +%} +% \begin{macrocode} + if ( typeof ProbValue[probno] == "undefined" ) { + var g = f.getArray(); +% \end{macrocode} +% We calculate the total number of correct alternatives in this MS field +% \begin{macrocode} + var nTotalCorrect = 0; + for ( var i=0; i<g.length; i++ ) + nTotalCorrect += (1*g[i].exportValues[0].charAt(0)); + ProbValue[probno] = new Array(); + RightWrong[probno] = new Array(); + ProbValue[probno] = [nTotalCorrect,pts,[]]; + RightWrong[probno][2] = new Array(); + } else var nTotalCorrect = ProbValue[probno][0]; + var fck = this.getField("mck."+qtfield+"."+probno+"."+quizno); + if ( fck.isBoxChecked(0) ) { + ProbValue[probno][2][quizno] = ppts; + RightWrong[probno][2][quizno] = key; + } else { + ProbValue[probno][2][quizno] = undefined; + } + var pointsThisProblem=0; + var scoreThisProblem = 0; + var letterResponses = new Array(); + var areAllCorrect=1; + var numCorrect=0; + for ( var i=1; i< ProbValue[probno][2].length; i++ ) { + if ( typeof ProbValue[probno][2][i] != "undefined" ) + letterResponses[i] = (String.fromCharCode(96+i)); + pointsThisProblem += ( ( typeof ProbValue[probno][2][i]==% +"undefined" )?0:ProbValue[probno][2][i]); + if ( typeof ProbValue[probno][2][i]!="undefined" ) { +% \end{macrocode} +% As we go through the \texttt{ProbValue[probno][2]} array, we use the index +% to make some tallies in the \texttt{RightWrong[probno][2]} array. We multiply +% and add all entries together. The value of \texttt{areAllCorrect} will be 1 if the +% student only chooses correct answers, while \texttt{numCorrect} totals the number of +% correct responses. +% \begin{macrocode} + areAllCorrect *= (1*RightWrong[probno][2][i]); + numCorrect +=(1*RightWrong[probno][2][i]); + } + } +% \end{macrocode} +% The value of \texttt{scoreThisProblem} will be 0 if the user selects any false +% answers, and will be the number of correct answers selected otherwise. +% \begin{macrocode} + scoreThisProblem = areAllCorrect*numCorrect; +% \end{macrocode} +% Now the value of \texttt{scoreThisProblem} is 0 if the user selects any false +% answers, and~1 if the number of correct answer equals the total number of +% correct answers for this problem. +% \begin{macrocode} + var scoreThisProblem = Number( scoreThisProblem == nTotalCorrect ); +% \end{macrocode} +% \texttt{(02/02/09)}: If we determine this problem is right, but \texttt{pointsThisProblem==0}, +% then there must be no partial credit specification of the points, so we'll award all points. +% \begin{macrocode} + if (scoreThisProblem==1 && pointsThisProblem==0 ) + pointsThisProblem=pts; + ProbValue[probno][1] = + ( (ProbValue[probno][1] == 0) && (scoreThisProblem == 1) ) + ? pts : pointsThisProblem; +% \end{macrocode} +% \texttt{passKey} represents whether positive credit is assigned; \texttt{passKey} is only 1 +% when points are awarded. \texttt{scoreThisProblem} is 0 or 1 dependent +% on whether the problem is wrong or right. +% \begin{macrocode} + var passKey = ( pointsThisProblem > 0 ) ? 1 : 0; + var retn = [ [ scoreThisProblem, passKey ], letterResponses ] ; + return retn; +} +function LimitSelection(n,fname,k) { + var f = this.getField(fname); + var g = f.getArray(); + var total=0; + for (var i=0; i<g.length; i++) { + total+=( g[i].isBoxChecked(0) ); + } + if (total > n) { + eqAppAlert(\limSelWarningMsg,3); + f=this.getField(fname+"."+k); + f.checkThisBox(0,false); + return false + } else return true; +} +\end{newsegment} +% \end{macrocode} +% \subsection{Miscellaneous JS} +% \begin{macrocode} +\begin{newsegment}{Eq: Miscellaneous JS} +% \end{macrocode} +% This function notifies the calling field of the results. If flag=0, +% it changes the color of the field and updates the tally field. +% \begin{macrocode} +function chooseJSColor( b, c1, c2 ) { + return ( b ) ? c1 : c2; +} +function notifyField(success, flag, fieldname) { + if ( flag != 0 ) + return (success)?true:false; +% \end{macrocode} +% if \texttt{flag == 0}, then we are working with a \texttt{shortquiz}, and immediate response +% is needed. +% \begin{macrocode} + var f = this.getField(fieldname); + var re=/^(obj|grpobj)\./; + var gname=fieldname.replace(re,"rbmarkup\."); + var g =this.getField(gname); + var isthereRBUP = ( g !=null ); +% \end{macrocode} +% Extract the quiz name from the field name: \texttt{obj.QName.num} or \texttt{grpobj.QName.num} +% \begin{macrocode} + var h = fieldname.replace(re,""); + var index=h.indexOf("."); + var oQName = eval(h.substring(0,index)); + var rightColor=(typeof oQName.RightColorJSLoc=="undefined")% +?\rghtColorJS:oQName.RightColorJSLoc; + var rightSymb=(typeof oQName.RightColorJSLoc=="undefined")% +?\rghtAnsSymbJS:oQName.RightAnsSymbJSLoc; + var wrongColor=(typeof oQName.WrongColorJSLoc=="undefined")% +?\wrngColorJS:oQName.WrongColorJSLoc; + var wrongSymb=(typeof oQName.WrongAnsSymbJSLoc=="undefined")% +?\wrngAnsSymbJS:oQName.WrongAnsSymbJSLoc; + if (success) { + f.strokeColor = rightColor; + if (isthereRBUP) { + g.style = rightSymb; + g.textColor=rightColor; + g.display=display.visible; + } + return true; + } else { + updateTally.downState=false; + updateTally(fieldname); + f.strokeColor = wrongColor; + if (isthereRBUP) { + b2 = ( typeof oQName.WrongAnsSymbJSLoc == "undefined" ); + g.style = wrongSymb; + g.textColor=wrongColor; + g.display=display.visible; + } + return false; + } +// return null; // remove ? +} +% \end{macrocode} +% \begin{macrocode} +function updateTally(fieldname) +{ + var objre = /^obj\./; + var grpre = /^grpobj\./; +% \end{macrocode} +% If the question is part of a group of questions, then it has a root name of \texttt{grpobj}. +% This root needs to be removed, as well as the sub-group number. +% \begin{macrocode} + if ( grpre.test(fieldname) ) { + fieldname = fieldname.replace(grpre,""); + var pos = fieldname.lastIndexOf("."); + fieldname = fieldname.substring(0,pos); + } else if ( objre.test(fieldname) ) + fieldname = fieldname.replace(objre,""); + var f = this.getField("tally."+fieldname); + if ( f != null ) { + if (!updateTally.downState) f.value += 1; + return true; + } else return false; + +} +% \end{macrocode} +% Below is the \texttt{noPeek} JS function that has been part of \textsf{exerquiz} from the +% beginning. +%\begin{verbatim} +%function noPeek(qtfield,rtnPage) +%{ +% if ( (typeof (aQuizControl[qtfield]) == "undefined") % +%|| (aQuizControl[qtfield] != -1) ) { +% this.pageNum = rtnPage-1; +% eqAppAlert(\noPeekMsg,3); +% } +%} +%\end{verbatim} +% (2010/08/09 v6.3s) One user recently reported that Acrobat/Reader can crash when \texttt{noPeek} is in effect. +% This occurs when the down arrow on the scroll bar is pressed and kept pressed by the mouse. +% The pages can jump between the quiz and a solution page, and build up alert boxes each time. +% Eventually, there is a crash (though I haven't experienced the crash, I have seen the effects +% of using the down arrow on the scroll bar). Below is a proposed ``fix'' for using this +% hellish button. We turn off the alert for 5 milliseconds but always return to the +% starting page (\texttt{rtnPage}), it is not the best solution, but it fixes the crashing +% problem. +% \begin{macrocode} +var bNoPeekWait=false; +var oNoPeekTimer; +function noPeek(qtfield,rtnPage) +{ + if (!bNoPeekWait) { + if ( (typeof (aQuizControl[qtfield]) == "undefined") % +|| (aQuizControl[qtfield] != -1) ) { + bNoPeekWait=true; + oNoPeekTimer=app.setTimeOut("bNoPeekWait=false;% +app.clearTimeOut(oNoPeekTimer);",5); + this.pageNum = rtnPage-1; + \NoPeekAlert; + } + } else this.pageNum = rtnPage-1; +} +% \end{macrocode} +% When the user exits a fill-in shortquiz field, this function is called. +% It immediately notifies user of whether their answer is right +% or wrong, and changes the color of the boundary field. +% \begin{macrocode} +var oCB=\bcheckboxused +function OnBlurRespBox (retn) +{ + var qname = arguments[1]; + var oQName = eval(qname); + var respMsg; + var cTitle = "AcroTeX eDucation Bundle"; + if (retn != null) { + if ( typeof appAlerts[qname] == "undefined") + appAlerts[qname] = {bAfterValue: false, % +cMsg: "\doNotShowAgainMsg"}; + var respMsg = (retn) ? \eqsqrtmsg\space : \eqsqwgmsg; + if ( (event.target == this) || !oCB) + eqAppAlert({ cMsg: respMsg, nIcon: 3, cTitle: cTitle }); + else { + if ( ! appAlerts[arguments[1]].bAfterValue ) + eqAppAlert({ cMsg: respMsg, nIcon: 3, cTitle: cTitle, % +oCheckbox: appAlerts[qname]}); + } + } + else { + var re=/^(obj|grpobj)\./; + var gname=event.target.name.replace(re,"rbmarkup\."); + var g =this.getField(gname); + var isthereRBUP = ( g !=null ); + var str = event.target.value.toString(); + if (str.replace(/\s/g,"") == "") { + var defaultColor=% +(typeof oQName.DefaultColorJSLoc=="undefined")% +?color.black:oQName.DefaultColorJSLoc; + if (isthereRBUP) g.display=display.hidden; + event.target.strokeColor = defaultColor; + } + } +} +function jmpToNamedDest(fName,cDest,bAlert) { + if ( (typeof appAlerts[fName]!="undefined" % +&& appAlerts[fName].bAfterValue) || bAlert==0) + app.setTimeOut("this.gotoNamedDest(\""+cDest+"\")",500); + else + this.gotoNamedDest(cDest); +} +% \end{macrocode} +% Description: This is the default function for determining whether +% the minimal requirements for finishing a quiz have been met. The +% default is that there is no minimal requirement. +% Arguments: qtfield = name of the field. +% Returns: true if minimum threshold is met, false otherwise. +% \begin{macrocode} +function lowThreshold(nQuestions) +{ + return true; +} +% \end{macrocode} +% Description: This is the default function for determining whether +% the minimal requirements for finishing a quiz have been met. Here +% the requirements are to answer all the questions. +% Arguments: nQuestions = number of questions. +% Returns: true if minimum threshold is met, false otherwise. +% +% \noindent You can define this function as the default threshold function by +% typing\par +%\begin{verbatim} +%\renewcommand\minQuizResp{highThreshold} +%\end{verbatim} +% \begin{macrocode} +function highThreshold(nQuestions) +{ + var cnt=0; + for ( var i=0; i< Responses.length; i++ ) { + if ( typeof Responses[i]!="undefined") cnt++ + } + if ( cnt<nQuestions ) + eqAppAlert(\highThresholdMsg,3); + return (cnt >= nQuestions); +} +\end{newsegment} +% \end{macrocode} +% \subsection{Support for Grouped Questions} +% These function can be called by the \texttt{mathGrp} environment to score the user's +% responses to the grouped questions. +% \begin{macrocode} +\begin{newsegment}{Eq: Support for Grouped Questions} +function groupEval(doc,qtfield,probno,aKey,aWeights) +{ + var totalGrpPts = aWeights[0]; + var totalWeight = aWeights[1]; + for ( var i=1,total=0; i< aKey.length; i++ ) + if (aKey[i] != undefined) total += aKey[i]*aWeights[i+1]; + return total; +} +function WeightedEval(doc,qtfield,probno,aKey,aWeights) +{ + var f = doc.getField("grpobj." + qtfield + "." + probno); + var nGrpQno = f.getArray().length; + var totalGrpPts = aWeights[0]; + var totalWeight = aWeights[1]; + for ( var i=1,total=0; i < aKey.length; i++ ) + if (aKey[i] != undefined) total += aKey[i]*aWeights[i+1]; + total /= totalWeight; + total = Math.floor( total * totalGrpPts ); + return total; +} +% \end{macrocode} +% This function gives full credit if all parts are answer correctly, +% otherwise, it gives no credit. This defeats the purpose of partial +% credit. But someone asked for it. +% \begin{macrocode} +function groupBernoulliEval(doc,qtfield,probno,aKey,aWeights) +{ + var f = doc.getField("grpobj." + qtfield + "." + probno); + var nGrpQno = f.getArray().length; + var totalGrpPts = aWeights[0]; + for ( var i=1,isCorrect=1; i<= nGrpQno; i++ ) + isCorrect *= (aKey[i] != undefined) ? (Number(aKey[i])) : 0; + return (isCorrect*totalGrpPts); +} +\end{newsegment} +\end{insDLJS*} +%</aebjs> +%<*sumrytbls> +% \end{macrocode} +% This function is called by the \cs{CorrButton}, it does nothing if the ``SanityCheck'' +% fields are not present; otherwise, it colors the boundaries red, green or blue +% depending on whether the problem is wrong, right, or wrong with partial credit given. +% \begin{macrocode} +\begin{insDLJS}[correctSumryTbl]{sumtbljs}{Eq: Populate Summary Table} +function correctSumryTbl(qtfield,nQuestions) { +% \end{macrocode} +% \paragraph*{Checkboxes.} We begin by correcting the second column of the summary table. +% \begin{macrocode} + var oQName=eval(qtfield); + var rightColor=(typeof oQName.RightColorJSLoc=="undefined")% +?\rghtColorJS:oQName.RightColorJSLoc; + var wrongColor=(typeof oQName.WrongColorJSLoc=="undefined")% +?\wrngColorJS:oQName.WrongColorJSLoc; + var partialColor=(typeof oQName.PartialColorJSLoc=="undefined")% +?\partialColorJS:oQName.PartialColorJSLoc; + var sc=this.getField(qtfield+"SanityCheck"); + var nc=this.getField(qtfield+"NoCorrections"); + if (sc != null && nc == null ) { + for (var i=0; i<nQuestions; i++) { + var cb=this.getField(qtfield+"SanityCheck."+(i+1)); + if (typeof RightWrong[i+1] == "undefined" ) { + cb.strokeColor=wrongColor; + continue; + } + if ( RightWrong[i+1] == 1 ) { + cb.strokeColor=rightColor; + continue; + } + if ( RightWrong[i+1] == 0 ) { + // this is either an obj or multiple choice q + if ( typeof ProbValue[i+1] == "object" ) + cb.strokeColor=( ProbValue[i+1][2] > 0 )?% +partialColor:wrongColor; + else cb.strokeColor=wrongColor; // obj q + continue; + } + // either multiple selection or grouped math + if ( RightWrong[i+1][0] == "grp" ) { + // grouped question + var f = this.getField("grpobj."+qtfield+"."+(i+1)); + var l = f.getArray().length; + // is this right? + for (var sum=0, j=1; j<=l; j++) + sum+=(!!RightWrong[i+1][j]); + if ( sum == l ) cb.strokeColor=["RGB", 0, .6, 0]; + else cb.strokeColor=( sum > 0 )?% +partialColor:wrongColor; + continue; + } + // multiple selection + if ( RightWrong[i+1][0] == 1 ) cb.strokeColor=rightColor; + else cb.strokeColor=(RightWrong[i+1][1]== 1)?% +partialColor:wrongColor; + } + } +% \end{macrocode} +% \paragraph*{Markup text fields.} Now, we insert the points into the +% markup text fields for the summary table. We look for two types of +% fields, in the next two lines. Each type is formatted differently. +% \begin{macrocode} + var f1=this.getField(qtfield+"SanityCheckPts"); + var f2=this.getField(qtfield+"SanityCheckOOPts"); + var h=this.getField(qtfield+"activateSC"); +% \end{macrocode} +% If nonnull here, we format these text fields in the usual way, `2 pts', for example. +% \begin{macrocode} + if ( f1 != null ) { + for ( var i = 1; i <= nQuestions; i++) { + if ( ProbValue[i] == undefined ) ProbValue[i]=0 + // find the next non-null field + var g=this.getField(qtfield+"SanityCheckPts."+i); + var qpts=(ProbDist[i]==undefined) ? 0 : ProbDist[i]; + var thesePts= qpts + (( qpts == 1 )?% +" \eqptLabel":" \eqptsLabel"); + g.value = thesePts; + } + } +% \end{macrocode} +% \texttt{f2} is nonnull when \texttt{showOutOf=true} for any of the tables supporting \texttt{qtfield}, +% we repeat basically the same loop, but formatting the value differently. +% \begin{macrocode} + if ( f2 != null ) { + for ( var i = 1; i <= nQuestions; i++) { + if ( ProbValue[i] == undefined ) ProbValue[i]=0 + // find the next non-null field + var g=this.getField(qtfield+"SanityCheckOOPts."+i); + var qpts=(ProbDist[i]==undefined) ? 0 : ProbDist[i]; + var ptValue = oQName.PtValues[i]; + var probPts = ptValue + (( ptValue == 1 )?% +" \eqptLabel":" \eqptsLabel"); + g.value = qpts +" \stOutOf\space"+probPts; + } + } +} +function popVisitsTbl(qtfield,nQuestions) { + if ( aQuizControl[qtfield] == 1) { + this.resetForm([qtfield+"SanityCheck"]); + for ( var i=0; i < nQuestions; i++ ) { + var f=this.getField(qtfield+"SanityCheck."+(i+1)); + f.checkThisBox(0,(typeof Responses[i+1]!="undefined")); + } + } +} +% \end{macrocode} +% \DescribeMacro{fieldPopTbl} is called when there is a change in a response. +% it gets info contained in a button embedded in the summary table (\texttt{nQuestions}) +% and then calls \texttt{popVisitsTbl()}. +% \begin{macrocode} +function fieldPopTbl(qtfield) { + var f=this.getField(qtfield+"activateSC"); + if ( f != null) { + var n=Number(f.userName); + var a = [ qtfield, n ]; + popVisitsTbl.apply(null,a); + } +} +\end{insDLJS} +%</sumrytbls> +%<*mcfi> +\newcommand{\clickChkBxMCFI}{"Click the check box preceding this + math input field to enter text."} +\begin{insDLJS}{mcf}{Eq: Supports MCFI-type questions} +function mcfiKeyStroke(qname,n) { + if (event.change=="") return; + var qNumMC=--n; + var mcName="mc."+qname+"."+qNumMC; + var mc= this.getField(mcName); + var aExpVs=mc.exportValues; + var l=aExpVs.length-1; + if (!mc.isBoxChecked(l)) { + eqAppAlert(\clickChkBxMCFI,3); + event.rc=false; + } +} +function qRadioButtonMCFI(key,qname,n) { + var fname = "obj."+qname+"."+(n+1); + if ( key == 0) this.resetForm(fname); +} +\end{insDLJS} +%</mcfi> +% \end{macrocode} +% \section{Language Definitions} +% \StopEventually{Comment out \cs{OnlyDescription} +% at the beginning of this file to see the language code.} +% \subsection{French} +% \begin{macrocode} +%<*eqfr> +% \end{macrocode} +% \begin{macrocode} +%%%%%%%%%%%%%%%%%%%%%%% eqfr.def %%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Jean-Michel SARLAT %% +%% Language: French %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Exercise label +\renewcommand\exlabel{Exercice} +% The value of this macro is written to \jobname.sol, +% accented characters must be protected with a \protect +\renewcommand\exlabelsol{\exlabel} + +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{Solution} :} + +% Title of exercise solution section +\renewcommand\exsectitle{Solutions des \exlabelsol s} +\renewcommand\exsecrunhead{\exsectitle} + +% Title of quiz solution section +\renewcommand\eq@sqslsectitle{Les r\'{e}ponses aux questionnaires} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to quizzes +\renewcommand\eq@sqslsecrunhead{Les r\'{e}ponses aux questionnaires} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{% + \protect\textbf{R\protect\'{e}ponse :}} +\renewcommand\sqsllabel{\eq@sqsllabel}% User access + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Solution} :} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Question.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +% No formatting allowed +\renewcommand\eq@sqslrtnlabel{Retour au questionnaire.} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Exact !"} +\renewcommand\eqsqwgmsg{"Faux !"} + +% Here is the default quiz label. No formatting allowed! +\renewcommand\eq@bqlabel{D\'ebut} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +%==> modif JMS <==% +% Les modifications du contenu de \eqlabel ne seront pas prises en +% compte dans les messages de javascript (pb pour faire passer les +% accents dans le code !). Ceci justifie pour moi l'introduction de +% la variable \bqlabelISO ou le label de debut de questionnaire est +% cod\'{e} ISO (octal). Cela parce que je veux utiliser le mot D\'ebut. +% Use \protect\351, this helps out TeX4ht by Eitan Gurari +\renewcommand\eq@bqlabelISO{D\string\351but} +\renewcommand\bqlabelISO{\eq@bqlabelISO} + +% Here is the default quiz label. +\renewcommand\eq@eqlabel{Fin} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments +\renewcommand\eq@Score{Score :}\renewcommand\eq@OutOf{sur} +\renewcommand\eqInitQuizMsg{% + "Vous devez initialiser le questionnaire ! Clicker sur "+msg+"."} +\renewcommand\eqMadeChoice{ + "Vous avez d\string\\351j\string\\340 fait un choix," + + " ce choix est ("+Responses[probno]+")." + + " Souhaitez vous le modifier ?"} +% +% Valeur "Yes" d'Acrobat +% +% Default button labels for \eqButton +%\renewcommand\eq@local@CA{R\string\351ponses} +\renewcommand\eq@local@CA{% + R\texorpdfstring{\'}{\string\351}ponses} +\renewcommand\eq@local@RC{Correctes} +\renewcommand\eq@local@AC{SVP !} +%</eqfr> +% \end{macrocode} +% \subsection{German} +% \begin{macrocode} +%<*eqde> +% \end{macrocode} +% \begin{macrocode} +%%%%%%%%%%%%%%%%%%%% eqde.def %%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Michael Wiedmann %% +%% e-mail address: michael.wiedmann@detewe.de %% +%% Language: German %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% The exercise label +\renewcommand\exlabel{\"Ubung} +% The value of this macro is written to \jobname.sol, +% accented characters must be protected with a \protect +\renewcommand\exlabelsol{\protect\"Ubung} + +% Title of exercise solution section +\renewcommand\exsectitle{L\"osungen der \exlabel en} +\renewcommand\exsecrunhead{L\protect\"osungen der \exlabelsol en} + +% Solution label for solutionafter option +\renewcommand{\eq@exsolafterDefault}{\textit{L\"osung}:} + +% Title of quiz solution section +\renewcommand\eq@sqslsectitle{L\"osungen der Aufgaben} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to quizzes +%\renewcommand\eq@sqslsecrunhead{L\"osungen der \"Ubungen} +\renewcommand\eq@sqslsecrunhead{L\"osungen der Aufgaben} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{% + \protect\textbf{L\protect\"osung zu Aufgabe:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{L\"osung}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Aufgabe}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +%\renewcommand\eq@sqslrtnlabel{Ende Aufgabe} +%\renewcommand\eq@sqslrtnlabel{Test beenden} +\renewcommand\eq@sqslrtnlabel{zur\"{u}ck zur Aufgabe} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Richtig!"} +\renewcommand\eqsqwgmsg{"Falsch!"} + +% Here is the default quiz label. +%\renewcommand\eq@bqlabel{Beginn Aufgabe} +\renewcommand\eq@bqlabel{Test starten} +% User access to quiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. Use PDFDocEncoding +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabelISO} + +% Here is the default quiz label. +%\renewcommand\eq@eqlabel{Ende Aufgabe} +\renewcommand\eq@eqlabel{Test beenden} +% User access to quiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +\renewcommand\eq@Score{Punkte:}\renewcommand\eq@OutOf{von} +\renewcommand\eq@ptScore{Punkte:} +\renewcommand\eqInitQuizMsg{% + "Sie m\374ssen die Aufgaben zuerst initialisieren!" + + " Bitte klicken Sie hierf\374r auf "+msg+" am Anfang des Tests."} +\renewcommand\eqMadeChoice{% + "Sie haben bereits geantwortet. Ihre Antwort war + ("+Responses[probno]+")." + " Wollen Sie dies \string\344ndern?"} +\renewcommand\eq@local@CA{Korrigiere} +\renewcommand\eq@local@RC{Meine Antworten!} +\renewcommand\eq@local@AC{Bitte!} +\renewcommand{\AnsPromptBtnStr}{Antwort:\space} +\renewcommand\eqerrABS{"Betr\string\344ge sind nicht ausgeglichen. + Bitte korrigieren Sie das."} +\renewcommand\eqerrBadMathFunc{"Der Ausdruck '"+aF[i]+"' ist weder + eine definierte Funktion noch ein g\string\374ltiger mathematischer + Ausdruck."} +\renewcommand\eqParens{"runde Klammern"} % ( ) +\renewcommand\eqBrackets{"eckige Klammern"} % [ ] +\renewcommand\eqBraces{"geschweifte Klammern"} % { } +\renewcommand\eqerrDelimNotBal{aGroup[i][2] + " sind nicht ausgeglichen. + Bitte korrigieren Sie das."} +\renewcommand\eqerrBadExp{"Ung\string\374ltiger mathematischer Ausdruck. + Es gibt ein Problem mit einem der Exponenten. + Bitte korrigieren Sie das!"} +\renewcommand\eqerrUnfinishQuiz{"Sie haben einen Test nicht beendet. + Bitte beenden Sie diesen, bevor Sie einen neuen Test beginnen."} +\dlJSStr*[noquotes]{\noPeekMsg}{"Bevor Sie den Test nicht beendet + haben, ist es nicht erlaubt, die L\"{o}sungen anzuschauen!"} +\renewcommand\highThresholdMsg{"Sie m\string\374ssen alle Fragen + beantworten, bevor der Test ausgewertet wird."} +\dlJSStr*[noquotes]{\eqSyntaxErrorUndefVar}{"Syntax Error: Es existiert + m\"{o}glicherweise eine undefinierte Variable oder ein Ausdruck + ist nicht im erwarteten Format geschrieben."} +\dlJSStr[noquotes]{\eqSyntaxErrorComma}{"Syntax Error: Ein Komma wurde" + + " in Ihrer Antwort \"" + + UserAns + "\" gefunden. Bitte entfernen Sie das Komma," + + " sonst wird diese Antwort als falsch gewertet."} +\dlJSStr*[noquotes]{\limSelWarningMsg}{"F\"{u}r diese Aufgabe k\"{o}nnen + sie h\"{o}chstens " + n + " ausw\string\344hlen."} +\fieldJSStr*[noquotes]{\promptButtonMsg}{% + "M\"{o}chten Sie die richtige Antwort jetzt sehen?" + + " Ihre derzeitige Antwort ist diejenige, die gewertet wird." + + " Wenn Sie auf \\"Yes\\" klicken, k\"{o}nnen Sie ihre Antwort + nicht mehr \string\344ndern." +} +\renewcommand{\defaultReqFormMsg}{% + "Der Ausdruck ist nicht in der erwarteten Form."} +%</eqde> +% \end{macrocode} +% \subsection{Norwegian} +% \begin{macrocode} +%<*eqno> +%%%%%%%%%%%%%%%%%%%% eqno.def %%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Hans Fredrik Nordhaug %% +%% e-mail address: hansfn@mi.uib.no %% +%% Language: Norwegian %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\renewcommand\exlabel{{\O}velse} +\renewcommand\exlabelsol{{\protect\O}velse} + +\renewcommand\exsectitle{L{\o}sning p{\aa} {\o}velsene} +\renewcommand\exsecrunhead{L{\protect\o}sning p{\protect\aa} + {\protect\o}velsene} + +\renewcommand{\eq@exsolafterDefault}{\textit{L{\o}sning}:} + +\renewcommand\eq@sqslsectitle{L{\o}sning p{\aa} oppgavene} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +\renewcommand\eq@sqslsecrunhead{L{\o}sning p{\aa} oppgavene} +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +\renewcommand\eq@sqsllabel{% + \protect\textbf{L{\protect\o}sning p{\protect\aa} oppgave:}} +\renewcommand\sqsllabel{\eq@sqsllabel} + +\renewcommand\sqsolafter{\textit{L{\o}sning}:} + +\renewcommand\eq@sqlabel{\textcolor{red}{Oppgave}} +\renewcommand\sqlabel{\eq@sqlabel} + +\renewcommand\eq@sqslrtnlabel{Slutt} +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +\renewcommand\eqsqrtmsg{"Rett!"} +\renewcommand\eqsqwgmsg{"Feil!"} + +\renewcommand\eq@bqlabel{Start oppgaver} +\renewcommand\bqlabel{\eq@bqlabel} +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +\renewcommand\eq@eqlabel{Slutt} +\renewcommand\eqlabel{\eq@eqlabel} + +\renewcommand\eqScore{Poeng:}\renewcommand\eqOutOf{av} +\renewcommand\eqInitQuizMsg{"Du m\string\\345 initialisere testen!" ++" Klikk p\string\\345 "+msg+"."} +\renewcommand\eqMadeChoice{% + "Du har allerede gjort et valg. + Valget var ("+Responses[probno]+"). + Vil du endre det?"} +\renewcommand\eq@local@CA{Rett} +\renewcommand\eq@local@RC{mine svar!} +%\renewcommand\eq@local@AC{V\string\346r s\string\345 snill!}} +\renewcommand\eq@local@AC{% + V\texorpdfstring{\ae}{\string\346}r + s\texorpdfstring{\r}{\string\345}snill!} +%</eqno> +% \end{macrocode} +% \subsection{Dutch} +% \begin{macrocode} +%<*eqnl> +%%%%%%%%%%%%%%%%%%% eqnl.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Henny Wilbrink %% +%% e-mail address: wsdwhw@win.tue.nl %% +%% Language: Dutch %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% The exercise label +\renewcommand\exlabel{Opgave} +\renewcommand\exlabelsol{\exlabel} + +% Title of exercise solution section +\renewcommand\exsectitle{Oplossingen van de Opgaven} +\renewcommand\exsecrunhead{\exsectitle} + +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{Oplossing}:} + +% Title of short quiz solution section +\renewcommand\eq@sqslsectitle{Oplossingen van de Toetsen} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{Oplossingen van de Toetsen} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Solution label for solutionafter option +\renewcommand{\eq@exsolafterDefault}{\textit{Oplossing}:} + +% Label for solutions to short quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{\string\textbf{Oplossing van Toets:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Oplossing}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Toets.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +\renewcommand\eq@sqslrtnlabel{Terug naar Toets} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Goed!"} +\renewcommand\eqsqwgmsg{"Fout!"} + +% Here is the default quiz label. +\renewcommand\eq@bqlabel{Begin Toets} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. Use PDFDocEncoding +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{Einde Toets} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} + +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +\renewcommand\eq@Score{Score:}\renewcommand\eq@OutOf{van de} + +\renewcommand\eqInitQuizMsg{% + "U moet de Toets initialiseren! Klik op "+msg+"."} +\renewcommand\eqMadeChoice{% + "U hebt al een keuze gemaakt. + Uw keuze was ("+Responses[probno]+"). + Wil u dit veranderen?"} +% +% Default button labels for \eqButton +\renewcommand\eq@local@CA{Corrigeer} +\renewcommand\eq@local@RC{Mijn Antwoorden!} +\renewcommand\eq@local@AC{AUB!} +%</eqnl> +% \end{macrocode} +% \subsection{Spanish} +% \begin{macrocode} +%<*eqes> +%%%%%%%%%%%%%%%%%%% eqes.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Pedro Luis Luque %% +%% e-mail address: calvo@cica.es %% +%% Language: (spanish) %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% The exercise label +\renewcommand\exlabel{Ejercicio} +% The value of this macro is written to \jobname.sol, +\renewcommand\exlabelsol{\exlabel} + +% Title of exercise solution section +\renewcommand\exsectitle{Soluciones a los \exlabel s} +\renewcommand\exsecrunhead{\exsectitle} %% change to @ form + +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{Soluci\'{o}n}:} + +% Title of short quiz solution section +\renewcommand\eq@sqslsectitle{Soluciones a los Tests} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{Soluciones a los Tests} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to short quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{% + \string\textbf{Soluci\protect\'{o}n al Test:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Soluci\'{o}n}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Test.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +\renewcommand\eq@sqslrtnlabel{Final del Test} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Correcto!"} +\renewcommand\eqsqwgmsg{"Incorrecto!"} + +% Here is the default quiz label. +\renewcommand\eq@bqlabel{Inicio del Test} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. Use PDFDocEncoding +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{Final del Test} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +\renewcommand\eq@Score{Puntos:}\renewcommand\eq@OutOf{de} +\renewcommand\eqInitQuizMsg{"Debes inicializar el Test! + Click sobre "+msg+"."} +\renewcommand\eqMadeChoice{% + "Ya has elegido una respuesta. + Tu respuesta fue ("+Responses[probno]+"). + Quieres cambiarla?"} +% +% Default button labels for \eqButton +\renewcommand\eq@local@CA{Correctas} +\renewcommand\eq@local@RC{Mis Respuestas!} +\renewcommand\eq@local@AC{Por Favor!} +%</eqes> +% \end{macrocode} +% \subsection{Italian} +% \begin{macrocode} +%<*eqit> +%%%%%%%%%%%%%%%%%%% eqit.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: PierLuigi Zezza %% +%% e-mail address: pzezza@cce.unifi.it %% +%% Language: Italian %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% The exercise label +\renewcommand\exlabel{Esercizio} +% +% The value of this macro is written to \jobname.sol, +\renewcommand\exlabelsol{\exlabel} +% +% Title of exercise solution section +\renewcommand\exsectitle{Soluzioni degli Esercizi } +\renewcommand\exsecrunhead{\exsectitle} +% +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{Soluzione}:} +% +% Title of short quiz solution section +\renewcommand\eq@sqslsectitle{Soluzioni dei Quiz} +\renewcommand\sqslsectitle{\eq@sqslsectitle} +% +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{Soluzioni dei Quiz} +% +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} +% +% Label for solutions to short quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{\string\textbf{Soluzione del Quiz:}} +% +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} +% +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Soluzione}:} +% +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Quiz.}} +% +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} +% +% Here is the default short quiz return label +\renewcommand\eq@sqslrtnlabel{Fine Quiz} +% +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} +% +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Giusto!"} +\renewcommand\eqsqwgmsg{"Sbagliato!"} +% +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@bqlabel{Inizio Test} +% +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} +% +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{Fine Test} +% +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +\renewcommand\eq@Score{Punteggio:}\renewcommand\eq@OutOf{su} +\renewcommand\eqInitQuizMsg{"Dovete inizializzare il Quiz! + Click su "+msg+"."} +\renewcommand\eqMadeChoice{% + "Avete gi\string\\340 fatto una scelta. + La vostra scelta era ("+Responses[probno]+"). + Volete cambiarla ?"} +% +% Default button labels for \eqButton +\renewcommand\eq@local@CA{Correggere} +\renewcommand\eq@local@RC{Le mie risposte!} +\renewcommand\eq@local@AC{Per favore!} +%</eqit> +% \end{macrocode} +% \subsection{Russian} +% \begin{macrocode} +%<*eqru> +%%%%%%%%%%%%%%%%%%% eqru.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Sergei V. Znamenskii %% +%% e-mail address: znamensk@rustex.botik.ru %% +%% Language: Russian %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%\PassOptionsToPackage{unicode}{hyperref} +\expandafter\ifx\csname inputencoding\endcsname\relax + \RequirePackage{inputenc}\fi +\inputencoding{cp1251}\makeatletter +\expandafter\ifx\csname Russian\endcsname\relax + \RequirePackage[russian]{babel}\fi +% Language dependent definitions for Web.sty + \def\web@versionlabel{\^{A}{\aa}ð\~{n}\`{e}\"{y}}% + \def\web@toc{\~{N}\^{\i}\"{a}{\aa}ð{\ae}\`{a}\'{\i}\`{e}{\aa}}% + \def\web@continued{\"{\i}ð\^{\i}\"{a}\^{\i}\"{e}{\ae}.}% + \def\web@article{\'{I}\`{a}{\div}\`{a}\"{e}\^{\i} + \hyperlink{section.1}{}}% + \def\web@directory{\"{I}\`{a}\"{\i}\^{e}\`{a}}% + \def\web@revision{\"{A}\`{a}\`{o}\`{a} \"{\i}\^{\i}\~{n}\"{e}% + {\aa}\"{a}\'{\i}{\aa}\~{a}\^{\i} \`{e}\c{c}\`{\i}{\aa}% + \'{\i}{\aa}\'{\i}\`{e}\"{y}:}% + \def\web@copyright{\^{E}\^{\i}\"{\i}\`{e}ð\`{a}\'{e}\`{o}}% + \def\web@section{\textsection\ }% + % Label Navibar + \def\web@back{\'{I}\`{a}\c{c}\`{a}\"{a}}% + \def\web@doc{\"{A}\^{\i}\^{e}.}% restricted to three characters + +% The exercise label +% Accents: \renewcommand\exlabel{\"Ubung} (German) +\renewcommand\exlabel{\'{O}\"{\i}ð\`{a}{\ae}\'{\i}{\aa}\'{\i}\`{e}{\aa}} +% The value of this macro is written to \jobname.sol, +% accented characters must be protected with a \protect +% E.g., \renewcommand\exlabelsol{\protect\"Ubung} (German) +\renewcommand\exlabelsol{\^{E} \'{o}\"{\i}ð\`{a}{\ae}% + \'{\i}{\aa}\'{\i}\`{e}þ} + +% Title of exercise solution section +% E.g.: \renewcommand\exsectitle +% {L\"osungen der \exlabel en} (German) +\renewcommand\exsectitle{Ð{\aa}{\o}{\aa}\'{\i}\`{e}\"{y} + \'{o}\"{\i}ð\`{a}{\ae}\'{\i}{\aa}\'{\i}\`{e}\'{e}} +\renewcommand\exsecrunhead{\exsectitle} %% change to @ form + +% Solution label for solutionafter option for exercise +\renewcommand\exsolafter{\textit{Ð{\aa}{\o}{\aa}\'{\i}\`{e}{\aa}}:} + +% Title of short quiz solution section +% Example: \renewcommand\eq@sqslsectitle +% {L\"osungen der Aufgaben} (German) +\renewcommand\eq@sqslsectitle{\^{I}\`{o}\^{a}{\aa}\`{o}\^{u} + \^{e} \`{o}{\aa}\~{n}\`{o}\`{a}\`{\i}} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{\^{I}\`{o}\^{a}{\aa}\`{o}\^{u} + \^{e} \^{e}\^{\i}ð\^{\i}\`{o}\^{e}\`{e}\`{\i} + \`{o}{\aa}\~{n}\`{o}\`{a}\`{\i}} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to short quizzes, appears +% in solutions sections +% Protect accents with \protect +% E.g.: \renewcommand\eq@sqsllabel +% {\string\textbf{L\protect\"osung zu Aufgabe:}} (German) +\renewcommand\eq@sqsllabel{% + \string\textbf{\^{I}\`{o}\^{a}{\aa}\`{o}\^{u}:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Ð{\aa}{\o}{\aa}\'{\i}\`{e}{\aa}}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{% + \textcolor{red}{\c{C}\`{a}\"{a}\`{a}\'{\i}\`{e}{\aa}.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +% No formatting allowed +\renewcommand\eq@sqslrtnlabel{\^{a}{\aa}ð\'{\i}\'{o}\`{o}\"{u}\~{n}\"{y}} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +\cyrCommand\eqsqslrtnlabel{\^{E} \^{o}\^{\i}ð\`{\i}\'{o}\"{e}% + \`{e}ð\^{\i}\^{a}\^{e}{\aa} \c{c}\`{a}\"{a}\`{a}\'{\i}\`{e}\"{y}} +\renewcommand\eq@sqslrtnlabel{\eqsqslrtnlabel} + + +% Here is the default quiz label. +% No formatting allowed +% For Example: \renewcommand\eq@bqlabel{D\'ebut} (French) +\renewcommand\eq@bqlabel{CTAPT} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. +% Use PDFDocEncoding +% For Example: +% \renewcommand\eq@bqlabelISO{D\string\351but} (French) +% Use \string not \protect, this helps out +% TeX4ht by Eitan Gurari. +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{\^{O}\`{E}\'{I}\`{E}{\O}} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +\def\ScoreFieldDefaults +{% + \Ff{\FfReadOnly}\BC{1 0 0}\BG{}\S{S} + \DV{\^{A}{\aa}ð\'{\i}\^{\i}:}\W{1} +} +% Default button labels for \eqButton +\renewcommand\eq@local@CA{\`{E}\~{n}\"{\i}ð\`{a}\^{a}\`{e}\`{o}\"{u}} +\renewcommand\eq@local@RC{\`{\i}\^{\i}\`{e} \^{\i}\`{o}\^{a}{\aa}% + \`{o}\^{u}!} +\renewcommand\eq@local@AC{\"{I}\^{\i}{\ae}\`{a}\"{e}\'{o}\'{e}\~{n}% + \`{o}\`{a}!} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% In the Text Field showing the score, there is the default phrase in +% English Score: 2 out of 3, the word "Score" and "out of" needs +% translation. +%% In Cyrillic, at least with pdflatex v.1.40.3 , the same \eq@Score +%% unfortunately can not serve both \ScoreFieldDefaults and +%% \eqQuizTotalMsg. + +\renewcommand\eq@Score{\u0412\u0435\u0440\u043D\u043E:} +\renewcommand\eq@OutOf{\u0438\u0437} + +% Short quiz feedback messages +%\def\eq@sqrtmsg{"\u0412\u0435\u0440\u043D\u043E!"} +%\def\eq@sqwgmsg{"\u041E\u0448\u0438\u0431\u043A\u0430!"} +\def\eqsqrtmsg{"\u0412\u0435\u0440\u043D\u043E!"} +\def\eqsqwgmsg{"\u041E\u0448\u0438\u0431\u043A\u0430!"} + +% If you are taking a quiz and click on an alternative without +% initializing the quiz first, this message appears. +% Example: \renewcommand\eqInitQuizMsg{"Sie m\string\\374ssen die +% Aufgaben initialisieren! Bitte klicken Sie auf "+msg+"."}%(German) +\def\eqInitQuizMsg{"\u041A\u043B\u0438\u043A\u043D\u0438\u0442\u0435 + \u043D\u0430 \u00AB"+msg+"\u00BB, \u0447\u0442\u043E\u0431\u044B + \u043D\u0430\u0447\u0430\u0442\u044C + \u043E\u0442\u0432\u0435\u0442."} + +% This macro doesn't usually need translation, it uses +% \eqScore and \eqOutOf. However, if the sentence "Score: 2 out of 3" +% does not translate conveniently into a particular language, +% this macro may have to be modified. It's the one that puts the +% message in the message box. +% \renewcommand\eqQuizTotalMsg {"\eqScore\space"+Score+" +% \eqOutOf\space"+nQuestions} +% \renewcommand\eqQuizPointsMsg{"\eqptScore\space"+ptScore+" +% \eqOutOf\space"+nPointTotal} +% \renewcommand\eqQuizPercentMsg{pcScore+"\%"} +% \renewcommand\eqQuizGradeMsg{quizGrade} +% In the link form of a quiz, of you change your choice, this message +% appears. +% For Example: \renewcommand\eqMadeChoice{"Vous avez +% d\string\\351j\string\\340 fait un choix, ce choix est +% ("+Responses[probno]+"). Souhaitez vous le modifier ?"}%(French) +\renewcommand\eqMadeChoice{"\u0412\u044B \u0443\u0436\u0435 + \u0432\u044B\u0431\u0440\u0430\u043B\u0438 + \u043E\u0442\u0432\u0435\u0442 + ("+Responses[probno]+"). \u0418\u043B\u0438 \u0412\u044B + \u043F\u0435\u0440\u0435\u0434\u0443\u043C\u0430\u043B\u0438?"} +% Default button label of \CorrAnsButton. +\renewcommand\eq@local@CorrAnsButton{Ans} +% These (error) messages are generated when the user enters an invalid +% math expression into a math fill-in response box. The messages come in +% the form of an eqAppAlert() so PDFDocEncoding needs to be used. +\renewcommand\eqerrABS{"\u0417\u043D\u0430\u043A\u0438 + \u0430\u0431\u0441\u043E\u043B\u044E\u0442\u043D\u043E\u0439 + \u0432\u0435\u043B\u0438\u0447\u0438\u043D\u044B \u043D\u0435 + \u0441\u0431\u0430\u043B\u0430\u043D\u0441\u0438\u0440\u043E\u0432% + \u0430\u043D\u044B. + \u0418\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435, + \u043F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430."} +\renewcommand\eqerrBadMathFunc{"\u0412\u044B\u0440\u0430\u0436\u0435% + \u043D\u0438\u0435 `"+aF[i]+"' \u043D\u0435 \u044F\u0432\u043B% + \u044F\u0435\u0442\u0441\u044F \u043D\u0438 + \u0432\u0441\u0442\u0440\u043E\u0435\u043D\u043D\u043E\u0439 " + +"\u0444\u0443\u043D\u043A\u0446\u0438\u0435\u0439, + \u043D\u0438 \u043A\u043E\u0440\u0440\u0435\u043A\u0442\u043D% + \u044B\u043C\u043C\u0430\u0442\u0435\u043C\u0430\u0442\u0438\u0447% + \u0435\u0441\u043A\u0438\u043C \u0432\u044B\u0440\u0430\u0436\u0435% + \u043D\u0438\u0435\u043C."} +\renewcommand\eqParens{"\u041A\u0440\u0443\u0433\u043B\u044B\u0435 + \u0441\u043A\u043E\u0431\u043A\u0438"} +\renewcommand\eqBrackets{"\u041A\u0432\u0430\u0434\u0440\u0430\u0442% + \u043D\u044B\u0435 \u0441\u043A\u043E\u0431\u043A\u0438"} +\renewcommand\eqBraces{"\u0424\u0438\u0433\u0443\u0440\u043D\u044B\u0435 + \u0441\u043A\u043E\u0431\u043A\u0438"} +\renewcommand\eqerrDelimNotBal{aGroup[i][2] + " \u043D\u0435 + \u0441\u0431\u0430\u043B\u0430\u043D\u0441\u0438\u0440% + \u043E\u0432\u0430\u043D\u043E. + \u041F\u043E\u0436\u0430\u043B\u0443\u0439\u0441\u0442\u0430, + \u0438\u0441\u043F\u0440\u0430\u0432\u044C\u0442\u0435."} +\renewcommand\eqerrBadExp{"\u0418\u0441\u043F\u0440\u0430\u0432% + \u044C\u0442\u0435, \u043F\u043E\u0436\u0430\u043B\u0443\u0439% + \u0441\u0442\u0430, \u0432\u044B\u0440\u0430\u0436\u0435\u043D% + \u0438\u0435 \u0441\u043E \u0441\u0442\u0435\u043F\u0435\u043D% + \u044C\u044E."} +\renewcommand\eqerrUnfinishQuiz{"\u041F\u043E\u0436\u0430\u043B\u0443% + \u0439\u0441\u0442\u0430, \u0437\u0430\u043A\u043E\u043D\u0447% + \u0438\u0442\u0435 \u043D\u0430\u0447\u0430\u0442\u043E\u0435 + \u0440\u0430\u043D\u0435\u0435 \u0437\u0430\u0434\u0430\u043D% + \u0438\u0435."} +\renewcommand\noPeekMsg{"\u0420\u0435\u0448\u0435\u043D\u0438\u044F + \u043D\u0435 \u043F\u043E\u043A\u0430\u0436\u0443\u0442\u0441\u044F, + \u043F\u043E\u043A\u0430 \u0437\u0430\u0434\u0430\u043D\u0438\u0435 + \u043D\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043A + \u043E\u043D\u0447\u0435\u043D\u043E!"} +\renewcommand\highThresholdMsg{"\u0412\u044B \u043D\u0435 + \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u0435 + \u043E\u0446\u0435\u043D\u043A\u0438, \u043F\u043E\u043A\u0430 + \u043D\u0435 \u043E\u0442\u0432\u0435\u0442\u0438\u0442\u0435 + \u043D\u0430 \u0412\u0421\u0415 \u0432\u043E\u043F\u0440\u043E% + \u0441\u044B."} +\renewcommand\eqSyntaxErrorUndefVar{"\u0421\u0438\u043D\u0442\u0430% + \u043A\u0441\u0438\u0447\u0435\u0441\u043A\u0430\u044F + \u043E\u0448\u0438\u0431\u043A\u0430: + \u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E, + \u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u0430\u044F + \u043D\u0435 \u043E\u043F\u0440\u0435\u0434\u0435\u043B\u0435% + \u043D\u0430."} +%</eqru> +% \end{macrocode} +% \subsection{Danish} +% \begin{macrocode} +%<*eqda> +%%%%%%%%%%%%%%%%%%%% eqda.def %%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Erik Leimand %% +%% e-mail address: buhlleimand@worldonline.dk %% +%% Language: Danish %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\renewcommand\exlabel{{\O}velse} +\renewcommand\exlabelsol{{\protect\O}velse} + +\renewcommand\exsectitle{L{\o}sning p{\aa} {\o}velserne} +\renewcommand\exsecrunhead{L{\protect\o}sning p{\protect\aa} + {\protect\o}velserne} + +\renewcommand{\eq@exsolafterDefault}{\textit{L{\o}sning}:} + +\renewcommand\eq@sqslsectitle{L{\o}sning p{\aa} opgaverne} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +\renewcommand\eq@sqslsecrunhead{L{\o}sning p{\aa} opgaverne} +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +\renewcommand\eq@sqsllabel{% + \string\textbf{L{\protect\o}sning p{\protect\aa} opgave:}} +\renewcommand\sqsllabel{\eq@sqsllabel} + +\renewcommand\sqsolafter{\textit{L{\o}sning}:} + +\renewcommand\eq@sqlabel{\textcolor{red}{Opgave.}} +\renewcommand\sqlabel{\eq@sqlabel} + +\renewcommand\eq@sqslrtnlabel{Slut} +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +\renewcommand\eqsqrtmsg{"Rigtigt!"} +\renewcommand\eqsqwgmsg{"Forkert!"} + +\renewcommand\eq@bqlabel{Start opgaver} +\renewcommand\bqlabel{\eq@bqlabel} +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +\renewcommand\eq@eqlabel{Slut} +\renewcommand\eqlabel{\eq@eqlabel} + +\renewcommand\eq@Score{Score:}\renewcommand\eq@OutOf{ud af} +\renewcommand\eqQuizTotalMsg{"\eqScore\space"+Score+" + \eqOutOf\space"+nQuestions} +\renewcommand\eqInitQuizMsg{"Du skal starte testen! Klik + p\string\\345 "+msg+"."} +\renewcommand\eqMadeChoice{% + "Du har allerede valgt. + Du valgte ("+Responses[probno]+"). + Vil du \string\\346ndre det?"} +\renewcommand\eq@local@CA{Ret} +\renewcommand\eq@local@RC{Mine svar!} +%\renewcommand\eq@local@AC{V\string\346r s\string\345 god!}} +\renewcommand\eq@local@AC{% + V\texorpdfstring{\ae}{\string\346}r + s\texorpdfstring{\r}{\string\345}god!} +%</eqda> +% \end{macrocode} +% \subsection{Polish} +% \begin{macrocode} +%<*eqpo> +%%%%%%%%%%%%%%%%%%%% eqpo.def %%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Jerzy Mycielski %% +%% e-mail address: jmyc@poczta.onet.pl %% +%% Language: Polish %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% The polish accented characters included in pdfendconding is +%% lslash and oacute, not included are zacute, zdot, cacute, +%% nacute, sacute, aogonek, eogonek and corresponding capital +%% characters. +% Z \'{Z} \u0179 +% a \k{a} \u0105 +% c \'{c} \u0107 +% l \l \u0142 +% s \'{s} \u015B +% z \.{z} \u017C +% \'{o} \'{o} \u00F3 +\renewcommand\exlabel{Zadanie} +\renewcommand\exlabelsol{\exlabel} + +\renewcommand\exsectitle{Rozwi\k{a}zania Zada\'{n}} +\renewcommand\exsecrunhead{\protect\exsectitle} + +\renewcommand{\eq@exsolafterDefault}{\textit{Rozwi\k{a}znie}:} + +\renewcommand\eq@sqslsectitle{Rozwi\k{a}zania Test\'{o}w} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +\renewcommand\eq@sqslsecrunhead{Rozwi\protect\k{a}zania + Test\protect\'{o}w} +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +\renewcommand\eq@sqsllabel{\string\textbf{Rozwi\protect\k{a}zanie + Testu:}} +\renewcommand\sqsllabel{\eq@sqsllabel} + +\renewcommand\sqsolafter{\textit{Rozwi\k{a}zanie}:} + +\renewcommand\eq@sqlabel{\textcolor{red}{Test.}} +\renewcommand\sqlabel{\eq@sqlabel} + +%\renewcommand\eq@sqslrtnlabel{Zako\protect\'{n}cz Test} +\renewcommand\eq@sqslrtnlabel{Zako\ifeq@solutionsafter\else + \expandafter\protect\fi\'{n}cz Test} +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +\renewcommand\eqsqrtmsg{"Dobrze!"} +\renewcommand\eqsqwgmsg{"\string\\u0179le!"} +%\renewcommand\eqsqwgmsg{"\'{Z}le!"} + +\renewcommand\eq@bqlabel{Rozpocznij Test} +\renewcommand\bqlabel{\eq@bqlabel} +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +\renewcommand\eq@eqlabel{Zakoncz Test} +% \renewcommand\eq@eqlabel{Zako\'{n}cz Test} +\renewcommand\eqlabel{\eq@eqlabel} + +\renewcommand\eq@Score{Punkt\'{o}w:} +\renewcommand\eq@OutOf{z mozliwych} +\renewcommand\eqQuizTotalMsg{"\eqScore\space"+Score + + " \eqOutOf\space"+nQuestions} + +\renewcommand\eqInitQuizMsg{"Musisz rozpoczac Test! Kliknij + na "+msg+"."} + +\renewcommand\eqMadeChoice{% + "Juz dokonal\string\\233e\string\\u015B wyboru. + Twoim wyborem by\string\\233o ("+Responses[probno]+"). + Czy chcesz go zmieni\string\\u0107?"} +%\renewcommand\eqMadeChoice{% +%"Ju\.{z} dokona\string\233e\'{s} wyboru. Twoim wyborem" +%+" by\string\233o ("+Responses[probno]+")."+" Czy chcesz go +%zmieni\'{c}?"} + +\renewcommand\eq@local@CA{Popraw} +\renewcommand\eq@local@RC{Moje odpowiedzi!} +\renewcommand\eq@local@AC{Prosze!} +%\renewcommand\eq@local@AC{Prosz\k{e}!} +%</eqpo> +% \end{macrocode} +% \subsection{Finnish} +% \begin{macrocode} +%<*eqfin> +%%%%%%%%%%%%%%%%%%%% eqfin.def %%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Paivi Porras %% +%% e-mail address: paivi.porras@lut.fi %% +%% Language: Finnish %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\renewcommand\exlabel{Harjoitus} +\renewcommand\exlabelsol{Harjoitus} + +\renewcommand\exsectitle{Ratkaisut} +\renewcommand\exsecrunhead{Ratkaisu \exlabelsol } + +\renewcommand{\eq@exsolafterDefault}{\textit{Ratkaisu}:} + +\renewcommand\eq@sqslsectitle{Vastaukset testikysymyksiin} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +\renewcommand\eq@sqslsecrunhead{Vastaukset testikysymyksiin} +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +\renewcommand\eq@sqsllabel{% + \string\textbf{Vastaus testikysymykseen:}} +\renewcommand\sqsllabel{\eq@sqsllabel} + +\renewcommand\sqsolafter{\textit{Ratkaisu}:} + +\renewcommand\eq@sqlabel{\textcolor{red}{Testikysymys}} +\renewcommand\sqlabel{\eq@sqlabel} + +\renewcommand\eq@sqslrtnlabel{Lopeta testi} +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +\renewcommand\eqsqrtmsg{"Oikein!"} %muokattu +\renewcommand\eqsqwgmsg{"V\string\344\string\344rin!"} %m +%\renewcommand\eqsqwgmsg{"V\"a\"arin!"} %m + +\renewcommand\eq@bqlabel{Aloita testi} +\renewcommand\bqlabel{\eq@bqlabel} +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabelISO} + +\renewcommand\eq@eqlabel{Lopeta testi} +\renewcommand\eqlabel{\eq@eqlabel} + +\renewcommand\eq@Score{Pisteet:}\renewcommand\eq@OutOf{/} +\renewcommand\eqInitQuizMsg{%m + "Testi on aloitettava painamalla "+msg+"."} +\renewcommand\eqMadeChoice{%m + "Olet jo kerran valinnut. + Valintasi oli ("+Responses[probno]+")." ++" Haluatko vaihtaa?"} +\AtEndOfPackage{% +\renewcommand\eq@local@CA{Oikein} +\renewcommand\eq@local@RC{Omat vastaukset!} +\renewcommand\eq@local@AC{Ole hyv\string\344!}} +%</eqfin> +% \end{macrocode} +% \subsection{catalan} +% \begin{macrocode} +%<*eqcat> +%%%%%%%%%%%%%%%%%%% eqcat.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Ramon Ballester %% +%% e-mail address: ramon.ballester@udg.es %% +%% Language: (catalan) %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% The exercise label +\renewcommand\exlabel{Exercici} +% The value of this macro is written to \jobname.sol, +\renewcommand\exlabelsol{\exlabel} + +% Title of exercise solution section +\renewcommand\exsectitle{Solucions als \exlabel s} +\renewcommand\exsecrunhead{\exsectitle} %% change to @ form + +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{Soluci\'o}:} + +% Title of short quiz solution section +\renewcommand\eq@sqslsectitle{Solucions als Tests} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{Solucions als Tests} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to short quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{% + \string\textbf{Soluci\protect\'{o} al Test:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Soluci\'o}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Test.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +\renewcommand\eq@sqslrtnlabel{Final del Test} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Correcte!"} +\renewcommand\eqsqwgmsg{"Incorrecte!"} + +% Here is the default quiz label. +\renewcommand\eq@bqlabel{Inici del Test} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. Use PDFDocEncoding +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{Final del Test} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +\renewcommand\eq@Score{Punts:}\renewcommand\eq@OutOf{de} +\renewcommand\eqInitQuizMsg{"Has d'iniciar el Test! + Prem sobre "+msg+"."} +\renewcommand\eqMadeChoice{% + "Ja has elegit una resposta. + La teva resposta ha estat ("+Responses[probno]+"). + Vols canviar--la?"} +% +% Default button labels for \eqButton +\renewcommand\eq@local@CA{Correctes} +\renewcommand\eq@local@RC{Les meves Respostes!} +\renewcommand\eq@local@AC{Si us plau!} +%</eqcat> +% \end{macrocode} +% +% \subsection{Czech} +% \begin{macrocode} +%<*eqcz> +%%%%%%%%%%%%%%%%%%% eqcat.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Robert Marik %% +%% e-mail address: marik@mendelu.cz %% +%% Language: (czech) %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\SFW{1.75in} + +% The exercise label +\renewcommand\exlabel{Cvi\v{c}en\'{\i}} +% The value of this macro is written to \jobname.sol, +\renewcommand\exlabelsol{Cvi\protect\v{c}en\protect\'{\protect\i}} + +% Title of exercise solution section +\renewcommand\exsectitle{\texorpdfstring{\v{R}e\v{s}en\'{\i} + ke cvi\v{c}en\'{\i}m} + {Resen\355{} ke cvicen\355m}} %% change to @ form +\renewcommand\exsecrunhead{% + \string\v{R}e\string\v{s}en\string\'{\string\i} + ke cvi\string\v{c}en\string\'{\string\i}m} + +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{\v{R}e\v{s}en\'\i}:} + +% Title of short quiz solution section +\renewcommand\eq@sqslsectitle{\texorpdfstring{\v{R}e\v{s}en\'{\i} + kv\'{\i}z\r{u}}{Resen\355{} kv\355zu}} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{\v{R}e\v{s}en\'{\i} kv\'{\i}z\r{u}} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to short quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{\string\textbf{% + \string\v{R}e\string\v{s}en\string\'{\string\i} + kv\string\'{\string\i}zu:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{\v{R}e\v{s}en\'{\i}}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Kv\'{\i}z.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +%\renewcommand\eq@sqslrtnlabel{Konec kv\string\'{\string\i}zu} +\renewcommand\eq@sqslrtnlabel{Zp\string\v{e}t na ot\string\'{a}zky} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Spravne !"} +\renewcommand\eqsqwgmsg{"Spatne !"} + +% Here is the default quiz label. +\renewcommand\eq@bqlabel{Zacatek kvizu} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. Use PDFDocEncoding +\renewcommand\eq@bqlabelISO{Zacatek kvizu} +\renewcommand\bqlabelISO{Zacatek kvizu} + +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{Konec kvizu} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +%\renewcommand\eq@Score{Hodnoceni:} +\renewcommand\eq@Score{} +\renewcommand\eq@OutOf{z celkovych} +\renewcommand\eqInitQuizMsg{% + "Chcete-li pracovat s kvizem, musite jej nejprve spustit! + Kliknete na "+msg+"."} +\renewcommand\eqMadeChoice{% + "Uz jste si jednou odpoved vybral(a). Vase odpoved byla (" + + Responses[probno]+"). Chcete ji opravdu zmenit?"} +% +% Default button labels for \eqButton +\renewcommand\eq@local@CA{Opravit} +\renewcommand\eq@local@RC{odpovedi!} +\renewcommand\eq@local@AC{Prosim!} +% Messages for math fill-in questions +\renewcommand\eqerrABS{"Spatne uzavrena absolutni hodnota. + Opravte prosim."} +\renewcommand\eqerrBadMathFunc{"Vyraz `"+aF[i]+"' neni ani + definovanou funkci ani " +", ani platnym matematickym vyrazem."} +\renewcommand\eqParens{"Zavorky (kulate)"} +\renewcommand\eqBrackets{"Hranate zavorky"} +\renewcommand\eqBraces{"Slozene zavorky"} +\renewcommand\eqerrDelimNotBal{aGroup[i][2] + " nejsou parove. + Opravte je prosim."} +\renewcommand\eqerrBadExp{"Spatny matematicky vyraz - problem v nekterem + exponentu. Opravte jej prosim."} +\renewcommand\eqerrUnfinishQuiz{"Chyba: Nektery kviz mate nedokonceny. + Musite jej dokoncit, nez budete pokracovat u dalsiho kvizu. Pokud si + nepamatuje, ktery kviz jste nechali rozpracovany, zavrete cely + soubor, znovu jej otevrete a k testu, ktery chcete vyplnovat, + se vratte."} +\renewcommand\noPeekMsg{"Prohlizeni reseni neni povoleno pred dokoncenim + kvizu!"} +\renewcommand\highThresholdMsg{"Musite odpovedet na vsechny otazky, nez + ukoncite kviz."} +\renewcommand\eqSyntaxErrorUndefVar{"Chyba: Pravdepodobne pouzivate + nespravnou promennou nebo mate preklep ve jmenu nektere funkce."} +\renewcommand{\promptButtonMsg}{% + "Chcete ted videt spravnou odpoved? "\r\t\t + + "Hodnocena bude Vase soucasna odpoved. "\r\t\t + + "Kliknete-li na \\"Yes\\", uvidite spravnou odpoved, ale svou + stavajici odpoved na tuto otazku uz nebudete moct zmenit." +} +%</eqcz> +% \end{macrocode} +% \subsection{brazil} +% \begin{macrocode} +%<*eqbr> +%%%%%%%%%%%%%%%%%%% eqbr.def %%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Koichi Sameshima %% +%% e-mail address: ksameshi@usp.br %% +%% Language: (brazil) %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% The exercise label +\renewcommand\exlabel{Exerc\texorpdfstring{\'{\i}}{\string\355}cio} +% The value of this macro is written to \jobname.sol, +\renewcommand\exlabelsol{Exerc\string\'{\string\i}cio} + +% Title of exercise solution section +\renewcommand\exsectitle{Solu\texorpdfstring{\c{c}}{\string\347}% + \texorpdfstring{\~{o}}{% + \string\365}es dos Exerc\texorpdfstring{\'{\i}}{\string\355}cios} + %{Solu\string\\347\string\\363es dos Exerc\string\\355cios}} +\renewcommand\exsecrunhead{% + Solu\protect\c{c}\protect\~{o}es dos Exerc\protect\'{i}cios} + +% Solution label for solutionafter option for exercise +\renewcommand{\eq@exsolafterDefault}{\textit{Solu\c{c}\~{a}o}:} + +% Title of short quiz solution section +\renewcommand\eq@sqslsectitle{Solu\c{c}\~{o}es + dos Testes} +\renewcommand\sqslsectitle{\eq@sqslsectitle} + +% Running header/section title for solutions to short quizzes +\renewcommand\eq@sqslsecrunhead{Solu\protect\c{c}\protect\~{o}es + dos Testes} +% User access +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} + +% Label for solutions to short quizzes, appears in solutions sections +\renewcommand\eq@sqsllabel{% + \string\textbf{Solu\protect\c{c}\protect\~{a}o do Teste:}} +% User access +\renewcommand\sqsllabel{\eq@sqsllabel} + +% Solution label for solutionafter option for shortquiz +\renewcommand\sqsolafter{\textit{Solu\protect\c{c}\protect\~{a}o}:} + +% Here is the default short quiz label. +\renewcommand\eq@sqlabel{\textcolor{red}{Teste.}} +% User access to shortquiz label +\renewcommand\sqlabel{\eq@sqlabel} + +% Here is the default short quiz return label +\renewcommand\eq@sqslrtnlabel{Finaliza Teste} +% User access to shortquiz label +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} + +% Short quiz feedback messages +\renewcommand\eqsqrtmsg{"Correto!"} +\renewcommand\eqsqwgmsg{"Incorreto!"} + +% Here is the default quiz label. +\renewcommand\eq@bqlabel{Inicia Teste} +% User access to shortquiz label +\renewcommand\bqlabel{\eq@bqlabel} +% Used for writing JavaScript Messages on screen. Use PDFDocEncoding +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabel} + +% Here is the default quiz label. +% No formatting allowed +\renewcommand\eq@eqlabel{Finaliza Teste} +% User access to shortquiz label +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript Messages for Quiz Environments. Use PDFDocEncoding +% +\renewcommand\eq@Score{Pontos:}\renewcommand\eq@OutOf{de} +\renewcommand\eqInitQuizMsg{% ****** + "Voc\string\352 precisa iniciar o Teste! Clique sobre "+msg+"."} +\renewcommand\eqMadeChoice{% + "Voc\string\352 j\string\341 respondeu. + Sua resposta foi ("+Responses[probno]+"). + Quer alter\string\341-la?"} +% +% Default button labels for \eqButton +\renewcommand\eq@local@CA{Corretas} +\renewcommand\eq@local@RC{Minhas Respostas!} +\renewcommand\eq@local@AC{Por Favor!} +%</eqbr> +% \end{macrocode} +% \subsection{turkish} +% \begin{macrocode} +%<*eqtr> +%%%%%%%%%%%%%%%%%%%% eqtr.def %%%%%%%%%%%%%%%%%%%%%%%%%% +%% Foreign language support for the exerquiz package. %% +%% Name of translator: Mahmut Ko\c{c}ak %% +%% e-mail address: mkocak@ogu.edu.tr %% +%% Language: Turkish %% +%% %% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\renewcommand\exlabel{Al\i \c st\i rma} +\renewcommand\exlabelsol{\noexpand\c C\noexpand\"oz\noexpand\"um} +\renewcommand\exsectitle{\exlabel lar{\i}n \c C\"oz\"umleri } +\renewcommand\exsecrunhead{Al\noexpand\i \noexpand\c st\noexpand\i rma + \exlabelsol leri } +\renewcommand\exsolafter{\textbf{\c C\"oz\"um}:} +\renewcommand\eq@sqslsectitle{Kuizlerin \c C\"oz\"umleri } +\renewcommand\sqslsectitle{\eq@sqslsectitle} +\renewcommand\eq@sqslsecrunhead{Kuizlerin \c C\"oz\"umleri} +\renewcommand\sqslsecrunhead{\eq@sqslsecrunhead} +\renewcommand\eq@sqsllabel{% + \protect\textbf{Kuiz \noexpand\c C\noexpand\"oz\noexpand\"um% + \noexpand\"u:}} +\renewcommand\sqsllabel{\eq@sqsllabel} +\renewcommand\sqsolafter{\textit{\c C\"oz\"um}:} +\renewcommand\eq@sqlabel{\textcolor{red}{Soru}} +\renewcommand\sqlabel{\eq@sqlabel} +\renewcommand\eq@sqslrtnlabel{Kuizi Bitir} +\renewcommand\sqslrtnlabel{\eq@sqslrtnlabel} +% JavaScript alert box text +\renewcommand\eqsqrtmsg{"Do\protect\u011Fru!"} +\renewcommand\eqsqwgmsg{"Yanl\protect\u0131\protect\u015F!"} +% +\renewcommand\eq@bqlabel{Kuize Ba\c sla} +\renewcommand\bqlabel{\eq@bqlabel} +\renewcommand\eq@bqlabelISO{\eq@bqlabel} +\renewcommand\bqlabelISO{\eq@bqlabelISO} +\renewcommand\eq@eqlabel{Kuizi Bitir} +\renewcommand\eqlabel{\eq@eqlabel} +% +% JavaScript messages +% +\renewcommand\eq@Score{Skor:} +\renewcommand\eq@OutOf{\protect\374zerinden} +\renewcommand\eqQuizTotalMsg{% + "\eqScore\space"+nQuestions+" \eqOutOf\space"+Score} + \renewcommand\eqQuizPointsMsg{% + "\eqptScore\space"+nPointTotal+" \eqOutOf\space"+ptScore} +\renewcommand\eq@local@CorrAnsButton{Cevap} +\renewcommand\eqInitQuizMsg{% + "Kuizi Bitirdiniz. Do\protect\u011Fru cevaplar\protect\u0131 + g\protect\u00F6rmek i\protect\u00E7in 'cevap' + tu\protect\u015Flar\protect\u0131na + bas\protect\u0131n\protect\u0131z."} +\renewcommand\eqMadeChoice{% + "Bir se\protect\u00E7im yapt\protect\u0131n\protect\u0131z. + Se\protect\u00E7iminiz ("+Responses[probno]+") idi." + +" Se\protect\u00E7iminizi de\protect\u011Fi\protect\u015Ftirmek + istermisiniz?"} +\renewcommand\eqerrABS{"Mutlak de\protect\u011Fer do\protect\u011Fru + degil. L\protect\u00FCtfen d\protect\u00FCzeltiniz."} +\renewcommand\eqerrBadMathFunc{" `"+aF[i]+"' ifadesi + tan\protect\u0131ml\protect\u0131 bir fonksiyon veya + ge\protect\u00E7erli bir matematiksel ifade de\protect\u011Fil."} +\renewcommand\eqParens{"Parentezler"} +\renewcommand\eqBrackets{"S\protect\u00FCsl\protect\u00FC Parentazle"} +\renewcommand\eqBraces{"K\protect\u00F6\protect\u015Feli Parentezler"} +\renewcommand\eqerrDelimNotBal{aGroup[i][2] + " do\protect\u011Fru + de\protect\u011Fil. L\protect\u00FCtfen d\protect\u00FCzeltiniz."} +\renewcommand\eqerrBadExp{"Ge\protect\u00E7ersiz matematiksel ifade. + \protect\u00FCstel ifadeli bir hata. + L\protect\u00FCtfen d\protect\u00FCzeltiniz."} +\renewcommand\eqerrUnfinishQuiz{"Bitirilmemi\protect\u015F bir kuiz var, + di\protect\u011Fer kuize ge\protect\u00E7meden \protect\u00F6nce + bu kuizi tamamlay\protect\u0131n."} +\renewcommand\noPeekMsg{"Kuizi bitirmeden yada kuizden + ba\protect\u015Far\protect\u0131l\protect\u0131 olana kadar + \protect\u00E7\protect\u00F6z\protect\u00FCmleri + g\protect\u00F6remezsiniz.!"} +\renewcommand\highThresholdMsg{"Kuiz sonucu hesaplanmadan + \protect\u00F6nce b\protect\u00FCt\protect\u00FCn + sorular\protect\u0131 cevapland\protect\u0131rmal\protect + \u0131s\protect\u0131n\protect\u0131z."} +\renewcommand\eqSyntaxErrorUndefVar{"Syntax Error: Tan\protect + \u0131mlanmam\protect\u0131\protect\u015F de\protect\u011Fi\protect + \u015Fken veya ifadeler istenilen formatta yaz\protect + \u0131lmam\protect\u0131\protect\u015Ft\protect\u0131r."} +\renewcommand\eq@local@CA{Dogru} +\renewcommand\eq@local@RC{Benim Cevaplar\protect\u0131m!} +\renewcommand\eq@local@AC{L\protect\374tfen!} +%</eqtr> +% \end{macrocode} +% \Finale +\endinput |