From 8c7d1cdf9705933f11e3dff4105c1054427677d2 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 23 Jul 2008 22:06:36 +0000 Subject: exam 2.3 (19jul08) git-svn-id: svn://tug.org/texlive/trunk@9734 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/latex/exam/exam.cls | 4054 ++++++++++++++++++----------- 1 file changed, 2600 insertions(+), 1454 deletions(-) (limited to 'Master/texmf-dist/tex/latex/exam') 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.3, 2008/07/16: % -% 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. +% Minor typographic corrections to comments. % %-------------------------------------------------------------------- +% Version 2.222$\beta$, 2008/07/13: % -% 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. +% 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.114$\beta$: -% -% We fixed up the code for \uplevel and \fullwidth so that they work -% correctly if a solution environment is inside the argument. -% -%-------------------------------------------------------------------- -% -% 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 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. -% -% 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. +% New command: \fillwithdottedlines +% New environment: solutionordottedlines % -% 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: % +% \fillwithdottedlines is similar to \fillwithlines except that it +% inserts dotted lines (created by \dotfill) instead of solid lines. % -% New commands: -% -% \coverheader -% \coverrunningheader -% \coverfirstpageheader +% \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. % -% \coverlhead -% \coverchead -% \coverrhead +% The distance between the lines is \dottedlinefillheight, whose +% default value is set with the command % -% \coverfooter -% \coverrunningfooter -% \coverfirstpagefooter +% \setlength\dottedlinefillheight{.25in} % -% \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$: +% Version 2.205$\beta$, 2005/08/22: % -% 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={}''. +% 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.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}. -% -%-------------------------------------------------------------------- -% -% Version 2.070$\beta$: -% -% 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. +% Version 2.204$\beta$, 2005/08/21: % -%-------------------------------------------------------------------- -% -% Version 2.067$\beta$: +% Bug fix: Hyperlinks didn't work on page numbers for horizontal +% grading tables indexed by page numbers. They do now. % -% 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. +% Version 2.203$\beta$, 2005/08/20: % -% \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. +% 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. % -% \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 -% -% 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). -% +% Created \correctchoice as a synonym for \CorrectChoice % -% \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}). +% Changed \CorrectChoiceDeclarations to \CorrectChoiceEmphasis, +% and created \correctchoiceemphasis as a synonym for that. % +%-------------------------------------------------------------------- % -% subsubparts environment -% Numbered using lower case greek letters. +% Version 2.201$\beta$, 2005/08/09: % +% We created a \CorrectChoice command for use in the choices and +% oneparchoices environments. % -% choices environment, for multiple choice answers +% When solutions are not being printed, \CorrectChoice is equivalent to +% \choice. % +% 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 % -% \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. +% \CorrectChoiceDeclarations % -% \noqformat returns to the standard question number formatting. +% command. The default is % +% \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 % -% The standard options -% a4paper -% a5paper -% b5paper -% letterpaper -% legalpaper -% executivepaper -% landscape -% now all work. +% \usepackage{color} % +% 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@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}}% - }% - {\find@subsubpart}% -} - -\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 +}% 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 }% - {\addtocounter{last@subpart}{1}% - \let\nextfind@lastsubpart=\find@lastsubpart + {\addtocounter{last@object}{1}% + \let\nextfind@lastobject=\find@lastobject }% - \nextfind@lastsubpart -} + \nextfind@lastobject +}% find@lastobject -\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}% @@ -2506,36 +2276,15 @@ \incomp@second \else \@ifundefined{Pg@@endquestions}% - {\incomp@first}% - {\ifnum \thepage < \PgInfo@get{@endquestions}% - \incomp@first - \else - \incomp@second - \fi - }% - \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. - + {\incomp@first}% + {\ifnum \thepage < \PgInfo@get{@endquestions}% + \incomp@first + \else + \incomp@second + \fi + }% + \fi +} %-------------------------------------------------------------------- % These are the commands for dealing with hlfcntr's, i.e., the things @@ -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 commands here accessible to the user are \gradetable, +% \bonusgradetable, \pointtable, \bonuspointtable, \partialgradetable, +% \partialbonusgradetable, \partialpointtable, +% \partialbonuspointtable, \begingradingrange, and \endgradingrange. -% The only command here accessible to the user is \gradetable. % 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 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 questions and pages, + % 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 -- cgit v1.2.3