16

In an exam I am writing, I have a short answer section and a multiple choice section. Each of these sections should have questions starting at 1. As pointed out in this question, if you want to do this and avoid warnings about name collisions of question labels you need to modify the question labels to include the section name; I have done this using \xpatchcmd as shown in the example below. The patch is successful (verified by looking at the .aux file and lack of warning messages).

The problem is that I do not want the grade table organized by page or grade number, but rather by section. Since there does not appear to be a built in way to create a grade table in this way, I am doing it manually by using \begingraderange, \endgraderange, and \pointsinrange in a custom table. The issue that I am having is that the \pointsinrange totals are not accurate. I think it is because there is still some sort of name collision beyond the question labels that happens when summing the points in the ranges; I think it has to do with the \newlabel commands in the .aux files (marked with <=== below), where the unique question labels are defined but the value for each of these are the same.

When I run the following code, in the grade table I get that both the Short Answer and Multiple Choice have 2 total points, but it should be 10 and 4, respectively. I get the correct value for the overall total points (14). Any thoughts on how I can get this to work properly while also being able to reset the question number in each section to 1?

\documentclass[11pt,addpoints]{exam}

% The following patches avoid name collisions with questions
% of the same number in different sections by adding the section
% name to the question label.
\usepackage{xpatch}
\xpatchcmd{\questions}{question@\arabic{question}}
                      {question@\arabic{section}@\arabic{question}}{}{}
\xpatchcmd{\parts}{part@\arabic{question}@\arabic{partno}}
                  {part@\arabic{section}@\arabic{question}@\arabic{partno}}{}{}
\xpatchcmd{\first@questionobject}{question\arabic{question}}
                                 {question\arabic{section}@\arabic{question}}{}{}
\xpatchcmd{\addquestionobject}{question\arabic{question}}
                              {question\arabic{section}@\arabic{question}}{}{}
\xpatchcmd{\questionobject@pluspagecheck}{question\arabic{question}}
                                         {question\arabic{section}@\arabic{question}}{}{}

\begin{document}

\section{Short Answer}
\begin{questions}
\begingradingrange{section1}
\question[5] First Question
\question[5] Second Question
\endgradingrange{section1}
\end{questions}

\section{Multiple Choice}
\begin{questions}
\begingradingrange{section2}
\question[2] First Question
\question[2] Second Question
\endgradingrange{section2}
\end{questions}

\section{Extra Credit}
\begin{questions}
\bonusquestion[5] Bonus
\end{questions}

\begin{center}
\begin{tabular}{|r|c|c|}
 \hline
 \multicolumn{3}{|c|}{\textbf{Exam Score}}                           \\ \hline
 \textbf{Section} & \textbf{Points}                 & \textbf{Score} \\ \hline
 Short Answer     & \pointsinrange{section1}        &                \\ \hline
 Multiple Choice  & \pointsinrange{section2}        &                \\ \hline
 Bonus            & \numbonuspoints                 &                \\ \hline
 Total            & \numpoints                      &                \\ \hline
\end{tabular}
\end{center}

\end{document}

Excerpt of the .aux file:

...
\PgInfo{question@1@2}{1}
\PgInfo{question1@2@object1}{1}
\newlabel{question@1@2}{{2}{1}}  <=== Value same as question@2@2
...
\PgInfo{question@2@2}{1}
\PgInfo{question2@2@object1}{1}
\newlabel{question@2@2}{{2}{1}}  <=== Value same as question@1@2
3
  • Have you tried prepending a total points calculation before section? You can do this by the inverse of \g@addto@macro (prepend version). Then calculate the total points with basic TeX arithmetic.
    – 1010011010
    Jan 5, 2015 at 16:34
  • @1010011010 I wouldn't even know where to start to try that. Can you give me an example or point me to a tutorial to show me how? Jan 5, 2015 at 16:36
  • \long\def\g@prepend@macro#1#2{% \begingroup \toks@\expandafter{#2#1}% \xdef#1{\the\toks@}% \endgroup} Then use this to store the current amount of points in some macro. Then \AtEndDocument you can say \foreach \i in {0,...,\thesection}{\advance \thex by \numbercorrespondingtosection} or something. Would probably be one (general) way to do it. (Untested though, but it may provide a framework to get done what you want.)
    – 1010011010
    Jan 5, 2015 at 16:40

3 Answers 3

9
+100

This is another solution that uses a fake counter for printing fake question numbers.

First of all, we define the counter (which gets reset at each \section) and the format for titled questions and titled bonus questions:

\newcounter{fakecount}[section]
\qformat{\thefakecount. (\thepoints) \thequestiontitle\hfill}
\bonusqformat{\thefakecount. (\thebonuspoints) \thequestiontitle\hfill}

At the beginning of questions we redefine \titledquestion and \bonustitledquestion to increment the fake counter:

\let\oldtitledquestion\titledquestion
\renewcommand{\titledquestion}{\stepcounter{fakecount}\oldtitledquestion}
\let\oldbonustitledquestion\bonustitledquestion
\renewcommand{\bonustitledquestion}{\stepcounter{fakecount}\oldbonustitledquestion}

At this point, you only have to use \titledquestion instead of \question and \bonustitledquestion instead of \bonusquestion to let it work.

MWE (notice the use of \leavevmode before EnvFullwidth environments to avoid unwanted behaviors...)

\documentclass[11pt,addpoints]{exam}
\usepackage{lipsum}
\newcounter{fakecount}[section]
\qformat{\thefakecount. (\thepoints) \thequestiontitle\hfill}
\bonusqformat{\thefakecount. (\thebonuspoints) \thequestiontitle\hfill}

\begin{document}

\begin{questions}
\let\oldtitledquestion\titledquestion
\renewcommand{\titledquestion}{\stepcounter{fakecount}\oldtitledquestion}
\let\oldbonustitledquestion\bonustitledquestion
\renewcommand{\bonustitledquestion}{\stepcounter{fakecount}\oldbonustitledquestion}

\begin{EnvFullwidth}
\section{Short Answer}
\lipsum[2]
\end{EnvFullwidth}

\begingradingrange{section1}
\titledquestion{First Question}[5]
\titledquestion{Second Question}[5]
\endgradingrange{section1}

\leavevmode
\begin{EnvFullwidth}
\section{Multiple Choice}
\lipsum[2]
\end{EnvFullwidth}

\begingradingrange{section2}
\titledquestion{First Question}[2]
\titledquestion{Second Question}[2]
\endgradingrange{section2}

\leavevmode
\begin{EnvFullwidth}
\section{Extra Credit}
\lipsum[2]
\end{EnvFullwidth}

\bonustitledquestion{Bonus}[5]
\end{questions}

\begin{center}
\begin{tabular}{|r|c|c|}
 \hline
 \multicolumn{3}{|c|}{\textbf{Exam Score}}                           \\ \hline
 \textbf{Section} & \textbf{Points}                 & \textbf{Score} \\ \hline
 Short Answer     & \pointsinrange{section1}        &                \\ \hline
 Multiple Choice  & \pointsinrange{section2}        &                \\ \hline
 Bonus            & \numbonuspoints                 &                \\ \hline
 Total            & \numpoints                      &                \\ \hline
\end{tabular}
\end{center}

\end{document} 

Output:

enter image description here

3
  • 1
    Great! And just in the nick of time for the bounty! Jan 9, 2015 at 14:18
  • @SethMMorton Happy that this is what you wanted. And thanks for the bounty. Jan 9, 2015 at 17:15
  • If the body of the question starts with a verbatim (or Verbatim from the fancyvrb package), the question starts from the same line instead of the next. Leaving the standard empty line for paragraphs or forcing vspace doesn't seem to work in that case either. Oct 8, 2019 at 17:50
6

I know this is not exactly what you were looking for, but the mechanism that is behind the calculation of points in the exam class is so intricate that I propose you a different solution.

As you may know, the issue arises when you use more than one questions environment, so my suggestion is to embed \sections and whatever else in a EnvFullwidth environment inside only one questions environment.

In this way you can also eliminate the patches you have in your preamble.

MWE:

\documentclass[11pt,addpoints]{exam}
\usepackage{lipsum}

\begin{document}

\begin{questions}
\begin{EnvFullwidth}
\section{Short Answer}
\lipsum[2]
\end{EnvFullwidth}

\begingradingrange{section1}
\question[5] First Question
\question[5] Second Question
\endgradingrange{section1}

\begin{EnvFullwidth}
\section{Multiple Choice}
\lipsum[2]
\end{EnvFullwidth}

\begingradingrange{section2}
\question[2] First Question
\question[2] Second Question
\endgradingrange{section2}

\begin{EnvFullwidth}
\section{Extra Credit}
\lipsum[2]
\end{EnvFullwidth}

\bonusquestion[5] Bonus
\end{questions}

\begin{center}
\begin{tabular}{|r|c|c|}
 \hline
 \multicolumn{3}{|c|}{\textbf{Exam Score}}                           \\ \hline
 \textbf{Section} & \textbf{Points}                 & \textbf{Score} \\ \hline
 Short Answer     & \pointsinrange{section1}        &                \\ \hline
 Multiple Choice  & \pointsinrange{section2}        &                \\ \hline
 Bonus            & \numbonuspoints                 &                \\ \hline
 Total            & \numpoints                      &                \\ \hline
\end{tabular}
\end{center}

\end{document} 

Output (table):

enter image description here

3
  • Thanks for the suggestion, but the problem with this method is that it does not reset the questions numbers to 1 at the start of each section, and this is a requirement for me. Dec 30, 2014 at 15:44
  • Is there a way to make the question numbers display an offset from the internal counter (i.e. questionnumber - offset)? This way at each section I could modify the offset to make it appear that the counter was reset to 1 without messing with the exam internals. Jan 4, 2015 at 21:11
  • @SethMMorton See the other answer of mine. Jan 9, 2015 at 8:25
1

Sorry, I don't know nothing about exam package. I've only kept your markup in your example code and defined the sequences \begingradingrange, \endgradingrange, \question, \bonusquestion \pointsinrange, \numbonuspoints and \numpoints in order they work what do you need. I've totally ignored the features of exam. May be this is wrong because you need to connect the exam features with features described here. But my example shows that if we know TeX primitives then we needn't to use external package and do complicated patches on this package, because it is more simple to write own code.

\documentclass[11pt,addpoints]{exam}

\newcount\qnum \newcount\points \newcount\totpoints
\def\begingradingrange#1{\bgroup\def\currrange{#1}}
\def\endgradingrange#1{%
   \expandafter\xdef\csname p:\currrange\endcsname{\the\points}%
   \egroup\vskip2\baselineskip}
\def\question[#1]{\par\everypar={}\smallskip
  \advance\qnum by1 \advance\points by#1 \global\advance\totpoints by#1
  \indent\llap{\the\qnum. }(#1 point\ifcase#1s\or\else s\fi)
  \ignorespaces
}
\def\bonusquestion[#1]{%
  \expandafter\gdef\csname p:bonus\endcsname{#1}% 
  \question[#1]%
}
\def\pointsinrange#1{\csname p:#1\endcsname}
\def\numpoints{\the\totpoints}
\def\numbonuspoints{\csname p:bonus\endcsname}

\begin{document}

\section{Short Answer}
%\begin{questions}
\begingradingrange{section1}
\question[5] First Question
\question[5] Second Question
\endgradingrange{section1}
%\end{questions}

\section{Multiple Choice}
%\begin{questions}
\begingradingrange{section2}
\question[2] First Question
\question[2] Second Question
\endgradingrange{section2}
%\end{questions}

\section{Extra Credit}
%\begin{questions}
\bonusquestion[5] Bonus
%\end{questions}
\bigskip

\begin{center}
\begin{tabular}{|r|c|c|}
 \hline
 \multicolumn{3}{|c|}{\textbf{Exam Score}}                           \\
\hline
 \textbf{Section} & \textbf{Points}                 & \textbf{Score} \\
\hline
 Short Answer     & \pointsinrange{section1}        &                \\
\hline
 Multiple Choice  & \pointsinrange{section2}        &                \\
\hline
 Bonus            & \numbonuspoints                 &                \\
\hline
 Total            & \numpoints                      &                \\
\hline
\end{tabular}
\end{center}

\end{document}
1
  • 1
    Thank you for the suggestion, but there are other features of the exam class that I need besides what I showed in the MWE, Jan 4, 2015 at 21:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .