summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/exam
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2008-07-23 22:06:36 +0000
committerKarl Berry <karl@freefriends.org>2008-07-23 22:06:36 +0000
commit8c7d1cdf9705933f11e3dff4105c1054427677d2 (patch)
tree0e9c65ee772af82525eb5256345d3481ea83d2f7 /Master/texmf-dist/tex/latex/exam
parent52efa785279f9f2f1f79c0836a3a67eecaa4ed16 (diff)
exam 2.3 (19jul08)
git-svn-id: svn://tug.org/texlive/trunk@9734 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/exam')
-rw-r--r--Master/texmf-dist/tex/latex/exam/exam.cls4036
1 files changed, 2591 insertions, 1445 deletions
diff --git a/Master/texmf-dist/tex/latex/exam/exam.cls b/Master/texmf-dist/tex/latex/exam/exam.cls
index d6165bf4155..ea3516cbb46 100644
--- a/Master/texmf-dist/tex/latex/exam/exam.cls
+++ b/Master/texmf-dist/tex/latex/exam/exam.cls
@@ -3,7 +3,7 @@
% A LaTeX2e document class for preparing exams.
%% exam.cls
-%% Copyright (c) 1994, 1997, 2000, 2004 Philip S. Hirschhorn
+%% Copyright (c) 1994, 1997, 2000, 2004, 2008 Philip S. Hirschhorn
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
@@ -31,14 +31,10 @@
% from my web page: http://www-math.mit.edu/~psh/
-\def\fileversion{2.2}
-\def\filedate{2004/08/14}
+\def\fileversion{2.3}
+\def\filedate{2008/07/19}
%---------------------------------------------------------------------
%---------------------------------------------------------------------
-% PLEASE DO NOT MAKE ANY CHANGES TO THIS FILE!
-%
-% If you wish to make changes to this file, rename this file
-% to something other than exam.cls BEFORE YOU MAKE THE CHANGES!
%
% If there's some feature that you'd like that this file doesn't
% provide, tell me about it.
@@ -86,845 +82,684 @@
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-% Changelog:
-
+% Changelog since version 2.2:
-% Version 2.2:
-%
-% Enough already with betatest.
-%
-%--------------------------------------------------------------------
-%
-% Version 2.116$\beta$:
-%
-% We futzed with the oneparchoices environment so that a bit more
-% space will be left before the first choice when the list of choices
-% continues the paragraph of the question.
-%
%--------------------------------------------------------------------
+% Version 2.3, 2008/07/16:
%
-% Version 2.115$\beta$:
-%
-% New environment: oneparchoices
-%
-% Intended for multiple choice questions (just like the choices
-% environment), except that the oneparchoices prints all the choices in
-% a single paragraph. This environment does *not* create a paragraph
-% break at its beginning, so if you begin the environment without
-% skipping a line before it, the choices will be printed as a
-% continuation of the paragraph preceding the environment.
+% Minor typographic corrections to comments.
%
%--------------------------------------------------------------------
+% Version 2.222$\beta$, 2008/07/13:
%
-% Version 2.114$\beta$:
-%
-% We fixed up the code for \uplevel and \fullwidth so that they work
-% correctly if a solution environment is inside the argument.
+% Corrected a typo in the error message displayed when
+% \shadedsolutions is used without having said \usepackage{color}.
%
%--------------------------------------------------------------------
+% Version 2.221$\beta$, 2008/07/03:
%
-% Version 2.113$\beta$:
-%
-% Added code to warn if point totals have changed since the last run of
-% LaTeX (which requires running LaTeX again to make sure that
-% gradetables, pointsofquestion, and pointsonpage values are correct).
-%
-%
-% We also added code to create a label for every question, part,
-% subpart, and subsubpart. We make no use of these labels, but we put
-% them there so that if a question (or part, etc.) is, e.g., moved from
-% one page to another, LaTeX will notice this and warn the user that
-% LaTeX must be run one more time to be sure everything is correct.
-%
-% We need to do this even though we've already included code to check
-% when point totals change because questions (and parts, etc.) know what
-% page they're on from reading the info written to the .aux file on the
-% previous run. Thus, if a question (or part, etc.) is moved to a
-% different page, then the pointsonpage totals won't notice until the
-% *second* subsequent run of LaTeX, and so there'll be no warning to the
-% user on the *first* run. Including these labels gives the user a
-% warning on that first run.
+% \themarginpoints used to expand to
+% \@points \@marginpointname
+% whether the points were bonus or non-bonus. We fixed that, so that
+% it expands to either
+% \@points \@marginbonuspointname
+% or
+% \@points \@marginpointname
+% depending on whether or not the points are bonus points.
%
%--------------------------------------------------------------------
+% Version 2.220$\beta$, 2008/05/24:
%
-% Version 2.112$\beta$:
+% New command: \fillwithdottedlines
+% New environment: solutionordottedlines
%
-% New environment: coverpages
%
-% This is for use only *before* any questions (or parts, or subparts, or
-% subsubparts). It allows you to print one or more cover pages,
-% numbered in a different sequence of page numbers from the main pages.
-% That is, the page number is reset to 1 at the end of a coverpages
-% environment.
+% \fillwithdottedlines is similar to \fillwithlines except that it
+% inserts dotted lines (created by \dotfill) instead of solid lines.
%
-% The default is that headers and footers are empty on the coverpages,
-% but if you print the page number (using \thepage in the header or
-% footer) then the page number will be printed in roman numerals. When
-% the coverpages environment ends, the page number is reset to 1 and the
-% page numbers revert to the (standard) arabic numbers.
+% \fillwithdottedlines takes one argument, which is either a length or
+% \fill, and it fills that much vertical space with dotted horizontal
+% lines that run the length of the current line. That is, they extend
+% from the current left margin (which depends on whether we're in a
+% question, part, subpart, or subsubpart) to the right margin.
%
-% Headers and footers on coverpages are determined by commands
-% completely analogous to the relevant commands for the main pages,
-% except that the names of the commands begin with the word ``cover''.
-% That is, the following commands are available to define headers and
-% footers, and to leave additional space for the headers and footers as
-% needed:
+% The distance between the lines is \dottedlinefillheight, whose
+% default value is set with the command
%
+% \setlength\dottedlinefillheight{.25in}
%
-% New commands:
-%
-% \coverheader
-% \coverrunningheader
-% \coverfirstpageheader
-%
-% \coverlhead
-% \coverchead
-% \coverrhead
-%
-% \coverfooter
-% \coverrunningfooter
-% \coverfirstpagefooter
-%
-% \coverlfoot
-% \covercfoot
-% \coverrfoot
+% This value can be changed by giving a new \setlength command.
%
-% \coverextraheadheight
-% \coverextrafootheight
+% The solutionordottedlines environment is almost identical to the
+% solutionorlines environment, except that when solutions are not
+% being printed and an optional argument appears specifying an amount
+% of space to be left for answers, that space is filled with dotted
+% lines (created by \dotfill), rather than filled with solid lines (as
+% it is by the solutionorlines environment).
%
%--------------------------------------------------------------------
-%
-% Version 2.111$\beta$:
-%
-% Bugfix: There was an incompatibility with spanish.ldf (loaded when the
-% user loads the babel package with the spanish option) (and possibly
-% with other language packages as well). That file redefines \@roman,
-% which is used by \roman, which I had used to define some internally
-% used command names. I replaced
-%
-% \roman{countername}
-%
-% with
-%
-% \romannumeral \csname c@countername\endcsname
-%
-% for all of those command names, and now all at least seems to be
-% well.
-%
-%
-% The following stuff isn't really complete yet:
-% New environment: coverpages
-%
+% Version 2.219$\beta$, 2007/11/24:
+%
+% There can now be partial grade tables and point tables, either bonus
+% or non-bonus.
+%
% New commands:
-%
-% \coverheader
-% \coverrunningheader
-% \coverfirstpageheader
-%
-% \coverlhead
-% \coverchead
-% \coverrhead
-%
-% \coverfooter
-% \coverrunningfooter
-% \coverfirstpagefooter
-%
-% \coverlfoot
-% \covercfoot
-% \coverrfoot
-%
-% \coverextraheadheight
-% \coverextrafootheight
-%
-%--------------------------------------------------------------------
-%
-% Version 2.110$\beta$:
-%
-% We change the definition of \half to print a fraction one half that
-% uses a slanted fraction bar. We also created two new commands:
-%
-% \newcommand*\usehorizontalhalf
-% \newcommand*\useslantedhalf
-%
-% The first one changes the definition of \half so that it produces a
-% fraction with a horizontal fraction bar (via $\frac{1}{2}$), and the
-% second one returns the definition of \half to its default.
-%
+%
+% \partialgradetable
+% \partialbonusgradetable
+% \partialpointtable
+% \partialbonuspointtable
+% \begingradingrange
+% \endgradingrange
+%
+% The user defines a grading range by saying
+%
+% \begingradingrange{whatever}
+%
+% to start the range and
+%
+% \endgradingrange{whatever}
+%
+% to end the range (where ``whatever'' is a name chosen by the user).
+% To create the table, the user says, e.g.,
+%
+% \partialgradetable{whatever}[v][questions]
+%
+% That is, each of \partialgradetable, \partialbonusgradetable,
+% \partialpointtable, and \partialbonuspointtable takes
+%
+% one required argument (the name of the grading range) and
+%
+% two optional arguments, the first being either ``[v]'' or ``[h]'',
+% the second being either ``[questions]'' or ``[pages]''.
+%
+% If either or both of the optional arguments are omitted, [questions]
+% and [v] will be used.
+%
+% If the table is indexed by questions, then it will include all
+% questions following the \begingradingrange{whatever} and preceding the
+% \endgradingrange{whatever}.
+%
+% If the table is indexed by pages, then it will include all pages with
+% points starting with the page containing the
+% \begingradingrange{whatever} and ending with the page containing the
+% \endgradingrange{whatever}.
+%
+% Otherwise,
+%
+% \partialgradetable is similar to \gradetable
+% \partialbonsugradetable is similar to \bonusgradetable
+% \partialpointtable is similar to \pointtable
+% \partialbonuspointtable is similar to \bonuspointtable
+%
%--------------------------------------------------------------------
-%
-% Version 2.109$\beta$:
-%
-% Point values for questions (and parts, etc.) can now include half
-% points. To specify a half point, you include ``\half'' immediately
-% following the integer part (or just with ``\half'' if the integer part
-% is zero). For example, the following are all valid point values:
-%
-% 0
-% \half
-% 1
-% 1\half
-% 2
-% 2\half
-% Etc.
+% Version 2.218$\beta$, 2007/10/31:
+%
+% Instead of appending
+% \the \pageinfo@commands \the \point@toks
+% to \everypar, we insert them into the box \@labels. This corrects the
+% problem that arose when a question (or part, etc.) begins with a list
+% environment (including verbatim, flushleft, center, flushright, and
+% possibly others that are implemented as trivlist environments). The
+% \item command in those environments throws away the previous contents
+% of \everypar, and so the tokens
+% \the \pageinfo@commands \the \point@toks
+% didn't get inserted where we expected. List environments *do*
+% preserve the contents of the box \@labels, though.
+
+% This version of exam.cls is not completely backward compatible with
+% older versions. The changes only affect documents in which the user
+% was doing something that probably should not have been done with the
+% older versions, though. This new version does something useful in
+% situations in which older versions did something not very useful:
+
+% This change introduces a change in behavior for documents in which a
+% question with points begins with a parts environment, so that the
+% points for the first part (if any) would appear on the same line as
+% the points for the question. In earlier versions of exam.cls, the
+% points for the question would not be printed if there are points for
+% the part that begins on the same line. In this version of exam.cls,
+% all points will be printed. If they're both printed in the left
+% margin, or both in the right margin, then they'll be printed directly
+% on top of one another, which is not what you want. (You can use
+% \pointsinmargin, \pointsinrightmargin, and \nopointsinmargin to print
+% them in different places.) If points are being printed right in the
+% text (i.e., \nopointsinmargin), then the points for the question will
+% be printed *before* the label (a) for the first part is printed.
+
+% The behavior of this new version of exam.cls seems clearly preferable
+% to the old behavior, but it is a change!
%
%--------------------------------------------------------------------
+% Version 2.217$\beta$, 2007/10/22:
+%
+% We changed things so that we're now compatible with calc.sty
%
-% Version 2.108$\beta$:
+% calc.sty redefines \setcounter and \addtocounter in a way that
+% conflicts with a trick we were using to deal with \half points.
%
-% New environment: solutionorlines
+% We replaced one \setcounter command with
%
-% This is almost identical to the solution environment, except that when
-% solutions are not being printed and an optional argument appears
-% specifying an amount of space to be left for answers, that space is
-% filled with ruled lines (created by \fillwithlines), rather than being
-% left blank (as it is by the solution environment).
+% \global\csname c@#1\endcsname 0#2\relax
%
-% Also: Changed the shade of gray used as the default color for
-% \shadedsolutions.
+% and one \addtocounter command with
%
-% Changed the default thickness of lines used by \fillwithlines.
+% \global\advance\csname c@#1\endcsname 0#2\relax
%
%--------------------------------------------------------------------
-%
-% Version 2.107$\beta$:
-%
-% We added an option to have solution environments use a \colorbox (from
-% the color package) instead of an \fbox. Instead of surrounding the
-% solution with a printed box, it prints the solution on a colored
-% background. The default color is a light gray (so that it can be
-% printed on any printer that can do grayscale), but the color can be
-% changed.
-%
-% To use this option, the user must load the color package with the
+% Version 2.216$\beta$, 2007/08/27:
+%
+% The command \answerline now takes an optional argument. If the
+% optional argument appears, then when \printanswers is true the
+% argument will be printed on the answer line. When \printanswers is
+% false, the optional argument is ignored.
+%
+% When the argument is printed, it is printed with
+% \CorrectChoiceEmphasis and it is a distance of \answerclearance above
+% the line. The default value of \answerclearance is set with the
% command
-%
-% \usepackage{color}
-%
-% in the preamble. (If appropriate, optional arguments can be used in
-% that command.) The user can then give the command
-%
-% \shadedsolutions
-%
-% to have all solutions printed using a \colorbox. After giving that
-% command, the user can change the color of the backgrounds of solutions
-% by defining the color ``SolutionColor''. The default SolutionColor is
-% set via the command
-%
-% \definecolor{SolutionColor}{gray}{0.9}
-%
-% and the user can change that by giving a \definecolor command *after*
-% giving the command \shadedsolutions. For example, the command
-%
-% \definecolor{SolutionColor}{rgb}{0.8,0.9,1}
-%
-% sets the background color to a light blue.
-%
-% You can return to the default situation of having solutions printed
-% inside an \fbox by giving the command
-%
-% \framedsolutions
-%
-% Note added later: The default shade of gray was changed in version
-% 2.108$\beta$.
-%
+%
+% \setlength\answerclearance{0.2ex}
+%
+% and it can be changed with a \setlength command.
+%
+% The optional argument is centered on the answer line unless it is too
+% long, in which case it extends to the right of the answer line.
+%
%--------------------------------------------------------------------
-%
-% Version 2.106$\beta$:
-%
-%
-% We redid the solution environment to use Donald Arseneau's framed.sty
-% macros, so that the solution can be broken across pages with each
-% piece enclosed in a frame.
-%
-% We also changed the default definition of \solutiontitle; it's now
-% defined by:
-%
-% \newcommand{\solutiontitle}{\noindent\textbf{Solution:}\enspace}
-%
-%
+% Version 2.215$\beta$, 2007/08/24:
+%
+% New commands:
+%
+% \pointtable
+% \bonuspointtable
+%
+% Both of these take up to two optional arguments:
+%
+% The first can be either [v] or [h].
+% The second can be either [questions] or [pages].
+%
+% These commands are similar to the commands
+%
+% \gradetable
+% \bonusgradetable
+%
+% except that the new commands print only two columns (or rows),
+% omitting the column (or row) for the score.
+%
%--------------------------------------------------------------------
+% Version 2.214$\beta$, 2007/07/19:
%
-% Version 2.105$\beta$:
-%
-% We're making the thickness of the lines used by \fillwithlines
-% changeable, and changing the default thickness.
-%
-% We're doing this by defining a new command:
-%
-% \linefill,
-%
-% which is similar to \hrulefill, except that \linefill uses a line of
-% height \linefillthickness, whose default value is 0.2pt.
-% (\fillwithlines used to use \hrulefill, which uses a line of height
-% 0.4pt.)
-%
-% The default value of \linefillthickness is set by the command
-%
-% \setlength\linefillthickness{0.2pt}
+% New commands:
%
-% and this can be changed by giving a new \setlength command.
+% \questionshook
+% \partshook
+% \subpartshook
+% \subsubpartshook
+% \choiceshook
%
-% Note added later: The default thickness was changed in version
-% 2.108$\beta$.
+% These are for advanced users who want to customize the list
+% parameters (\topsep, \partopsep, \itemsep, \parsep, etc.) for the
+% lists that these environments create. They are all defined to be
+% empty, but the user can change them using \renewcommand.
%
%--------------------------------------------------------------------
-%
-% Version 2.104$\beta$:
-%
-% We added a new command: \fillwithlines
-%
-% \fillwithlines takes one argument, which is either a length or \fill,
-% and it fills that much vertical space with horizontal lines that run
-% the length of the current line. That is, they extend from the current
-% left margin (which depends on whether we're in a question, part,
-% subpart, or subsubpart) to the right margin.
-%
-% The distance between the lines is \linefillheight, whose default value
-% is set with the command
-%
-% \setlength\linefillheight{.25in}
-%
-% This value can be changed by giving a new \setlength command.
+% Version 2.213$\beta$, 2006/11/27:
+%
+% New documentclass option: addpoints
+% Using this option is equivalent to giving the command
+% \addpoints
+% at the beginning of the document.
+%
+% New commands:
+%
+% \bonusquestion
+% \bonustitledquestion
+% \bonuspart
+% \bonussubpart
+% \bonussubsubpart
+%
+% \bonuspointsofquestion
+% \bonuspointsonpage
+%
+% \numbonuspoints
+%
+% \bonuspointpoints
+% \bonuspointformat
+% \thebonuspoints
+% \bonuspoints
+% \bonuspointname
+% \marginbonuspointname
+%
+% \bonusgradetable
+%
+% \bhqword
+% \bhpword
+% \bhsword
+% \bhtword
+% \bvqword
+% \bvpword
+% \bvsword
+% \bvtword
+%
+% \bvpgword
+% \bhpgword
+%
+%
+% The commands
+%
+% \bonusquestion
+% \bonustitledquestion
+% \bonuspart
+% \bonussubpart
+% \bonussubsubpart
+%
+% are the same as the commands
+%
+% \question
+% \titledquestion
+% \part
+% \subpart
+% \subsubpart
+%
+% except that any points assigned become ``bonus points'', which by
+% default are typeset in the form
+%
+% 1. (1 point (bonus))
+%
+% or
+%
+% 1. (2 points (bonus))
+%
+% If no points are assigned, then these ``bonus'' versions of the
+% commands are equivalent to the non-bonus versions.
+%
+% The command
+%
+% \bonusgradetable
+%
+% is analogous to the command \gradetable; it can be used in any of the
+% four forms
+%
+% \bonusgradetable[v][questions]
+% \bonusgradetable[h][questions]
+% \bonusgradetable[v][pages]
+% \bonusgradetable[h][pages]
+%
+% and it counts only bonus points, while \gradetable counts only
+% non-bonus points.
+%
+% The commands
+%
+% \bonuspointsofquestion
+% \bonuspointsonpage
+% \numbonuspoints
+%
+% are analogous to the commands
+%
+% \pointsofquestion
+% \pointsonpage
+% \numpoints
+%
+% The remaining new commands are for customizing the appearance of bonus
+% points and bonusgradetable. The command
+%
+% \bonuspointpoints
+%
+% is analogous to the command \pointpoints; it takes two arguments, the
+% first of which will appear after 1 or \half points the second to
+% appear after any other number of points. The default was created by
+% the equivalent of the command
+%
+% \bonuspointpoints{point (bonus)}{points (bonus)}
+%
+% If, for example, you give the command
+%
+% \bonuspointpoints{bonus point}{bonus points}
+%
+% then bonus points will look like
+%
+% 1. (1 bonus point)
+%
+% or
+%
+% 1. (2 bonus points)
+%
+% (The commands \bracketedpoints, \boxedpoints, and \nobracketedpoints
+% have the same effect on bonus points that they have on non-bonus
+% points, and the command \marksnotpionts replaces ``point'' with
+% ``mark'' in all of these cases.)
+%
+% \bonuspointname is analogous to \pointname, and the defaults were
+% created by the commands
+%
+% \pointname{ \points}
+% \bonuspointname{ \bonuspoints}
+%
+% (Note the intentional space in each of those commands.)
+%
+% \marginbonuspointname is analogous to \marginpointname, and the
+% default was created by the command
+%
+% \marginbonuspointname{ (bonus)}
+%
+% \bonuspointformat is analogous to \pointformat.
+%
+%
+% The commands for customizing the words used in \bonusgradetable are
+% analogous to those used for customizing the words used in \gradetable,
+% except that they begin with a ``b'':
+%
+% \bhqword is analogous to \hqword
+% \bhpword is analogous to \hpword
+% \bhsword is analogous to \hsword
+% \bhtword is analogous to \htword
+% \bvqword is analogous to \vqword
+% \bvpword is analogous to \vpword
+% \bvsword is analogous to \vsword
+% \bvtword is analogous to \vtword
+% is analogous to
+% \bvpgword is analogous to \vpgword
+% \bhpgword is analogous to \hpgword
+%
%
%--------------------------------------------------------------------
+% Version 2.212$\beta$, 2006/11/13:
%
-% Version 2.103$\beta$:
-%
-% We added a new command: \answerline
-%
-% This is intended for short answer questions. It inserts a \vskip of
-% length \answerskip and then inserts a horizontal line of length
-% \answerlinelength at the right margin, preceded by the number of the
-% current question, part, subpart, or subsubpart.
-%
-% The default values are set by the commands
-%
-% \setlength\answerlinelength{1in}
-% \setlength\answerskip{2ex}
-%
-% and these can be changed by giving new \setlength commands.
+% Made \useslantedhalf and \usehorizontalhalf global.
%
%--------------------------------------------------------------------
+% Version 2.211$\beta$, 2006/10/29:
%
-% Version 2.101$\beta$:
-%
-% We eliminated the command \marks, since it conflicts with a definition
-% of that name in some package or other. We changed the definition of
-% \marksnotpoints so that it still accomplishes the same thing, but now
-% it works through the \pointpoints command.
-%
-% We changed the default format for the \droptotalpoints command, so
-% that it now prints
-%
-% Total for Question 1: 25
-%
-% where the ``25'' is followed by \marginpointname, whose default value
-% is empty.
-%
-%--------------------------------------------------------------------
+% New commands:
%
-% Version 2.098$\beta$:
+% \pointformat
+% \themarginpoints
%
-% We moved the definitions of \thepartno, \thesubpart, and
-% \thesubsubpart outside of the associated list environments, so that
-% the user can redefine them once at the beginning of the LaTeX file and
-% not have their redefinition overridden in every such list.
+% An old command that's also useful here is
%
-% We also replaced most occurrences of \thequestion with
-% \arabic{question}, so that the user can safely redefine \thequestion
-% to something like \Alph{question}, etc.
+% \thepoints
%
-% We rewrote the components of the \gradetable[v][questions] and
-% \gradetable[h][questions] to use the question counter in place of
-% @iterator, and to insert \thequestion instead of \the@iterator as the
-% question number in the table (so that if the user redefines
-% \thequestion, then the table will print the question ``numbers'' (or
-% letters, etc.) in whatever format \thequestion prints the question
-% numbers on the exam).
+% \pointformat: The \pointformat command allows you to change the
+% format used to print the points. It takes one argument, and that
+% argument becomes the command to print the points, whether the points
+% are being printed at the beginning of the question, in the left
+% margin (because of \pointsinmargin), in the right margin (because of
+% \pointsinrightmargin), or dropped in the right margin at the end of
+% the question (because of \pointsdroppedatright).
%
-% We also created a new command:
+% The argument to \pointformat should contain either the command
%
-% \totalpoints
+% \thepoints
%
-% for use in the argument of a \totalformat command. \totalpoints is
-% just an abbreviation for \pointsofquestion{\arabic{question}}. That
-% is, it's a macro that prints the total number of points for the
-% current question.
+% which expands to the number of points followed by the argument to
+% the last \pointname command, or the command
%
-% We changed the longsolution environment to make it easy to change the
-% amount by which the left and right margins are increased. The default
-% amount is set by the command
+% \themarginpoints
%
-% \setlength{\longsolutionindent}{2em}
+% which expands to the number of points followed by the argument to
+% the last \marginpointname command.
%
-% and the user can change this by giving a new \setlength command.
+% For example, the command \bracketedpoints is equivalent to
%
-% Note added later: longsolution was eliminated in version
-% 2.106$\beta$.
+% \pointformat{[\thepoints]}
%
-%--------------------------------------------------------------------
+% if points are not being printed in the margin and to
%
-% Version 2.097$\beta$:
+% \pointformat{[\themarginpoints]}
%
-% We've changed the default format for the total points for a question
-% printed by the \droptotalpoints command. This command still prints
-% the total points for the question right justified a distance of
-% \rightpointsmargin from the right edge of the paper, but now the
-% number of points will, by default, be surrounded by either
+% if points are being printed in the margin.
%
-% a double box, if \boxedpoints is in effect,
-% double brackets, if \bracketedpoints is in effect, or
-% double parentheses, otherwise.
+% For another example, the command \boxedpoints is equivalent to
%
-% It's still true that if you use a \totalformat command, then the
-% format of the printed total points is completely controlled by the
-% argument of the \totalformat command and the default doesn't matter at
-% all.
+% \pointformat{\fbox{\thepoints}}
%
+% if points are not being printed in the margin and to
%
-% Note added later: We changed the default format again in version
-% 2.101$\beta$; see the notes above.
+% \pointformat{\fbox{\themarginpoints}}
%
-%--------------------------------------------------------------------
+% if points are being printed in the margin.
%
-% Version 2.096$\beta$:
+% For another example, if you give the commands
%
-% The labels for questions, parts, subparts, and subsubparts can now be
-% customized. The format now depends on the commands
+% \pointsinmargin
+% \marginpointname{\%}
+% \pointformat{\slshape (\themarginpoints)}
%
-% \questionlabel
-% \partlabel
-% \subpartlabel
-% \subsubpartlabel
+% then the points will be printed in the left margin, followed by the
+% symbol `%', surrounded by parentheses, all in slanted type.
%
-% the default definitions of which are:
+% For another example, if you give the commands
%
-% \newcommand\questionlabel{\thequestion.}
-% \newcommand\partlabel{(\thepartno)}
-% \newcommand\subpartlabel{\thesubpart.}
-% \newcommand\subsubpartlabel{\thesubsubpart)}
+% \pointsinrightmargin
+% \marginpointname{\%}
+% \pointformat{\fbox{\bfseries \boldmath \themarginpoints}}
%
-% These definions can be changed by using a \renewcommand command.
-% Note that the definition of \partlabel used `\thepartno', and *not*
-% `\thepart'. This is because `\thepart' refers to the counter for the
-% standard sectioning command \part, and not the counter used in the
-% parts environment. The counter used by the parts environment is
-% inserted with the command `\thepartno'.
+% then the points will be printed in the right margin, followed by the
+% symbol `%', all in bold and surrounded by a box. (Note: The commands
+% \bfseries and \boldmath are needed here because the ``one half''
+% printed when you use half points is printed in math mode while the
+% rest of the points are printed in text mode.)
%
%--------------------------------------------------------------------
+% Version 2.210$\beta$, 2006/09/28:
%
-% Version 2.095$\beta$:
-%
-% Added solution and longsolution environments.
-%
-% The command \printanswers causes both of these environments print the
-% solution, and the command \noprintanswers causes both of these
-% environments not to print the solution. The default is
-% \noprintanswers.
-%
-% The commands \printanswers and \noprintanswers can be given as many
-% times as desired to switch back and forth between the two.
-%
-% The documentclass option ``answers'' is equivalent to giving a
-% \printanswers command at the beginning of the file.
-%
-%
-% Both of these environments take an optional argument which is an
-% amount of blank vertical space to be left when \noprintanswers is in
-% effect. (The default value of this blank vertical space is 0pt.)
-%
-%
-% The solution environment prints the solution inside of a box, which
-% cannot be broken across pages. Thus, it is only appropriate for
-% solutions that are short enough to fit on a page.
-%
-% The longsolution environment prints the solution with left and right
-% margins slightly increased, and it can be broken across pages.
-%
-% When printing the solution, both environments begin with
-% \solutiontitle, the default value of which is created by the command
-%
-% \newcommand{\solutiontitle}{\textbf{Solution:}\enspace}
-%
-% This can be changed with the \renewcommand command.
-%
-% Note added later: solution was changed and longsolution was
-% eliminated in version 2.106$\beta$.
+% Fixed the bug that prevented having two consecutive \correctchoice's
+% in a choices or oneparchoices environment.
%
%--------------------------------------------------------------------
+% Version 2.209$\beta$, 2006/05/26:
%
-% Version 2.094$\beta$:
-%
-% We've expanded the options of the \gradetable command, so that you
-% can now get a grading table indexed by either question numbers or by
-% page numbers, and in either case you can have either a horizontally
-% oriented table or a vertically oriented table.
-%
-% \gradetable now takes two optional arguments: The first can be either
-% `[v]' or `[h]', and the second can be either `[questions]' or
-% `[pages]'. The defaults are `[v]' and `[questions]', and you must
-% specify a first option if you want to specify a second option.
-%
-% Thus: \gradetable is equivalent to \gradetable[v][questions]
-%
-% `[v]' and `[h]' are as before: Vertically oriented or horizontally
-% oriented.
-%
-% `[questions]' is the same as the earlier version: A table that lists
-% the question numbers, the possible total points for each question the
-% total for the entire exam, and spaces are left for the score on each
-% question.
-%
-% `[pages]' prints a table indexed by page numbers instead of by
-% question numbers. It lists only the numbers of pages that have points
-% on them, and for each such page it lists the number of points possible
-% on that page. It also lists the total possible points on the exam,
-% and spaces are left for the score on each page.
-%
-% For both tables indexed by questions and tables indexed by points,
-% there are commands that allow you to change the column and row
-% headings (the following are shown setting the default values:)
-%
-% \hpword{Points:}
-% \hsword{Score:}
-% \htword{Total}
-% \vpword{Points}
-% \vsword{Score}
-% \vtword{Total:}
-%
-% For tables indexed by questions, the appropriate row and column titles
-% are set by the following commands:
-%
-% \hqword{Question:}
-% \vqword{Question}
-%
-% For tables indexed by pages, the appropriate row and column titles are
-% set by the following commands:
-%
-% \hpgword{Page:}
-% \vpgword{Page}
-%
-%
-% For both \gradetable[h] and \gradetable [v], the width of the blank
-% cells created for filling in the grades can be changed with the
-% command \cellwidth, and the arraystretch applied to the table can be
-% changed with the command \gradetablestretch. The default values are
-% created by the commands:
-%
-% \cellwidth{2em}
-% \gradetablestretch{1.5}
+% We corrected the problem that \ifcontinuation and \ifincomplete paid
+% attention only to parts, subparts, and subsubparts when deciding on
+% which page a question ended, but ignored choices. We corrected this,
+% so that a question is now thought to end on the page on which its last
+% part, subpart, subsubpart, or choice begins.
%
%--------------------------------------------------------------------
-%
-% Version 2.093$\beta$:
-%
-% If the user gives the comman \addpoints, then
-% \pointsonpage{n} expands to the number of points on page n.
-%
+% Version 2.208$\beta$, 2006/01/30:
+%
+% We corrected the description of the usage of \ifthenelse in the
+% comments describing what's new in version 2.207beta.
+%
%--------------------------------------------------------------------
-%
-% Version 2.092$\beta$:
-%
-% Increased the \leftmargin in the choices environment.
-%
+% Version 2.207$\beta$, 2006/01/29:
+%
+% New feature: It's possible to say
+%
+% \ifprintanswers
+% Some stuff
+% \fi
+%
+% to insert ``Some stuff'' only when answers are being printed. It's
+% also possible to say
+%
+% \ifprintanswers
+% Some stuff
+% \else
+% Other stuff
+% \fi
+%
+% to insert ``Some stuff'' when answers are being printed and ``Other
+% stuff'' when answers aren't being printed.
+%
+% Alternatively, it's possible to accomplish the same thing by saying
+%
+% \ifthenelse{\boolean{printanswers}}{Some stuff}{Other stuff}
+%
+% If you want to ``Stuff'' only when answers aren't being printed, you
+% can say either
+%
+% \ifprintanswers
+% \else
+% Stuff
+% \fi
+%
+% or
+%
+% \ifthenelse{\boolean{printanswers}}{}{Stuff}
+%
+% We accomplished this by changing all uses of \if@printanswers,
+% \@printanswerstrue, and \@printanswersfalse to \ifprintanswers,
+% \printanswerstrue, and \printanswersfalse.
+%
%--------------------------------------------------------------------
+% Version 2.206$\beta$, 2005/08/24:
+%
+% New feature: When using a grading table indexed by questions, it's
+% possible to replace the question numbers in the table with titles
+% for the questions.
%
-% Version 2.091$\beta$:
-%
-% New commands:
-% \pointsdroppedatright
-% \droppoints
-% \droptotalpoints
-% \totalformat
-%
-% \pointsdroppedatright: The command \pointsdroppedatright causes points
-% not to be printed until you give the command \droppoints, except that
-% a \qformat command still works as expected (i.e., if you include
-% ``\thepoints'' in the argument of the \qformat, it will print the
-% points as usual).
-%
-%
-% \droppoints: The command \droppoints should be given only at the end
-% of a paragraph or between paragraphs; if you give it within a
-% paragraph, it causes the paragraph to end. \droppoints prints the
-% most recent point value in the right margin, formatted as it is when
-% you give the command \pointsinrightmargin, except that the points
-% appear opposite the last line of the paragraph (or, if the command
-% \droppoints is given between paragraphs, then additional vertical
-% space is left between the paragraphs and the points are printed
-% opposite the blank space). Thus, the formatting can be changed by
-% using giving the commands \bracketedpoints, \boxedpoints, or
-% \marginpointname.
-%
-% The command \droppoints actually works this way even if one of the
-% commands \pointsdroppedatright, \pointsinmargin, or
-% \pointsinrightmargin, is in effect, but if you use it that way the
-% points will appear twice on the page.
-%
-%
-% \droptotalpoints: To use the command \droptotalpoints, you must first
-% give the command \addpoints. The command \droptotalpoints should be
-% given only at the end of a paragraph or between paragraphs; if you
-% give it within a paragraph, it causes the paragraph to end.
-% \droptotalpoints prints the total points for the current question
-% (i.e., the sum of the points assigned to the question and to all of
-% its parts, subparts, and subsubparts) in the right margin, formatted
-% formatted by default inside either double brackets, double box, or
-% double parentheses, depending on whether \bracketedpoints,
-% \boxedpoints, or neither is in effect.
-%
-% \totalformat: The \totalformat command allows you to change the format
-% used by the \droptotalpoints command. It takes one argument, and that
-% argument becomes the command to print the total points, right
-% justified a distance of \rightpointsmargin from the right edge of the
-% paper. The argument should contain the expression
-% ``\pointsofquestion{\arabic{question}}'' at the point at which the number
-% of points should appear. For example, the command
-%
-% \totalformat{[\pointsofquestion{\arabic{question}}]}
-%
-% will produce the same appearance as the default does when the command
-% \bracketedpoints is in effect and \marginpointname is empty, and the
-% command
+%
+% There are two new commands: \titledquestion and \thequestiontitle.
+%
+%
+% \titledquestion is a replacement for \question; it has one required
+% argument (the title) and one optional argument (the point value), as
+% in
+%
+% \titledquestion{Question \thequestion: Concepts}
+%
+% which sets the question title to ``Question 2: Concepts'' (if this
+% is the second question) and doesn't set any pointvalues, or
+%
+% \titledquestion{Design}[10]
+%
+% which sets the question title to ``Design'' and sets the pointvalue
+% to ``10''. (Note that the question title doesn't include the number
+% of the question unless you put it there using the \thequestion
+% command.)
+%
+% The title of the question then automatically replaces the question
+% number in a grading table indexed by question numbers.
+%
+%
+%
%
-% \totalformat{\fbox{Total: \pointsofquestion{\arabic{question}}}}
+%
+% \thequestiontitle: This command expands to the question title. This
+% is for use in the argument of a \qformat command, so that you can make
+% the question title appear in the actual question.
+%
+% If a question is begun with \question (instead of \titledquestion),
+% then the value of \thequestiontitle will automatically be set to the
+% number of the question.
+%
+% Note: The contents of \thequestiontitle don't appear anywhere in the
+% actual question unless you do something to make it appear. For
+% example, the command
+%
+% \qformat{\textbf{Question \thequestion: \thequestiontitle}\dotfill\thepoints}
+%
+% would insert the number of the question along with the title of the
+% question and the point value at the beginning of the question.
+%
+%
+% Note: If you use a grading table indexed by questions and you use the
+% \titledquestion command, then the number of the question won't appear
+% in the grading table unless you include \thequestion in the title of
+% the question.
+%
%
-% produces a box surrounding ``Total: 25''.
+% Note: If \thequestion appears in both the argument to \qformat and the
+% title of the question, then the question number will be printed
+% twice.
+%
+%
+% If the command \thequestiontitle is never used, then the only effect
+% of using the command \titledquestion is that in a grading table
+% indexed by question number, this question will be indexed by the
+% number of the question, rather than by the argument to
+% \titledquestion, and the title of the question would never appear
+% except in the grading table.
%
+%
%--------------------------------------------------------------------
%
-% Version 2.087$\beta$:
-%
-% We changed ``\point@toks={}'' into ``\global \point@toks={}'' when
-% \point@toks is set, so that if the user somehow arranges for us to be
-% inside of a group when we enter horizontal mode, the \point@toks will
-% be properly set equal to null, and so the points won't accidentally be
-% placed a second time at the second paragraph of the question.
-%
-% Similarly, we changed ``\pageinfo@commands={}'' to
-% ``\global \pageinfo@commands={}''.
-%
-%--------------------------------------------------------------------
+% Version 2.205$\beta$, 2005/08/22:
%
-% Version 2.080$\beta$:
-%
-% We added a new command \gradetable that produces a grading table,
-% oriented either vertically or horizontally, that lists the questions,
-% their point values, and the total points, and leaves spaces for
-% entering the grade for each question and the total grade. We also
-% added a new command \pointsofquestion that takes one argument that is
-% assumed to be the number of a question and returns the total number of
-% points for that question. \pointsofquestion is used by the
-% \gradetable command, but the user can choose to use it separately.
-
-% To use either \gradetable or \pointsofquestion, the user must give the
-% command \addpoints. \pointsofquestion{n} will then return the total
-% number of points for question n and all of its parts, subparts, and
-% subsubparts. Since all this information is stored in the .aux file
-% and then read back on the next run of LaTeX, the user must run LaTeX
-% twice after any changes to the questions or points.
-
-% \gradetable[h] produces a horizonatlly oriented grade table, and
-% \gradetable[v] produces a vertically oriented grade table. The
-% command \gradetable is equivalent to \gradetable[v].
-
-% \gradetable[h] produces a table with three rows, titled (by default)
-% ``Question:'', ``Points:'', and ``Score:'' (the titles are in the
-% first column of the table). There is then one column for each
-% question (with the question number and point value in the first two
-% rows), plus a final column labelled ``Total'' with the total points in
-% the second row.
-
-% \gradetable[v] produces a table with three columns, titled (by
-% default) ``Question'', ``Points'', and ``Score'' (the titles are in
-% the first row of the table). There is then one row for each question
-% (with the question number and point value in the first two columns),
-% plus a final row labelled ``Total:'' with the total points in the
-% second column.
-
-% Note that \gradetable[h] produces row titles whose default values
-% contains colons, while \gradetable[v] produces column titles whose
-% default values do not contain colons.
-
-% The row and column titles and the word ``Total'' can be changed using
-% the commands \hqword, \hpword, \hsword, \htword, \vqword,
-% \vpword, \vsword, and \vtword, where the first four affect
-% \gradetable[h] and the second four affect \gradetable[v]. The default
-% values are created by the commands:
-
-% \hqword{Question:}
-% \hpword{Points:}
-% \hsword{Score:}
-% \htword{Total}
-% \vqword{Question}
-% \vpword{Points}
-% \vsword{Score}
-% \vtword{Total:}
-
-% For both \gradetable[h] and \gradetable [v], the width of the blank
-% cells created for filling in the grades can be changed with the
-% command \cellwidth, and the arraystretch applied to the table can be
-% changed with the command \gradetablestretch. The default values are
-% created by the commands:
-
-% \cellwidth{2em}
-% \gradetablestretch{1.5}
-
-
-
-% Changing the definition of \points:
-
-% The default definition of \points is that it expands to ``point'' if
-% the number of points is 1 and to ``points'' otherwise. There is now a
-% command ``\pointpoints'' that takes two arguments, after which
-% \points will expand to the first argument when the number of points is
-% 1 and to the second argument otherwise. For example, the default is
-% the result of the command \pointpoints{point}{points}.
+% Bug fix: If a question began with a parts environment (i.e., if the
+% parts environment began before we entered horizontal mode in the
+% question), then a grading table indexed by questions would get the
+% part number instead of the question number. That's fixed now.
%
%--------------------------------------------------------------------
%
-% Version 2.070$\beta$:
+% Version 2.204$\beta$, 2005/08/21:
%
-% We made this compatible with hyperref.sty.
-% We did this by eliminating all use of LaTeX's
-% \label, \newlabel, \ref, and \pageref commands.
-% We now put information into the .aux file using the
-% \PgInfo@write command, and get that info out of the aux file
-% using \PgInfo and \PgInfo@get, along with a few \gdef commands
-% written straight to the .aux file.
+% Bug fix: Hyperlinks didn't work on page numbers for horizontal
+% grading tables indexed by page numbers. They do now.
%
%--------------------------------------------------------------------
%
-% Version 2.067$\beta$:
+% Version 2.203$\beta$, 2005/08/20:
%
-% We're adding code to enable headers and footers
-% to know whether the current page continues a question started on an
-% earlier page, and whether the page ends with a question still
-% incomplete.
-
-%--------------------------------------------------------------------
-% For use in headers and footers:
-%
-% \ifcontinuation{Text 1}{Text 2}
-% Expands to ``Text 1'' if this page begins with a part or subpart or
-% subsubpart that continues a question begun on an earlier page, and
-% expands to ``Text 2'' if this page begins with a new question.
-%
-% \ContinuedQuestion expands to the number of the question that is
-% being continued from an earlier page.
+% Eliminated \do@int@lbl, and replaced it with labels for each
+% question, part, subpart, and subsubpart the names of which
+% tell you what they're labelling.
%
-% \ifincomplete{Text 1}{Text 2}
-% Expands to ``Text 1'' if the last question begun on or before this
-% page has a part, subpart, or subsubpart that begins on a later page,
-% and if we have not yet encountered a \nomorequestions command.
-%
-% \IncompleteQuestion expands to the number of the question that is
-% continued on the next page.
+% That allowed us to rewrite the grade table stuff so that, for tables
+% indexed by question numbers, the question numbers are inserted with a
+% \ref, so that if \usepackage{hyperref} and pdflatex are used, those
+% question numbers will be clickable links that take you to the relevant
+% question.
%
-% \nomorequestions is a command that you can give after the last
-% question if you intend to include extra material (e.g., tables for
-% use on the exam) but you don't want the pages containing the extra
-% material to be labelled as continuing the last question on the exam.
+% We also added a label for the first points to appear on each page, and
+% rewrote the grade table stuff for tables indexed by page number so
+% that the page numbers are inserted with a \pageref, so that if
+% \usepackage{hyperref} and pdflatex are used, those page numbers will
+% be clickable links that take you to the relevant page.
%
%--------------------------------------------------------------------
%
+% Version 2.202$\beta$, 2005/08/10:
%
-% Also:
-% Changed the code for headers and footers to
-% use the command \normalfont instead of \rm so that the main
-% document font will appear in headers and footers even when the
-% main document font is *not* a roman font.
-%
-% \def\marksnotpoints
+% Created \correctchoice as a synonym for \CorrectChoice
%
-% Changes \pointname so that it is identical to the default \pointname
-% except that the work ``mark'' is used instead of the word
-% ``point''. That is, if the number of points is 1, then you'll get
-% ``1 mark'', and if the number of points is other than 1 then you'll
-% get ``n marks'' (where n is the number of points).
+% Changed \CorrectChoiceDeclarations to \CorrectChoiceEmphasis,
+% and created \correctchoiceemphasis as a synonym for that.
%
+%--------------------------------------------------------------------
%
-% \bracketedpoints
-% \nobracketedpoints
-%
-% The default remains to put the points inside of parentheses.
-% \bracketedpoints switches to points inside of square brackets and
-% \boxedpoints switches to points in side of a box. Both
-% \nobracketedpoints and \noboxedpoints return to the default of
-% points inside of parentheses no matter how many \boxedpoints and
-% \bracketedpoints commands have been given in any order.
-%
-%
-% \pointsinrightmargin
-% \nopointsinrightmargin
-%
-% The default remains to put the points right after the question
-% number, before the text of the question. \pointsinrightmargin
-% switches to points in the right margin and \pointsinleftmargin
-% switches to points in the left margin. Both \nopointsinrightmargin
-% and \nopointsinleftmargin return to the default of points right
-% after the question number, before the text of the question, no
-% matter how many \pointsinrightmargin and \pointsinleftmargin
-% commands have been given in any order.
-%
-% if \pointsinrightmargin is used, then the points are printed
-% right justified in the right margin, with the right edge a distance
-% of \rightpointsmargin from the right edge of the paper.
-% The default value of \rightpointsmargin is 1 cm, but it can be set
-% to any other length with the usual \setlength command
-% (as in \setlength{\rightpointsmargin}{0.5cm}).
-%
+% Version 2.201$\beta$, 2005/08/09:
%
-% subsubparts environment
-% Numbered using lower case greek letters.
+% We created a \CorrectChoice command for use in the choices and
+% oneparchoices environments.
%
+% When solutions are not being printed, \CorrectChoice is equivalent to
+% \choice.
%
-% choices environment, for multiple choice answers
+% When solutions *are* being printed, the choice that was created with
+% \CorrectChoice (rather than with \choice) will be printed subject to
+% the declarations in the argument of the
%
+% \CorrectChoiceDeclarations
%
-% \qformat{Format line}
-%
-% Format line must have some stretch (e.g., at least one \hfil or
-% \dotfill or something similar).
-% \thequestion inserts the question number,
-% \thepoints inserts the number of points followed by pointname if
-% a number of points has been specified for this question, and it
-% inserts nothing at all if no points have been specified.
+% command. The default is
%
-% \noqformat returns to the standard question number formatting.
+% \CorrectChoiceDeclarations{\bfseries}
%
+% and so, when solutions are being printed, the correct choice is
+% printed in boldface by default. If, e.g., you give the command
%
+% \usepackage{color}
%
-% The standard options
-% a4paper
-% a5paper
-% b5paper
-% letterpaper
-% legalpaper
-% executivepaper
-% landscape
-% now all work.
-%
+% after the \documentclass command and then give the command
%
+% \CorrectChoiceDeclarations{\color{red}}
%
-% Two new commands for use in \pointname, \marginpointname, and
-% \qformat:
+% then the correct choice will be printed in red. If, e.g., you give
+% the command
%
-% \points expands to either ``point'' or ``points'', depending on
-% whether the number of points is 1 or other than 1.
+% \CorrectChoiceDeclarations{\color{red}\bfseries}
%
-% \marks expands to either ``mark'' or ``marks'', depending on
-% whether the number of points is 1 or other than 1.
+% then the correct choice will be printed in red and in boldface.
%
+% Note added later: \CorrectChoiceDeclarations was changed
+% to \CorrectChoiceEmphasis in version 2.202$\beta$.
%
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-%
-% The only change from version 2.0 to version 2.01 is that this
-% documentclass (and its accompanying documentation) is now
-% explicitly distributed under the LaTeX Project Public License.
-%
-%--------------------------------------------------------------------
%--------------------------------------------------------------------
\NeedsTeXFormat{LaTeX2e}
@@ -934,10 +769,29 @@
\RequirePackage{ifthen}
-\newif\if@printanswers
-\@printanswersfalse
-\DeclareOption{answers}{\@printanswerstrue}
-\DeclareOption{noanswers}{\@printanswersfalse}
+\newif\ifprintanswers
+\printanswersfalse
+\DeclareOption{answers}{\printanswerstrue}
+\DeclareOption{noanswers}{\printanswersfalse}
+
+% The following keeps track of whether the user has requested that we
+% add up the points on the exam. We make the default false so that
+% users who put other than numbers into the points argument of a
+% question (or part, or subpart) won't get error messages.
+% We use \if@printtotalpoints as a flag to signal that we are counting
+% points, so that we will know to print the total on the screen (and
+% in the log file). We use this separate flag so that the user can
+% use both \addpoints and \noaddpoints to count some points and not
+% others, but still have the total printed when we finish the file no
+% matter what the state of \if@addpoints.
+\newif\if@addpoints
+\newif\if@printtotalpoints
+\def\addpoints{\global\@addpointstrue\global\@printtotalpointstrue}
+\def\noaddpoints{\global\@addpointsfalse}
+\@addpointsfalse
+\@printtotalpointsfalse
+\DeclareOption{addpoints}{\addpoints}
+
\DeclareOption*{%
\PassOptionsToClass{\CurrentOption}{article}%
@@ -983,10 +837,6 @@
\setlength{\marginparwidth}{.5in}
\setlength{\marginparsep}{5pt}
-
-
-
-
%--------------------------------------------------------------------
% ****************
@@ -1014,9 +864,6 @@
\advance\@rightmargin by -\@extrawidth
}
-
-
-
%--------------------------------------------------------------------
%--------------------------------------------------------------------
% Making room for large headers and footers
@@ -1053,7 +900,6 @@
\setlength{\covrun@exft}{0in}
\setlength{\covfp@exft}{0in}
-
\newcommand*\adj@hdht@ftht{%
\if@coverpages
\ifnum\value{page}=1
@@ -1074,7 +920,6 @@
\fi
}
-
\newcommand*\extraheadheight{%
\@ifnextchar[{\@xtrahd}{\@ytrahd}%
}
@@ -1107,7 +952,6 @@
\adj@hdht@ftht
}
-
\newcommand*\coverextraheadheight{%
\@ifnextchar[{\cov@xtrahd}{\cov@ytrahd}%
}
@@ -1285,8 +1129,6 @@
}%
}
-
-
\newcommand*\@dohead{%
\def\@oddhead{%
\if@coverpages
@@ -1335,9 +1177,6 @@
\let\@evenfoot=\@oddfoot
}
-
-
-
%--------------------------------------------------------------------
% \@fullhead, \run@fullhead, \@fullfoot, and \run@fullfoot:
@@ -1358,7 +1197,6 @@
}% vbox
}
-
\newcommand*\run@fullhead{%
\vbox to \headheight{%
\vss
@@ -1376,8 +1214,6 @@
}% vbox
}
-
-
% We arrange it so that the very top of first line of text in the
% foot is at a fixed position on the page, whether or not there's
% a footrule:
@@ -1400,7 +1236,6 @@
}% vbox
}
-
\newcommand*\run@fullfoot{%
\vbox to 0pt{%
\ifrun@footrule
@@ -1440,7 +1275,6 @@
}% vbox
}
-
\newcommand*\covrun@fullhead{%
\vbox to \headheight{%
\vss
@@ -1458,8 +1292,6 @@
}% vbox
}
-
-
% We arrange it so that the very top of first line of text in the
% foot is at a fixed position on the page, whether or not there's
% a footrule:
@@ -1482,7 +1314,6 @@
}% vbox
}
-
\newcommand*\covrun@fullfoot{%
\vbox to 0pt{%
\ifcovrun@footrule
@@ -1501,7 +1332,6 @@
}% vbox
}
-
%--------------------------------------------------------------------
%--------------------------------------------------------------------
%
@@ -1563,7 +1393,6 @@
\runningheader{#1}{#2}{#3}%
}
-
\def\firstpagefooter#1#2#3{%
\def\@lfoot{#1}%
\def\@cfoot{#2}%
@@ -1581,8 +1410,6 @@
\runningfooter{#1}{#2}{#3}%
}
-
-
\def\lhead{\@ifnextchar[{\@xlhead}{\@ylhead}}
\def\@xlhead[#1]#2{\def\@lhead{#1}\def\run@lhead{#2}}
\def\@ylhead#1{\def\run@lhead{#1}\def\@lhead{#1}}
@@ -1610,8 +1437,6 @@
% Initialize head and foot:
-
-
\pagestyle{headandfoot}
\lhead{}
@@ -1679,7 +1504,6 @@
\coverrunningheader{#1}{#2}{#3}%
}
-
\def\coverfirstpagefooter#1#2#3{%
\def\cov@lfoot{#1}%
\def\cov@cfoot{#2}%
@@ -1697,8 +1521,6 @@
\coverrunningfooter{#1}{#2}{#3}%
}
-
-
\def\coverlhead{\@ifnextchar[{\cov@xlhead}{\cov@ylhead}}
\def\cov@xlhead[#1]#2{\def\cov@lhead{#1}\def\covrun@lhead{#2}}
\def\cov@ylhead#1{\def\covrun@lhead{#1}\def\cov@lhead{#1}}
@@ -1726,7 +1548,6 @@
% Initialize coverpage head and foot:
-
\coverlhead{}
\coverchead{}
\coverrhead{}
@@ -1754,8 +1575,6 @@
\def\headrule{\@headruletrue\run@headruletrue}
\def\noheadrule{\@headrulefalse\run@headrulefalse}
-
-
\newif\if@footrule
\newif\ifrun@footrule
@@ -1768,14 +1587,11 @@
\def\footrule{\@footruletrue\run@footruletrue}
\def\nofootrule{\@footrulefalse\run@footrulefalse}
-
-
% Initialize:
\noheadrule
\nofootrule
-
% Cover page headrules and footrules:
\newif\ifcov@headrule
@@ -1790,8 +1606,6 @@
\def\coverheadrule{\cov@headruletrue\covrun@headruletrue}
\def\nocoverheadrule{\cov@headrulefalse\covrun@headrulefalse}
-
-
\newif\ifcov@footrule
\newif\ifcovrun@footrule
@@ -1804,15 +1618,11 @@
\def\coverfootrule{\cov@footruletrue\covrun@footruletrue}
\def\nocoverfootrule{\cov@footrulefalse\covrun@footrulefalse}
-
-
% Initialize:
\nocoverheadrule
\nocoverfootrule
-
-
%--------------------------------------------------------------------
%--------------------------------------------------------------------
@@ -1825,73 +1635,103 @@
% the number of questions as \numquestions,
% the number of parts as \numparts, and
% the number of subparts as \numsubparts
-%\def\numpages{\pageref{@lastpage}}
-%\def\numpoints{\pageref{@numpoints}}
-%\def\numquestions{\pageref{@numquestions}}
-%\def\numparts{\pageref{@numparts}}
-%\def\numsubparts{\pageref{@numsubparts}}
-%\def\numsubsubparts{\pageref{@numsubsubparts}}
-
-% This was previously done with \pageref commands. When I eliminated
-% all \label, \ref, and \pageref commands in order to make this
-% compatible with hyperref.sty, this stuff was created:
-
-% \gdef commands for exam@lastpage, exam@numpoints, exam@numquestions,
-% exam@numparts, exam@numsubparts and exam@numsubsubparts are written to
-% the .aux file via \AtEndDocument.
-
-% \gdef commands for pointsofq@i, pointsofq@ii, etc. are written to the
-% .aux file as each question is completed (see the definition of the
+
+% This was previously done with \pageref commands. When I stopped
+% using \pageref for this (in order to make this compatible with
+% hyperref.sty), this stuff was created:
+
+% \gdef commands for exam@lastpage, exam@numpoints,
+% exam@numbonuspoints, exam@numquestions, exam@numparts,
+% exam@numsubparts and exam@numsubsubparts are written to the .aux
+% file via \AtEndDocument.
+
+% \gdef commands for pointsofq@i, pointsofq@ii, etc. and
+% bonuspointsofq@i, bonuspointsofq@ii, etc. are written to the .aux
+% file as each question is completed (see the definition of the
% questions environment).
-% \gdef commands for pointsonpage@i, pointsonpage@ii, etc. are written
-% to the .aux file as we encounter points defined for a later page, and
-% for the last such page with AtEndDocument.
+% \gdef commands for pointsonpage@i, pointsonpage@ii, etc. and
+% bonuspointsonpage@i, bonuspointsonpage@ii, etc. are written to the
+% .aux file as we encounter points defined for a later page, and for
+% the last such page with AtEndDocument.
\def\numpages{\@ifundefined{exam@lastpage}%
{\mbox{\normalfont\bf ??}}%
\exam@lastpage
-}
+}% numpages
\def\numpoints{\@ifundefined{exam@numpoints}%
{\mbox{\normalfont\bf ??}}%
\exam@numpoints
-}
+}% numpoints
+\def\numbonuspoints{\@ifundefined{exam@numbonuspoints}%
+ {\mbox{\normalfont\bf ??}}%
+ \exam@numbonuspoints
+}% numbonuspoints
\def\numquestions{\@ifundefined{exam@numquestions}%
{\mbox{\normalfont\bf ??}}%
\exam@numquestions
-}
+}% numquestions
\def\numparts{\@ifundefined{exam@numparts}%
{\mbox{\normalfont\bf ??}}%
\exam@numparts
-}
+}% numparts
\def\numsubparts{\@ifundefined{exam@numsubparts}%
{\mbox{\normalfont\bf ??}}%
\exam@numsubparts
-}
+}% numsubparts
\def\numsubsubparts{\@ifundefined{exam@numsubsubparts}%
{\mbox{\normalfont\bf ??}}%
\exam@numsubsubparts
-}
+}% numsubsubparts
\def\pointsofquestion#1{\@ifundefined{pointsofq@\romannumeral #1}%
{\mbox{\normalfont\bf ??}}%
{\csname pointsofq@\romannumeral #1\endcsname}%
-}
+}% pointsofquestion
+\def\bonuspointsofquestion#1{\@ifundefined{bonuspointsofq@\romannumeral #1}%
+ {\mbox{\normalfont\bf ??}}%
+ {\csname bonuspointsofq@\romannumeral #1\endcsname}%
+}% bonuspointsofquestion
\def\pointsonpage#1{\@ifundefined{pointsonpage@\romannumeral #1}%
{\mbox{\normalfont\bf ??}}%
{\csname pointsonpage@\romannumeral #1\endcsname}%
-}
+}% pointsonpage
+\def\bonuspointsonpage#1{\@ifundefined{bonuspointsonpage@\romannumeral #1}%
+ {\mbox{\normalfont\bf ??}}%
+ {\csname bonuspointsonpage@\romannumeral #1\endcsname}%
+}% bonuspointsonpage
\newif\if@pointschanged
\@pointschangedfalse
+\newcommand*{\CheckIfChanged@hlf}[2]{%
+ % The first argument is the name of a half counter.
+ % The second argument expands to the name (without the escape
+ % character, and not assumed to be defined) of the control sequence
+ % holding the previous value.
+ \@ifundefined{#2}%
+ {\global\@pointschangedtrue}%
+ {%
+ % OK; it's defined. See if it's changed:
+ \begingroup
+ \set@hlfcntr{tmp@hlfcntr}{\csname #2\endcsname}%
+ \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
+ \edef\pt@check{\prtaux@hlfcntr{#1}}%
+ \ifx \pt@check \othpt@check
+ % Do nothing
+ \else
+ \global\@pointschangedtrue
+ \fi
+ \endgroup
+ }%
+}% CheckIfChanged@hlf
%%%\let\@realenddocument=\enddocument
@@ -1904,7 +1744,6 @@
%%% \@realenddocument
%%%}
-
\AtEndDocument{%
\clearpage
\if@filesw
@@ -1913,23 +1752,15 @@
{\string\gdef\string\exam@lastpage{\arabic{page}}}%
\advance\c@page+1 % In case some other package looks at \c@page
\immediate\write\@mainaux
- {\string\gdef\string\exam@numpoints{\prtaux@hlfcntr{numpoints}}}%
+ {\string\gdef\string\exam@numpoints{%
+ \prtaux@hlfcntr{numpoints}}}%
% See if this has changed from the last run of LaTeX:
- \@ifundefined{exam@numpoints}%
- {\global\@pointschangedtrue}%
- {%
- % OK; it's defined. See if it's changed:
- \begingroup
- \set@hlfcntr{tmp@hlfcntr}{\exam@numpoints}%
- \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
- \edef\pt@check{\prtaux@hlfcntr{numpoints}}%
- \ifx \pt@check \othpt@check
- % Do nothing
- \else
- \global\@pointschangedtrue
- \fi
- \endgroup
- }%
+ \CheckIfChanged@hlf{numpoints}{exam@numpoints}%
+ \immediate\write\@mainaux
+ {\string\gdef\string\exam@numbonuspoints{%
+ \prtaux@hlfcntr{numbonuspoints}}}%
+ % See if this has changed from the last run of LaTeX:
+ \CheckIfChanged@hlf{numbonuspoints}{exam@numbonuspoints}%
\immediate\write\@mainaux
{\string\gdef\string\exam@numquestions{\thenumquestions}}%
\immediate\write\@mainaux
@@ -1944,23 +1775,16 @@
\csname c@pageof@pagepoints\endcsname
{\prtaux@hlfcntr{@pagepoints}}}%
% See if this has changed from the last run of LaTeX:
- \@ifundefined{pointsonpage@\romannumeral
+ \CheckIfChanged@hlf{@pagepoints}{pointsonpage@\romannumeral
\csname c@pageof@pagepoints\endcsname}%
- {\global\@pointschangedtrue}%
- {%
- % OK; it's defined. See if it's changed:
- \begingroup
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@pageof@pagepoints\endcsname\endcsname}%
- \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
- \edef\pt@check{\prtaux@hlfcntr{@pagepoints}}%
- \ifx \pt@check \othpt@check
- % Do nothing
- \else
- \global\@pointschangedtrue
- \fi
- \endgroup
- }%
+ \fi
+ \ifnum \thepageof@pagebonuspoints > 0\relax
+ \immediate\write\@mainaux
+ {\string\gdef\string\bonuspointsonpage@\romannumeral
+ \csname c@pageof@pagebonuspoints\endcsname
+ {\prtaux@hlfcntr{@pagebonuspoints}}}%
+ \CheckIfChanged@hlf{@pagebonuspoints}{bonuspointsonpage@\romannumeral
+ \csname c@pageof@pagebonuspoints\endcsname}%
\fi
\immediate\write\@mainaux
{\string\gdef\string\lastpage@withpoints{\page@withpoints}}%
@@ -1979,6 +1803,23 @@
\fi
\endgroup
}%
+ \immediate\write\@mainaux
+ {\string\gdef\string\lastpage@withbonuspoints{\page@withbonuspoints}}%
+ % See if this has changed from the last run of LaTeX:
+ \@ifundefined{lastpage@withbonuspoints}%
+ {\global\@pointschangedtrue}%
+ {%
+ % OK; it's defined. See if it's changed:
+ \begingroup
+ \edef\othpt@check{\page@withbonuspoints}%
+ \edef\pt@check{\lastpage@withbonuspoints}%
+ \ifx \pt@check \othpt@check
+ % Do nothing
+ \else
+ \global\@pointschangedtrue
+ \fi
+ \endgroup
+ }%
\fi
% Echo numbers of questions, parts, and subparts:
\typeout{This exam contains \thenumquestions\space questions
@@ -1994,13 +1835,20 @@
\fi
}
\typeout{This exam has a total of \typ@expnd\space points.}
+ \def\typ@expnd{%
+ \thenumbonuspoints
+ \ifnumbonuspoints@half
+ \space and a half%
+ \fi
+ }
+ \typeout{This exam has a total of \typ@expnd\space bonus points.}
\endgroup
\fi
\if@pointschanged
\ClassWarningNoLine{exam}{Point totals have changed.
Rerun to get point totals right}%
\fi
-}
+}% AtEndDocument
% We define \iflastpage so that it can safely be used
@@ -2008,12 +1856,12 @@
\def\iflastpage#1#2{%
\@ifundefined{exam@lastpage}{\def\@@lastpage{-1}}%
{\edef\@@lastpage{\exam@lastpage}}%
- \ifnum\value{page}=\@@lastpage
+ \ifnum\value{page}=\@@lastpage\relax
#1%
\else
#2%
\fi
-}
+}% iflastpage
% The macro \oddeven takes two arguments. If the page number is odd,
@@ -2025,7 +1873,7 @@
\else
#2
\fi
-}
+}% oddeven
@@ -2048,7 +1896,7 @@
% with hyperref.sty, which redefines those commands.)
% We use \PgInfo, \PgInfo@write, and \PgInfo@get to know on which page
-% each question, part, subpart, and subsubpart appears.
+% each question, part, subpart, subsubpart, and choice appears.
% We use \PgInfo@write to write \PgInfo commands to the .aux file. The
% \PgInfo command takes two arguments: A question (or part, or subpart,
@@ -2066,6 +1914,10 @@
% The label for a subsubpart is of the form `subsubpart@2@1@3@4' (if
% it's subsubpart $\delta$ of subpart iii of part a of question 2).
+% Each question, part, subpart, subsubpart, and choice also gets a
+% \PgInfo@write command using a label of the form question2@object3 (if
+% it's the third object of the second question).
+
% The \PgInfo command defines a control sequence of the form `Pg@label'
% that expands to the page number for the corresponding question. For
% example, \PgInfo{subsubpart@2@1@3@4}{7} defines
@@ -2108,15 +1960,14 @@
% *before* calling \Pginfo@get
\def\PgInfo@get#1{\csname Pg@#1\endcsname}
-% \set@counter@to@pageof takes two arguments: The first is the name
-% of a counter, and the second (expands to) the label of a question,
-% part, subpart, or subsubpart. If that label exists, then we set
-% the counter equal to the page on which the question (or part, etc.)
-% appears. If that label doesn't exist, we set the counter equal
-% to -1. (No labels exist on the first run of LaTeX on the file,
-% and if a new question (or part, etc.) was created by editing the
-% file, then the label will not exist until the second run of LaTeX
-% after that.
+% \set@counter@to@pageof takes two arguments: The first is the name of a
+% counter, and the second (expands to) the label of a question, part,
+% subpart, subsubpart, or choice. If that label exists, then we set the
+% counter equal to the page on which the question (or part, etc.)
+% appears. If that label doesn't exist, we set the counter equal to -1.
+% (No labels exist on the first run of LaTeX on the file, and if a new
+% question (or part, etc.) was created by editing the file, then the
+% label will not exist until the run of LaTeX after that.)
\def\set@counter@to@pageof#1#2{%
\@ifundefined{Pg@#2}%
{\setcounter{#1}{-1}}%
@@ -2128,8 +1979,8 @@
% \ifcontinuation#1#2 expands to #2 if either: (1) The current page is
% before the page containing question number 1, or (2) A question begins
-% on this page before any part, subpart, or subsubpart begins, or (3)
-% The current page is later than a page with the \nomorequestions
+% on this page before any part, subpart, subsubpart, or choice begins,
+% or (3) The current page is later than a page with the \nomorequestions
% command. Otherwise, it expands to #1.
@@ -2182,8 +2033,6 @@
\PgInfo@write{@endquestions}%
}
-
-
%--------------------------------------------------------------------
% \ContinuedQuestion is for use in headers and footers, where we can
% assume that \thepage is the number of the page on which we'll
@@ -2195,14 +2044,14 @@
% ACTUALLY: \ContinuedQuestion expands to a positive number if either
% (1) this page doesn't contain the beginning of any question, part,
-% subpart, or subsubpart, or (2) this page has a part, subpart, or
-% subsubpart that appears before any question. That means that if the
-% current page actually begins with space for a continuation of the
-% previous question (but doesn't begin any part, subpart, or subsubpart
-% of that question) and then has a question, then we'll be asserting
-% that this page begins with a new question, but the actual top of the
-% page will begin with some blank space that's intended for the previous
-% question.
+% subpart, subsubpart, or choice, or (2) this page has a part, subpart,
+% subsubpart, or choice that appears before any question. That means
+% that if the current page actually begins with space for a continuation
+% of the previous question (but doesn't begin any part, subpart,
+% subsubpart, or choice of that question) and then has a question, then
+% we'll be asserting that this page begins with a new question, but the
+% actual top of the page will begin with some blank space that's
+% intended for the previous question.
% \ContinuedQuestion works by examining the value of the macro
% Contin@\thepage. If this page starts with a question (i.e., if no
@@ -2213,22 +2062,22 @@
% If Contin@\thepage is undefined, then when it is used in an \ifx
% command it will be temporarily set equal to \relax (which is
% *different* from being a macro that expands to \relax); in this case,
-% there is no question, part, subpart, or subsubpart that begins on this
-% page, and so \ContinuedQuestion will be set equal to the last question
-% that was begun on a page before this one.
+% there is no question, part, subpart, subsubpart, or choice that begins
+% on this page, and so \ContinuedQuestion will be set equal to the last
+% question that was begun on a page before this one.
% The last possibility is that this page begins with either a part,
-% subpart, or subsubpart. In this case, Contin@\thepage is defined, and
-% it expands to the number of the question that is continues onto this
-% page.
+% subpart, subsubpart, or choice. In this case, Contin@\thepage is
+% defined, and it expands to the number of the question that is
+% continues onto this page.
\def\ref@relax{\relax}
\def\ContinuedQuestion{%
\expandafter\ifx\csname Contin@\thepage\endcsname\relax
- % We get here if there's no question, part, subpart, or
- % subsubpart on this page, and so Contin@\thepage has
+ % We get here if there's no question, part, subpart,
+ % subsubpart, or choice on this page, and so Contin@\thepage has
% never been defined at all. In that case, this page
% continues whichever question was last begun on or
% before this page.
@@ -2240,10 +2089,10 @@
% which is why Contin@\thepage has been defined to be
% a macro that expands to \relax.
% ACTUALLY: We get here if this page has a question that
- % appears before any part, subpart, or subsubpart. That
+ % appears before any part, subpart, subsubpart, or choice. That
% means that if the current page actually begins with space
% for a continuation of the previous question but doesn't begin
- % any part, subpart, or subsubpart of that question, then
+ % any part, subpart, subsubpart, or choice of that question, then
% we'll be asserting that this page begins with a new question,
% but the actual top of the page will begin with some space
% that's intended for the previous question.
@@ -2331,18 +2180,18 @@
\fi
\next@dlq
}
-
-
%--------------------------------------------------------------------
%--------------------------------------------------------------------
%--------------------------------------------------------------------
\newcounter{ques@end}
+\newcounter{last@object}
+
\def\find@quesend{%
% We find the last question started on or before the current page
% and then find the page containing the last part (or subpart, or
- % subsubpart) of that question, and set the counter ques@end to that
- % page number.
+ % subsubpart, or choice) of that question, and set the counter
+ % ques@end to that page number.
% Set latest@ques equal to the correct question number:
\find@latestques
\ifnum \value{latest@ques} < 0\relax
@@ -2350,117 +2199,39 @@
% \PgInfo commands in the .aux file:
\setcounter{ques@end}{-1}%
\else
- % See if this question has any parts. (It has one or more parts
- % if and only if it has a part number 1.)
- \@ifundefined{Pg@part@\thelatest@ques @1}%
- {%
- % Nope; no parts.
- \setcounter{ques@end}{\PgInfo@get{question@\thelatest@ques}}%
- }%
- {\find@part}%
+ % We now know that this question has at least one object (since
+ % we know that latest@ques isn't negative).
+ % We'll find its highest numbered object by setting last@object
+ % equal to 2 and then calling \find@lastobject to recursively
+ % test whether that object number exists and, if so, incrementing
+ % last@object to test for a higher numbered one:
+ \setcounter{last@object}{2}%
+ \find@lastobject
+ \setcounter{ques@end}{\PgInfo@get{question\thelatest@ques
+ @object\thelast@object}}%
\fi
-}
-
-\newcounter{last@part}
-\def\find@part{%
- % We now know that this question has at least one part.
- % We'll find its highest numbered part by setting last@part
- % equal to 2 and then calling \find@lastpart to recursively
- % test whether that part number exists and, if so, incrementing
- % last@part to test for a higher numbered one:
- \setcounter{last@part}{2}%
- \find@lastpart
- % Now: See if this part has any subparts. (It has one or more
- % subparts if and only if it has a subpart numbered 1.)
- \@ifundefined{Pg@subpart@\thelatest@ques @\thelast@part @1}%
- {%
- % Nope; no subparts.
- \setcounter{ques@end}{\PgInfo@get{part@\thelatest@ques
- @\thelast@part}}%
+}% find@quesend
+
+\def\find@lastobject{%
+ % We check whether this question has an object numbered last@object
+ % and recursively increment last@object to find the highest
+ % numbered value for which the object exists:
+ \@ifundefined{Pg@question\thelatest@ques @object\thelast@object}%
+ {\addtocounter{last@object}{-1}%
+ \let\nextfind@lastobject=\relax
}%
- {\find@subpart}%
-}
-
-\def\find@lastpart{%
- % We check whether this question has a part numbered last@part
- % and recursively increment last@part to find the highest
- % numbered value for which the part exists:
- \@ifundefined{Pg@part@\thelatest@ques @\thelast@part}%
- {\addtocounter{last@part}{-1}%
- \let\nextfind@lastpart=\relax
- }%
- {\addtocounter{last@part}{1}%
- \let\nextfind@lastpart=\find@lastpart
- }%
- \nextfind@lastpart
-}
-
-\newcounter{last@subpart}
-\def\find@subpart{%
- % We now know that this part has at least one subpart.
- % We'll find its highest numbered subpart by setting last@subpart
- % equal to 2 and then calling \find@lastsubpart to recursively
- % test whether that subpart number exists and, if so, incrementing
- % last@subpart to test for a higher numbered one:
- \setcounter{last@subpart}{2}%
- \find@lastsubpart
- % Now: See if this subpart has any subsubparts. (It has one or more
- % subsubparts if and only if it has a subsubpart numbered 1.)
- \@ifundefined{Pg@subsubpart@\thelatest@ques
- @\thelast@part @\thelast@subpart @1}%
- {%
- % Nope; no subsubparts
- \setcounter{ques@end}{\PgInfo@get{subpart@\thelatest@ques
- @\thelast@part @\thelast@subpart}}%
+ {\addtocounter{last@object}{1}%
+ \let\nextfind@lastobject=\find@lastobject
}%
- {\find@subsubpart}%
-}
+ \nextfind@lastobject
+}% find@lastobject
-\def\find@lastsubpart{%
- % We check whether this part has a subpart numbered last@subpart
- % and recursively increment last@subpart to find the highest
- % numbered value for which the subpart exists:
- \@ifundefined{Pg@subpart@\thelatest@ques
- @\thelast@part @\thelast@subpart}%
- {\addtocounter{last@subpart}{-1}%
- \let\nextfind@lastsubpart=\relax
- }%
- {\addtocounter{last@subpart}{1}%
- \let\nextfind@lastsubpart=\find@lastsubpart
- }%
- \nextfind@lastsubpart
-}
-
-\newcounter{last@subsubpart}
-\def\find@subsubpart{%
- % We now know that this subpart has at least one subsubpart.
- % We'll find its highest numbered subsubpart by setting last@subsubpart
- % equal to 2 and then calling \find@lastsubsubpart to recursively
- % test whether that subsubpart number exists and, if so, incrementing
- % last@subsubpart to test for a higher numbered one:
- \setcounter{last@subsubpart}{2}%
- \find@lastsubsubpart
- \setcounter{ques@end}{\PgInfo@get{subsubpart@\thelatest@ques
- @\thelast@part @\thelast@subpart @\thelast@subsubpart}}%
-}
-
-\def\find@lastsubsubpart{%
- % We check whether this subpart has a subsubpart numbered last@subsubpart
- % and recursively increment last@subsubpart to find the highest
- % numbered value for which the subsubpart exists:
- \@ifundefined{Pg@subsubpart@\thelatest@ques
- @\thelast@part @\thelast@subpart @\thelast@subsubpart}%
- {\addtocounter{last@subsubpart}{-1}%
- \let\nextfind@lastsubsubpart=\relax
- }%
- {\addtocounter{last@subsubpart}{1}%
- \let\nextfind@lastsubsubpart=\find@lastsubsubpart
- }%
- \nextfind@lastsubsubpart
-}
%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+%--------------------------------------------------------------------
+
\newcounter{incmp@ques}
\def\IncompleteQuestion{%
@@ -2497,7 +2268,6 @@
\fi
}
-
\def\ifincomplete#1#2{%
\def\incomp@first{#1}%
\def\incomp@second{#2}%
@@ -2516,27 +2286,6 @@
\fi
}
-
-
-
-%---------------------------------------------------------------------
-%
-% ***************************
-% ** QUESTION ENVIRONMENTS **
-% ***************************
-%
-%
-%
-
-% We define the command \part only inside of a parts environment, so
-% that we don't interfere with the meaning of the standard article
-% documentclass command \part if that is used inside of a questions
-% environment. The commands \question, \subpart, and \subsubpart are
-% defined everywhere inside of a questions environment. If the user
-% accidentally gives a \subpart command outside of a subparts
-% environment, then an error will be created.
-
-
%--------------------------------------------------------------------
% These are the commands for dealing with hlfcntr's, i.e., the things
% used to count points.
@@ -2549,12 +2298,14 @@
%
% The commands:
%
+% \new@hlfcntr{countername}
% \set@hlfcntr{countername}{value}
% \copy@hlfcntr{tocounter}{fromcounter}
% \addto@hlfcntr{countername}{value}
-% \add@hlfcntrtohlfcntr
+% \add@hlfcntrtohlfcntr{getsaddedto}{whatsadded}
% \ifhlfcntr@pos{countername}
% \prtaux@hlfcntr{countername}
+% \prt@hlfcntr{countername}
%
% ``value'' can be either a (nonnegative) integer, an integer followed by
% ``\half'', or just plain ``\half''. (Actually, ``value'' can be empty
@@ -2576,52 +2327,66 @@
% \ifsomething) aren't. Thus, we need to say ``\global'' when setting
% these things.
+% To create a hlfcntr:
+\newcommand*\new@hlfcntr[1]{%
+ \newcounter{#1}%
+ \expandafter\newif\csname if#1@half\endcsname
+}% new@hlfcntr
+
+
% A scratch hlfcntr:
-\newcounter{tmp@hlfcntr}
-\newif\iftmp@hlfcntr@half
+\new@hlfcntr{tmp@hlfcntr}
\newcommand*\horiz@half{$\frac{1}{2}$}
\newcommand*\slanted@half{%
$\raise0.6ex\hbox{$\scriptstyle 1$}\kern -.2em/\kern -.2em
\raise-0.5ex\hbox{$\scriptstyle 2$}$%
-}
-\newcommand*\useslantedhalf{\let\half\slanted@half}
-\newcommand*\usehorizontalhalf{\let\half\horiz@half}
+}% slanted@half
+\newcommand*\useslantedhalf{\global\let\half\slanted@half}
+\newcommand*\usehorizontalhalf{\global\let\half\horiz@half}
\newcommand*\half{\slanted@half}
\newcommand*\set@hlfcntr[2]{%
\begingroup
- \expandafter\global\csname #1@halffalse\endcsname
+ \global\csname #1@halffalse\endcsname
% If there as a `\half' present, it will be executed
% right after the assignment of the digit part of #2
% to the counter #1.
\def\half{%
- \expandafter\global\csname #1@halftrue\endcsname
+ \global\csname #1@halftrue\endcsname
}%
% We insert a `0' in case there are no digits present:
- \setcounter{#1}{0#2}\relax
+ % We avoid using \setcounter, because calc.sty redefines
+ % \setcounter in a way that conflicts with the \half trick
+ % we're using:
+ % \setcounter{#1}{0#2}\relax
+ \global\csname c@#1\endcsname 0#2\relax
\endgroup
-}
+}% set@hlfcntr
\newcommand*\copy@hlfcntr[2]{%
% We set #1 to the value of #2
\setcounter{#1}{\value{#2}}%
\csname if#2@half\endcsname
- \expandafter\global\csname #1@halftrue\endcsname
+ \global\csname #1@halftrue\endcsname
\else
- \expandafter\global\csname #1@halffalse\endcsname
+ \global\csname #1@halffalse\endcsname
\fi
-}
+}% copy@hlfcntr
\newcommand*\addto@hlfcntr[2]{%
% We add the valueandhalf #2 to hlfcntr #1
\begingroup
\def\half{\add@half{#1}}%
% We insert a `0' in case there are no digits present:
- \addtocounter{#1}{0#2}\relax
+ % We avoid using \addtocounter, because calc.sty redefines
+ % \addtocounter in a way that conflicts with the \half trick
+ % we're using:
+ % \addtocounter{#1}{0#2}\relax
+ \global\advance\csname c@#1\endcsname 0#2\relax
\endgroup
-}
+}% addto@hlfcntr
\newcommand*\add@hlfcntrtohlfcntr[2]{%
% We add the hlfcntr #2 to the hlfcntr #1
@@ -2629,17 +2394,17 @@
\csname if#2@half\endcsname
\add@half{#1}%
\fi
-}
+}% add@hlfcntrtohlfcntr
\newcommand*\add@half[1]{%
% We add one half to hlfcntr #1:
\csname if#1@half\endcsname
\addtocounter{#1}{1}%
- \expandafter\global\csname #1@halffalse\endcsname
+ \global\csname #1@halffalse\endcsname
\else
- \expandafter\global\csname #1@halftrue\endcsname
+ \global\csname #1@halftrue\endcsname
\fi
-}
+}% add@half
\newcounter{ifpos@cntr}
\def\ifhlfcntr@pos#1{%
@@ -2651,7 +2416,7 @@
\addtocounter{ifpos@cntr}{1}%
\fi
\ifnum \value{ifpos@cntr} > 0
-}
+}% ifhlfnctr@pos
% \prtaux@hlfcntr is used inside the argument of a \write command for
% writing to the .aux file:
@@ -2670,20 +2435,68 @@
% there's no \if visible until the \csname is expanded:
\prtaux@halforblank{#1}%
\fi
-}
+}% prtaux@hlfcntr
\newcommand*\prtaux@halforzero[1]{%
\csname if#1@half\endcsname
\string\half
\else
0%
\fi
-}
+}% prtaux@hlforzero
\newcommand*\prtaux@halforblank[1]{%
\csname if#1@half\endcsname
\string\half
\fi
-}
+}% prtaux@halforblank
+
+\newcommand*\prt@hlfcntr[1]{%
+ % We don't want a \relax after the 0 in the following
+ % line, because it would sometimes appear in the aux file:
+ \ifnum \value{#1} = 0
+ % We have to make the following a macro, because if we
+ % don't do this part, the \fi will cause confusion, since
+ % there's no \if visible until the \csname is expanded:
+ \prt@halforzero{#1}%
+ \else
+ \arabic{#1}%
+ % We have to make the following a macro, because if we
+ % don't do this part, the \fi will cause confusion, since
+ % there's no \if visible until the \csname is expanded:
+ \prt@halforblank{#1}%
+ \fi
+}% prt@hlfcntr
+\newcommand*\prt@halforzero[1]{%
+ \csname if#1@half\endcsname
+ \half
+ \else
+ 0%
+ \fi
+}% prt@hlforzero
+\newcommand*\prt@halforblank[1]{%
+ \csname if#1@half\endcsname
+ \half
+ \fi
+}% prt@halforblank
+
+% End of the commands for dealing with hlfcntr's
+
%--------------------------------------------------------------------
+%---------------------------------------------------------------------
+%
+% ***************************
+% ** QUESTION ENVIRONMENTS **
+% ***************************
+%
+%
+%
+
+% We define the command \part only inside of a parts environment, so
+% that we don't interfere with the meaning of the standard article
+% documentclass command \part if that is used inside of a questions
+% environment. The commands \question, \subpart, and \subsubpart are
+% defined everywhere inside of a questions environment. If the user
+% accidentally gives a \subpart command outside of a subparts
+% environment, then an error will be created.
@@ -2697,12 +2510,14 @@
\newcounter{subpart}
\newcounter{subsubpart}
\newcounter{choice}
-\newcounter{numpoints}
-\newif\ifnumpoints@half
+\new@hlfcntr{numpoints}
\set@hlfcntr{numpoints}{0}
-\newcounter{pointsof@thisquestion}
-\newif\ifpointsof@thisquestion@half
+\new@hlfcntr{numbonuspoints}
+\set@hlfcntr{numbonuspoints}{0}
+\new@hlfcntr{pointsof@thisquestion}
\set@hlfcntr{pointsof@thisquestion}{0}
+\new@hlfcntr{bonuspointsof@thisquestion}
+\set@hlfcntr{bonuspointsof@thisquestion}{0}
\newcounter{numquestions}
\newcounter{numparts}
\newcounter{numsubparts}
@@ -2710,19 +2525,22 @@
\newcounter{Curr@Page}
% @pagepoints accumulates the points on a single page:
-\newcounter{@pagepoints}
-\newif\if@pagepoints@half
-%\setcounter{@pagepoints}{0}
+\new@hlfcntr{@pagepoints}
\set@hlfcntr{@pagepoints}{0}
+\new@hlfcntr{@pagebonuspoints}
+\set@hlfcntr{@pagebonuspoints}{0}
\newcounter{pageof@pagepoints}
\setcounter{pageof@pagepoints}{0}
+\newcounter{pageof@pagebonuspoints}
+\setcounter{pageof@pagebonuspoints}{0}
% latest@points is a holding area for points until we know
% whether they'll land on the same page as the points
% currently counted in @pagepoints:
-\newcounter{latest@points}
-\newif\iflatest@points@half
+\new@hlfcntr{latest@points}
\set@hlfcntr{latest@points}{0}
+\new@hlfcntr{latest@bonuspoints}
+\set@hlfcntr{latest@bonuspoints}{0}
% Whenever we meet a new page on which points are defined, we'll
% redefine \page@withpoints to expand to that page. At the end of the
@@ -2730,10 +2548,11 @@
% a \gdef\lastpage@withpoints command to the .aux file.
% We initialize \page@withpoints here:
\def\page@withpoints{0}%
+\def\page@withbonuspoints{0}%
% \pageinfo@commands is used by each question, part, subpart, and
% subsubpart to insert into everypar the \PgInfo@write command to put
-% its page number inot the .aux file, the \PgInfo@get command to read
+% its page number into the .aux file, the \PgInfo@get command to read
% the page number into the counter Curr@Page, and to test and set
% \Contin@\theCurr@Page. \temp@toks is used by part, subpart, and
% subsubpart to append all that to \pageinfo@commands, rather than
@@ -2760,7 +2579,7 @@
$\rho$\or $\sigma$\or $\tau$\or $\upsilon$\or $\phi$\or $\chi$\or
$\psi$\or $\omega$\else \@ctrerr
\fi
-}%
+}% lc@greek
% The following macros are a variation on a trick from Victor
@@ -2773,24 +2592,26 @@
\def\prepend@toklist#1#2{%
\edef\do@it{\noexpand#1={\the#2\the#1}}%
\do@it
-}%
+}% prepend@toklist
\def\append@toklist#1#2{%
\edef\do@it{\noexpand#1={\the#1\the#2}}%
\do@it
-}%
+}% append@toklist
% The command \qformat is provided for the user who wants to
% design a nonstandard question line. If this command is used,
-% then the usual line containing the question numbers will be
-% replaced by the line specified by the \qformat command.
+% then the usual line containing the question number and the beginning
+% of the question will be replaced by the line specified by the
+% \qformat command, and the question will begin on the following
+% line.
% Within the argument of the \qformat command:
% \thequestion will be replaced by the question number, and
% \thepoints will be replaced by ``\@points \@pointname'' if the
% number of points has been specified for this question, and otherwise
% it inserts nothing at all. (The conditional @placepoints is used to
-% determine if the number of points is nonzero.)
+% determine if there were points specified for this question.)
% The argument to the \qformat command *must* contain some
% stretch, i.e., at least one \hfil or \dotfill or ...
\newif\if@qformat
@@ -2799,17 +2620,43 @@
\def\qformat#1{%
\global\@qformattrue
\gdef\@questionformat{#1}%
-}
+}% qformat
\newcommand\noqformat{%
\global\@qformatfalse
-}
-
+}% noqformat
+
+% \thepoints is for use in either a \qformat command
+% or a \pointformat command. It needs to have the
+% \if@placepoints so that if it's used in a \qformat command
+% it won't print anything if there are no points:
+%\newcommand\thepoints{%
+% \if@placepoints
+% \@points \@pointname
+% \fi
+%}
\newcommand\thepoints{%
\if@placepoints
- \@points \@pointname
+ \if@bonus
+ \@points \@bonuspointname
+ \else
+ \@points \@pointname
+ \fi
\fi
-}
+}% thepoints
+
+% \themarginpoints is for use only in a \pointformat command,
+% and so it doesn't need the \if@placepoints bit in \thepoints:
+%\newcommand\themarginpoints{%
+% \@points \@marginpointname
+%}% themarginpoints
+\newcommand\themarginpoints{%
+ \if@bonus
+ \@points \@marginbonuspointname
+ \else
+ \@points \@marginpointname
+ \fi
+}% themarginpoints
% We define the \subpart and \subsubpart commands when we enter a
% questions environment (rather than waiting until we enter a subparts
@@ -2819,6 +2666,31 @@
% can use the standard sectioning \part command outside of a parts
% environment.)
+% The counter ques@object will count the items in each question, where
+% an item is defined as either the question itself, or a part, or a
+% subpart, or a subsubpart, or a choice. This will be used by
+% \find@quesend to find the last page occupied by the last question
+% begun on or before the current page:
+\newcounter{ques@object}
+
+% if@bonus will be true when we're doing a bonusquestion or bonuspart
+% or etc., and it will also be used also to distinguish between
+% \gradetable and \bonusgradetable (and between \pointtable and
+% \bonuspointtable, etc.):
+\newif\if@bonus
+\@bonusfalse
+
+% The following are for advanced users who want to customize the list
+% parameters (\topsep, \partopsep, \itemsep, \parsep, etc.) for the
+% lists that these environments create. They are all defined to be
+% empty, but the user can change them using \renewcommand.
+\newcommand\questionshook{}
+\newcommand\partshook{}
+\newcommand\subpartshook{}
+\newcommand\subsubpartshook{}
+\newcommand\choiceshook{}
+
+
\newenvironment{questions}{%
% \@queslevel is used for two purposes:
% (1) We check that every \question, \part, \subpart, and
@@ -2829,7 +2701,29 @@
% \global \point@toks={} to avoid setting the points for a
% question other than via the qformat command.
\def\@queslevel{question}%
+ \def\titledquestion##1{%
+ \@bonusfalse
+ \def\thequestiontitle{##1}%
+ \process@question
+ }%
+ \def\bonustitledquestion##1{%
+ \@bonustrue
+ \def\thequestiontitle{##1}%
+ \process@question
+ }%
\def\question{%
+ \@bonusfalse
+ \def\thequestiontitle{\csname p@question\endcsname
+ \csname thequestion\endcsname}%
+ \process@question
+ }%
+ \def\bonusquestion{%
+ \@bonustrue
+ \def\thequestiontitle{\csname p@question\endcsname
+ \csname thequestion\endcsname}%
+ \process@question
+ }%
+ \def\process@question{%
\if@coverpages
\cover@question@error
\fi
@@ -2841,38 +2735,35 @@
% number of the question that was just completed.)
\if@filesw
\ifnum \arabic{question} > 0\relax
+ % First do regular points:
\immediate\write\@mainaux
{\string\gdef\string\pointsofq@
\romannumeral \csname c@question\endcsname
{\prtaux@hlfcntr{pointsof@thisquestion}}}%
% See if this has changed from the last run of LaTeX:
- \@ifundefined{pointsofq@\romannumeral
+ \CheckIfChanged@hlf{pointsof@thisquestion}{pointsofq@\romannumeral
\csname c@question\endcsname}%
- {\global\@pointschangedtrue}%
- {%
- % OK; it's defined. See if it's changed:
- \begingroup
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsofq@\romannumeral
- \csname c@question\endcsname\endcsname}%
- \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
- \edef\pt@check{\prtaux@hlfcntr{pointsof@thisquestion}}%
- \ifx \pt@check \othpt@check
- % Do nothing
- \else
- \global\@pointschangedtrue
- \fi
- \endgroup
- }%
+ % Now do bonus points:
+ \immediate\write\@mainaux
+ {\string\gdef\string\bonuspointsofq@
+ \romannumeral \csname c@question\endcsname
+ {\prtaux@hlfcntr{bonuspointsof@thisquestion}}}%
+ % See if this has changed from the last run of LaTeX:
+ \CheckIfChanged@hlf{bonuspointsof@thisquestion}%
+ {bonuspointsofq@\romannumeral
+ \csname c@question\endcsname}%
\fi
\fi
\set@hlfcntr{pointsof@thisquestion}{0}%
+ \set@hlfcntr{bonuspointsof@thisquestion}{0}%
% If there was a question with points immediately preceding
% this question (i.e., there were no parts in the previous
% question), then @placepoints will still be true, and we need to
% cancel it. (We used to do this inside of the \thepoints macro,
% but that allowed for an error if the user specified points for a
% question but had a \qformat that didn't mention \thepoints.) We
- % also set @placepoints to be false in the \part command.
+ % also set @placepoints to be false when entering a parts
+ % environment.
\global \@placepointsfalse
% point@toks will normally be empty at this point, but it might be
% nonempty if there were points somewhere in the previous question
@@ -2888,10 +2779,47 @@
\pageinfo@commands={%
\edef\@queslabel{question@\arabic{question}}%
\PgInfo@write{\@queslabel}%
+ \setcounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ % In addition to the \PgInfo@write we use an actual \label
+ % command. We do this in order to make the question numbers in
+ % the grade tables into \ref's, so that if the user says
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ %
+ % Further futzing required: Since this is being put into the
+ % token list \pageinfo@commands, the contents of which won't
+ % actually be executed until we enter horizontal mode (which
+ % may well be in the first part of a parts environment), we need
+ % to make sure that \@currentlabel is the number of the
+ % question:
+ \begingroup % to confine the change to \@currentlabel
+% \def\@currentlabel{\csname p@question\endcsname
+% \csname thequestion\endcsname}%
+ \def\@currentlabel{\thequestiontitle}%
+ \label{\@queslabel}%
+ \endgroup
\set@counter@to@pageof{Curr@Page}{\@queslabel}%
\expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- % We're the first \question, \part, \subpart, or \subsubpart
- % on this page:
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
\global\expandafter\edef
\csname Contin@\theCurr@Page\endcsname{\relax}%
\fi
@@ -2904,8 +2832,17 @@
\unskip\unskip \par
\fi
\@doitem
- }% question
+ }% process@question
\def\subpart{%
+ \@bonusfalse
+ \process@subpart
+ }%
+ \def\bonussubpart{%
+ \@bonustrue
+ \process@subpart
+ }%
+ \def\process@subpart{%
+ \@bonusfalse
\if@coverpages
\cover@question@error
\fi
@@ -2919,10 +2856,35 @@
\edef\@subpartlabel{subpart@\arabic{question}%
@\arabic{partno}@\arabic{subpart}}%
\PgInfo@write{\@subpartlabel}%
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ % In addition to the \PgInfo@write we use an actual \label
+ % command. We do this in order to make the question numbers in
+ % the grade tables into \ref's, so that if the user says
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ \label{\@subpartlabel}%
\set@counter@to@pageof{Curr@Page}{\@subpartlabel}%
\expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- % We're the first \question, \part, \subpart, or \subsubpart
- % on this page:
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
\global\expandafter\edef\csname
Contin@\theCurr@Page\endcsname{\arabic{question}}%
\fi
@@ -2936,8 +2898,17 @@
\unskip\unskip \par
\fi
\@doitem
- }% subpart
+ }% process@subpart
\def\subsubpart{%
+ \@bonusfalse
+ \process@subsubpart
+ }%
+ \def\bonussubsubpart{%
+ \@bonustrue
+ \process@subsubpart
+ }%
+ \def\process@subsubpart{%
+ \@bonusfalse
\if@coverpages
\cover@question@error
\fi
@@ -2951,10 +2922,35 @@
\edef\@subsubpartlabel{subsubpart@\arabic{question}%
@\arabic{partno}@\arabic{subpart}@\arabic{subsubpart}}%
\PgInfo@write{\@subsubpartlabel}%
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ % In addition to the \PgInfo@write we use an actual \label
+ % command. We do this in order to make the question numbers in
+ % the grade tables into \ref's, so that if the user says
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ \label{\@subsubpartlabel}%
\set@counter@to@pageof{Curr@Page}{\@subsubpartlabel}%
\expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
- % We're the first \question, \part, \subpart, or \subsubpart
- % on this page:
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
\global\expandafter\edef\csname
Contin@\theCurr@Page\endcsname{\arabic{question}}%
\fi
@@ -2968,7 +2964,7 @@
\unskip\unskip \par
\fi
\@doitem
- }% subsubpart
+ }% process@subsubpart
\list{\question@number}%
{\usecounter{question}%
% We use the default definition of \makelabel
@@ -2977,39 +2973,36 @@
\settowidth{\leftmargin}{10.\hskip\labelsep}%
\labelwidth\leftmargin\advance\labelwidth-\labelsep
\partopsep=0pt
+ \questionshook
}%
- }%
+ }% End of the first argument of \newenvironment{questions}
{%
\endlist
% Write the number of points of the final question
% to the .aux file:
\if@filesw
\ifnum \arabic{question} > 0\relax
+ % First do the regular points:
\immediate\write\@mainaux
{\string\gdef\string\pointsofq@\romannumeral
\csname c@question\endcsname
{\prtaux@hlfcntr{pointsof@thisquestion}}}%
% See if this has changed from the last run of LaTeX:
- \@ifundefined{pointsofq@\romannumeral
+ \CheckIfChanged@hlf{pointsof@thisquestion}%
+ {pointsofq@\romannumeral
+ \csname c@question\endcsname}%
+ % Now do the bonus points:
+ \immediate\write\@mainaux
+ {\string\gdef\string\bonuspointsofq@\romannumeral
+ \csname c@question\endcsname
+ {\prtaux@hlfcntr{bonuspointsof@thisquestion}}}%
+ % See if this has changed from the last run of LaTeX:
+ \CheckIfChanged@hlf{bonuspointsof@thisquestion}%
+ {bonuspointsofq@\romannumeral
\csname c@question\endcsname}%
- {\global\@pointschangedtrue}%
- {%
- % OK; it's defined. See if it's changed:
- \begingroup
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsofq@\romannumeral
- \csname c@question\endcsname\endcsname}%
- \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
- \edef\pt@check{\prtaux@hlfcntr{pointsof@thisquestion}}%
- \ifx \pt@check \othpt@check
- % Do nothing
- \else
- \global\@pointschangedtrue
- \fi
- \endgroup
- }%
\fi
\fi
- }
+ }% End of the second argument of \newenvironment{questions}
% \question@number is used as the label in the question list (instead
% of \questionlabel) so that if the user uses a \qformat command,
@@ -3031,8 +3024,8 @@
\newenvironment{parts}{%
\def\@queslevel{part}%
% If the question numbers are being inserted via a \qformat,
- % and if a question is beginning with a parts environmnt, then
- % we need to enter horizonal mode to the the qformat printed
+ % and if a question is beginning with a parts environment, then
+ % we need to enter horizonal mode to get the qformat printed
% on the page, rather than saving up the question label (and
% possible points) to be combined with the label of the first
% part. (\if@inlabel tells us if we are still waiting to enter
@@ -3052,6 +3045,14 @@
\global \@placepointsfalse
\fi
\def\part{%
+ \@bonusfalse
+ \process@part
+ }%
+ \def\bonuspart{%
+ \@bonustrue
+ \process@part
+ }%
+ \def\process@part{%
\if@coverpages
\cover@question@error
\fi
@@ -3064,6 +3065,31 @@
\temp@toks={%
\edef\@partlabel{part@\arabic{question}@\arabic{partno}}%
\PgInfo@write{\@partlabel}%
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ % In addition to the \PgInfo@write we use an actual \label
+ % command. We do this in order to make the question numbers in
+ % the grade tables into \ref's, so that if the user says
+ % \usepackage{hyperref}, those question numbers will be clickable.
+ %
+ % A further purpose of these labels (which we actually do for all
+ % questions, parts, subparts, and subsubparts) is that if a
+ % question (or part, etc.) is, e.g., moved from one page to
+ % another, LaTeX will notice this and warn the user that LaTeX
+ % must be run one more time to be sure everything is correct.
+ %
+ % We need to do this even though we've already included code to
+ % check when point totals change because questions (and parts,
+ % etc.) know what page they're on from reading the info written to
+ % the .aux file on the previous run. Thus, if a question (or
+ % part, etc.) is moved to a different page, then the pointsonpage
+ % totals won't notice until the *second* subsequent run of LaTeX,
+ % and so there'll be no warning to the user on the *first* run.
+ % Including these labels gives the user a warning on that first
+ % run.
+ \label{\@partlabel}%
\set@counter@to@pageof{Curr@Page}{\@partlabel}%
\expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
\global\expandafter\edef\csname
@@ -3079,7 +3105,7 @@
\unskip\unskip \par
\fi
\@doitem
- }% part
+ }% process@part
\list{\partlabel}%
{%
\usecounter{partno}\def\makelabel##1{\hss\llap{##1}}%
@@ -3087,6 +3113,7 @@
\labelwidth\leftmargin\advance\labelwidth-\labelsep
\topsep=0pt
\partopsep=0pt
+ \partshook
}%
}% newenvironment{parts}
{\endlist}
@@ -3102,6 +3129,7 @@
\labelwidth\leftmargin\advance\labelwidth-\labelsep
\topsep=0pt
\partopsep=0pt
+ \subpartshook
}%
}%
{\endlist}
@@ -3117,6 +3145,7 @@
\labelwidth\leftmargin\advance\labelwidth-\labelsep
\topsep=0pt
\partopsep=0pt
+ \subsubpartshook
}%
}%
{\endlist}
@@ -3124,6 +3153,8 @@
\def\thesubsubpart{\greeknum{subsubpart}}
+
+
\pagepoint@commands={%
\ifhlfcntr@pos{latest@points}%
% We're putting a question (or part, etc.)
@@ -3139,27 +3170,17 @@
\romannumeral \csname c@pageof@pagepoints\endcsname
{\prtaux@hlfcntr{@pagepoints}}}%
% See if this has changed from the last run of LaTeX:
- \@ifundefined{pointsonpage@\romannumeral
+ \CheckIfChanged@hlf{@pagepoints}{pointsonpage@\romannumeral
\csname c@pageof@pagepoints\endcsname}%
- {\global\@pointschangedtrue}%
- {%
- % OK; it's defined. See if it's changed:
- \begingroup
- \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@pageof@pagepoints\endcsname\endcsname}%
- \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
- \edef\pt@check{\prtaux@hlfcntr{@pagepoints}}%
- \ifx \pt@check \othpt@check
- % Do nothing
- \else
- \global\@pointschangedtrue
- \fi
- \endgroup
- }%
\fi
% The following is a macro because \theCurr@Page and
% \thepageof@pagepoints might differ by more than 1:
\increment@pageof@pagepoints
+ % The following label is so that we can make the page
+ % numbers in a grade table indexed by page into \pageref's
+ % so that \usepackage{hyperref} and pdflatex will
+ % make them clickable:
+ \label{firstpoints@onpage@\arabic{Curr@Page}}%
\else
% These points go on the same page as the points
% currently counted in @pagepoints:
@@ -3167,7 +3188,40 @@
\set@hlfcntr{latest@points}{0}%
\fi
\fi
-}
+ \ifhlfcntr@pos{latest@bonuspoints}%
+ % We're putting a question (or part, etc.)
+ % with bonus points onto this page:
+ \ifnum \theCurr@Page > \thepageof@pagebonuspoints\relax
+ % These bonus points go on a later page than
+ % the points currently counted in @pagebonuspoints:
+ \ifnum \thepageof@pagebonuspoints = 0\relax
+ % Do nothing...
+ \else
+ \immediate\write\@mainaux
+ {\string\gdef\string\bonuspointsonpage@
+ \romannumeral \csname c@pageof@pagebonuspoints\endcsname
+ {\prtaux@hlfcntr{@pagebonuspoints}}}%
+ % See if this has changed from the last run of LaTeX:
+ \CheckIfChanged@hlf{@pagebonuspoints}%
+ {bonuspointsonpage@\romannumeral
+ \csname c@pageof@pagebonuspoints\endcsname}%
+ \fi
+ % The following is a macro because \theCurr@Page and
+ % \thepageof@pagebonuspoints might differ by more than 1:
+ \increment@pageof@pagebonuspoints
+ % The following label is so that we can make the page
+ % numbers in a bonus grade table indexed by page into \pageref's
+ % so that \usepackage{hyperref} and pdflatex will
+ % make them clickable:
+ \label{firstbonuspoints@onpage@\arabic{Curr@Page}}%
+ \else
+ % These points go on the same page as the points
+ % currently counted in @pagebonuspoints:
+ \add@hlfcntrtohlfcntr{@pagebonuspoints}{latest@bonuspoints}%
+ \set@hlfcntr{latest@bonuspoints}{0}%
+ \fi
+ \fi
+}% pagepoint@commands
\def\increment@pageof@pagepoints{%
\addtocounter{pageof@pagepoints}{1}%
\ifnum \theCurr@Page > \thepageof@pagepoints\relax
@@ -3198,13 +3252,48 @@
\set@hlfcntr{latest@points}{0}%
% \page@withpoints will be used to find the last
% page that has points, which will be written to
- % the .aux file vis \AtEndDocument:
+ % the .aux file via \AtEndDocument:
\global\edef\page@withpoints{\thepageof@pagepoints}%
\let\next@incr@pageof = \relax
\fi
\next@incr@pageof
-}
-
+}% increment@pageof@pagepoints
+\def\increment@pageof@pagebonuspoints{%
+ \addtocounter{pageof@pagebonuspoints}{1}%
+ \ifnum \theCurr@Page > \thepageof@pagebonuspoints\relax
+ \immediate\write\@mainaux
+ {\string\gdef\string\bonuspointsonpage@
+ \romannumeral \csname c@pageof@pagebonuspoints\endcsname{0}}%
+ % See if this has changed from the last run of LaTeX:
+ \@ifundefined{bonuspointsonpage@\romannumeral
+ \csname c@pageof@pagebonuspoints\endcsname}
+ {\global\@pointschangedtrue}%
+ {%
+ % OK; it's defined. See if it's changed:
+ \begingroup
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@pageof@pagebonuspoints\endcsname\endcsname}%
+ \edef\othpt@check{\prtaux@hlfcntr{tmp@hlfcntr}}%
+ \def\pt@check{0}%
+ \ifx \pt@check \othpt@check
+ % Do nothing
+ \else
+ \global\@pointschangedtrue
+ \fi
+ \endgroup
+ }%
+ \let\next@incr@pageof = \increment@pageof@pagebonuspoints
+ \else
+ \copy@hlfcntr{@pagebonuspoints}{latest@bonuspoints}%
+ \set@hlfcntr{latest@bonuspoints}{0}%
+ % \page@withbonuspoints will be used to find the last
+ % page that has bonus points, which will be written to
+ % the .aux file via \AtEndDocument:
+ \global\edef\page@withbonuspoints{\thepageof@pagebonuspoints}%
+ \let\next@incr@pageof = \relax
+ \fi
+ \next@incr@pageof
+}% increment@pageof@pagebonuspoints
@@ -3241,46 +3330,29 @@
\def\@points{#1}%
\global \@placepointstrue
\if@addpoints
- \addto@hlfcntr{numpoints}{\@points}%
- \addto@hlfcntr{pointsof@thisquestion}{\@points}%
- % latest@points is a holding area for points to be
- % added to @pagepoints after we check whether they're
- % on the same page as the points currently counted
- % by @pagepoints:
- \addto@hlfcntr{latest@points}{\@points}%
+ \if@bonus
+ \addto@hlfcntr{numbonuspoints}{\@points}%
+ \addto@hlfcntr{bonuspointsof@thisquestion}{\@points}%
+ % latest@bonuspoints is a holding area for bonus points to be
+ % added to @pagepoints after we check whether they're
+ % on the same page as the points currently counted
+ % by @pagepoints:
+ \addto@hlfcntr{latest@bonuspoints}{\@points}%
+ \else
+ \addto@hlfcntr{numpoints}{\@points}%
+ \addto@hlfcntr{pointsof@thisquestion}{\@points}%
+ % latest@points is a holding area for points to be
+ % added to @pagepoints after we check whether they're
+ % on the same page as the points currently counted
+ % by @pagepoints:
+ \addto@hlfcntr{latest@points}{\@points}%
+ \fi
\fi
\item@points@pageinfo
}
-% do@int@lbl is the command used to create a label for every question,
-% part, subpart, and subsubpart. We make no use of these labels, but we
-% put them there so that if a question (or part, etc.) is, e.g., moved
-% from one page to another, LaTeX will notice this and warn the user
-% that LaTeX must be run one more time to be sure everything is correct.
-%
-% We need to do this even though we've already included code to check
-% when point totals change because questions (and parts, etc.) know what
-% page they're on from reading the info written to the .aux file on the
-% previous run. Thus, if a question (or part, etc.) is moved to a
-% different page, then the pointsonpage totals won't notice until the
-% *second* subsequent run of LaTeX, and so there'll be no warning to the
-% user on the *first* run. Including these labels gives the user a
-% warning on that first run.
-
-\newcounter{lbl@cntr}
-\def\do@int@lbl{%
- \addtocounter{lbl@cntr}{1}%
- % Looking at latex.ltx reveals that the argument to \label is
- % expanded, so we don't really need the \expandafter's in the
- % following, but I haven't seen any statement anywhere in
- % documentation about it being expanded, so we'll be paranoid and
- % protect against future changes in latex.ltx by using
- % \expandafter's:
- \expandafter\label\expandafter{\thelbl@cntr @@exam@lbl}%
-}
-
% Bug fix, 5 April 2004: \item@points@pageinfo
% Appending \point@toks and \pageinfo@commands to \everypar:
@@ -3298,10 +3370,10 @@
% Since we've put the command \global \point@toks={} inside of
% \point@toks and the command \pageinfo@commands={} inside of
% \pageinfo@commands, when the contents of \point@toks and of
-% \pageinfo@commands are executed when we enter horizontal mode and
-% \everypar is dumped in, the contents of \point@toks and
+% \pageinfo@commands are executed (when we enter horizontal mode and
+% \everypar is dumped in), the contents of \point@toks and
% \pageinfo@commands will be made empty, and so if
-% the second paragraph also get \the\point@toks and
+% the second paragraph also gets \the\point@toks and
% \the\pageinfo@commands, it won't matter.
\def\item@points@pageinfo{%
@@ -3327,12 +3399,42 @@
\fi
\fi
\if@placepoints
- % \setup@point@toks defines \point@block to be a macro that prints
- % the points with the correct choice of parentheses, brackets, or
- % box, and \@pointname or \@marginpointname and puts commands into
- % \point@toks to place \point@block at the correct spot. It
- % doesn't append anything to \everypar (we do that in this macro,
- % below).
+ % Since we want the user to be able to say \thepoints in the
+ % argument to a \pointformat command, we need \@placepointstrue
+ % when \point@block is expanded so that \thepoints will actually
+ % print something. (After setting up \point@toks, we do
+ % \@placepointsfalse, but \point@block isn't actually expanded
+ % until we enter horizontal mode.) Thus, we define
+ % \padded@point@block, and use that instead of \point@block. We
+ % put \begingroup and \endgroup around this to confine the
+ % effect of \@placepointstrue and also to confine the effect of
+ % any declarations like, e.g., \bfseries that the user might put
+ % in the argument of a \pointformat command.
+ %
+ % Note: We first tried using an \edef to expand \point@block right
+ % here, while @placepoints is true, but that causes problems if
+ % the user puts a \boldmath declaration in the argument of a
+ % \pointformat command. Apparently, expanding \boldmath (without
+ % executing anything) gives you bunches of undefined control
+ % sequence errors.
+ \if@bonus
+ \def\padded@point@block{%
+ \begingroup
+ \@placepointstrue
+ \bonuspoint@block
+ \endgroup
+ }%
+ \else
+ \def\padded@point@block{%
+ \begingroup
+ \@placepointstrue
+ \point@block
+ \endgroup
+ }%
+ \fi
+ % \setup@point@toks puts commands into \point@toks to place
+ % \padded@point@block at the correct spot. It doesn't append
+ % anything to \everypar (we do that in this macro, below).
\if@pointsdropped
% Do nothing!
\else
@@ -3347,11 +3449,17 @@
% Also: It's important to do this *after* the \item command above,
% since the \item command discards the previous contents of
% \everypar.
- \edef\append@everypar{\noexpand\everypar={\the\everypar
- \noexpand\the \noexpand\pageinfo@commands
- \noexpand\the \noexpand\point@toks}}%
- \append@everypar
- \do@int@lbl
+ % Version 2.217-beta changes:
+ % Instead of appending stuff to \everypar, we insert
+ % \the \pageinfo@commands and \the \point@toks
+ % into the box \@labels:
+ \global\setbox\@labels\hbox{\unhbox\@labels
+ \the \pageinfo@commands
+ \the \point@toks}%
+ % \edef\append@everypar{\noexpand\everypar={\the\everypar
+ % \noexpand\the \noexpand\pageinfo@commands
+ % \noexpand\the \noexpand\point@toks}}%
+ % \append@everypar
}
@@ -3361,20 +3469,19 @@
% Initialize \@points:
-% (Now that I think of it, this seems totally unnecessary,
-% but we're not deleting it because we're chicken.)
+% (The only reason I think this is necessary is in case the user uses
+% a \qformat command, puts \themarginpoints into the format (which is
+% *not* the intended use of \themarginpoints), and then doesn't have
+% any points for the first question.)
\def\@points{0}
\def\setup@point@toks{%
-% We begin by defining \point@block so that it expands to the properly
-% formatted points (including either \pointname or \marginpointname,
-% enclosed in either parentheses, brackets, or a box). We then set
-% the token list \point@toks equal to the sequence of commands needed
-% to put \point@block at the correct location, followed by the tokens
-% ``\global \point@toks={}''. The \question, \part, \subpart, or
-% \subsubpart command then adds the two tokens ``\the\point@toks'' to
-% \everypar.
+% We set the token list \point@toks equal to the sequence of commands
+% needed to put \padded@point@block at the correct location, followed by the
+% tokens ``\global \point@toks={}''. The \question, \part, \subpart,
+% or \subsubpart command then adds the two tokens ``\the\point@toks''
+% to \everypar.
%
% Note: It is not the *contents* of \point@toks that is added to
% \everypar; just the two tokens ``\the\point@toks''. This difference
@@ -3394,17 +3501,9 @@
% tokens ``\the\point@toks'' will insert an *empty* token list, which
% will do no harm.
%
-%
-% \point@block consists of \point@string surrounded by either
-% parentheses, brackets, or an fbox.
-%
-% \point@string is either \@points\@pointname or
-% \@points\@marginpointname.
- \setup@point@block
\if@pointsinleftmargin
- \def\point@string{\@points\@marginpointname}%
\point@toks={%
- \llap{\point@block
+ \llap{\padded@point@block
\hskip\@totalleftmargin
\hskip\marginpointssep
}%
@@ -3412,21 +3511,19 @@
}%
\else
\if@pointsinrightmargin
- \def\point@string{\@points\@marginpointname}%
\point@toks={%
\rlap{\hskip-\@totalleftmargin
\hskip\textwidth
\hskip\@rightmargin
\hskip-\rightpointsmargin
- \llap{\point@block}%
+ \llap{\padded@point@block}%
}%
\global \point@toks={}%
}%
\else
% The points just go after the question number:
- \def\point@string{\@points\@pointname}%
\point@toks={%
- \point@block
+ \padded@point@block
\enspace
\global \point@toks={}%
}%
@@ -3435,47 +3532,19 @@
}% setup@point@toks
-\def\setup@point@block{%
- \if@boxedpoints
- \def\point@block{\fbox{\point@string}}%
- \else
- \if@bracketedpoints
- \def\point@block{[\point@string]}%
- \else
- % plain old parentheses:
- \def\point@block{(\point@string)}%
- \fi
- \fi
-}
\def\droppoints{%
- \def\point@string{\@points\@marginpointname}%
- \setup@point@block
\leavevmode\unskip\nobreak\hfill
\rlap{\hskip\rightmargin % Defined by the list environment
\hskip\@rightmargin % Defined by exam.cls
\hskip-\rightpointsmargin
- \llap{\point@block}%
+ \llap{\padded@point@block}%
}% rlap
\par
}
-% The following is the default definition.
-% It will be redefined if the user givea a \totalformat command.
-\def\setup@total@block{%
- \def\total@block{%
- Total for Question \thequestion: \totalpoints\@marginpointname
- }%
-}
-
-\def\totalformat#1{%
- \def\setup@total@block{\def\total@block{#1}}%
-}
-% The following is for use in the argument to a \totalformat command:
-\def\totalpoints{\pointsofquestion{\arabic{question}}}
\def\droptotalpoints{%
- \setup@total@block
\leavevmode\unskip\nobreak\hfill
\rlap{\hskip\rightmargin % Defined by the list environment
\hskip\@rightmargin % Defined by exam.cls
@@ -3483,7 +3552,36 @@
\llap{\total@block}%
}% rlap
\par
-}
+}% droptotalpoints
+\def\droptotalbonuspoints{%
+ \leavevmode\unskip\nobreak\hfill
+ \rlap{\hskip\rightmargin % Defined by the list environment
+ \hskip\@rightmargin % Defined by exam.cls
+ \hskip-\rightpointsmargin
+ \llap{\bonustotal@block}%
+ }% rlap
+ \par
+}% droptotalbonuspoints
+
+% The following is the default definition;
+% it can be changed by a \totalformat command.
+\def\total@block{%
+ Total for Question \thequestion: \totalpoints\@marginpointname
+}% total@block
+\def\bonustotal@block{%
+ Total for Question \thequestion: \totalbonuspoints\@marginbonuspointname
+}% bonustotal@block
+
+\def\totalformat#1{%
+ \gdef\total@block{\begingroup #1\endgroup}%
+}% totalformat
+\def\bonustotalformat#1{%
+ \gdef\bonustotal@block{\begingroup #1\endgroup}%
+}% bonustotalformat
+% The following is for use in the argument to a \totalformat command:
+\def\totalpoints{\pointsofquestion{\arabic{question}}}
+\def\totalbonuspoints{\bonuspointsofquestion{\arabic{question}}}
+
% @placepoints is set true when we encounter a question (or part, etc.)
@@ -3491,12 +3589,12 @@
% to the sequence of commands required to put the properly formatted
% points onto the page (this happens only if @qformat is false or if
% @qformat is true but we're not doing a question), or (2) by a
-% \question or \part command (since if we're doing a question and
-% @qformat is true, we need to leave @placepoints true so that the
-% \thepoints command can tell if it should expand to points or to
-% nothing, and encountering a \question or \part command tells us that
-% we no longer have to deal with a possible \thepoints, since we won't
-% be expanding a qformat).
+% \question command or entering a parts environment (since if we're
+% doing a question and @qformat is true, we need to leave @placepoints
+% true so that the \thepoints command can tell if it should expand to
+% points or to nothing, and encountering a \question command or parts
+% environment tells us that we no longer have to deal with a possible
+% \thepoints, since we won't be expanding a qformat).
\newif\if@placepoints
\@placepointsfalse
@@ -3519,39 +3617,72 @@
\newif\if@pointsinrightmargin
\def\pointsinleftmargin{\global\@pointsinleftmargintrue
\global\@pointsinrightmarginfalse
- \global\@pointsdroppedfalse}
+ \global\@pointsdroppedfalse
+ \gdef\pt@name{\@marginpointname}%
+ \gdef\bnspt@name{\@marginbonuspointname}}
\def\pointsinrightmargin{\global\@pointsinrightmargintrue
\global\@pointsinleftmarginfalse
- \global\@pointsdroppedfalse}
+ \global\@pointsdroppedfalse
+ \gdef\pt@name{\@marginpointname}%
+ \gdef\bnspt@name{\@marginbonuspointname}}
\def\nopointsinmargin{\global\@pointsinleftmarginfalse
\global\@pointsinrightmarginfalse
- \global\@pointsdroppedfalse}
+ \global\@pointsdroppedfalse
+ \gdef\pt@name{\@pointname}%
+ \gdef\bnspt@name{\@bonuspointname}}
\def\pointsdroppedatright{\global\@pointsdroppedtrue
\global\@pointsinleftmarginfalse
- \global\@pointsinrightmarginfalse}
+ \global\@pointsinrightmarginfalse
+ \gdef\pt@name{\@marginpointname}%
+ \gdef\bnspt@name{\@marginbonuspointname}}
\let\pointsinmargin\pointsinleftmargin
\let\nopointsinrightmargin\nopointsinmargin
\let\nopointsinleftmargin\nopointsinmargin
-
\nopointsinmargin
% Will the points be displayed inside parentheses (the default), or
-% will they be boxed or bracketed:
-\newif\if@boxedpoints
-\def\boxedpoints{\global\@boxedpointstrue \global\@bracketedpointsfalse}
-\def\noboxedpoints{\global\@boxedpointsfalse \global\@bracketedpointsfalse}
-\@boxedpointsfalse
+% will they be boxed or bracketed, or customized using pointformat:
+\def\boxedpoints{%
+ \gdef\point@block{\fbox{\@points\pt@name}}%
+ \gdef\bonuspoint@block{\fbox{\@points\bnspt@name}}%
+}
+\def\noboxedpoints{%
+ \gdef\point@block{(\@points\pt@name)}%
+ \gdef\bonuspoint@block{(\@points\bnspt@name)}%
+}
+\def\bracketedpoints{%
+ \gdef\point@block{[\@points\pt@name]}%
+ \gdef\bonuspoint@block{[\@points\bnspt@name]}%
+}
+\let\nobracketedpoints=\noboxedpoints
+
+\def\pointformat#1{%
+ % We don't have to worry about the user putting things
+ % like \bfseries, etc. into \point@block, because
+ % \padded@point@block encloses \point@block in a group,
+ % which confines the effects of anything here:
+ \gdef\point@block{#1}%
+}
+
+\def\bonuspointformat#1{%
+ % We don't have to worry about the user putting things
+ % like \bfseries, etc. into \point@block, because
+ % \padded@point@block encloses \point@block in a group,
+ % which confines the effects of anything here:
+ \gdef\bonuspoint@block{#1}%
+}
+\def\thebonuspoints{\@points \@bonuspointname}
+
+%Initialize:
+\noboxedpoints
-\newif\if@bracketedpoints
-\def\bracketedpoints{\global\@bracketedpointstrue \global\@boxedpointsfalse}
-\def\nobracketedpoints{\global\@bracketedpointsfalse \global\@boxedpointsfalse}
-\@bracketedpointsfalse
\def\pointname#1{\gdef\@pointname{#1}}
+\def\bonuspointname#1{\gdef\@bonuspointname{#1}}
% Initialize to leave a space, and then the word `points':
%%\pointname{ points}
% The following improvement was contributed by
@@ -3563,13 +3694,21 @@
% Note the space before the \points in the following; it's
% intentional!)
\pointname{ \points}
-
+\bonuspointname{ \bonuspoints}
\newcommand\point@sing{point}
\newcommand\point@plur{points}
\newcommand\pointpoints[2]{%
\renewcommand\point@sing{#1}%
\renewcommand\point@plur{#2}%
}
+%\newcommand\bonuspoint@sing{bonus point}
+%\newcommand\bonuspoint@plur{bonus points}
+\newcommand\bonuspoint@sing{point (bonus)}
+\newcommand\bonuspoint@plur{points (bonus)}
+\newcommand\bonuspointpoints[2]{%
+ \renewcommand\bonuspoint@sing{#1}%
+ \renewcommand\bonuspoint@plur{#2}%
+}
@@ -3590,7 +3729,15 @@
\ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half}}
{\point@sing}{\point@plur}%
\endgroup
-}
+}% \points
+\newcommand\bonuspoints{%
+ \begingroup
+ \let\half=\relax
+ \edef\pt@string{\@points}%
+ \ifthenelse{\equal{\pt@string}{1} \or \equal{\pt@string}{\half}}
+ {\bonuspoint@sing}{\bonuspoint@plur}%
+ \endgroup
+}% \bonuspoints
%\newcommand\points{%
% \begingroup
% \let\half=\relax
@@ -3613,7 +3760,10 @@
% except that it expands to either ``mark'' or ``marks'', but that
% conflicts with some package or other. Thus, we'll implement
% \marksnotpoints using the \pointpoints command instead:
-\newcommand\marksnotpoints{\pointpoints{mark}{marks}}
+\newcommand\marksnotpoints{%
+ \pointpoints{mark}{marks}%
+ \bonuspointpoints{mark (bonus)}{marks (bonus)}%
+}% \marksnotpoints
% \@marginpointname is used in place of \@pointname if any of
@@ -3621,25 +3771,10 @@
% true:
\def\marginpointname#1{\gdef\@marginpointname{#1}}
\marginpointname{}
+\def\marginbonuspointname#1{\gdef\@marginbonuspointname{#1}}
+\marginbonuspointname{ (bonus)}
-% The following keeps track of whether the user has requested that we
-% add up the points on the exam. We make the default false so that
-% users who put other than numbers into the points argument of a
-% question (or part, or subpart) won't get error messages.
-% We use \if@printtotalpoints as a flag to signal that we are counting
-% points, so that we will know to print the total on the screen (and
-% in the log file). We use this separate flag so that the user can
-% use both \addpoints and \noaddpoints to count some points and not
-% others, but still have the total printed when we finish the file no
-% matter what the state of \if@addpoints.
-\newif\if@addpoints
-\newif\if@printtotalpoints
-\def\addpoints{\global\@addpointstrue\global\@printtotalpointstrue}
-\def\noaddpoints{\global\@addpointsfalse}
-\@addpointsfalse
-\@printtotalpointsfalse
-
%--------------------------------------------------------------------
% choices (for multiple choice)
@@ -3647,37 +3782,148 @@
\renewcommand\thechoice{\Alph{choice}}
\newcommand\choicelabel{\thechoice.}
+% We will have \@correctchoicetrue when we're printing solutions
+% and we're printing the correct choice of a choices or
+% oneparchoices environment.
+% We'll say \begingroup before saying \@correctchoicetrue
+% and we'll say \endgroup at either the next \choice or \correctchoice
+% or the end of the choices or oneparchoices environment.
+% Thus, we'll never again need to say \@correctchoicefalse
+\newif\if@correctchoice
+\@correctchoicefalse
+
+\newcommand\CorrectChoiceEmphasis[1]{%
+ \def\CorrectChoice@Emphasis{#1}%
+}
+\CorrectChoiceEmphasis{\bfseries}
+\let\correctchoiceemphasis\CorrectChoiceEmphasis
+
+
+\newtoks\choice@toks
+\def\do@choice@pageinfo{%
+ \choice@toks={%
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ \set@counter@to@pageof{Curr@Page}{\q@object@label}%
+ \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
+ \global\expandafter\edef\csname
+ Contin@\theCurr@Page\endcsname{\arabic{question}}%
+ \fi
+ \choice@toks={}%
+ }%
+ % Version 2.217-beta changes:
+ % Instead of appending stuff to \everypar, we insert
+ % \the \pageinfo@commands and \the \point@toks
+ % into the box \@labels:
+ \global\setbox\@labels\hbox{\unhbox\@labels
+ \the \choice@toks}%
+ % \edef\append@everypar{\noexpand\everypar={\the\everypar
+ % \noexpand\the \noexpand\choice@toks}}%
+ % \append@everypar
+}% do@choice@pageinfo
+
+
+
% Added 22 April 2004: Increased the \leftmargin by 2.5em,
% so the choices will be visibly indented.
\newenvironment{choices}%
{\list{\choicelabel}%
{\usecounter{choice}\def\makelabel##1{\hss\llap{##1}}%
\settowidth{\leftmargin}{W.\hskip\labelsep\hskip 2.5em}%
- \let\choice=\item
+ \def\choice{%
+ \if@correctchoice
+ \endgroup
+ \fi
+ \item
+ \do@choice@pageinfo
+ } % choice
+ \def\CorrectChoice{%
+ \if@correctchoice
+ \endgroup
+ \fi
+ \ifprintanswers
+ % We can't say \choice here, because that would
+ % insert an \endgroup:
+ \begingroup \@correctchoicetrue
+ \CorrectChoice@Emphasis
+ \fi
+ \item
+ \do@choice@pageinfo
+ } % CorrectChoice
+ \let\correctchoice\CorrectChoice
\labelwidth\leftmargin\advance\labelwidth-\labelsep
\topsep=0pt
\partopsep=0pt
+ \choiceshook
}%
}%
- {\endlist}
+ {\if@correctchoice \endgroup \fi \endlist}
\newenvironment{oneparchoices}%
{%
\setcounter{choice}{0}%
\def\choice{%
- \refstepcounter{choice}%
- \ifnum\value{choice}>1
- \penalty -50\hskip 1em plus 1em\relax
- \fi
- \choicelabel\nobreak\enskip
- }%
+ \if@correctchoice \endgroup \fi
+ \refstepcounter{choice}%
+ \ifnum\value{choice}>1
+ \penalty -50\hskip 1em plus 1em\relax
+ \fi
+ \choicelabel
+ % No need to put the following into a token string; we just put
+ % the choicelabel onto the page, so we're at the spot whose page
+ % number we want to record:
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ \set@counter@to@pageof{Curr@Page}{\q@object@label}%
+ \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
+ \global\expandafter\edef\csname
+ Contin@\theCurr@Page\endcsname{\arabic{question}}%
+ \fi
+ \nobreak\enskip
+ }% choice
+ \def\CorrectChoice{%
+ \if@correctchoice \endgroup \fi
+ \refstepcounter{choice}%
+ \ifprintanswers
+ \begingroup \@correctchoicetrue
+ \CorrectChoice@Emphasis
+ \fi
+ \ifnum\value{choice}>1
+ \penalty -50\hskip 1em plus 1em\relax
+ \fi
+ \choicelabel
+ % No need to put the following into a token string; we just put
+ % the choicelabel onto the page, so we're at the spot whose page
+ % number we want to record:
+ \addtocounter{ques@object}{1}%
+ \edef\q@object@label{%
+ question\arabic{question}@object\arabic{ques@object}}%
+ \PgInfo@write{\q@object@label}%
+ \set@counter@to@pageof{Curr@Page}{\q@object@label}%
+ \expandafter\ifx\csname Contin@\theCurr@Page\endcsname\relax
+ % We're the first \question, \part, \subpart, \subsubpart,
+ % or choice on this page:
+ \global\expandafter\edef\csname
+ Contin@\theCurr@Page\endcsname{\arabic{question}}%
+ \fi
+ \nobreak\enskip
+ }% CorrectChoice
+ \let\correctchoice\CorrectChoice
\let\par\@empty
% If we're continuing the paragraph containing the question,
% then leave a bit of space before the first choice:
\ifvmode\else\enskip\fi
\ignorespaces
}%
- {}
+ {\if@correctchoice \endgroup \fi}
%--------------------------------------------------------------------
@@ -3692,10 +3938,13 @@
\newlength\answerlinelength
\newlength\answerskip
+\newlength\answerclearance
\setlength\answerlinelength{1in}
\setlength\answerskip{2ex}
+\setlength\answerclearance{0.2ex}
-\def\answerline{%
+\newcommand\answerline[1][{}]{%
+ % One optional argument, the default value of which is empty.
\ifx\@queslevel\ques@ref
\let\ans@l=\questionlabel
\else
@@ -3717,9 +3966,16 @@
\fi
\fi
\par \nobreak \vskip \answerskip
- \hfill \ans@l~\hbox to \answerlinelength{\hrulefill}%
+ \hfill
+ \ifprintanswers
+ \ans@l~\hbox to 0pt{\hbox to \answerlinelength{\hrulefill}\hss}%
+ \raise \answerclearance\hbox to \answerlinelength{%
+ \CorrectChoice@Emphasis \hfil #1\hss}%
+ \else
+ \ans@l~\hbox to \answerlinelength{\hrulefill}%
+ \fi
\par
-}
+}% answerline
%--------------------------------------------------------------------
% \fillwithlines
@@ -3727,9 +3983,9 @@
% \fillwithlines takes one argument, which is either a length or \fill,
% and it fills that much vertical space with horizontal lines that run
-% the length of the current line. That is, the extend from the current
-% left margin (which depends on whether we're in a quesiton, parts,
-% subpart, or subsubpart) to the right margin.
+% the length of the current line. That is, they extend from the
+% current left margin (which depends on whether we're in a question,
+% part, subpart, or subsubpart) to the right margin.
%
% The distance between the lines is \linefillheight, whose default value
% is set with the command
@@ -3741,7 +3997,7 @@
% The thickness of the lines is \linefillthickness, whose default value
% is set with the command
%
-% \setlength\linefillthickness{.2pt}
+% \setlength\linefillthickness{.1pt}
%
% This value can be changed by giving a new \setlength command.
@@ -3772,6 +4028,46 @@
\endgroup
}
+%--------------------------------------------------------------------
+% \fillwithdottedlines
+
+
+% \fillwithdottedlines is similar to \fillwithlines, except that it
+% fills the space with dotted lines (created by \dotfill) rather than
+% with solid lines.
+
+% \fillwithdottedlines takes one argument, which is either a length or
+% \fill, and it fills that much vertical space with dotted lines that
+% run the length of the current line. That is, they extend from the
+% current left margin (which depends on whether we're in a question,
+% part, subpart, or subsubpart) to the right margin.
+%
+% The distance between the lines is \dottedlinefillheight, whose
+% default value is set with the command
+%
+% \setlength\dottedlinefillheight{.25in}
+%
+% This value can be changed by giving a new \setlength command.
+
+\newlength\dottedlinefillheight
+\setlength\dottedlinefillheight{.25in}
+
+\def\fillwithdottedlines#1{%
+ \begingroup
+ \ifhmode
+ \par
+ \fi
+ \hrule height \z@
+ \nobreak
+ \setbox0=\hbox to \hsize{\hskip \@totalleftmargin
+ \vrule height \dottedlinefillheight depth \z@ width \z@
+ \dotfill}%
+ % We use \cleaders (rather than \leaders) so that a given
+ % vertical space will always produce the same number of lines
+ % no matter where on the page it happens to start:
+ \cleaders \copy0 \vskip #1 \hbox{}%
+ \endgroup
+}
%--------------------------------------------------------------------
% \uplevel and \fullwidth:
@@ -3840,6 +4136,20 @@
\def\vpgword#1{\def\@vpgword{#1}}
\def\hpgword#1{\def\@hpgword{#1}}
+% The following are the versions for bonusgradetable:
+\def\bhqword#1{\def\@bhqword{#1}}
+\def\bhpword#1{\def\@bhpword{#1}}
+\def\bhsword#1{\def\@bhsword{#1}}
+\def\bhtword#1{\def\@bhtword{#1}}
+\def\bvqword#1{\def\@bvqword{#1}}
+\def\bvpword#1{\def\@bvpword{#1}}
+\def\bvsword#1{\def\@bvsword{#1}}
+\def\bvtword#1{\def\@bvtword{#1}}
+
+\def\bvpgword#1{\def\@bvpgword{#1}}
+\def\bhpgword#1{\def\@bhpgword{#1}}
+
+
% Initialize:
\cellwidth{2em}
\gradetablestretch{1.5}
@@ -3850,17 +4160,32 @@
\vsword{Score}
\vtword{Total:}
+\bhpword{Bonus Points:}
+\bhsword{Score:}
+\bhtword{Total}
+\bvpword{Bonus Points}
+\bvsword{Score}
+\bvtword{Total:}
+
% For tables indexed by question number:
\vqword{Question}
\hqword{Question:}
+\bvqword{Question}
+\bhqword{Question:}
% For tables indexed by page number:
\vpgword{Page}
\hpgword{Page:}
+\bvpgword{Page}
+\bhpgword{Page:}
-% The only command here accessible to the user is \gradetable.
+% The only commands here accessible to the user are \gradetable,
+% \bonusgradetable, \pointtable, \bonuspointtable, \partialgradetable,
+% \partialbonusgradetable, \partialpointtable,
+% \partialbonuspointtable, \begingradingrange, and \endgradingrange.
+
% The possibilities are
% \gradetable[v][questions]
@@ -3868,385 +4193,1181 @@
% \gradetable[h][questions]
% \gradetable[h][pages]
-% If one or both optional arguments are omitted, the defaults are `[v]'
-% and `[questions]'.
+% \bonusgradetable[v][questions]
+% \bonusgradetable[v][pages]
+% \bonusgradetable[h][questions]
+% \bonusgradetable[h][pages]
+
+% \pointtable[v][questions]
+% \pointtable[v][pages]
+% \pointtable[h][questions]
+% \pointtable[h][pages]
+
+% \bonuspointtable[v][questions]
+% \bonuspointtable[v][pages]
+% \bonuspointtable[h][questions]
+% \bonuspointtable[h][pages]
+
+% \partialgradetable{whatever}[v][questions]
+% \partialgradetable{whatever}[v][pages]
+% \partialgradetable{whatever}[h][questions]
+% \partialgradetable{whatever}[h][pages]
+
+% \partialbonusgradetable{whatever}[v][questions]
+% \partialbonusgradetable{whatever}[v][pages]
+% \partialbonusgradetable{whatever}[h][questions]
+% \partialbonusgradetable{whatever}[h][pages]
+
+% \partialpointtable{whatever}[v][questions]
+% \partialpointtable{whatever}[v][pages]
+% \partialpointtable{whatever}[h][questions]
+% \partialpointtable{whatever}[h][pages]
+
+% \partialbonuspointtable{whatever}[v][questions]
+% \partialbonuspointtable{whatever}[v][pages]
+% \partialbonuspointtable{whatever}[h][questions]
+% \partialbonuspointtable{whatever}[h][pages]
+
+% \begingradingrange{whatever}
+% \endgradingrange{whatever}
+%
+% where ``whatever'' is a label chosen by the user.
+
+% If one or both optional arguments are omitted, the defaults are
+% `[v]' and `[questions]'.
+
+% \@scorestrue means we're doing \gradetable
+% \@scoresfalse mans we're doing \pointtable
+\newif\if@scores
+
+% \@partialtrue means we're doing \partialgradetable,
+% \partialbonusgradetable, \partialpointtable, or
+% \partialbonuspointtable:
+\newif\if@partial
+
+
+% It's OK to use the counter num@cols as a scratch counter
+% in \begingradingrange and \endgradingrange because
+% it's only used in typesetting tables:
+\def\begingradingrange#1{%
+ \setcounter{num@cols}{\value{question}}%
+ \addtocounter{num@cols}{1}%
+ \immediate\write\@mainaux
+ {\string\expandafter\string\gdef
+ \string\csname\space tbl@#1@firstq\string\endcsname
+ {\arabic{num@cols}}}%
+ \write\@mainaux
+ {\string\expandafter\string\gdef
+ \string\csname\space tbl@#1@firstp\string\endcsname
+ {\thepage}}%
+}% begingradingrange
+
+\def\endgradingrange#1{%
+ \setcounter{num@cols}{\value{question}}%
+ \immediate\write\@mainaux
+ {\string\expandafter\string\gdef
+ \string\csname\space tbl@#1@lastq\string\endcsname
+ {\arabic{num@cols}}}%
+ \write\@mainaux
+ {\string\expandafter\string\gdef
+ \string\csname\space tbl@#1@lastp\string\endcsname
+ {\thepage}}%
+}% endgradingrange
+
+
+
+
+% Now that grading tables may be for only part of the exam,
+% we need the counter tbl@points to add up the total points
+% for the questions (or pages) that appear on the table:
+\new@hlfcntr{tbl@points}
+
+
+\def\partialgradetable#1{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialtrue
+ \def\tbl@range{#1}%
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% partialgradetable
+
+\def\partialbonusgradetable#1{%
+ \@scorestrue
+ \@bonustrue
+ \@partialtrue
+ \def\tbl@range{#1}%
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% partialbonusgradetable
+
+\def\partialpointtable#1{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialtrue
+ \def\tbl@range{#1}%
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% partialpointtable
+
+\def\partialbonuspointtable#1{%
+ \@scoresfalse
+ \@bonustrue
+ \@partialtrue
+ \def\tbl@range{#1}%
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% partialbonuspointtable
+
+%--------------------------------------------------------------------
\def\gradetable{%
+ \@scorestrue
+ \@bonusfalse
+ \@partialfalse
% If the user doesn't include the optional argument
% choosing between vertical and horizontal,
% we give them vertical:
\@ifnextchar[{\i@gtable}{\i@gtable[v]}%
-}
-\def\i@gtable[#1]{%
+}% gradetable
+
+\def\bonusgradetable{%
+ \@scorestrue
+ \@bonustrue
+ \@partialfalse
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% bonusgradetable
+
+\def\pointtable{%
+ \@scoresfalse
+ \@bonusfalse
+ \@partialfalse
% If the user doesn't include the optional argument
- % choosing between questions and pages,
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% pointtable
+
+\def\bonuspointtable{%
+ \@scoresfalse
+ \@bonustrue
+ \@partialfalse
+ % If the user doesn't include the optional argument
+ % choosing between vertical and horizontal,
+ % we give them vertical:
+ \@ifnextchar[{\i@gtable}{\i@gtable[v]}%
+}% bonuspointtable
+
+%--------------------------------------------------------------------
+
+% \i@gtable and \ii@gtable insert any missing optional arguments
+% (the defaults being [v] and [questions]) and then make sure
+% that the user said \addpoints and that this isn't the
+% first run of LaTeX.
+% \do@table then branches, depending on whether the user
+% selected [questions] or [pages].
+
+\def\i@gtable[#1]{%
+ % If the user doesn't include the second optional argument,
+ % which chooses between questions and pages,
% we give them questions:
\@ifnextchar[{\ii@gtable{#1}}{\ii@gtable{#1}[questions]}%
}
\def\ii@gtable#1[#2]{%
+ % We make sure the user said \addpoints, and then make sure
+ % that this isn't the first run of LaTeX (by checking that
+ % \exam@numpoints is defined). If both of those are OK,
+ % we go on to \do@table to see whether we're doing a table
+ % indexed by questions or by pages.
\if@addpoints
\@ifundefined{exam@numpoints}%
{\ClassWarning{exam}%
{%
- You must run LaTeX again to produce the grade table.
- \MessageBreak
+ You must run LaTeX again to produce the
+ table.\MessageBreak
}%
\fbox{Run \LaTeX{} again to produce the table}%
}%
- {\do@gtable{#1}{#2}}%
+ {\do@table{#1}{#2}}%
\else
\ClassError{exam}{%
You must give the command \protect\addpoints\MessageBreak
- \space\space in order to use the command \protect\gradetable
- \MessageBreak
+ \space\space in order to create a grade table.\MessageBreak
}{%
If you don't give the command \protect\addpoints\MessageBreak
\space\space then we're not keeping track of point values.
\MessageBreak
}%
\fi
-}
+}% ii@gtable
+
+
\def\@questionsref{questions}
\def\@pagesref{pages}
-\def\do@gtable#1#2{%
+\def\do@table#1#2{%
+ % See whether we're doing a table indexed by
+ % questions or by pages:
\begingroup % avoid trouble from using \@temp
\def\@temp{#2}%
\ifx\@temp\@questionsref
- \@grdtblquestions{#1}%
+ \find@qrange{#1}%
\else
\ifx\@temp\@pagesref
- \@grdtblpages{#1}%
+ \find@prange{#1}%
\else
\ClassError{exam}{%
- The second optional argument to \protect\gradetable \MessageBreak
- \space \space must be either `questions' or `pages'\MessageBreak
+ The second optional argument to a\MessageBreak
+ \space\space grade table or point table command\MessageBreak
+ \space \space must be either `questions' or
+ `pages',\MessageBreak
+ \space\space not `#2'.\MessageBreak
}{%
- Grade tables can be indexed by questions or pages;\MessageBreak
+ Grade tables and point tables can be indexed by questions or
+ pages;\MessageBreak
\space\space for others, you're on your own.\MessageBreak
}%
- \fbox{Error: Grade table: Invalid second optional argument `#1'.}%
+ \fbox{Error: grade or point table: Invalid second
+ optional argument `#2'.}%
\fi
\fi
\endgroup
-}
+}% do@table
+
+
+\def\range@undefined{%
+ \fbox{Warning: grading range `\tbl@range ' not defined;
+ run \LaTeX{} again.}%
+ \ClassWarning{exam}{%
+ Grading range `\tbl@range ' not defined.\MessageBreak
+ \space\space Run LaTeX again to produce the table.\MessageBreak
+ }%
+}% range@undefined
+
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-% Grading tables indexed by question numbers:
+% Grade and point tables indexed by question numbers:
+
+% \find@qrange makes sure the grading range is defined and that
+% its last question isn't before its first question.
+% \@tblquestions branches, depending on whether the user
+% selected [v] or [h].
+
+\def\find@qrange#1{%
+ % We're doing a table indexed by question numbers.
+ \if@partial
+ \@ifundefined{tbl@\tbl@range @firstq}%
+ {%
+ \range@undefined
+ }%
+ {%
+ \@ifundefined{tbl@\tbl@range @lastq}%
+ {%
+ \range@undefined
+ }%
+ {%
+ \edef\tbl@firstq{\csname tbl@\tbl@range @firstq\endcsname}%
+ \edef\tbl@lastq{\csname tbl@\tbl@range @lastq\endcsname}%
+ % Check that firstq precedes or equals lastq:
+ \ifnum \tbl@firstq > \tbl@lastq
+ \fbox{Error: Grading Range `\tbl@range ':
+ Last question precedes first question.}%
+ \ClassError{exam}{%
+ In grading range `\tbl@range ',
+ the last question\MessageBreak
+ \space\space comes before the first question.\MessageBreak
+ }{%
+ \string\begingradingrange \space must precede
+ \string\endgradingrange \space by at
+ least one question.\MessageBreak
+ }%
+ \else
+ \@tblquestions{#1}%
+ \fi
+ }%
+ }%
+ \else
+ \def\tbl@firstq{1}%
+ % \numquestions is always defined, even if this is the first
+ % run of LaTeX and \exam@numquestions isn't defined.
+ % If it's the first run of LaTeX, then its value isn't useful,
+ % but it's never used until a later run (when its value is useful).
+ \def\tbl@lastq{\numquestions}%
+ \@tblquestions{#1}%
+ \fi
+}% find@qrange
-\def\@grdtblquestions#1{%
+\def\@tblquestions#1{%
\if v#1%
- \@vgrdtblquestions
+ \@vtblquestions
\else
\if h#1%
- \@hgrdtblquestions
+ \@htblquestions
\else
\ClassError{exam}{%
- The first optional argument to \protect\gradetable \MessageBreak
- \space \space must be either `h' or `v'\MessageBreak
+ The first optional argument to \protect\gradetable,\MessageBreak
+ \space\space \protect\bonusgradetable,
+ \protect\pointtable, or\MessageBreak
+ \space\space \protect\bonuspointtable
+ \space must be either `h' or `v'\MessageBreak
}{%
- Grade tables can be either horizontal or vertical;\MessageBreak
+ Grade tables and point tables can be either horizontal or
+ vertical;\MessageBreak
\space\space no diagonals allowed.\MessageBreak
}%
- \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
+ \if@scores
+ \if@bonus
+ \fbox{Error: bonusgradetable: Invalid first optional argument
+ `#1'.}%
+ \else
+ \fbox{Error: gradetable: Invalid first optional argument
+ `#1'.}%
+ \fi
+ \else
+ \if@bonus
+ \fbox{Error: bonuspointtable: Invalid first optional argument
+ `#1'.}%
+ \else
+ \fbox{Error: pointtable: Invalid first optional argument
+ `#1'.}%
+ \fi
+ \fi
\fi
\fi
-}
+}% @tblquestions
%--------------------------------------------------------------------
% Vertical, indexed by question numbers:
-\def\@vgrdtblquestions{%
+\def\@vtblquestions{%
+ % The table is vertical and indexed by question numbers.
+ % See whether it's bonus or non-bonus, and
+ % gradetable or pointtable:
\begingroup
% Save the current value of question in @iterator, so that
- % we cna restore it after doing the table:
- \setcounter{@iterator}{\arabic{question}}%
+ % we can restore it after doing the table:
+ \setcounter{@iterator}{\value{question}}%
\renewcommand\arraystretch{\@gtblstretch}%
- \begin{tabular}{|c|c|c|}
- \hline
- {\@vqword}& {\@vpword}& {\@vsword}\\
- \hline
- \setcounter{question}{0}\do@vloop
- {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
+ \if@bonus
+ \if@scores
+ \@bvgrdtblquestions
+ \else
+ \@bvpttblquestions
+ \fi
+ \else
+ \if@scores
+ \@vgrdtblquestions
+ \else
+ \@vpttblquestions
+ \fi
+ \fi
% Restore the saved value of question:
- \setcounter{question}{\arabic{@iterator}}%
+ \setcounter{question}{\value{@iterator}}%
\endgroup
-}
+}% @vtblquestions
+
+\def\@bvgrdtblquestions{%
+ % Vertical bonus gradetable, indexed by questions:
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@bvqword}& {\@bvpword}& {\@bvsword}\\
+ \hline
+ \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@bvloop
+ {\@bvtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+}% @bvgrdtblquestions
+\def\do@bvloop{%
+ % \do@bvloop is used by \@bvgrdtblquestions
+ \addtocounter{question}{1}%
+ \ref{question@\arabic{question}} &
+ \bonuspointsofquestion{\arabic{question}}&\\
+ \hline
+ \@ifundefined{bonuspointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@bvloop=\do@bvloop
+ \else
+ \let\next@bvloop=\relax
+ \fi
+ \next@bvloop
+}% do@bvloop
+
+\def\@bvpttblquestions{%
+ % Vertical bonus point table, indexed by questions:
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|c|c|}
+ \hline
+ {\@bvqword}& {\@bvpword}\\
+ \hline
+ \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@bvptloop
+ {\@bvtword}& \prt@hlfcntr{tbl@points}\\
+ \hline
+ \end{tabular}%
+}% @bvpttblquestions
+\def\do@bvptloop{%
+ % \do@bvptloop is used by \@bvpttblquestions
+ \addtocounter{question}{1}%
+ \ref{question@\arabic{question}} &
+ \bonuspointsofquestion{\arabic{question}}\\
+ \hline
+ \@ifundefined{bonuspointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@bvptloop=\do@bvptloop
+ \else
+ \let\next@bvptloop=\relax
+ \fi
+ \next@bvptloop
+}% do@bvptloop
+
+\def\@vgrdtblquestions{%
+ % Vertical non-bonus grade table, indexed by questions:
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@vqword}& {\@vpword}& {\@vsword}\\
+ \hline
+ \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@vloop
+ {\@vtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+}% @vgrdtblquestions
\def\do@vloop{%
+ % \do@vloop is used by \@vgrdtblquestions
\addtocounter{question}{1}%
- \thequestion & \pointsofquestion{\arabic{question}}&\\
+ \ref{question@\arabic{question}} &
+ \pointsofquestion{\arabic{question}}&\\
\hline
- \ifnum \arabic{question} < \numquestions\relax
+ \@ifundefined{pointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname pointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
\let\next@vloop=\do@vloop
\else
\let\next@vloop=\relax
\fi
\next@vloop
-}
+}% do@vloop
+
+\def\@vpttblquestions{%
+ % Vertical non-bonus point table, indexed by questions:
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|c|c|}
+ \hline
+ {\@vqword}& {\@vpword}\\
+ \hline
+ \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@vptloop
+ {\@vtword}& \prt@hlfcntr{tbl@points}\\
+ \hline
+ \end{tabular}%
+}% @vpttblquestions
+\def\do@vptloop{%
+ % \do@vptloop is used by \@vpttblquestions
+ \addtocounter{question}{1}%
+ \ref{question@\arabic{question}} &
+ \pointsofquestion{\arabic{question}}\\
+ \hline
+ \@ifundefined{pointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname pointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@vptloop=\do@vptloop
+ \else
+ \let\next@vptloop=\relax
+ \fi
+ \next@vptloop
+}% do@vptloop
+
%--------------------------------------------------------------------
% Horizontal, indexed by question numbers:
-\def\@hgrdtblquestions{%
+\def\@htblquestions{%
+ % The table is horizontal and indexed by question numbers.
+ \@ifundefined{exam@numquestions}%
+ {}%
+ {%
+ \setcounter{num@cols}{\tbl@lastq}%
+ \addtocounter{num@cols}{-\tbl@firstq}%
+ \addtocounter{num@cols}{1}%
+ }%
+ % See whether it's bonus or non-bonus, and
+ % gradetable or pointtable:
\begingroup
% Save the current value of question in @iterator, so that
% we can restore it after doing the table:
- \setcounter{@iterator}{\arabic{question}}%
+ \setcounter{@iterator}{\value{question}}%
\renewcommand\arraystretch{\@gtblstretch}%
- \begin{tabular}{|l|*{\numquestions}{c|}c|}
- \hline
- {\@hqword}& \setcounter{question}{0}\do@qnumloop
- {\@htword}\\
- \hline
- {\@hpword}& \setcounter{question}{0}\do@ptloop
- \numpoints\\
- \hline
- {\@hsword}& \setcounter{question}{0}\do@sloop
- \\
- \hline
- \end{tabular}%
+ \if@bonus
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
+ \hline
+ {\@bhqword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@qnumloop
+ {\@bhtword}\\
+ \hline
+ {\@bhpword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@bptloop
+ \prt@hlfcntr{tbl@points}\\
+ \hline
+ % If it's a grade table, add in the score line:
+ \if@scores
+ {\@bhsword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@sloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \else
+ \set@hlfcntr{tbl@points}{0}%
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
+ \hline
+ {\@hqword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@qnumloop
+ {\@htword}\\
+ \hline
+ {\@hpword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@ptloop
+ \prt@hlfcntr{tbl@points}\\
+ \hline
+ % If it's a grade table, add in the score line:
+ \if@scores
+ {\@hsword}& \setcounter{question}{\tbl@firstq}%
+ \addtocounter{question}{-1}\do@sloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \fi
% Restore the saved value of question:
- \setcounter{question}{\arabic{@iterator}}%
+ \setcounter{question}{\value{@iterator}}%
\endgroup
-}
+}% @htblquestions
+
+
+% \do@qnumloop and \do@sloop are used both by non-bonus gradetable and
+% by bonusgradetable:
\def\do@qnumloop{%
\addtocounter{question}{1}%
- \thequestion &
- \ifnum \arabic{question} < \numquestions\relax
+ \ref{question@\arabic{question}} &
+ \ifnum \value{question} < \tbl@lastq\relax
\let\next@qnloop=\do@qnumloop
\else
\let\next@qnloop=\relax
\fi
\next@qnloop
-}
+}% do@qnumloop
+\def\do@sloop{%
+ \addtocounter{question}{1}%
+ \hbox to \@cellwidth{\hfill}&
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@sloop=\do@sloop
+ \else
+ \let\next@sloop=\relax
+ \fi
+ \next@sloop
+}% do@sloop
+
+% \do@ptloop is used only by non-bonus gradetable:
\def\do@ptloop{%
\addtocounter{question}{1}%
\pointsofquestion{\arabic{question}}&
- \ifnum \arabic{question} < \numquestions\relax
+ \@ifundefined{pointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname pointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
\let\next@ptloop=\do@ptloop
\else
\let\next@ptloop=\relax
\fi
\next@ptloop
-}
-\def\do@sloop{%
+}% do@ptloop
+
+% \do@bptloop is used only by bonusgradetable:
+\def\do@bptloop{%
\addtocounter{question}{1}%
- \hbox to \@cellwidth{\hfill}&
- \ifnum \arabic{question} < \numquestions\relax
- \let\next@sloop=\do@sloop
+ \bonuspointsofquestion{\arabic{question}}&
+ \@ifundefined{bonuspointsofq@\romannumeral \c@question}%
+ {}%
+ {\addto@hlfcntr{tbl@points}
+ {\csname bonuspointsofq@\romannumeral \c@question\endcsname}}%
+ \ifnum \value{question} < \tbl@lastq\relax
+ \let\next@bptloop=\do@bptloop
\else
- \let\next@sloop=\relax
+ \let\next@bptloop=\relax
\fi
- \next@sloop
-}
+ \next@bptloop
+}% do@bptloop
%--------------------------------------------------------------------
%--------------------------------------------------------------------
-% Grading tables indexed by page numbers:
-%
+% Grade and point tables indexed by page numbers:
+
+
% The only pages listed are those on which there is a nonzero number
-% of points. We check pages 1 through \lastpage@withpoints; this way,
-% once we've checked that \lastpage@withpoints and
+% of points. We check pages \tbl@firstp through \tbl@lastp
+% Once we've checked that, e.g., \lastpage@withpoints and
% \pointsonpage@\romannumeral{\lastpage@withpoints} are defined, we
% can safely (we think) check \pointsonpage@\romannumeral{n} for all n
-% between 1 and \lastpage@withpoints without generating errors.
+% between \tbl@firstp and \tbl@lastp without generating errors.
+%
+% Actually: Since we added the notion of half points and half counters
+% (a long time ago), there won't be any errors even if
+% \pointsonpage@\romannumeral{n} isn't defined, since it's tested by the
+% lines:
+% \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
+% \csname c@@iterator\endcsname\endcsname}%
+% \ifhlfcntr@pos{tmp@hlfcntr}%
+% and if
+% \csname pointsonpage@\romannumeral
+% \csname c@@iterator\endcsname\endcsname
+% isn't defined, tmp@hlfcntr gets the value zero (because of the way
+% that \set@hlfcntr is written).
+
+
+% \find@prange makes sure the grading range is defined and that
+% its last page isn't before its first page.
+
+
+\def\find@prange#1{%
+ % We're doing a table indexed by pages.
+ \if@partial
+ \@ifundefined{tbl@\tbl@range @firstp}%
+ {%
+ \range@undefined
+ }%
+ {%
+ \@ifundefined{tbl@\tbl@range @lastp}%
+ {%
+ \range@undefined
+ }%
+ {%
+ \edef\tbl@firstp{\csname tbl@\tbl@range @firstp\endcsname}%
+ \edef\tbl@lastp{\csname tbl@\tbl@range @lastp\endcsname}%
+ % Check that firstp precedes or equals lastp:
+ \ifnum \tbl@firstp > \tbl@lastp
+ \fbox{Error: Grading Range `\tbl@range ':
+ Last page precedes first page.}%
+ \ClassError{exam}{%
+ In grading range `\tbl@range ', the last page\MessageBreak
+ \space\space comes before the first page.\MessageBreak
+ }{%
+ \string\begingradingrange \space must precede
+ \string\endgradingrange.\MessageBreak
+ }%
+ \else
+ \@tblpages{#1}%
+ \fi
+ }%
+ }%
+ \else
+ \def\tbl@firstp{1}%
+ % \tbl@lastp isn't used on the first run of LaTeX, and
+ % \lastpage@withbonuspoints is defined on the second and later runs.
+ \if@bonus
+ \def\tbl@lastp{\lastpage@withbonuspoints}%
+ \else
+ \def\tbl@lastp{\lastpage@withpoints}%
+ \fi
+ \@tblpages{#1}%
+ \fi
+}% find@prange
+
+
% Check that there's enough info from the .aux file to do a page
% indexed grade table:
-\def\@grdtblpages#1{%
+\def\@tblpages#1{%
\@ifundefined{lastpage@withpoints}%
{\ClassWarning{exam}{%
- You must run LaTeX twice more\MessageBreak
- \space\space to produce the grade table.\MessageBreak}%
- \fbox{Run \LaTeX{} twice more to produce the grade table}%
+ You must run LaTeX twice more\MessageBreak
+ \space\space to produce the table.\MessageBreak}%
+ \fbox{Run \LaTeX{} twice more to produce the table}%
}%
{%
\@ifundefined{pointsonpage@\romannumeral
\csname lastpage@withpoints\endcsname}%
{\ClassWarning{exam}{%
- You must run LaTeX again\MessageBreak
- \space\space to produce the grade table.\MessageBreak}%
- \fbox{Run \LaTeX{} again to produce the grade table}%
+ You must run LaTeX again\MessageBreak
+ \space\space to produce the table.\MessageBreak}%
+ \fbox{Run \LaTeX{} again to produce the table}%
}%
{%
\@whchtblpgs#1
}%
}%
-}
+}% @tblpages
\def\@whchtblpgs#1{%
+ % At this point, we know the table is indexed by pages.
+ % It can be vertical or horizontal,
+ % grade or point, and bonus or non-bonus.
\if v#1%
- \@vgrdtblpages
+ \@vtblpages
\else
\if h#1%
- \@hgrdtblpages
+ \@htblpages
\else
\ClassError{exam}{%
- The first optional argument to \protect\gradetable \MessageBreak
- \space \space must be either `h' or `v'\MessageBreak
+ The first optional argument to
+ \protect\gradetable,\MessageBreak
+ \space\space \protect\bonusgradetable,
+ \protect\pointtable, or\MessageBreak
+ \space\space
+ \protect\bonuspointtable \space must be either `h' or
+ `v'\MessageBreak
}{%
- Grade tables can be either horizontal or vertical;\MessageBreak
+ Grade tables and point tables can be either horizontal or
+ vertical;\MessageBreak
\space\space no diagonals allowed.\MessageBreak
}%
- \fbox{Error: Grade table: Invalid first optional argument `#1'.}%
+ \if@scores
+ \if@bonus
+ \fbox{Error: bonusgradetable: Invalid first optional argument
+ `#1'.}%
+ \else
+ \fbox{Error: gradetable: Invalid first optional argument
+ `#1'.}%
+ \fi
+ \else
+ \if@bonus
+ \fbox{Error: bonuspointtable: Invalid first optional argument
+ `#1'.}%
+ \else
+ \fbox{Error: pointtable: Invalid first optional argument
+ `#1'.}%
+ \fi
+ \fi
\fi
\fi
-}
+}% \@whchtblpgs
%--------------------------------------------------------------------
% Vertical, indexed by pages:
-\def\@vgrdtblpages{%
+\def\@vtblpages{%
+ % At this point, we know it's a vertical table indexed by pages.
+ % It can be grade or point, and bonus or non-bonus.
\begingroup
\renewcommand\arraystretch{\@gtblstretch}%
- \begin{tabular}{|c|c|c|}
- \hline
- {\@vpgword}& {\@vpword}& {\@vsword}\\
- \hline
- \setcounter{@iterator}{0}\pg@vloop
- {\@vtword}& \numpoints&\hbox to \@cellwidth{\hfill}\\
- \hline
- \end{tabular}%
+ \set@hlfcntr{tbl@points}{0}%
+ \if@bonus
+ \if@scores
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@bvpgword}& {\@bvpword}& {\@bvsword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@bvloop
+ {\@bvtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+ \else
+ \begin{tabular}{|c|c|}
+ \hline
+ {\@bvpgword}& {\@bvpword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@ptbvloop
+ {\@bvtword}& \prt@hlfcntr{tbl@points}\\
+ \hline
+ \end{tabular}%
+ \fi
+ \else
+ \if@scores
+ \begin{tabular}{|c|c|c|}
+ \hline
+ {\@vpgword}& {\@vpword}& {\@vsword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@vloop
+ {\@vtword}& \prt@hlfcntr{tbl@points}&\hbox to \@cellwidth{\hfill}\\
+ \hline
+ \end{tabular}%
+ \else
+ \begin{tabular}{|c|c|}
+ \hline
+ {\@vpgword}& {\@vpword}\\
+ \hline
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\pg@ptvloop
+ {\@vtword}& \prt@hlfcntr{tbl@points}\\
+ \hline
+ \end{tabular}%
+ \fi
+ \fi
\endgroup
-}
+}% @vtblpages
+
+
+% \pg@ptvloop and \pg@ptvloopline are used only by non-bonus pointtable:
+\def\pg@ptvloop{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \pg@ptvloopline
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@pg@ptvloop=\pg@ptvloop
+ \else
+ \let\next@pg@ptvloop=\relax
+ \fi
+ \next@pg@ptvloop
+}% pg@ptvloop
+\def\pg@ptvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstpoints@onpage@\arabic{@iterator}} &
+ \pointsonpage{\the@iterator}\\
+ \hline
+}% pg@ptvloopline
+
+% \pg@vloop and \pg@vloopline are used only by non-bonus gradetable:
\def\pg@vloop{%
\addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
\set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
-% \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
-% spanish.ldf redefines \@roman, so we'll avoid \roman
+ \csname c@@iterator\endcsname\endcsname}%
\ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
\pg@vloopline
\fi
- \ifnum \the@iterator < \lastpage@withpoints\relax
+ \ifnum \the@iterator < \tbl@lastp\relax
\let\next@pg@vloop=\pg@vloop
\else
\let\next@pg@vloop=\relax
\fi
\next@pg@vloop
-}
+}% pg@vloop
\def\pg@vloopline{%
% We still don't understand why we need to hide this inside of a
% macro; there's some weird interaction with the \ifnum checking to
% see if something is ``>0''; checking that something is ``=0''
% doesn't cause the ``\ifnum incomplete'' (or whatever) error.
- \the@iterator & \pointsonpage{\the@iterator}&\\
+ \pageref{firstpoints@onpage@\arabic{@iterator}} &
+ \pointsonpage{\the@iterator}&\\
\hline
-}
+}% pg@vloopline
+
+% \pg@bvloop and \pg@bvloopline are used only by bonus gradetable:
+\def\pg@bvloop{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \pg@bvloopline
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@pg@bvloop=\pg@bvloop
+ \else
+ \let\next@pg@bvloop=\relax
+ \fi
+ \next@pg@bvloop
+}% pg@bvloop
+\def\pg@bvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstbonuspoints@onpage@\arabic{@iterator}} &
+ \bonuspointsonpage{\the@iterator}&\\
+ \hline
+}% pg@bvloopline
+
+% \pg@ptbvloop and \pg@ptbvloopline are used only by bonus pointtable:
+\def\pg@ptbvloop{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \pg@ptbvloopline
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@pg@ptbvloop=\pg@ptbvloop
+ \else
+ \let\next@pg@ptbvloop=\relax
+ \fi
+ \next@pg@ptbvloop
+}% pg@ptbvloop
+\def\pg@ptbvloopline{%
+ % We still don't understand why we need to hide this inside of a
+ % macro; there's some weird interaction with the \ifnum checking to
+ % see if something is ``>0''; checking that something is ``=0''
+ % doesn't cause the ``\ifnum incomplete'' (or whatever) error.
+ \pageref{firstbonuspoints@onpage@\arabic{@iterator}} &
+ \bonuspointsonpage{\the@iterator}\\
+ \hline
+}% pg@ptbvloopline
%--------------------------------------------------------------------
% Horizontal, indexed by pages:
-% For a horizontal table, we need to know how many pages there are
-% with points on them:
-\newcounter{numpgs@withpts}
+% For a horizontal table, before we begin we need to know how many
+% pages there are with points on them:
+\newcounter{num@cols}
\def\count@pgswpts{%
- \setcounter{numpgs@withpts}{0}%
- \setcounter{@iterator}{0}%
- \docount@pgswpts
-}
+ % \count@pgswpts is used for horizontal
+ % grade tables and point tables, both
+ % bonus and non-bonus.
+ \setcounter{num@cols}{0}%
+ \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}%
+ \if@bonus
+ \docount@pgswbpts
+ \else
+ \docount@pgswpts
+ \fi
+}% count@pgswpts
+
+% \docount@pgswpts is used for non-bonus gradetable:
\def\docount@pgswpts{%
\addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
\set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
-% \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
-% spanish.ldf redefines \@roman, so we'll avoid \roman
+ \csname c@@iterator\endcsname\endcsname}%
\ifhlfcntr@pos{tmp@hlfcntr}%
- \addtocounter{numpgs@withpts}{1}%
+ \addtocounter{num@cols}{1}%
\fi
- \ifnum \the@iterator < \lastpage@withpoints\relax
+ \ifnum \the@iterator < \tbl@lastp\relax
\let\next@docount=\docount@pgswpts
\else
\let\next@docount=\relax
\fi
\next@docount
-}
+}% docount@pgswpts
+% \docount@pgswbpts is used for bonusgradetable:
+\def\docount@pgswbpts{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \addtocounter{num@cols}{1}%
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@docount=\docount@pgswbpts
+ \else
+ \let\next@docount=\relax
+ \fi
+ \next@docount
+}% docount@pgswbpts
-\def\@hgrdtblpages{%
+%--------------------------------------------------------------------
+
+\def\@htblpages{%
\begingroup
\renewcommand\arraystretch{\@gtblstretch}%
\count@pgswpts
- \begin{tabular}{|l|*{\thenumpgs@withpts}{c|}c|}
- \hline
- {\@hpgword}& \setcounter{@iterator}{0}\do@pgnumloop
- {\@htword}\\
- \hline
- {\@hpword}& \setcounter{@iterator}{0}\do@pgptloop
- \numpoints\\
- \hline
- {\@hsword}& \setcounter{@iterator}{0}\do@pgsloop
- \\
- \hline
- \end{tabular}%
+ % Suppress ``extra alignment tab'' errors if \thenum@cols = 0:
+ \ifnum \thenum@cols = 0
+ \setcounter{num@cols}{1}%
+ \fi
+ \set@hlfcntr{tbl@points}{0}%
+ \if@bonus
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
+ \hline
+ {\@bhpgword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@bpgnumloop
+ {\@bhtword}\\
+ \hline
+ {\@bhpword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@bpgptloop
+ \prt@hlfcntr{tbl@points}\\
+ \hline
+ % If it's a grade table, do the line for scores:
+ \if@scores
+ {\@bhsword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@bpgsloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \else
+ \begin{tabular}{|l|*{\thenum@cols}{c|}c|}
+ \hline
+ {\@hpgword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@pgnumloop
+ {\@htword}\\
+ \hline
+ {\@hpword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@pgptloop
+ \prt@hlfcntr{tbl@points}\\
+ \hline
+ % If it's a grade table, do the line for scores:
+ \if@scores
+ {\@hsword}& \setcounter{@iterator}{\tbl@firstp}%
+ \addtocounter{@iterator}{-1}\do@pgsloop
+ \\
+ \hline
+ \fi
+ \end{tabular}%
+ \fi
\endgroup
-}
+}% @htblpages
+% \do@pgnumloop, \pg@line, \do@pgptloop, \pgpt@line, \do@pgsloop, and
+% \pg@sline are only for non-bonus gradetable:
\def\do@pgnumloop{%
\addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
\set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
-% \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
-% spanish.ldf redefines \@roman, so we'll avoid \roman
+ \csname c@@iterator\endcsname\endcsname}%
\ifhlfcntr@pos{tmp@hlfcntr}%
\pg@line
\fi
- \ifnum \the@iterator < \lastpage@withpoints\relax
+ \ifnum \the@iterator < \tbl@lastp\relax
\let\next@pgnumloop=\do@pgnumloop
\else
\let\next@pgnumloop=\relax
\fi
\next@pgnumloop
-}
+}% \do@pgnumloop
\def\pg@line{%
- \the@iterator &
-}
+ \pageref{firstpoints@onpage@\arabic{@iterator}}&
+}% \pg@line
\def\do@pgptloop{%
\addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
\set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
-% \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
-% spanish.ldf redefines \@roman, so we'll avoid \roman
+ \csname c@@iterator\endcsname\endcsname}%
\ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
\pgpt@line
\fi
- \ifnum \the@iterator < \lastpage@withpoints\relax
+ \ifnum \the@iterator < \tbl@lastp\relax
\let\next@pgptloop=\do@pgptloop
\else
\let\next@pgptloop=\relax
\fi
\next@pgptloop
-}
+}% \do@pgptloop
\def\pgpt@line{%
- \csname pointsonpage@\romannumeral \csname c@@iterator\endcsname\endcsname &
-% \csname pointsonpage@\roman{@iterator}\endcsname &
-% spanish.ldf redefines \@roman, so we'll avoid \roman
-}
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \csname pointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname &
+}% \pgpt@line
\def\do@pgsloop{%
\addtocounter{@iterator}{1}%
-% \ifnum \csname pointsonpage@\roman{@iterator}\endcsname > 0\relax
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
\set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\romannumeral
- \csname c@@iterator\endcsname\endcsname}%
-% \set@hlfcntr{tmp@hlfcntr}{\csname pointsonpage@\roman{@iterator}\endcsname}%
-% spanish.ldf redefines \@roman, so we'll avoid \roman
+ \csname c@@iterator\endcsname\endcsname}%
\ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
\pg@sline
\fi
- \ifnum \the@iterator < \lastpage@withpoints\relax
+ \ifnum \the@iterator < \tbl@lastp\relax
\let\next@pgsloop=\do@pgsloop
\else
\let\next@pgsloop=\relax
\fi
\next@pgsloop
-}
+}% \do@pgsloop
\def\pg@sline{%
\hbox to \@cellwidth{\hfill}&
-}
+}% \pg@sline
+
+%--------------------------------------------------------------------
+% These things are for bonusgradetable:
+
+% \do@bpgnumloop, \bpg@line, \do@bpgptloop, \bpgpt@line, \do@bpgsloop,
+% and \bpg@sline are only for bonusgradetable:
+\def\do@bpgnumloop{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \bpg@line
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@bpgnumloop=\do@bpgnumloop
+ \else
+ \let\next@bpgnumloop=\relax
+ \fi
+ \next@bpgnumloop
+}% do@bpgnumloop
+\def\bpg@line{%
+ \pageref{firstbonuspoints@onpage@\arabic{@iterator}}&
+}% bpg@line
+
+\def\do@bpgptloop{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \bpgpt@line
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@bpgptloop=\do@bpgptloop
+ \else
+ \let\next@bpgptloop=\relax
+ \fi
+ \next@bpgptloop
+}% do@bpgptloop
+\def\bpgpt@line{%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname &
+}% bpgpt@line
+
+\def\do@bpgsloop{%
+ \addtocounter{@iterator}{1}%
+ % spanish.ldf redefines \@roman, so we'll avoid using \roman:
+ \set@hlfcntr{tmp@hlfcntr}{\csname bonuspointsonpage@\romannumeral
+ \csname c@@iterator\endcsname\endcsname}%
+ \ifhlfcntr@pos{tmp@hlfcntr}%
+ \add@hlfcntrtohlfcntr{tbl@points}{tmp@hlfcntr}%
+ \bpg@sline
+ \fi
+ \ifnum \the@iterator < \tbl@lastp\relax
+ \let\next@bpgsloop=\do@bpgsloop
+ \else
+ \let\next@bpgsloop=\relax
+ \fi
+ \next@bpgsloop
+}% do@bpgsloop
+\def\bpg@sline{%
+ \hbox to \@cellwidth{\hfill}&
+}% bpg@sline
%--------------------------------------------------------------------
@@ -4259,21 +5380,22 @@
% If the documentclass options include ``answers'', then the command
-% \@printanswerstrue is given at the beginning of the run.
+% \printanswerstrue is given at the beginning of the run.
% If the documentclass options include ``noanswers'', then the command
-% \@printanswersfalse is given at the beginning of the run.
+% \printanswersfalse is given at the beginning of the run.
-\def\printanswers{\@printanswerstrue}
-\def\noprintanswers{\@printanswersfalse}
+\def\printanswers{\printanswerstrue}
+\def\noprintanswers{\printanswersfalse}
-% If @printanswers is true, we print the solution using a TheSolution
-% environment. If @printanswers is false, we insert blank vertical space
-% equal to the optional argument (the default value of which is 0pt).
+% If printanswers is true, we print the solution using a TheSolution
+% environment. If printanswers is false, we insert blank vertical
+% space equal to the optional argument (the default value of which is
+% 0pt).
\newenvironment{solution}[1][0pt]%
{%
- \if@printanswers
+ \ifprintanswers
\begin{TheSolution}%
\else
\par
@@ -4281,19 +5403,20 @@
\setbox\z@\vbox\bgroup
\fi
}{%
- \if@printanswers
+ \ifprintanswers
\end{TheSolution}%
\else
\egroup
\fi
}%
-% If @printanswers is true, we print the solution using a TheSolution
-% environment. If @printanswers is false, we insert lined vertical space
-% equal to the optional argument (the default value of which is 0pt).
+% If printanswers is true, we print the solution using a TheSolution
+% environment. If printanswers is false, we insert lined vertical
+% space equal to the optional argument (the default value of which is
+% 0pt).
\newenvironment{solutionorlines}[1][0pt]%
{%
- \if@printanswers
+ \ifprintanswers
\begin{TheSolution}%
\else
\par
@@ -4301,7 +5424,29 @@
\setbox\z@\vbox\bgroup
\fi
}{%
- \if@printanswers
+ \ifprintanswers
+ \end{TheSolution}%
+ \else
+ \egroup
+ \fi
+ }%
+
+
+% If printanswers is true, we print the solution using a TheSolution
+% environment. If printanswers is false, we insert dotted lined
+% vertical space equal to the optional argument (the default value of
+% which is 0pt).
+\newenvironment{solutionordottedlines}[1][0pt]%
+ {%
+ \ifprintanswers
+ \begin{TheSolution}%
+ \else
+ \par
+ \fillwithdottedlines{#1}%
+ \setbox\z@\vbox\bgroup
+ \fi
+ }{%
+ \ifprintanswers
\end{TheSolution}%
\else
\egroup
@@ -4309,12 +5454,13 @@
}%
-% The environment TheSolution is called from the solution environment
-% when @printanswers is true. It uses Donald Arseneau's
+% The environment TheSolution is called from the solution,
+% solutionorlines, and solutionordottedlines environments
+% when printanswers is true. It uses Donald Arseneau's
% framed.sty macros (included at the end if this file) to allow the
% solution to be broken across pages and have each piece enclosed in
% an fbox (or a colorbox, if the user has given the command
-% \shadedsolution).
+% \shadedsolutions).
%
% Of course, the user can change TheSolution with a \renewenvironment
% command.
@@ -4351,7 +5497,7 @@
\ClassError{exam}{%
You must load the color package with the command\MessageBreak
\space\space\protect\usepackage{color}\MessageBreak
- in order to use the command \protect\colorsolutions
+ in order to use the command \protect\shadedsolutions
\MessageBreak
}{%
This command makes use of the package color.sty,\MessageBreak