summaryrefslogtreecommitdiff
path: root/texmf-dist/source/latex/jj-game/jj_game.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'texmf-dist/source/latex/jj-game/jj_game.dtx')
-rw-r--r--texmf-dist/source/latex/jj-game/jj_game.dtx1747
1 files changed, 1747 insertions, 0 deletions
diff --git a/texmf-dist/source/latex/jj-game/jj_game.dtx b/texmf-dist/source/latex/jj-game/jj_game.dtx
new file mode 100644
index 00000000..2d2b2db7
--- /dev/null
+++ b/texmf-dist/source/latex/jj-game/jj_game.dtx
@@ -0,0 +1,1747 @@
+% \iffalse
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% jj_game.cls class file, %%
+%% Copyright (C) 2000-2016 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. %%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%<package>\NeedsTeXFormat{LaTeX2e}[1997/12/01]
+%<package>\ProvidesClass{jj_game}[2016/11/24 v3.1 jj_game Class (dps)]
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage[colorlinks,hyperindex=false]{hyperref}
+%\pdfstringdefDisableCommands{\let\\\textbackslash}%
+\OnlyDescription % comment out for implementation details
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\InputIfFileExists{aebdocfmt.def}{\PackageInfo{jj_game}{Inputting aebdocfmt.def}}
+ {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax
+ \PackageInfo{jj_game}{aebdocfmt.def cannot be found}}
+\begin{document}
+\def\CMD#1{\textbackslash#1}
+\let\pkg\textsf
+\let\opt\texttt
+%\addtolength{\marginparwidth}{3pt}
+ \GetFileInfo{jj_game.cls}
+ \title{\pkg{jj\_game}\texorpdfstring{\\}{:} A {\LaTeX} class to construct Jeopardy-like Games}
+ \author{D. P. Story\\
+ Email: \texttt{dpstory@uakron.edu}}
+ \date{processed \today}
+ \maketitle
+ \tableofcontents
+ \let\Email\texttt
+ \DocInput{jj_game.dtx}
+\IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex}{\paragraph*{Index} The index goes here.\\Execute
+ \texttt{makeindex -s gind.ist -o jj\_game.ind jj\_game.idx} on the command line and recompile
+ \texttt{jj\_game.dtx}.}
+\IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here.\\Execute
+ \texttt{makeindex -s gglo.ist -o jj\_game.gls jj\_game.glo} on the command line and recompile
+ \texttt{jj\_game.dtx}.}
+\end{document}
+%</driver>
+% \fi
+%
+% \MakeShortVerb{|}
+% \InputIfFileExists{aebdonotindex.def}{\PackageInfo{jj_game}{Inputting aebdonotindex.def}}
+% {\PackageInfo{jj_game}{cannot find aebdonotindex.def}}
+%
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+% \section{Declare Options}
+% \begin{macrocode}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+% Add \pkg{ifpdf} and \pkg{ifxetex} for automatic driver detection.
+% \changes{v3.1}{2016/11/24}{Add automatic driver detection for \string\pkg{ifpdf} and \string\pkg{ifxetex}}
+% \changes{v3.1}{2016/11/24}{Added support for \opt{xetex} driver. There are numerous changes to get
+% the positioning of the form fields correct. Changes are characterized by uses of \string\cs{ifxetex}
+% and \string\cs{efKern}.}
+% \begin{macrocode}
+\RequirePackage{ifpdf}[2006/02/20]
+\RequirePackage{ifxetex}[2006/08/21]
+\newcounter{jjgdriver}
+% \end{macrocode}
+% Here is the list of supported drivers:\IndexOpt{dvips}\IndexOpt{pdftex}\IndexOpt{xelex}\IndexOpt{luatex}
+% \texttt{pdftex}, \texttt{luatex}, and \texttt{xetex} are automatically detected and need not be specified.
+% Other less used drivers are also supported.
+% \begin{macrocode}
+\DeclareOptionX{pdftex}{\setcounter{jjgdriver}{0}
+ \def\jjgdriver{\@gobble}}
+\DeclareOptionX{luatex}{\setcounter{jjgdriver}{0}
+ \def\jjgdriver{\@gobble}}
+\DeclareOptionX{dvips}{\setcounter{jjgdriver}{1}
+ \def\jjgdriver{dvips}\PassOptionsToPackage{dvips}{web}}
+\DeclareOptionX{dvipsone}{\setcounter{jjgdriver}{1}
+ \def\jjgdriver{dvipsone}\PassOptionsToPackage{dvipsone}{web}}
+\DeclareOptionX{dvipdfm}{\setcounter{jjgdriver}{2}
+ \def\jjgdriver{dvipdfm}\PassOptionsToPackage{dvipdfm}{web}}
+\DeclareOptionX{dvipdfmx}{\setcounter{jjgdriver}{2}
+ \def\jjgdriver{dvipdfmx}\PassOptionsToPackage{dvipdfmx}{web}}
+\DeclareOptionX{xetex}{\setcounter{jjgdriver}{2}
+ \def\jjgdriver{\@gobble}}
+% \end{macrocode}
+% \begin{macrocode}
+\DeclareOptionX*{\PassOptionsToClass{\CurrentOption}{article}}
+% \end{macrocode}
+% Used for debugging:
+% Where's the bug?\IndexOpt{debug}
+% \begin{macrocode}
+\newif\ifdebug \debugfalse
+\DeclareOptionX{debug}{\debugtrue}
+% \end{macrocode}
+% This option \IndexOpt{final}\opt{final} removes window ui and other things.
+% \begin{macrocode}
+\newif\iffinal \finalfalse
+\DeclareOptionX{final}{\finaltrue}
+% \end{macrocode}
+% Play \textbf{Double Jeopardy!}\IndexOpt{double} Double the amounts, double the fun!
+% \begin{macrocode}
+\newif\ifdouble \doublefalse
+\def\scaleFactor{1}
+\DeclareOptionX{double}{\doubletrue\def\scaleFactor{2}}
+% \end{macrocode}
+% We implement a two player game\IndexOpt{twoplayer}, by first declaring \texttt{twoplayer} as an option.
+% \changes{v3.0h}{2008/11/16}{Added \texttt{twoplayer} option, as well as additional properties for
+% setting up the option.}
+% \begin{macrocode}
+\newif\ifjjgtwoplayer\jjgtwoplayerfalse
+\def\twoplayerGame{false}
+\DeclareOptionX{twoplayer}{\jjgtwoplayertrue\def\twoplayerGame{true}}
+% \end{macrocode}
+% Inputs the \IndexOpt{pro}\texttt{pro} code: uses layers, distiller 7.0 or later is required.
+% If the \texttt{pro} option is taken, then allow peeking as layers are used to hide the questions.
+% \begin{macrocode}
+\DeclareOptionX{pro}{\let\jjgInputProCode\jjg@InputProCode
+ \ExecuteOptionsX{allowpeeking}
+ \AtBeginDocument{\@ifundefined{xBld}{\PackageError{jj_game}
+ {You have specified the `pro' option, but\MessageBreak
+ the aeb_pro package is not loaded with its\MessageBreak
+ `uselayers' option}{See jjg_pro_ca.tex as an example of
+ the correct loading\MessageBreak
+ of aeb_pro}}{}}}
+\def\jjg@InputProCode{\InputIfFileExists{jjgpro.def}%
+ {\ClassWarning{jj_game}{Inputting code for pro option}
+ \ClassWarningNoLine{jj_game}{AeB Pro required with uselayers
+ option}}{\ClassWarning{jjg_game}{Cannot find jjgpro.def.
+ \MessageBreak Reinstall or refresh your file name database.}}}
+\let\jjgInputProCode\relax
+\AtEndOfClass{\jjgInputProCode}
+% \end{macrocode}
+% For credit play\IndexOpt{forcredit}. Enables a Jeopardy game to be handed in for credit. Adds security measures so
+% student cannot cheat. Works best when the \texttt{pro} option is used.
+% \begin{macrocode}
+\DeclareOptionX{forcredit}{%
+ \let\jjImportForCreditCode\jj@ImportForCreditCode}
+% \end{macrocode}
+% The normal behavior\IndexOpt{allowpeeking} of the game is that if the contestant looks ahead at a question,
+% then the tile on the game board corresponding to the question viewed is hidden.
+% The contestant is not allowed to answer that question. Use \opt{allowpeeking} option to remove
+% this feature of the game.
+% \changes{v3.0c}{2007/10/29}{
+% Added the \texttt{allowpeeking} option}
+% \begin{macrocode}
+\DeclareOptionX{allowpeeking}{\jjnopeekingfalse}
+\newif\ifjjnopeeking \jjnopeekingtrue
+% \end{macrocode}
+% \begin{macrocode}
+\let\jjImportForCreditCode\relax
+\def\jj@ImportForCreditCode{\@ifpackageloaded{aeb_pro}
+ {\InputIfFileExists{jjcredit.def}
+ {\ClassWarning{jj_game}{Inputting forcredit code}
+ \ClassWarningNoLine{jj_game}{Don't forget to use
+ \string\contestantName\MessageBreak
+ and \string\gameboardPrintButton}}
+ {\ClassWarning{jj_game}{Cannot find jjcredit.def}}}
+ {\ClassWarningNoLine{jj_game}
+ {The forcredit option requires the aeb_pro package}}}
+% \end{macrocode}
+% Several pre-defined designs are accessible through \IndexOpt{design}\opt{design} option. Design
+% choices are \texttt{jeopardy}, \texttt{florida}, \texttt{iceland}, \texttt{hornet}, \texttt{qatar}, \texttt{norway},
+% \texttt{germany}, \texttt{bahamas}, \texttt{spain}.
+% \begin{macrocode}
+\let\jjg@madedesignselection0
+\define@choicekey+{jj_game.cls}{design}{jeopardy,florida,iceland,%
+ hornet,qatar,norway,germany,bahamas,spain,custom}{%
+ \ifx\jjg@madedesignselection0\def\jj@design@choice{#1}%
+ \AtEndOfClass{\jjInputDesignChoice}%
+ \global\let\jjg@madedesignselection1
+ \def\jjg@useddesign{design}\else
+ \ClassWarning{jj_game}{Do not use both design
+ and customdesign\MessageBreak
+ at the same time.\MessageBreak
+ Using the \jjg@useddesign\space selection}\fi}
+{\ClassWarning{jj_game}{Bad choice for design, permissible values
+ are jeopardy, florida, iceland, hornet, qatar, norway, %
+ germany, bahamas, spain. Try again}}
+\def\jjInputDesignChoice{%
+ \InputIfFileExists{design_\jj@design@choice.def}%
+ {\ClassWarning{jj_game}{Inputting design choice \jj@design@choice}}%
+ {\ClassWarning{jj_game}{Cannot find the file
+ design_\jj@design@choice.def}}%
+}
+% \end{macrocode}
+% Allow the user to create his own design\IndexOpt{customdesign}. The file \verb!design_\jj@design@choice.def! then is input.
+% \begin{macrocode}
+\define@key{jj_game.cls}{customdesign}{%
+ \ifx\jjg@madedesignselection0\def\jj@design@choice{#1}%
+ \AtEndOfClass{\jjInputDesignChoice}%
+ \global\let\jjg@madedesignselection1
+ \def\jjg@useddesign{customdesign}\else
+ \ClassWarning{jj_game}{Do not use both design and customdesign
+ \MessageBreak at the same time.\MessageBreak
+ Using the \jjg@useddesign\space selection}\fi}
+% \end{macrocode}
+% When the \texttt{nodesigngraphics}\IndexOpt{nodesigngraphics} option is taken,
+% the effects of the commands\medskip
+%\begin{verbatim}
+% \defineInstructionPageGraphic
+% \defineGameboardPageGraphic
+% \defineQuestionPagesGraphic
+%\end{verbatim}
+%are cancelled out.
+% \begin{macrocode}
+\DeclareOptionX{nodesigngraphics}{\let\jjgdesigngraphics\endinput}
+\let\jjgdesigngraphics\relax
+% \end{macrocode}
+% Language \opt{lang}\IndexOpt{lang} option, languages supported are \texttt{english} and \texttt{german} options.
+% \begin{macrocode}
+\define@choicekey+{jj_game.cls}{lang}[\val\nr]{english,german}
+{\xdef\jjLangOpt{\nr}}{\ClassWarning{jj_game}
+ {Bad choice for lang, permissible values are english and german.
+ Try again.}}
+\def\jjLangOpt{0}
+% \end{macrocode}
+%
+% Look for configuration file
+%
+% \begin{macrocode}
+\ifpdf\ExecuteOptionsX{pdftex}\else
+ \ifxetex\ExecuteOptionsX{xetex}\else
+% \end{macrocode}
+% For backward compatibility, we \cs{let} \cs{ExecuteOptions} to
+% \cs{ExecutedOptionsX}, saving and restoring as we go.
+% \begin{macrocode}
+ \let\ExecuteOptions@SAVE\ExecuteOptions
+ \let\ExecuteOptions\ExecuteOptionsX
+ \InputIfFileExists{jj_game.cfg}{}
+ {\@ifundefined{l@tex@@@@driver}{\ExecuteOptionsX{dvips}}
+ {\ExecuteOptionsX{dvipsone}}}%
+ \let\ExecuteOptions\ExecuteOptions@SAVE
+ \fi\fi
+% \end{macrocode}
+% \subsection{Process Options}
+% \begin{macrocode}
+\ProcessOptionsX
+% \end{macrocode}
+% \section{Load the article class}
+% We model the \pkg{jj\_game} class after the \pkg{article} class.
+% \begin{macrocode}
+\LoadClass{article}[2014/09/29]
+% \end{macrocode}
+% \section{Required Packages}
+% We do not pass the driver options \texttt{pdftex}, \texttt{luatex}, or \texttt{xetex} to \pkg{web}, because that
+% package detects these drivers as well.
+% \begin{macrocode}
+\edef\x{\noexpand
+ \RequirePackage[\jjgdriver,usetemplates,dvipsnames]{web}}\x
+\RequirePackage[execJS]{eforms}[2016/08/29]
+\RequirePackage{verbatim}
+\RequirePackage{comment}
+\RequirePackage{calc}
+% \end{macrocode}
+% If user has chosen the \texttt{final} option, we use hyperref to set the viewer window;
+% otherwise we set \verb!\let\JJinitSetup\relax!. The user who is using
+% \texttt{aeb\_pro} with \texttt{jj\_game} can use the extensive controls in that package.
+% \begin{macrocode}
+\iffinal
+ \def\JJinitSetup{%
+ \hypersetup{%
+ pdfmenubar=false,
+ pdftoolbar=false,
+ pdffitwindow=true,
+ pdfcenterwindow=true,
+ pdfwindowui=false%
+ }
+ }
+\else
+ \let\JJinitSetup\relax
+\fi
+\AtEndOfClass{\JJinitSetup}
+% \end{macrocode}
+% Process the language option, the default is english
+% \begin{macrocode}
+\ifcase\jjLangOpt\relax
+ \includecomment{JJLangEnglish}
+ \excludecomment{JJLangGerman}
+\or
+ \includecomment{JJLangGerman}
+ \excludecomment{JJLangEnglish}
+ \AtEndOfClass{\germanLocalization}
+\fi
+\@ifundefined{jjImportForCreditCode}
+ {\excludecomment{JJForCredit}}
+ {\includecomment{JJForCredit}}
+% \end{macrocode}
+% \cs{germanLocalization} consists of some definitions that specialize
+% certain strings of \texttt{jj\_game}.
+% \begin{macrocode}
+\def\germanLocalization{%
+ \currencyHeading{\bfseries For~\EUR\theCurrencyAmt:}%
+ \correctText{Richtig!}\incorrectText{Falsch!}%
+ \def\jb@sepStyle{2}\def\jb@currStyle{0}%
+ \def\APScore@Currency@def{"\string\\u20ac"}%
+ \printButtonCaption{Drucken}%
+ \printButtonLabel{Diese Seite drucken}%
+ \contestantNameLabel{Student}%
+ \timestampLabel{Zeitstempel}%
+ \timeStampFormat{dd/mm/yy, H:MM:ss.}%
+ \enterNamePlease{Bitte geben Sie Ihren Namen auf
+ der ersten Seite ein, bevor Sie das Spiel beginnen!}
+ \def\jb@Score{"Punkte "}
+ \illegalAccessMsg{Sie haben gespickelt! Bitte w\string\344hlen
+ Sie erst eine Frage vom Spielbrett, bevor Sie umbl\string\344ttern -
+ diese Antwort wird nicht gewertet! \string\326ffnen Sie das
+ PDF erneut und spielen Sie dieses Mal ohne zu spickeln.}
+ \illegalAnswerTwiceMsg{\string\304ndern Ihrer Antwort
+ ist nicht erlaubt!}
+
+}
+% \end{macrocode}
+% Default color definitions for the Jeopardy game. These will be used
+% if no colors are specified.
+% \begin{macrocode}
+\definecolor{defaultfillCells}{rgb}{0.98,0.92,0.73}
+\def\defaultfillCells{defaultfillCells}
+\definecolor{defaultfillBanner}{rgb}{0.5,0,0.5}
+\def\defaultfillBanner{defaultfillBanner}
+\definecolor{defaulttextBanner}{rgb}{1,1,0} % yellow
+\def\defaulttextBanner{defaulttextBanner}
+\definecolor{defaulttextBoard}{rgb}{1,1,0} % yellow
+\def\defaulttextBoard{defaulttextBoard}
+\definecolor{defaultfillInstructions}{rgb}{0.98,0.92,0.73}
+\def\defaultfillInstructions{defaultfillInstructions}
+\definecolor{defaultfillGameBoard}{rgb}{1,0.8,0.6}
+\def\defaultfillGameBoard{defaultfillGameBoard}
+\definecolor{defaultfillQuestions}{rgb}{1,0.8,0.6}
+\def\defaultfillQuestions{defaultfillQuestions}
+\def\defaultDollarColorAmt{blue}
+\def\defaultLinkColor{webgreen}
+\definecolor{jj_banner_bg}{named}{defaultfillBanner}
+\definecolor{jj_banner_txt}{named}{defaulttextBanner}
+\def\jj@transparent{transparent}
+% \end{macrocode}
+% \begin{macro}{\bannerTextFont}
+% \begin{macro}{\titleBanner}
+% Commands for defining the banner text and font.
+% \begin{macrocode}
+\newcommand{\bannerTextFont}{\sffamily\huge}
+\def\bannerTextColor{\ifx\textBanner\jj@transparent
+ \else\color{\textBanner}\fi}
+\def\titleBanner#1{\def\@titleBanner{#1}}
+\titleBanner{You are the Winner!}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\insertJJTitleBanner}
+% The title banner is displayed on the first page, the text of the first page
+% is the content of the \texttt{instructions} environment. If you want more than
+% one page of instructions, begin an new page with \cs{newpage}, then insert
+% \cs{insertJJTitleBanner} to get the start up banner to appear.
+% \begin{macrocode}
+\def\insertJJTitleBanner{\newpage\jb@Banner{\@titleBanner}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\includeFootBanner}
+% \begin{macro}{\authorURL}
+% Use \cs{includeFootBanner} to get a matching banner at the foot of the first page.
+% The banner contains the author's name and university. Use \cs{author} and \cs{university}
+% from the web package to properly populate this command. Use it in the preamble.
+% \begin{macrocode}
+\newcommand{\includeFootBanner}{%
+ \renewcommand{\@oddfoot}
+ {%
+ \ifnum\thepage=1\relax
+ \colorbox{jj_banner_bg}{\makebox[\linewidth-2\fboxsep]{%
+ \href{\jjgauthorURL}%
+ {\textcolor{jj_banner_txt}{\webauthor\ \copyright\ \the\year}}%
+ \hfill\textcolor{jj_banner_txt}{\webuniversity}}}\else\hfil\fi
+ }%
+}
+\newcommand{\authorURL}[1]{\def\jjgauthorURL{#1}}
+\authorURL{http://www.example.com}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \section{The Main Code}
+% Much of the code below was adapted from the web package.
+% \begin{macrocode}
+\newdimen\jb@paperheight
+\newdimen\jb@tmpdimb
+\jb@paperheight=\paperheight
+\newdimen\@Leftmargin \@Leftmargin=0cm
+\newdimen\@Rightmargin \@Rightmargin=0cm
+\newdimen\@Topmargin \@Topmargin=0in
+\newdimen\@Bottommargin \@Bottommargin=0in
+\parindent0pt
+\setlength\headheight{0pt}
+\setlength\headsep {0pt}
+\setlength\footskip {0pt}
+\hoffset=0pt
+\voffset=0pt
+\pagestyle{empty}
+\def\InitLayout{%
+ \setlength{\textwidth}{\paperwidth}
+ \addtolength{\textwidth}{-\@Leftmargin}
+ \addtolength{\textwidth}{-\@Rightmargin}
+ \setlength{\textheight}{\paperheight}
+ \addtolength{\textheight}{-\@Topmargin}
+ \addtolength{\textheight}{-\@Bottommargin}
+ \addtolength{\textheight}{-\headheight}
+ \addtolength{\textheight}{-\headsep}
+ \addtolength{\textheight}{-\footskip}
+ \setlength{\oddsidemargin}{\@Leftmargin}
+ \addtolength{\oddsidemargin}{-1in}
+ \setlength{\evensidemargin}{\@Leftmargin}
+ \addtolength{\evensidemargin}{-1in}
+ \setlength{\topmargin}{\@Topmargin}
+ \addtolength{\topmargin}{-1in}
+ \setlength{\textscreenwidth}{\paperwidth}
+}
+\def\screensize#1#2{%
+ \paperheight=#1%
+ \paperwidth=#2
+ \web@set@paper
+ \InitLayout
+}
+\def\marginsize#1#2#3#4{%
+ \@Leftmargin=#1
+ \@Rightmargin=#2
+ \@Topmargin=#3
+ \@Bottommargin=#4
+ \InitLayout
+}
+% \end{macrocode}
+% The default margin size
+% \begin{macrocode}
+\marginsize{.25in}{.25in}{.25in}{.25in}
+\newcount\rownum \rownum=1 % These registers keep track of the row and
+\newcount\colnum \colnum=0 % column of the quizboard
+\newcount\corMsgnum \corMsgnum=0 % These registers keep track of the
+\newcount\errMsgnum \errMsgnum=0 % error messages
+\newcount\jb@n
+\newcount\jb@m
+\newtoks\jb@rowtoks
+\newcounter{newletter}
+\newdimen\cellHeight \cellHeight=1in
+\newdimen\cellWidth \cellWidth=.5in
+\newdimen\tablewidth
+\newdimen\tableheight
+\newcount\numCategories \numCategories=5
+\newcount\numQuestions \numQuestions=5
+\newdimen\rulewidth \rulewidth=1bp
+\newdimen\extraHeight \extraHeight=.2in
+\newdimen\extraWidth \extraWidth=0pt
+% \end{macrocode}
+% Calculate the size of the screen page.
+% \begin{macrocode}
+\def\calcPaperSize{%
+% \end{macrocode}
+% Calculate paperwidth and \cs{tablewidth}
+% \begin{macrocode}
+ \tablewidth=\numCategories\cellWidth
+ \advance\tablewidth by \rulewidth
+ \advance\tablewidth by \numCategories\rulewidth
+ \paperwidth=\tablewidth
+ \advance\paperwidth by\@Leftmargin % two times margin
+ \advance\paperwidth by\@Rightmargin % two times margin
+ \advance\paperwidth by2\extraWidth % need more width
+% \end{macrocode}
+% Calculate paperheight and \cs{tableheight}
+% \begin{macrocode}
+ \tableheight=\numQuestions\cellHeight
+ \advance\tableheight by\cellHeight % banner
+ \advance\tableheight by2\rulewidth % two rules for banner
+ \advance\tableheight by\numQuestions\rulewidth
+ \paperheight=\tableheight
+ \advance\paperheight by\cellHeight % score
+ \advance\paperheight by\@Topmargin
+ \advance\paperheight by\@Bottommargin
+ \advance\paperheight by\topskip
+ \advance\paperheight by\extraHeight
+ \screensize{\paperheight}{\paperwidth}
+}
+\def\verbatimwrite{\bgroup\catcode``=0 \@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\egroup}
+% \end{macrocode}
+% \subsection{Create Design Commands}
+% \begin{macrocode}
+\def\jb@linkColor{\defaultLinkColor}
+% \end{macrocode}
+% \begin{macrocode}
+\def\jj@setChoice#1#2{% this choice, default
+ \ifx#1\@empty#2\else#1\fi}
+\def\jj@updateChoice#1#2{% this choice, current choice
+ \ifx#1\@empty\xdef#1{#2}\else\xdef#2{#1}\fi}
+% \end{macrocode}
+% \begin{macro}{\convertToSetKeys}
+% We use the \textsf{xkeyval} package to parse the key, but we have a twist: The key-values are
+% given in the form of object properties \texttt{<key>:<value>}. The command
+% \cs{@convertColoniiEqual} does the work. The way \cs{convertToSetKeys} is used is
+% is shown below:
+%\begin{verbatim}
+%\define@key{dps}{fname}{\def\dpsfname{#1}}
+%\define@key{dps}{mname}{\def\dpsmname{#1}}
+%\define@key{dps}{lname}{\def\dpslname{#1}}
+%\def\setName#1{%
+% \convertToSetKeys{dps}{#1}}
+%...
+%\setName {
+% fname: D.,
+% mname: P.,
+% lname: Story
+%}
+%\end{verbatim}
+% where \cs{setName} is some command, \texttt{\#1} is the name of the
+% \textsf{xkeyval} family to be used, and \texttt{\#2} are the
+% \texttt{<key>:<value>} pairs.
+% \begin{macrocode}
+\newtoks\jb@tmptoks \jb@tmptoks={}
+\def\jjgdummy{dummy}
+\def\convertToSetKeys#1#2{%
+ \def\thisxkvFamily{#1}\def\jjg@scratch{}\jb@tmptoks={}%
+ \@convertColoniiEqual#2,dummy:dummy,\@nil
+}
+\def\@convertColoniiEqual#1:#2,#3\@nil{%
+ \def\jj@rgii{#2}\ifx\jj@rgii\jjgdummy
+ \edef\jj@next{\noexpand\setkeys{\thisxkvFamily}{\the\jb@tmptoks}}%
+ \else\jb@tmptoks=\expandafter{\jjg@scratch,#1=#2}%
+ \edef\jjg@scratch{\the\jb@tmptoks}%
+ \def\jj@next{\@convertColoniiEqual#3\@nil}\fi\jj@next
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\DeclareColors}
+% Macro to set the design parameters for LaTeX colors
+% \begin{macrocode}
+\define@key{declcolors}{fillCells}[\defaultfillCells]%
+ {\def\fillCells{#1}}
+\define@key{declcolors}{fillBanner}[\defaultfillBanner]%
+ {\def\fillBanner{#1}}
+\define@key{declcolors}{textBanner}[\defaulttextBanner]%
+ {\def\textBanner{#1}}
+\define@key{declcolors}{textBoard}[\defaulttextBoard]%
+ {\def\textBoard{#1}}
+\define@key{declcolors}{fillInstructions}[\defaultfillInstructions]%
+ {\def\fillInstructions{#1}}
+\define@key{declcolors}{fillGameBoard}[\defaultfillGameBoard]%
+ {\def\fillGameBoard{#1}}
+\define@key{declcolors}{fillQuestions}[\defaultfillQuestions]%
+ {\def\fillQuestions{#1}}
+\define@key{declcolors}{dollarColor}[\defaultDollarColorAmt]%
+ {\def\dollarColor{#1}}
+\define@key{declcolors}{linkColor}[\defaultLinkColor]%
+ {\def\@linkcolor{#1}}
+\setkeys{declcolors}{fillCells,fillBanner,textBanner,textBoard,%
+ fillInstructions,fillGameBoard,fillQuestions,dollarColor,linkColor}%
+\def\DeclareColors#1{\convertToSetKeys{declcolors}{#1}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\APDollar}
+% Macro to set the design parameters for the Dollar tile, this is the tile seen
+% on the game board showing the monetary amounts of each question. The name of
+% this tile is \verb!\the\rownum\the\colnum!, corresponding to the row and column
+% position of the tile in the game board.
+% \begin{macrocode}
+\def\APDollar@Font@def{TiRo}\def\APDollar@Size@def{20}
+\def\APDollar@TextColor@def{0 0 1}\def\APDollar@BorderColor@def{0 0 0}
+\def\APDollar@FillColor@def{1 0.35 1}
+\define@key{apdollar}{Font}[\APDollar@Font@def]{\def\APDollar@Font{#1}}
+\define@key{apdollar}{Size}[\APDollar@Size@def]{\def\APDollar@Size{#1}}
+\define@key{apdollar}{TextColor}[\APDollar@TextColor@def]%
+ {\def\APDollar@TextColor{#1}}
+\define@key{apdollar}{BorderColor}[\APDollar@BorderColor@def]%
+ {\def\APDollar@BorderColor{#1}%
+ \ifx\APDollar@BorderColor\jj@transparent\gdef\APD@llarBorder{}\else
+ \xdef\APD@llarBorder{\APDollar@BorderColor}\fi
+}
+\define@key{apdollar}{FillColor}[\APDollar@FillColor@def]%
+ {\def\APDollar@FillColor{#1}%
+ \ifx\APDollar@FillColor\jj@transparent\gdef\APD@llarFill{}\else
+ \xdef\APD@llarFill{\APDollar@FillColor}\fi
+}
+\def\APD@llar{/\APDollar@Font\space\APDollar@Size\space Tf
+ \APDollar@TextColor\space rg}
+\setkeys{apdollar}{Font,Size,TextColor,BorderColor,FillColor}
+\def\APDollar#1{\convertToSetKeys{apdollar}{#1}}
+\APDollar{}
+% \end{macrocode}
+% \end{macro}
+% A crude euro symbol that can be typeset in \TeX.
+% \begin{macrocode}
+\newcommand\EUR{%
+{\sffamily C%
+\makebox[0pt][l]{\kern-.70em\mbox{--}%
+}%
+\makebox[0pt][l]{\kern-.68em\raisebox{.25ex}{--}}}\,%
+}
+% \end{macrocode}
+% \begin{macro}{\APHidden}
+% This collection of key-values set the appearance of the text field whose name
+% is \texttt{GrandPoohbah}. It is a hidden text field above the game board
+% extending across the list of categories. If the player attains the goal,
+% the \texttt{GrandPoohbah} field becomes visible showing the \texttt{Champion} message.
+% \begin{macrocode}
+\def\APHidden@Font@def{TiRo}\def\APHidden@Size@def{20}
+\def\APHidden@TextColor@def{0 0 1}\def\APHidden@BorderColor@def{0 0 0}
+\def\APHidden@FillColor@def{0.98 0.92 0.73}
+\def\Champion@def{You are a Champion!}
+\define@key{aphidden}{Champion}[\Champion@def]{\def\jb@Champion{#1}}
+\define@key{aphidden}{Font}[\APHidden@Font@def]{\def\APHidden@Font{#1}}
+\define@key{aphidden}{Size}[\APHidden@Size@def]{\def\APHidden@Size{#1}}
+\define@key{aphidden}{TextColor}[\APHidden@TextColor@def]%
+ {\def\APHidden@TextColor{#1}}
+\define@key{aphidden}{BorderColor}[\APHidden@BorderColor@def]%
+ {\def\APHidden@BorderColor{#1}%
+ \ifx\APHidden@BorderColor\jj@transparent\gdef\APHidd@nBorder{}\else
+ \xdef\APHidd@nBorder{\APHidden@BorderColor}\fi
+}
+\define@key{aphidden}{FillColor}[\APHidden@FillColor@def]%
+ {\def\APHidden@FillColor{#1}%
+ \ifx\APHidden@FillColor\jj@transparent\gdef\APHidd@nFill{}\else
+ \xdef\APHidd@nFill{\APHidden@FillColor}\fi
+}
+\def\APHidd@n{/\APHidden@Font\space\APHidden@Size\space Tf
+ \APHidden@TextColor\space rg}
+\setkeys{aphidden}{Champion,Font,Size,TextColor,BorderColor,FillColor}
+\def\APHidden#1{\convertToSetKeys{aphidden}{#1}}
+\APHidden{}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\APRight}
+% Use this command to set the key-value pairs for the appearance of the push button
+% whose name is \verb!\the\rownum\the\colnum R!. When the player answers the question
+% correctly, this field, initially hidden, becomes visible with a message of congratulations,
+% the default message is \texttt{Right!}
+% \begin{macrocode}
+\def\APRight@Font@def{TiRo}\def\APRight@Size@def{20}
+\def\APRight@TextColor@def{0 0 1}\def\APRRight@Msg@def{Right!}
+\def\correctText#1{\gdef\@APRightMsg{#1}}\correctText{Right!}
+\define@key{apright}{Font}[\APRight@Font@def]{\def\APRight@Font{#1}}
+\define@key{apright}{Size}[\APRight@Size@def]{\def\APRight@Size{#1}}
+\define@key{apright}{TextColor}[\APRight@TextColor@def]%
+ {\def\@APRightTextColor{#1}}
+\define@key{apright}{Message}[\APRRight@Msg@def]{\def\@APRightMsg{#1}}
+\def\@APRight{/\APRight@Font\space\APRight@Size\space Tf
+ \@APRightTextColor\space rg}%
+\setkeys{apright}{Font,Size,TextColor,Message}
+\def\APRight#1{\convertToSetKeys{apright}{#1}}
+\APRight{}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\APWrong}
+% Use this command to set the key-value pairs for the appearance of the push button
+% whose name is \verb!\the\rownum\the\colnum W!. When the player answers the question
+% incorrectly, this field, initially hidden, becomes visible with a message,
+% the default message is \texttt{Wrong!}
+% \begin{macrocode}
+\def\APWrong@Font@def{TiRo}\def\APWrong@Size@def{20}
+\def\APWrong@TextColor@def{0 0 1}\def\APRWrong@Msg@def{Wrong!}
+\def\incorrectText#1{\gdef\@APWrongMsg{#1}}\incorrectText{Wrong!}
+\define@key{apwrong}{Font}[\APWrong@Font@def]{\def\APWrong@Font{#1}}
+\define@key{apwrong}{Size}[\APWrong@Size@def]{\def\APWrong@Size{#1}}
+\define@key{apwrong}{TextColor}[\APWrong@TextColor@def]%
+ {\def\@APWrongTextColor{#1}}
+\define@key{apwrong}{Message}[\APRWrong@Msg@def]{\def\@APWrongMsg{#1}}
+\def\@APWrong{/\APWrong@Font\space\APWrong@Size\space Tf
+ \@APWrongTextColor\space rg}
+\setkeys{apwrong}{Font,Size,TextColor,Message}
+\def\APWrong#1{\convertToSetKeys{apwrong}{#1}}
+\APWrong{}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\GameDesign}
+% Use this command to set the key-value pairs for designing the game board. Setting
+% these values are required for each game. There are default values, but the key-values
+% that are required to be filled is are \texttt{Cat}, and \texttt{NumQuestions}. The number of Cat entries
+% determines the number of categories, and \texttt{NumQuestions} determines the number of questions
+% in each category.
+% \begin{macrocode}
+\define@key{gamedesign}{Cat}{\global\advance\numCategories by1
+ \jb@Cat#1,}
+\define@key{gamedesign}{CellWidth}[1in]{\global\cellWidth=#1\relax}
+\define@key{gamedesign}{CellHeight}[.5in]{\global\cellHeight=#1\relax}
+\define@key{gamedesign}{NumQuestions}[5]{\global\numQuestions=#1\relax}
+\define@key{gamedesign}{Goal}[3500]{\def\jb@Goal{#1}}
+\define@key{gamedesign}{GoalPercentage}[0]{\def\jb@GoalPercentage{#1}}
+\define@key{gamedesign}{ExtraHeight}[.2in]{\global\extraHeight=#1\relax}
+\define@key{gamedesign}{ExtraWidth}[0pt]{\global\extraWidth=#1\relax}
+\define@key{gamedesign}{Champion}[\Champion@def]{\def\jb@Champion{#1}}
+\setkeys{gamedesign}{CellWidth,CellHeight,NumQuestions,Goal,%
+ GoalPercentage,ExtraHeight,ExtraWidth,Champion}
+% \end{macrocode}
+% Here is the code for \cs{GameDesign}, after gathering the key-value pairs for
+% the \texttt{gamedesign} family. We set the \texttt{Goal} (if \texttt{GoalPercentage} is specified),
+% then, based on the parameters, we calculate the page size for this game board.
+% \begin{macrocode}
+\def\GameDesign#1{\global\numCategories=0\relax
+ \convertToSetKeys{gamedesign}{#1}%
+ \ifdebug
+ \typeout{^^JClass jj_game Info:}
+ \typeout{Number of Categories: \the\numCategories}
+ \typeout{Number of Questions per Category: \the\numQuestions^^J}
+ \fi
+% \end{macrocode}
+%\begin{verbatim}
+% Let n = numQuestions, m = numCategories
+% 100*n*(n+1)/2 = 50*n*(n+1) = total for one category
+% 50*m*n*(n+1) = total money;
+% 100*m*n*(n+1) = total money for double jeopardy
+%\end{verbatim}
+% \begin{macrocode}
+ \jb@n = \numQuestions
+ \advance\jb@n by 1
+ \multiply\jb@n by\numQuestions
+ \multiply\jb@n by50 % total money/category
+ \multiply\jb@n by\numCategories % total money
+ \ifdouble
+ \multiply\jb@n by2 % total money, double jj
+ \fi
+ \ifdebug
+ \typeout{Total Money: \the\jb@n}
+ \fi
+ % See if GoalPercentage differs from the default value
+ \xdef\jb@tmp{\csname 0\endcsname}%
+ \xdef\jb@temp{\csname\jb@GoalPercentage\endcsname}%
+ \ifx\jb@tmp\jb@temp
+ \else
+ \ifdebug
+ \typeout{Goal Percentage Specified: \jb@GoalPercentage}
+ \fi
+ \multiply\jb@n by\jb@GoalPercentage
+ \divide\jb@n by100
+ \def\jb@Goal{\the\jb@n}
+ \fi
+ \xdef\Goal{\jb@Goal}
+ \ifdebug
+ \typeout{Goal: \Goal^^J}
+ \fi
+ \calcPaperSize
+ \jjCancelOutAeBProCatalog
+ \jjImportForCreditCode
+}
+\def\jjCancelOutAeBProCatalog{\iffinal\let\aeb@SetCatalog\@empty\fi}
+\def\jb@Cat{\@ifnextchar[{\jb@item}{\jb@item[] }}%
+\gdef\jb@item[#1]#2,{%
+ \expandafter\gdef\csname Category\the\numCategories\endcsname
+ {\forpbx{#1#2}}%
+ \expandafter\gdef\csname category\the\numCategories\endcsname{#2}%
+}%
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\APScore}
+% The \cs{APScore} command sets the key-value pairs for designing the score board. There
+% are three score boards: for a single player, the name of the field is \texttt{Total};
+% for the two player game, the names of the fields are \texttt{Total0} and \texttt{Total1}.
+% \begin{macrocode}
+\def\jb@Score{""}
+\def\jb@align@left{l}
+\def\jb@align@center{c}
+\def\jb@align@right{r}
+\def\APScore@Font@def{TiRo}
+\def\APScore@Size@def{20}
+\def\APScore@TextColor@def{0 0 1}
+\def\APScore@BorderColor@def{0 0 0}
+\def\APScore@FillColor@def{0.98 0.92 0.73}
+\def\APScore@CellHeight@def{\the\cellHeight}
+\def\APScore@CellWidth@def{\the\cellWidth}
+\def\APScore@AutoPlacement@def{true}
+\def\APScore@Score@def{""}
+\def\APScore@Currency@def{""}
+\def\APScore@align@def{r}
+\def\jb@align{r}
+%
+% twoplayer properties
+%
+\def\APScore@tp@ScaledCellWidth@def{.5}
+\let\APScore@tp@ScaledCellWidth\@empty
+\def\APScore@tp@HighlightBorderColor@def{1 0 0}
+%
+\define@key{apscore}{Font}[\APScore@Font@def]{\def\APScore@Font{#1}}
+\define@key{apscore}{Size}[\APScore@Size@def]{\def\APScore@Size{#1}}
+\define@key{apscore}{TextColor}[\APScore@TextColor@def]%
+ {\def\APScore@TextColor{#1}}
+\define@key{apscore}{BorderColor}[\APScore@BorderColor@def]%
+ {\def\APScore@BorderColor{#1}%
+ \ifx\APScore@BorderColor\jj@transparent\gdef\@APScoreBorder{}\else
+ \xdef\@APScoreBorder{\APScore@BorderColor}\fi
+}
+\define@key{apscore}{FillColor}[\APScore@FillColor@def]%
+ {\def\APScore@FillColor{#1}%
+ \ifx\APScore@FillColor\jj@transparent\gdef\@APScoreFill{}\else
+ \xdef\@APScoreFill{\APScore@FillColor}\fi
+}
+\define@key{apscore}{CellHeight}[\APScore@CellHeight@def]%
+ {\def\@APScorecellHeight{#1}}
+\define@key{apscore}{CellWidth}[\APScore@CellWidth@def]%
+ {\def\@APScorecellWidth{#1}}
+\define@boolkey{apscore}{AutoPlacement}[true]{}
+\define@key{apscore}{Score}[\APScore@Score@def]{\def\jb@Score{#1}}
+\define@key{apscore}{Currency}[\APScore@Currency@def]%
+ {\def\jb@Currency{#1}}
+\define@key{apscore}{align}[\APScore@align@def]{\def\jb@align{#1}}
+%
+% twoplayer properties
+%
+\define@key{apscore}{tpScaledCellWidth}%
+ [\APScore@tp@ScaledCellWidth@def]%
+ {\def\@APtpScaledCellWidth{#1}}
+\define@key{apscore}{tpHighlightBorderColor}
+ [\APScore@tp@HighlightBorderColor@def]%
+ {\def\@APtpHighlightBorderColor{#1}}
+\def\@APScore{/\APScore@Font\space\APScore@Size\space Tf
+ \APScore@TextColor\space rg}%
+%
+\setkeys{apscore}{Font,Size,TextColor,BorderColor,FillColor,%
+ CellHeight,CellWidth,AutoPlacement,Score,Currency,align,%
+ tpScaledCellWidth,tpHighlightBorderColor}
+%
+\def\APScore#1{\convertToSetKeys{apscore}{#1}%
+ \ifKV@apscore@AutoPlacement
+ \gdef\@PlaceScoreBoard{\@@PlaceScoreBoard}
+ \gdef\PlaceScoreBoard##1{%
+ \message{^^J\expandafter\string\csname APScore\endcsname:
+ `AutoPlacement: true', the use of \string\PlaceScoreBoard\space
+ is not valid in this case!^^J^^J}}%
+ \else
+ \gdef\@PlaceScoreBoard{\@@@PlaceScoreBoard\@gobble}%
+ \fi
+ \gdef\jb@Quad{2}%
+ \ifx\jb@align\jb@align@left\gdef\jb@Quad{0}%
+ \else\ifx\jb@align\jb@align@center\gdef\jb@Quad{1}%
+ \else\ifx\jb@align\jb@align@right\gdef\jb@Quad{2}%
+ \fi\fi\fi
+}
+\APScore{}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\PlaceScoreBoard}
+% A command for the user to place the location of the score board.
+% \begin{macrocode}
+\def\@@PlaceScoreBoard#1{#1}
+\long\def\PlaceScoreBoard#1{\def\@@@PlaceScoreBoard{#1}}
+\PlaceScoreBoard{{\centering\vbox{\ScoreBoard}}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\setTwoPlayerOptions}
+% The following are key-value definitions for the two player game
+% \begin{macrocode}
+\define@key{twoplayerKeys}{player1}[Player 1]{\def\jjg@playeri{#1}}
+\define@key{twoplayerKeys}{player2}[Player 2]{\def\jjg@playerii{#1}}
+\define@key{twoplayerKeys}{playerFmt}[\sffamily\small]%
+ {\def\jjg@playerFmt{#1}}
+\define@boolkey{twoplayerKeys}{checkbox}[true]{}
+\setkeys{twoplayerKeys}{player1,player2,playerFmt,checkbox}
+\newcommand{\setTwoPlayerOptions}[1]{%
+ \convertToSetKeys{twoplayerKeys}{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macrocode}
+\def\Rect#1{\pdf@rect{\textcolor{\@linkcolor}{#1}}}
+\def\({\noexpand\(}\def\){\noexpand\)}
+\def\Bbox#1#2{%
+ \vbox to#2{\hbox to#1{\hfill}\vfill}%
+}
+\def\hmark#1{\hypertarget{#1}{}}
+% \end{macrocode}
+% \begin{macro}{\bannerTextControl}
+% Use \cs{bannerTextControl} to tweak the positioning of the banner text.
+% \begin{macrocode}
+\newcommand{\bannerTextControl}[1]{#1}
+% \end{macrocode}
+% \end{macro}
+% Construct the running banners
+% \begin{macrocode}
+\def\jb@Banner#1{\vspace*{-\topskip}\hbox{\rlap{\ifx\fillBanner
+ \jj@transparent\else\color{\fillBanner}\fi
+ \setbox0=\hbox{\bannerTextFont\strut}\jb@tmpdimb=\ht0
+ \advance\jb@tmpdimb by6pt \jb@tmpdima=\dp0 \advance\jb@tmpdima by4pt
+ {\ifx\fillBanner\jj@transparent\else
+ \vrule height\jb@tmpdimb depth\jb@tmpdima width\textwidth\fi}}%
+ \vbox{\noindent\centering\bannerTextFont\bannerTextColor%
+ \strut\bannerTextControl{#1}}}\bigskip}
+% \end{macrocode}
+%
+% \subsection{Construct form fields}
+% This appearance is the opening face. Show dollar amounts. Clicking
+% jumps to the corresponding question.
+% \begin{macrocode}
+\def\dollarAP{%
+{\ifdouble\advance\rownum by\rownum\fi\xdef\@dollarAmt{\the\rownum00}}%
+\rlap{\pushButton[%
+ \H{P}\W{1}\S{S}\DA{\APD@llar}\BC{\APD@llarBorder}
+ \BG{\APD@llarFill}\CA{\@dollarAmt}
+ \A{/S/GoTo/D (Q\the\rownum\the\colnum) \jjAdditionalCellJSActions}
+]{\the\rownum\the\colnum}{\cellWidth}{\cellHeight}}}
+% \end{macrocode}
+% This appearance simply says Right! It appears if the user answers the
+% question correctly.
+% \begin{macrocode}
+\def\rightAP{\rlap{\efKern{0pt}{1bp}\pushButton[%
+ \F{\FHidden}\H{N}\S{S}\BG{}\DA{\@APRight}\CA{\@APRightMsg}
+]{\the\rownum\the\colnum R}{\cellWidth}{\cellHeight}}}
+% \end{macrocode}
+% This appearance simply says Wrong! It appears if the user answers the
+% question incorrectly.
+% \begin{macrocode}
+\def\wrongAP{\rlap{\efKern{0pt}{2bp}\pushButton[%
+ \F{\FHidden}\H{N}\S{S}\BG{}\DA{\@APWrong}\CA{\@APWrongMsg}
+]{\the\rownum\the\colnum W}{\cellWidth}{\cellHeight}}}
+% \end{macrocode}
+% \begin{macrocode}
+\def\jb@nDec{0}
+\def\jb@sepStyle{0}
+\def\jb@negStyle{0}
+\def\jb@currStyle{2}
+\def\jb@Currency{""}
+\def\jb@bCurrencyPrepend{true}
+% \end{macrocode}
+% \begin{macro}{\prependCurrency}
+% \begin{macro}{\appendCurrency}
+% Use these to prepend, the default, or append a currency symbol, if any. These
+% will appear in the \cs{ScoreBoard}.
+% \begin{macrocode}
+\newcommand{\prependCurrency}{\def\jb@bCurrencyPrepend{true}}
+\newcommand{\appendCurrency}{\def\jb@bCurrencyPrepend{false}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\ScoreBoard}
+% This is the text field for the score board. In two player mode, there are
+% two score boards, and in single player mode, there is only one.
+% \begin{macrocode}
+\def\AAVAction{event.target.textColor = event.value < 0 ?
+ "RGB \@APWrongTextColor".split(" ") :
+ "RGB \@APRightTextColor".split(" ");\r
+ this.dirty=false;}
+\def\AAFAction{AFNumber_Format\(\jb@nDec, \jb@sepStyle, \jb@negStyle,
+ \jb@currStyle, \jb@Currency, \jb@bCurrencyPrepend\);
+ event.value = \jb@Score\space + event.value;\r
+ this.dirty=false;}
+\let\jjgplayerihook\@empty
+\let\jjgplayeriihook\@empty
+\def\ScoreBoard{\ifjjgtwoplayer
+\setlength{\@tempdima}{\@APScorecellWidth}%
+\setlength{\@tempdima}{%
+ (\@APScorecellWidth)*\ratio{\@APtpScaledCellWidth\space pt}{1pt}}%
+\ifdim\@tempdima<\cellWidth
+\@tempdima=\cellWidth\fi
+ \edef\BboxWidth{\the\@tempdima}%
+\setlength{\@tempdima}{\@APScorecellHeight/2-4bp}%
+ \edef\BboxHeight{\the\@tempdima}%
+\ifKV@twoplayerKeys@checkbox
+\raisebox{\BboxHeight}{\checkBox[\Ff{\FfReadOnly}%
+ \textColor{\@APtpHighlightBorderColor\space rg}\BC{}%
+ \symbolchoice{circle}]{ckboxPlayer0}{10bp}{10bp}{On}}\fi\space
+\parbox[t]{\BboxWidth\ifxetex+4bp\fi}{\jjgplayerihook
+\textField[%
+ \H{N}\Q{\jb@Quad}\W{3}\S{I}\BC{\@APScoreBorder}\BG{\@APScoreFill}%
+ \DA{\@APScore}\autoCenter{n}\AA{\AAValidate{\AAVAction}%
+ \AAFormat{\AAFAction}}]{Total0}{\BboxWidth\ifxetex-4bp\fi}%
+ {\@APScorecellHeight\ifxetex-4bp\fi}\\[-3pt]
+\makebox[\linewidth][c]{\jjg@playerFmt\jjg@playeri}}\efKern{3pt}{0bp}\space
+\parbox[t]{\BboxWidth\ifxetex+4bp\fi}{%
+\textField[%
+ \H{N}\Q{\jb@Quad}\W{3}\S{I}\BC{\@APScoreBorder}\BG{\@APScoreFill}%
+ \DA{\@APScore}\autoCenter{n}\AA{\AAValidate{\AAVAction}%
+ \AAFormat{\AAFAction}}%
+]{Total1}{\BboxWidth\ifxetex-4bp\fi}%
+ {\@APScorecellHeight\ifxetex-4bp\fi}\jjgplayeriihook\\[-3pt]
+\makebox[\linewidth][c]{\jjg@playerFmt\jjg@playerii}}
+\ifKV@twoplayerKeys@checkbox
+\raisebox{\BboxHeight}{\checkBox[\Ff{\FfReadOnly}%
+ \textColor{\@APtpHighlightBorderColor\space rg}\BC{}%
+ \symbolchoice{circle}]{ckboxPlayer1}{10bp}{10bp}{On}}\fi
+\else\efKern{0pt}{-3bp}\textField[%
+ \H{N}\Q{\jb@Quad}\W{3}\S{I}\BC{\@APScoreBorder}%
+ \BG{\@APScoreFill}\DA{\@APScore}\autoCenter{n}%
+ \AA{\AAValidate{\AAVAction}\AAFormat{\AAFAction}}%
+]{Total}{\@APScorecellWidth\ifxetex-4bp\fi}%
+ {\@APScorecellHeight\ifxetex-4bp\fi}%
+\fi}
+% \end{macrocode}
+% \end{macro}
+% The pdf contents of a number rectangle: Three widgets superimposed
+% \begin{macrocode}
+\def\cell{\global\advance\colnum1 \ifnum\colnum>\numCategories
+ \global\colnum=1 \global\advance\rownum1 \fi
+ \moveleft.5\cellWidth\hbox{\efKern{0pt}{-1bp}\dollarAP
+ \efKern{0pt}{-1bp}\rightAP\efKern{0pt}{-1bp}\wrongAP}}%
+% \end{macrocode}
+% This provides the background color behind the banner
+% \begin{macrocode}
+\def\bgb{\ifxetex\rule{0pt}{\cellHeight+.6bp}\smash{\PoohBahBanner}\else
+ \PoohBahBanner\fi\smash{\rlap{\ifx\fillBanner\jj@transparent\else
+ \ifxetex\setlength{\tablewidth}{\tablewidth}%
+ \setlength{\cellHeight}{\cellHeight\ifxetex+.4pt\fi}\fi
+ \color{\fillBanner}{\vrule width\tablewidth height\cellHeight}\fi}}}
+% \end{macrocode}
+% This provides the background color behind the number board.
+% \begin{macrocode}
+\def\bgc{\smash{\rlap{{\ifx\fillCells\jj@transparent\else
+ \color{\fillCells}\vrule width\tablewidth height\cellHeight\fi}}}}
+% \end{macrocode}
+% The hidden banner set by \cs{APHidden} with the final message for the
+% contestant attaining the goal.
+% \begin{macrocode}
+\def\PoohBahBanner{\rlap{\ifxetex\advance\tablewidth-6bp\else
+ \advance\tablewidth-2bp\hskip1bp\fi
+\textField[%
+ \Q{1}\autoCenter{n}\F{\FHidden}\W{3}\S{I}\BC{\APHidd@nBorder}%
+ \BG{\APHidd@nFill}\DA{\APHidd@n}%
+ \DV{\jb@Champion}\V{\jb@Champion}%
+]{GrandPoohbah}{\tablewidth}{\cellHeight}}}
+% \end{macrocode}
+% \begin{macrocode}
+\def\forpbx#1{\vbox to\cellHeight{%
+ \hsize=\cellWidth\centering\vfill\strut\ifx\textBoard\jj@transparent
+ \else\color{\textBoard}\fi#1\strut\vfill}}
+\def\gameCategories{%
+ \jb@n=0
+ \jb@rowtoks={\bgb}%
+ \loop\ifnum\jb@n<\numCategories\advance\jb@n by1
+ \jb@tmptoks=\expandafter{%
+ \expandafter&\csname Category\the\jb@n\endcsname&}%
+ \edef\jb@temp{\the\jb@rowtoks\the\jb@tmptoks}%
+ \jb@rowtoks=\expandafter{\jb@temp}%
+ \repeat
+ \edef\jb@temp{\the\jb@rowtoks}%
+ \jb@rowtoks=\expandafter{\jb@temp\cr\\ }%
+\the\jb@rowtoks}
+
+% Hack a loop structure so I can do a double loop
+\long\def\oloop #1\orepeat{%
+ \def\oiterate{#1\relax % Extra \relax
+ \expandafter\oiterate\fi}%
+ \oiterate
+ \let\outeriterate\relax
+}
+\let\orepeat=\fi
+% \end{macrocode}
+% \begin{macrocode}
+\def\gamebody{%
+ \jb@rowtoks={}%
+ \jb@m=\numQuestions
+ \edef\jb@temp{}%
+ \oloop\advance\jb@m-1\ifnum\jb@m>0
+ \getrow
+ \orepeat
+ \the\jb@rowtoks}
+% \end{macrocode}
+% \begin{macrocode}
+\def\getrow{%
+ \jb@n=\numCategories
+ \edef\jb@temp{\the\jb@rowtoks}%
+ \jb@rowtoks=\expandafter{\jb@temp\bgc}%
+ \loop\advance\jb@n-1\ifnum\jb@n>0
+ \edef\jb@temp{\the\jb@rowtoks}%
+ \jb@rowtoks=\expandafter{\jb@temp&\cell&}%
+ \repeat
+ \edef\jb@temp{\the\jb@rowtoks}%
+ \jb@rowtoks=\expandafter{\jb@temp\cr\\ }%
+}
+% \end{macrocode}
+% \subsection{Construct Game Board}
+% The \cs{GameBoard} is as the name suggests is the game board. We set up a
+% tabular environment, then insert the \cs{gameCategories}, followed by
+% the \cs{gamebody}.
+% \begin{macrocode}
+\def\GameBoard{\vspace*{-\topskip}%
+\begingroup
+ % set up \halign environment
+ \tabskip0pt\offinterlineskip\parskip0pt\parindent0pt
+ \def\\{\noalign{\hrule height\rulewidth}}%
+ \hbox to\textwidth\bgroup\hfill
+ \vbox\bgroup\hsize=\tablewidth\hmark{GameBoard}%
+ \halign{##\vrule width\rulewidth
+ &&\hbox to\cellWidth{\hss\vbox to\cellHeight{\vss##\vss}\hss}%
+ &\vrule width\rulewidth##\cr\noalign{\hrule height\rulewidth}%
+ % Begin entering data into the different cells
+ \gameCategories
+ \gamebody
+ }%
+ \egroup\hfill
+ \egroup
+\endgroup\ifxetex\ifjjgtwoplayer\kern-1bp\else
+ \kern2bp\fi\fi
+% \end{macrocode}
+% Insert ScoreBoard
+% \begin{macrocode}
+\@PlaceScoreBoard{{\centering\vbox{\ScoreBoard}}}%
+\par\JJ@afterGameBoardInsertion}
+\let\JJ@afterGameBoardInsertion\@empty
+% \end{macrocode}
+% \begin{macro}{\afterGameBoardInsertion}
+% Use this command to insert material below the score board (hence below the game board).
+% \begin{macrocode}
+\newcommand{\afterGameBoardInsertion}[1]{%
+ \def\JJ@afterGameBoardInsertion{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+% \subsection{Begin Asking Questions}
+%
+% \begin{environment}{instructions}
+% The Instructions on first page.
+% \begin{macrocode}
+\def\instructions
+{%
+ \instructionPageTemplate
+ \ifx\fillInstructions\jj@transparent\else
+ \textBgColor{\fillInstructions}\fi
+ \jb@Banner{\@titleBanner}\par\parskip6pt
+}
+\def\endinstructions{\newpage}
+% \end{macrocode}
+% \end{environment}
+% \begin{macrocode}
+\let\Question\relax
+% \end{macrocode}
+% \begin{environment}{Questions}
+% The \texttt{Questions} environment contains the \texttt{Category} environment
+% which, in turn, contains the \texttt{Questions} environments.
+% \begin{macrocode}
+\def\Questions{\newpage\parskip0pt\relax\global\jb@n=0\relax
+ \gameboardPageTemplate
+ \ifx\fillGameBoard\jj@transparent\else
+ \textBgColor{\fillGameBoard}\fi\GameBoard
+ \newpage\ifx\fillQuestions\jj@transparent\else
+ \textBgColor{\fillQuestions}\fi
+ \rownum=0 \colnum=1 % initialize counters
+ \questionPagesTemplate
+}
+\def\endQuestions{%
+ \ifnum\jb@n=\numCategories\else
+ \typeout{Number of categories is not correct!}
+ \fi
+ \newpage}
+% \end{macrocode}
+% \end{environment}
+% \begin{environment}{Category}
+% The \texttt{Category} environment is nested within the \texttt{Questions} environment.
+% \begin{macrocode}
+\def\Category#1{
+ \def\currentCategory{#1}\global\advance\jb@n by1 \global\jb@m=0
+ \ifdebug
+ \typeout{^^JBegin Processing Category \the\jb@n: \currentCategory}
+ \typeout{If '\currentCategory' is different from}
+ \typeout{'\csname category\the\jb@n\endcsname',
+ then your categories are out of order!}
+ \fi}
+\def\endCategory{
+ \ifdebug
+ \ifnum\jb@m=\numQuestions
+ \else
+ \typeout{In the '\currentCategory' category,
+ the number of questions is not correct!}
+ \fi
+ \typeout{End Processing Category \the\jb@n:
+ \the\jb@m\space of \the\numQuestions\space Questions}
+ \fi
+}
+% \end{macrocode}
+% \end{environment}
+% \begin{macrocode}
+\let\jjAdditionalJSActions\@empty
+\def\jjAdditionalCellJSActions{\Next{\JS{%
+ var pushCell\the\rownum\the\colnum = true;\r
+ makeNameReadOnly();}}}
+\let\bJJGInsertLayer\@empty
+\let\eJJGInsertLayer\@empty
+% \end{macrocode}
+% \begin{macro}{\theCurrencyAmt}
+% \begin{macrocode}
+\def\theCurrencyAmt{{\count0=\the\rownum00\relax
+ \multiply\count0by\scaleFactor\relax\the\count0\relax}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\aboveCurrencySkip}
+% \begin{macrocode}
+\def\aboveCurrencySkip#1{\def\jj@aboveCurrencySkip{#1}}
+\aboveCurrencySkip{0pt}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\currencyHeading}
+% \begin{macrocode}
+\newcommand{\currencyHeading}[1]{\def\jj@currencyHeading{#1}}
+\currencyHeading{\bfseries For~\$\theCurrencyAmt:}
+% \end{macrocode}
+% \end{macro}
+% \begin{environment}{Question}
+% The environment for posing a question. It must appear within a \texttt{Category} environment.
+% \begin{macrocode}
+\def\Question{\newpage\global\advance\jb@m by1
+ \global\advance\rownum1 \ifnum\rownum>\numQuestions \global\rownum=1
+ \global\advance\colnum1 \fi
+ \global\advance\corMsgnum1 \ifnum\corMsgnum=8 \global\corMsgnum=1 \fi
+ \edef\peekingOpenAction{\ifjjnopeeking/H true/S/Hide%
+ /T (\the\rownum\the\colnum)\else\JS{;}\fi}%
+ \ifcase\thejjgdriver
+ \immediate\pdfobj{<< /O <<
+ \peekingOpenAction\space\jjAdditionalJSActions >> >> }
+ \edef\ThisPage{/AA \the\pdflastobj\space 0 R}
+ \global\pdfpageattr=\expandafter{\ThisPage}%
+ \or
+ \literalps@out{%
+ [ {ThisPage} << /AA << /O <<
+ \peekingOpenAction\space\jjAdditionalJSActions >> >> >>
+ /PUT pdfmark}%
+ \or
+ \@pdfm@mark{put @thispage << /AA << /O <<
+ \peekingOpenAction\space\jjAdditionalJSActions >> >> >>}%
+ \fi
+ \jb@Banner{\csname category\the\colnum\endcsname}%
+ \begingroup
+ \vskip\jj@aboveCurrencySkip
+ \parskip2pt
+ \setcounter{newletter}{0}%
+ \hmark{Q\the\rownum\the\colnum}\bJJGInsertLayer%
+ \@ifnextchar[%
+ {\let\Ans\Question@tabular\def\endQuestion{\end{tabular}%
+ \eJJGInsertLayer\endgroup\newpage}\getBracArg}%
+ {\let\Ans\Question@list\def\jb@numCols{1}\gdef\aeb@numCols{1}%
+ \noindent\textcolor{\dollarColor}{\jj@currencyHeading}\space
+ \ignorespaces%
+ \def\endQuestion{\end{list}\eJJGInsertLayer\endgroup\newpage}}%
+}
+% \end{macrocode}
+% \end{environment}
+% \begin{macrocode}
+\def\getBracArg[#1]{\def\jb@numCols{#1}\gdef\aeb@numCols{#1}\noindent%
+ \textcolor{\dollarColor}{\jj@currencyHeading}\space\ignorespaces}
+% \end{macrocode}
+% \cs{jjgtmplength} is a scratch length register that can be used to calculate lengths.
+% \begin{macrocode}
+\newlength{\jjgtmplength}
+% \end{macrocode}
+% \begin{macrocode}
+\newlength\jb@width \settowidth{\jb@width}{\normalfont(d)}
+\newdimen\jb@tmpdima
+\newlength\jb@tmplength
+\providecommand\PBS[1]{\let\jb@temp=\\#1\let\\=\jb@temp}
+\def\makelink#1{%
+\setLink[\A{\JS{qbrespond(#1,\the\rownum,\the\colnum);}
+ \Next{/S/GoTo/D (GameBoard)}}
+ ]{\makebox[\jb@width]{\normalfont(\hfil\alph{newletter}\hfil)\hfill}}}
+% \end{macrocode}
+% \begin{macro}{\setMClabelsep}
+% \changes{v3.0}{2006/18/06}
+% {
+% 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}
+% Added control over the separation between the MC label and subsequent text:
+% \cs{setMClabelsep} and \cs{resetMClabelsep}.
+% \begin{macrocode}
+\def\eq@hspanner{\ }
+\def\eq@hspanner@default{\ }
+\def\eq@lw@l{\eq@l@l\eq@hspanner}
+\def\setMClabelsep#1{\def\eq@hspanner{#1}}
+\def\resetMClabelsep{\let\eq@hspanner\eq@hspanner@default}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macrocode}
+\newskip\aboveanswersSkip
+\setlength\aboveanswersSkip{3pt}
+\def\Question@list{\vskip\aboveanswersSkip
+\begin{list}{}%
+{\usecounter{newletter}
+ \let\Ans=\JJ@Ans@list
+ \settowidth{\jb@tmplength}{\normalfont(d)}%
+ \settowidth{\labelwidth}{\normalfont(d)\eq@hspanner}%
+ \setlength{\parsep}{0pt}\setlength{\itemindent}{0pt}%
+ \setlength{\listparindent}{\parindent}%
+ \setlength{\leftmargin}{\labelwidth}%
+ \setlength{\labelsep}{0pt}%
+}\Ans}%
+\def\JJ@Ans@list#1{\stepcounter{newletter}\item[\makelink{#1}\hfill]}%
+
+\def\Question@tabular{%
+ \vskip\aboveanswersSkip
+ \setcounter{newletter}{0}%
+ \let\Ans=\JJ@Ans@tabular
+ \jb@tmpdima=\linewidth \divide\jb@tmpdima by\jb@numCols
+ \vskip\partopsep
+ \noindent\normalbaselines\tabcolsep=0pt
+ \begin{tabular}{*{\jb@numCols}{p{\jb@tmpdima}}}%
+\Ans}
+\def\JJ@Ans@tabular#1{\leavevmode\stepcounter{newletter}%
+ \PBS\raggedright
+ \settowidth{\jb@tmplength}{\normalfont(d)\eq@hspanner}%
+ \hangindent=\jb@tmplength\hangafter=1 %
+ \makelink{#1}\eq@hspanner\ignorespaces
+}
+% \end{macrocode}
+% \begin{environment}{oAnswer}
+% If \textsf{exerquiz} is input, then you can pose fill in questions. Enclose
+% the standard exerquiz fill in commands \cs{RespBoxMath} and \cs{RespBoxTxt}
+% \begin{macrocode}
+\newenvironment{oAnswer}
+{%
+ \gdef\oField{oQ\the\rownum\the\colnum}%
+ \gdef\curr@quiz{oQ\the\rownum\the\colnum}%
+ \def\currQuiz{oQ\the\rownum\the\colnum}%
+ \let\@qzsolndest\@empty
+ \stepcounter{questionno}%
+ \let\eqQuizType=s\gdef\eqPTs{1}\global\let\eqQT=\eq@na
+ \let\solution=\solution@sq
+ \let\endsolution=\endsolution@sq
+ \global\let\Ans=\Question@list
+% \end{macrocode}
+% \changes{v3.1}{2016/11/23}{Added \string\cs{sq@IDTxtField} to conform to new exerquiz standards}
+% (2016/11/23) Added \cs{sq@IDTxtField} to conform to new \textsf{exerquiz} standards.
+% \begin{macrocode}
+ \gdef\endQuestion{\endgroup\newpage}\sq@IDTxtField
+}{}
+% \end{macrocode}
+% \end{environment}
+% We need to redefine the action of \cs{RespBoxMath} and \cs{RespBoxTxt} so they behave like you
+% would expect with \texttt{jj\_game}.
+% \begin{macrocode}
+\def\JJ@@RespBoxMathActions
+{%
+ \AA{\AAKeystroke{if(event.willCommit) {\r\t
+ var retn = \processJSfunc(\rbArgs,\compareJSfunc);\r
+ if ( retn != null ) {\r\t
+ qbrespond(retn,\the\rownum,\the\colnum)\r\t
+ this.gotoNamedDest("GameBoard");\r
+ }
+ }}%
+ \AAFormat{\eqFormatArg}%
+ \AAOnFocus{\JS{var retn = null;}}%
+ }
+}
+\def\JJ@@RespBoxTxtActions
+{%
+ \AA{\AAKeystroke{if(event.willCommit) {\r\t
+ retn = ProcRespTxt(\rbTxtAlt);\r
+ if ( retn != null ) {\r\t
+ qbrespond(retn,\the\rownum,\the\colnum)\r\t
+ this.gotoNamedDest("GameBoard");\r
+ }
+ }}%
+ \AAOnFocus{\JS{var retn = null;}}
+ }%
+}
+\def\redefineRespBoxActions{%
+ \let\@@RespBoxMathActions\JJ@@RespBoxMathActions
+ \let\@@RespBoxTxtActions\JJ@@RespBoxTxtActions}
+% \end{macrocode}
+% \begin{macro}{\gameboardPrintButton}
+% \begin{macro}{\printButtonEOL}
+% \begin{macro}{\printButtonCaption}
+% \begin{macro}{\printButtonLabel}
+% \begin{macro}{\contestantNameLabel}
+% \begin{macro}{\timestampLabel}
+% We define a button to print the game board page, and a lot of
+% helper commands that allow the author to this button field.
+% \begin{macrocode}
+\newcommand{\printButtonCaption}[1]{\def\jj@printButtonCaption{#1}}
+\printButtonCaption{Print}
+\newcommand{\printButtonLabel}[1]{\def\jj@printButtonLabel{#1}}
+\printButtonLabel{Print this page:}
+\newcommand{\contestantNameLabel}[1]{\def\jjg@contestantNameLabel{#1}}
+\contestantNameLabel{Student:}
+\newcommand{\timestampLabel}[1]{\def\jjg@timestampLabel{#1}}
+\timestampLabel{Time stamp:}
+\newcommand{\printButtonEOL}[1]{\def\jjg@printButtonEOL{#1}}
+\printButtonEOL{\\[1ex]}
+\newcommand{\gameboardPrintButton}[1][]
+{%
+ \jj@printButtonLabel\space\pushButton[\CA{\jj@printButtonCaption}
+ \A{\JS{%
+ var pp = this.getPrintParams();\r
+ pp.firstPage=this.pageNum;\r
+ pp.lastPage=this.pageNum;\r
+ pp.pageHandling = pp.constants.handling.shrink;\r
+ var fv = pp.constants.flagValues;\r
+ pp.flags |= (fv.suppressCenter | fv.suppressRotate);\r
+ this.print(pp);}}#1]{printit}{}{11bp}\quad
+ \jjg@contestantNameLabel\space\textField[\BC{}\Ff\FfReadOnly
+ ]{jjContestantNameprint}{1.5in}{11bp}\jjg@printButtonEOL
+ \jjg@timestampLabel\space\textField[\BC{}\Ff\FfReadOnly
+ ]{timestamp}{1.5in}{11bp}%
+}%
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\contestantName}
+% A convenience macro that can be used to enter the contestant's name.
+% \begin{macrocode}
+\newcommand{\contestantName}[3][\BC{}\AA{\AAKeystroke{%
+ if ( event.willCommit ) {\r\t
+ var f = this.getField("jjContestantNameprint");\r\t
+ if ( f != null ) f.value = event.value;\r
+ }
+ }}]{\textField[#1]{jjContestantName}{#2}{#3}}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\timeStampFormat}
+% The format for the time stamp. The format is that of the formatting string for the
+% Acrobat JavaScript method \texttt{util.printd()}.
+% \begin{macrocode}
+\newcommand{\timeStampFormat}[1]{\def\jjTimeStampFormat{#1}}
+\timeStampFormat{mm-dd-yy, H:MM:ss.}
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+\AtBeginDocument{\redefineRespBoxActions}
+% \end{macrocode}
+% \begin{macro}{\enterNamePlease}
+% When the forcredit option is used, an alert box opens when the contestant
+% did not sign in. This is the message presented on that box.
+% \begin{macrocode}
+\newcommand{\enterNamePlease}[1]{\def\jjEnterNamePlease{#1}}
+\enterNamePlease{Please, enter your name on the first
+ page before you begin the game!}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\defineInstructionPageGraphic}
+% \begin{macro}{\defineGameboardPageGraphic}
+% \begin{macro}{\defineQuestionPagesGraphic}
+% Convenience commands for inserting graphics backgrounds on the instructions page,
+% the game board page and on the question pages. The single parameter is the basename
+% of a graphic file supported by the driver.
+% \begin{macrocode}
+\let\jjInstructionPageBG\relax
+\let\jjGameBoardPageBG\relax
+\let\jjQuestionPagesBG\relax
+\newcommand{\defineInstructionPageGraphic}[1]{%
+ \def\jjInstructionPageBG{#1}}
+\newcommand{\defineGameboardPageGraphic}[1]{\def\jjGameBoardPageBG{#1}}
+\newcommand{\defineQuestionPagesGraphic}[1]{\def\jjQuestionPagesBG{#1}}
+\newcommand{\instructionPageTemplate}{%
+ \@ifundefined{jjInstructionPageBG}{}{%
+ \edef\expand@templatename{\noexpand\template{\jjInstructionPageBG}}%
+ \expand@templatename}}
+\newcommand{\gameboardPageTemplate}{%
+ \@ifundefined{jjGameBoardPageBG}{}{%
+ \edef\expand@templatename{\noexpand\template{\jjGameBoardPageBG}}%
+ \expand@templatename}}
+\newcommand{\questionPagesTemplate}{%
+ \@ifundefined{jjQuestionPagesBG}{}{%
+ \edef\expand@templatename{\noexpand\template{\jjQuestionPagesBG}}%
+ \expand@templatename}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \begin{macro}{\illegalAccessMsg}
+% \begin{macro}{\illegalAnswerTwiceMsg}
+% Messages that appear in alert boxes when contestant acts illegally.
+% \begin{macrocode}
+\newcommand{\illegalAccessMsg}[1]{\def\jjIllegalAccessMsg{#1}}
+\illegalAccessMsg{You are peeking at this question.
+ Choose a question from the game board first!
+ You may want to start the game over now!}
+\newcommand{\illegalAnswerTwiceMsg}[1]{\def\jjIllegalAnswerTwiceMsg{#1}}
+\illegalAnswerTwiceMsg{Changing your answer is not allowed!}
+\newcommand{\playeriWinnerMsg}[1]{\def\jjplayeriWinner{#1}}
+\playeriWinnerMsg{\jjg@playeri\space is the winner!}
+\newcommand{\playeriiWinnerMsg}[1]{\def\jjplayeriiWinner{#1}}
+\playeriiWinnerMsg{\jjg@playerii\space is the winner!}
+\newcommand{\gameTiedMsg}[1]{\def\jjgameTied{#1}}
+\gameTiedMsg{It is all tied up! You are equally matched!}
+\newcommand{\bothLosersMsg}[1]{\def\jjbothlosers{#1}}
+\bothLosersMsg{You two either are not trying, or
+ you do not know anything about the subject!}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \section{JavaScript Support}
+% \begin{macrocode}
+\begin{insDLJS*}[qbrespond]{jjgdljs}
+\begin{newsegment}{JJG: JavaScript to Control Jeopardy}
+var _processLink=true;
+var twoplayerGame=\twoplayerGame;
+var whichPlayer=0;
+if ( twoplayerGame ) {
+ var reTrimSpaces=/^\s+|\s+$/g;
+ var reInsertCommas=/\b\s+\b|\b\s+(?=\.)/g;
+ var tpHighlightBorderColor="\@APtpHighlightBorderColor";
+ var hightLightColor=%
+ tpHighlightBorderColor.replace(reTrimSpaces,"").%
+replace(reInsertCommas,",");
+ var aHighlightColor = ("RGB,"+hightLightColor).split(",");
+ this.getField("Total"+whichPlayer).strokeColor=%
+aHighlightColor;
+ var ckBx = this.getField("ckboxPlayer"+whichPlayer);
+ if ( ckBx != null ) %
+this.getField("ckboxPlayer"+whichPlayer).checkThisBox(0,true);
+ this.dirty=false;
+}
+function qbrespond(ans,row,col)
+{
+ if (_processLink) {
+ \ifjjnopeeking\else this.getField(""+row+col).hidden=true;\fi
+ if ( eval("typeof pushCell"+row+col) == "undefined") {
+ app.alert("\jjIllegalAccessMsg");
+ return null;
+ }
+ if ( twoplayerGame )
+ var Total = this.getField("Total"+whichPlayer);
+ else
+ var Total = this.getField("Total");
+ var p = numQuestions*(col-1)+row-1;
+ if (QAed.charAt(p)==0)
+ {
+ QAed = QAed.substring(0,p)+1+%
+ QAed.substring(p+1,totalQuestions);
+ if (ans==1)
+ {
+ this.getField(""+row+col+'R').hidden=false;
+ Total.value += \scaleFactor*row*100;
+ app.alert(aCM[nCM],3);
+ if (++nCM > 6) nCM=0;
+ }
+ else
+ {
+ this.getField(""+row+col+'W').hidden=false;
+ var f = this.getField(""+row+col)
+ Total.value -= \scaleFactor*row*100;
+ app.alert(aEM[nEM],3);
+ if (++nEM > 6) nEM=0;
+ }
+% \end{macrocode}
+% 11/13/08. After we process this question, we hide the layer containing
+% the question, and reset \texttt{pushCell+row+col} to \texttt{undefined} so the layer
+% will not be made visible again by the open page action.
+% \begin{macrocode}
+ if ( typeof toggleSetThisLayer == "function" ) {
+ toggleSetThisLayer("q"+row+col,false);
+ eval("pushCell"+row+col+"=undefined");
+ }
+ if ( twoplayerGame ) {
+ this.getField("Total"+whichPlayer).strokeColor=["G",0]
+ var ckBx = this.getField("ckboxPlayer"+whichPlayer);
+ if (ckBx != null ) %
+this.getField("ckboxPlayer"+whichPlayer).checkThisBox(0,false);
+ whichPlayer = ( whichPlayer+1) \% 2;
+ this.getField("Total"+whichPlayer).strokeColor=%
+aHighlightColor;
+ ckBx = this.getField("ckboxPlayer"+whichPlayer);
+ if (ckBx != null ) %
+this.getField("ckboxPlayer"+whichPlayer).checkThisBox(0,true);
+
+ }
+% \end{macrocode}
+% The end of the game. We see if the GraphPoobah has been reached, if a two person
+% game we indicate who has won.
+% \begin{macrocode}
+ if ( ++NumQAed>=totalQuestions ) {
+ if (Total.value>=Goal)
+ this.getField("GrandPoohbah").hidden=false;
+ if ( twoplayerGame ) {
+ var player0 = this.getField("Total0");
+ var player1 = this.getField("Total1");
+ var player0Score = Number(player0.value);
+ var player1Score = Number(player1.value);
+ if ( player0Score > player1Score ) {
+ if ( player0Score <= 0 ) {
+ player0.strokeColor = ["RGB", 1, 0, 0];
+ player1.strokeColor = ["RGB", 1, 0, 0];
+ var timer=app.setTimeOut(
+ 'app.alert("\jjbothlosers")',250);
+ } else {
+ player0.strokeColor = ["RGB", 0, .6, 0];
+ player1.strokeColor = ["G",0];
+ var timer=app.setTimeOut(
+ 'app.alert("\jjplayeriWinner")',250);
+ }
+ }
+ else if ( player1Score > player0Score ) {
+ if ( player1Score <= 0 ) {
+ player0.strokeColor = ["RGB", 1, 0, 0];
+ player1.strokeColor = ["RGB", 1, 0, 0];
+ var timer=app.setTimeOut(
+ 'app.alert("\jjbothlosers")',250);
+ } else {
+ player1.strokeColor = ["RGB", 0, .6, 0];
+ player0.strokeColor = ["G",0];
+ var timer=app.setTimeOut(
+ 'app.alert("\jjplayeriiWinner")',250);
+ }
+ }
+ else {
+ if ( player1Score <= 0 ) {
+ player0.strokeColor = ["RGB", 1, 0, 0];
+ player1.strokeColor = ["RGB", 1, 0, 0];
+ var timer=app.setTimeOut(
+ 'app.alert("\jjbothlosers")',250);
+ } else {
+ player0.strokeColor = ["RGB", 0, 0, 1];
+ player1.strokeColor = ["RGB", 0, 0, 1];
+ var timer=app.setTimeOut(
+ 'app.alert("\jjgameTied")',250);
+ }
+ }
+ }
+ }
+ }
+ else
+ app.alert("\jjIllegalAnswerTwiceMsg");
+ }
+ this.dirty=false;
+}
+var tsfield = this.getField("timestamp");
+if ( tsfield != null )
+ tsfield.value = util.printd("\jjTimeStampFormat", new Date());
+this.dirty=false;
+function makeNameReadOnly()
+{
+ var f = this.getField("jjContestantName");
+ if ( (f != null) && !f.readonly ) f.readonly=true;
+ this.dirty=false;
+}
+\end{newsegment}
+\begin{newsegment}{JJG: Global Variables}
+var numQuestions = \the\numQuestions;
+var numCategories = \the\numCategories;
+var Goal = \Goal;
+var totalQuestions = numQuestions * numCategories;
+var QAed = "";
+for (var i=0; i< totalQuestions; i++) QAed +="0";
+var nEM = 0;
+var nCM = 0;
+var NumQAed = 0;
+this.dirty=false;
+\end{newsegment}
+\begin{JJLangEnglish}
+\begin{newsegment}{JJG: Arrays for Jeopardy for English}
+var aCM = new Array
+(
+ "That's Right! Way to go, Kiddo!",
+ "Wonderfully Done! Congrats!",
+ "Very Good! Keep up the good work!",
+ "Good, good, good, good!",
+ "Gee, you're smart! Try a harder one!",
+ "You're pretty sharp! Continuez, s'il vous pla\356t!",
+ "You're the tops! But wait...try another."
+)
+var aEM = new Array
+(
+ "That's wrong! Sorry. Try Again.",
+ "Error again. Don't guess, I'm watching!",
+ "Please! Please! Work it out first!",
+ "An error has insinuated itself into your calculations.\n"
+ +"Recalibrate your thinking!",
+ "Bah! Humbug! You're haunted by Errors!",
+ "Try again. This time with order and method.",
+ "Wrong again! Use your little gray cells!"
+)
+this.dirty=false;
+\end{newsegment}
+\end{JJLangEnglish}
+\begin{JJLangGerman}
+\begin{newsegment}{JJG: Arrays for Jeopardy for German}
+var aCM = new Array
+(
+ "Richtig! So ist's recht!",
+ "Gut gemacht! Gratuliere!",
+ "Sehr gut! Weiter so!",
+ "Gut, gut, gut, gut!",
+ "Du bist sehr clever! Jetzt versuch mal eine Schwierigere!",
+ "Jawoll! Continuez, s'il vous pla\356t!",
+ "Spitze! Auf geht's, zu einer weiteren Aufgabe!"
+)
+var aEM = new Array
+(
+ "Leider falsch!",
+ "Schon wieder falsch! Nicht raten!",
+ "Bitte denk erst nach bevor Du auf die Antwort klickst!",
+ "Ein Fehler hat sich eingeschlichen. Erst denken, dann ...!",
+ "Ohje! So ein Quatsch!",
+ "Versuch's nochmal. Es ist noch nicht aller Tage Abend.",
+ "Schon wieder falsch! Nutz Deine kleine grauen Zellen!"
+)
+this.dirty=false;
+\end{newsegment}
+\end{JJLangGerman}
+\begin{JJForCredit}
+\begin{newsegment}{JJG: JS to support forcredit}
+var noNameError, fname;
+function forCreditClosePage()
+{
+ fname = this.getField("jjContestantName");
+ if ( fname != null ) {
+ var JJjsCode = "if ( fname.value.replace(/\s*/g, '') == '' ) {"
+ + " if ( typeof closingJJ == 'undefined' ) {"
+ + " app.alert({cMsg: '\jjEnterNamePlease', %
+cTitle: 'AcroTeX eDucation Bundle'});"
+ + " this.pageNum = 0;"
+ + " } } else { fname.readonly = true; }";
+ noNameError = app.setTimeOut(JJjsCode, 15);
+ }
+ this.dirty=false;
+}
+\end{newsegment}
+\end{JJForCredit}
+\end{insDLJS*}
+% \end{macrocode}
+% \begin{macrocode}
+\AtEndOfClass{\thisPageAction{\JS{this.dirty=false;}}{}}
+%</package>
+%<*jjgpro>
+\def\noPrintLayer#1{%
+ \literalps@out{/Print [/Print] [(xb.#1)] AddASEvent}%
+ \literalps@out{(xb.#1) <<
+/Print<< /PrintState/OFF >> >> SetOCGUsage}%
+}
+\def\bJJGInsertLayer{\xBld{q\the\rownum\the\colnum}}
+\def\eJJGInsertLayer{\eBld\noPrintLayer{q\the\rownum\the\colnum}}
+\def\jjAdditionalJSActions{/Next <<\JS{%
+ if ( typeof pushCell\the\rownum\the\colnum\space!= "undefined")
+ toggleSetThisLayer("q\the\rownum\the\colnum",true);}>>}
+\begin{execJS}{lockocgs}
+var o = this.getOCGs();
+for (var i = 0; i < o.length; i++)
+ o[i].locked = true;
+\end{execJS}
+%</jjgpro>
+%<*jjsecurity>
+\begin{willClose}
+var closingJJ = true;
+\end{willClose}
+\begin{addJSToPageClose}
+forCreditClosePage();
+\end{addJSToPageClose}
+%</jjsecurity>
+%<*package>
+%</package>
+% \end{macrocode}
+% \Finale
+\endinput