% UOFTEXAM.STY
%
LaTeX style file for typesetting University of Toronto exams
% Version 1.81
%
% Martin J. Osborne (http://www.economics.utoronto.ca/osborne)
%
% History:
% 1.0 2000/1/29 Developed from style written in 1996
% 1.1 2000/3/19 \PointTable reimplemented as an alignment, with split
% between two tables allowed via optional argument giving
% number of columns
% 1.2 2005/1/28 Added PointsAtRight option.
% 1.3 2005/2/28 Added solutions option, \solution macro, and \roughpage macro.
% 1.4 2005/3/19 Added \xitem to deal with itemizations within questions
% or solutions.
% 1.5 2005/11/20 Added \PointTotal to allow for exams with optional question.
% 1.6 2013/3/22 Added StudentNumberOnly option.
% 1.61 2016/2/17 Bug in effect of draft and solutions options on \PointTable corrected
% 1.7 2016/10/22 Added crowdmark option, which adjusts format to suit Crowdmark test
% 1.71 2016/10/24 Bug in setup of options corrected
% 1.8 2017/10/15 Added crowdmarkAuto option, which, in combination with the crowdmark option,
% generates a format with space on the front page for the boxes for student
% information required for automatic matching
% 1.81 2017/12/1 Implemented crowdmarkAuto option for final exam as well as test.
%
% Problems:
% - Cannot handle an enumeration outside the one that contains the list of
% questions. (But can handle other lists outside that list.)
% - Cannot handle \begin{center} ... \end{center} within document (presumably
% because it calls \item??) Use \hspace{\fill} ... \hspace{\fill}
% instead.
%
% load after article.cls
%
% Future work: Could use \newfield construct from tcilcomm.tex (copy in
% \xy\let) to make style more friendly to SW users---can put all arguments
% at start of document in fields, which will display in SW, and put everything
% in a Shell.
%
\newcommand{\SP}[1]{\vspace*{#1mm}}
\newcommand{\pad}{\vspace*{\fill}}
\newcommand\nextpage{%
\vfil\par\hspace*{\fill}{\bf Page \thepage\ of \protect\pageref{lastpage}}\par\penalty -\@M%
}
% \qcontnextpage puts a statement that the question continues on the
% next page at the bottom of the page, and ends the current page
\newcommand{%
\qcontnextpage}{\hspace*{\fill}\emph{Question continues on next page}\nextpage%
}
% \scontnextpage puts a statement that space for answer continues on the
% next page at the bottom of the page, and ends the current page
\newcommand{%
\scontnextpage}{\hspace*{\fill}\emph{Space for answer continues on next page}\nextpage%
}
\newcommand{\roughpage}[1]{\nextpage{\bfseries #1}\pad}
\newif\ifutx@Draft
% \def\PointTable{} in following probably doesn't have any effect, because \PointTable is defined later?
\DeclareOption{draft}{%
\utx@Drafttrue%
\renewcommand\pad{}%
\renewcommand\nextpage{}%
\renewcommand\qcontnextpage{}%
\renewcommand\scontnextpage{}%
\renewcommand\SP{}%
\renewcommand{\roughpage}[1]{}%
\newcommand\PointTable{}%
}
\newif\ifutx@PointsAtRight
\DeclareOption{PointsAtRight}{\utx@PointsAtRighttrue}
\newif\ifutx@PleaseHandIn
\DeclareOption{PleaseHandIn}{\utx@PleaseHandIntrue}
\newif\ifutx@Solutions
\DeclareOption{solutions}{\utx@Solutionstrue}
\newif\ifutx@StudentNumberOnly
\DeclareOption{StudentNumberOnly}{\utx@StudentNumberOnlytrue}
\newif\ifutx@Crowdmark
\DeclareOption{crowdmark}{\utx@Crowdmarktrue}
\newif\ifutx@CrowdmarkAuto
\DeclareOption{crowdmarkAuto}{\utx@CrowdmarkAutotrue}
\ProcessOptions
\ifutx@Crowdmark%
\renewcommand\nextpage{\vfil\hspace*{\fill}\par\penalty -\@M}
% \qcontnextpage puts a statement that the question continues on the
% next page at the bottom of the page, and ends the current page
\renewcommand{\qcontnextpage}{\hspace*{\fill}\emph{Question continues on next page}\nextpage}
% \scontnextpage puts a statement that space for answer continues on the
% next page at the bottom of the page, and ends the current page
\renewcommand{\scontnextpage}{\hspace*{\fill}\emph{Space for answer continues on next page}\nextpage}
\fi
% The following settings assume you are using a driver that automatically adds a one inch
% margin (which is probably true). If not, you'll need to make adjustments.
\ifutx@Crowdmark
\oddsidemargin -0.6in \evensidemargin -0.6in
\topmargin -0.05in
\textwidth 7.5in
\textheight 9in
\else
\oddsidemargin 0in \evensidemargin 0in
\topmargin 0in
\textwidth 6.5in
\textheight 9in
\fi
\long\def\solution#1{%
\ifutx@Solutions
\begin{description}\xitem[Solution:]#1\end{description}%
\else\fi}
\long\def\comment#1{%
\ifutx@Solutions
\begin{description}\xitem[Comment:]#1\end{description}%
\else\fi}
\long\def\solutionx#1{%
\ifutx@Solutions#1\else\fi}
\def\endexam{%
\ifutx@Solutions%
\vfil\label{lastpage}%
\else\vfil\begin{center}\label{lastpage}{\bfseries End of examination}\\%
\bfseries Total pages: \protect\pageref{lastpage}\\%
\bfseries Total marks: \totalpoints%
\end{center}%
\fi%
}
\newcommand{\Course}[2]{\def\@coursenumber{#1}\def\@coursename{#2}}
\newcommand{\Instructor}[1]{\def\@instructor{#1}}
\newcommand{\TestName}[1]{\def\@testname{#1}}
\newcommand{\Date}[1]{\def\@testdate{#1}}
\newcommand{\Time}[1]{\def\@testtime{#1}}
\newcommand{\Aids}[1]{\def\@aids{#1}}
\newcommand{\QToBeAnswered}[1]{\def\@qtba{#1}}
\gdef\@pointtotal{}
\newcommand{\PointTotal}[1]{\gdef\@pointtotal{#1}}
\newcommand{\SpInstructions}[1]{\def\@spinstructions{#1}}
\def\@studentnameandnumber{%
\noindent\hspace*{\fill}{\bfseries Given name}:\rule{46mm}{0.6pt}\hspace*{2mm}{\bfseries Family name}:\rule{43mm}{0.6pt}\hspace*{\fill}\par\vspace{5mm}
\noindent\hspace*{\fill}{\bfseries Student number}:\rule{45mm}{0.6pt}\hspace*{2mm}%{\bfseries Signature}:\rule{60mm}{0.6pt}\hspace*{\fill}
}
\def\@studentnumber{\noindent\hspace*{\fill}{\bfseries Student number}:\rule{40mm}{0.6pt}\hspace*{\fill}}
\def\@studentemailnamenumber{%
\renewcommand{\arraystretch}{1.5}%
\hspace*{\fill}%
\begin{tabular}{rl}
{\bfseries U of T email address}&\rule{60mm}{0.6pt}\texttt{@mail.utoronto.ca}\\
{\bfseries Surname (last name)}&\rule{60mm}{0.6pt}\\
{\bfseries Given name (first name)}&\rule{60mm}{0.6pt}\\
{\bfseries Student number}&\rule{60mm}{0.6pt}\\
{\bfseries Signature}&\rule{60mm}{0.6pt}
\end{tabular}%
\hspace*{\fill}%
}
\ifutx@Solutions%
\def\@studentinfo{}%
\else
\ifutx@Crowdmark%
\ifutx@CrowdmarkAuto%
\def\@studentinfo{}%
\else%
\def\@studentinfo{\@studentemailnamenumber}%
\fi
\else
\ifutx@StudentNumberOnly%
\def\@studentinfo{\@studentnumber}%
\else
\def\@studentinfo{\@studentnameandnumber}%
\fi
\fi
\fi
\def\@uofthead{\textbf{UNIVERSITY OF TORONTO}\\%
\textbf{Faculty of Arts and Science}\\[4mm]}
\def\@testheader{\begin{center}%
\@uofthead%
\textbf{\@coursenumber\ (\@coursename)}\\%
Instructor: \@instructor\\[4mm]
\textbf{\@testname}\\
\textbf{\@testdate}\\[4mm]%
\textbf{Duration: \@testtime}\\[4mm]%
\ifutx@CrowdmarkAuto
\vspace{9cm}
\fi
\textbf{\@aids}\end{center}%
\noindent
\ifutx@Solutions%
\else
This examination paper consists of \textbf{\protect\pageref{lastpage}} pages and \textbf{\protect\ref{lastquestion}} questions. Please alert an invigilator to any discrepancy.
\fi
The number in brackets at the start of each question is the number of points the question is worth.\vspace*{3mm}\par
\noindent \@qtba\vspace*{3mm}\par
\noindent \@spinstructions}
\def\@crowdmarkheader{\begin{center}%
\@uofthead%
\textbf{\@coursenumber\ (\@coursename)}\\%
Instructor: \@instructor\\[4mm]
\textbf{\@testname}\\
\textbf{\@testdate}\\[4mm]%
\textbf{Duration: \@testtime}\\[4mm]%
\textbf{\@aids}\end{center}%
\noindent
\ifutx@Solutions%
\else
This examination paper consists of \textbf{\protect\pageref{lastpage}} pages and \textbf{\protect\ref{lastquestion}} questions. Please bring any discrepancy to the attention of an invigilator.
\fi
The number in brackets at the start of each question is the number of points the question is worth.\vspace*{3mm}\par
\noindent \@qtba\vspace*{3mm}\par
\noindent \@spinstructions}
\def\@finalheader{\begin{center}%
\@uofthead%
\ifutx@PleaseHandIn{%
\vspace*{-4mm}\hspace*{80mm}\includegraphics[bb=0 0 250 80,height=5mm]{/xy/m/courses/phandin.jpg}\\[-1mm]%
}\else\fi%
\textbf{\@testdate}\\[3mm]
\textbf{\@coursenumber\ (\@coursename)}\\%
Instructor: \@instructor\\[3mm]
\textbf{Duration: \@testtime}\\[3mm]%
\textbf{\@aids}\end{center}%
\ifutx@CrowdmarkAuto
\vspace{9cm}
\fi%
\noindent
This examination paper consists of \textbf{\protect\pageref{lastpage}} pages and \textbf{\protect\ref{lastquestion}} questions. Please bring any discrepancy to the attention of an invigilator. The number in brackets at the start of each question is the number of points the question is worth.\vspace*{3mm}\par
\noindent \@qtba\vspace*{3mm}\par
\noindent \@spinstructions%
}
\def\@compheader{\begin{center}%
\@uofthead%
\textbf{\@testdate}\\[4mm]
{\large\textbf{\@coursename}}\\[4mm]
\textbf{Duration: \@testtime}\\[4mm]%
\textbf{\@aids}\end{center}%
\noindent
This examination paper consists of \textbf{\protect\pageref{lastpage}} pages and \textbf{\protect\ref{lastquestion}} questions. Please bring any discrepancy to the attention of an invigilator. The number in brackets at the start of each question is the number of points the question is worth.\vspace*{3mm}\par
\noindent \@qtba\vspace*{3mm}\par
\noindent \@spinstructions}
\newcommand{\Test}{\thispagestyle{empty}%
\@testheader}
\newcommand{\WriteOnTest}{\thispagestyle{empty}%
\ifx\@studentinfo\empty%
\else\@studentinfo%
\vspace*{4mm}%
\fi
\@testheader}
\newcommand{\Final}{\thispagestyle{empty}%
\@finalheader}
\newcommand{\WriteOnFinal}{\thispagestyle{empty}%
\ifx\@studentinfo\empty%
\else\@studentinfo%
\vspace*{4mm}%
\fi
\@finalheader}
\newcommand{\WriteOnComp}{\thispagestyle{empty}%
\ifx\@studentinfo\empty%
\else\@studentinfo%
\vspace*{4mm}%
\fi
\@compheader}
\let\origendenumerate=\endenumerate
% redefine \end{enumerate} at level 1 to put a label for the last question
% and write number of points for last question and total points on test
% to AUX file (see \item, below)
\def\endenumerate{\ifnum\@enumdepth = 1%
\@bsphack
\protected@write\@auxout{}%
{\string\newlabel{Q\theenumi}{{\theqpoints}{\thepage}}}%
\typeout{Label Q\theenumi\space written by endenumerate}%
\@esphack%
\@bsphack
\ifx\@pointtotal\@empty
\gdef\totalpoints{\thepoints}
\else
\gdef\totalpoints{\@pointtotal}
\fi
\protected@write\@auxout{}%
{\string\newlabel{pointtotal}{{\totalpoints}{\thepage}}}%
\@esphack%
\label{lastquestion}%
\typeout{***** Total points on test: \totalpoints}\fi%
\origendenumerate}
\let\origenddocument=\enddocument
\def\enddocument{\endexam\origenddocument}
\renewcommand{\ps@plain}{%
\ifutx@Crowdmark%
\renewcommand{\@oddhead}{}%
\else%
\renewcommand{\@oddhead}{\hfil\textsc{page \thepage}}%
\fi%
\renewcommand{\@evenhead}{\@oddhead}%
\renewcommand{\@oddfoot}{}%
\renewcommand{\@evenfoot}{}}
\pagestyle{plain}
\newcounter{points}
\newcounter{qpoints}
% Redefine \item so that optional argument in parentheses is number of points
% (while optional argument in brackets has original meaning---for lists
% within questions). Original definition of \item from LATEX.LTX:
% \def\item{\@inmatherr\item
% \@ifnextchar [\@item{\@noitemargtrue \@item[\@itemlabel]}}
% Also make \item at list depth 1 write the number of points on the PREVIOUS
% question (held in qpoints) to the AUX file and reset the qpoints counter.
\def\xitem{%
\@inmatherr\item
\@ifnextchar [\@item{\@noitemargtrue \@item[\@itemlabel]}
}
% For points at right at end of each question
\ifutx@PointsAtRight
\def\@pointsox{\@pointsoe}
\else
\def\@pointsox{\@pointsob}
\fi
\def\item{%
\ifnum\@enumdepth=1\ifnum\thepoints>0%
\@bsphack
\protected@write\@auxout{}%
{\string\newlabel{Q\theenumi}{{\theqpoints}{\thepage}}}%
\typeout{Label Q\theenumi\space written by item}%
\@esphack%
\setcounter{qpoints}{0}\fi\fi%
\@ifnextchar(%
{\@pointsox}%
{\@ifnextchar[%
{\@item}%
{\@points}
}%
}
% Next group of lines for case of number of points in brackets
% after question number
\def\@pointsob(#1){\@noitemargtrue \@item[\@itemlabel]
{[#1]}\addtocounter{points}{#1}\addtocounter{qpoints}{#1}}
% Next group of lines for case of number of point right-justified
% on last line of question. REQUIRES SYNTAX \item (5){Question text}
% (NOTE BRACES!!).
\long\def\@pointsoe(#1)#2{\@noitemargtrue \@item[\@itemlabel]%
\addtocounter{points}{#1}\addtocounter{qpoints}{#1}#2%
{\unskip\nobreak\hfil\penalty50\quad\hbox{}\nobreak\hfill%
\hbox{[#1]}}}
\def\@points{\@noitemargtrue \@item[\@itemlabel]}
\newcounter{qnumber}
\setcounter{qnumber}{1}
% Optional argument of \PointTable splits table into several tables, set
% beside each other (so they fit on first page); argument is number of columns.
% This is the table inserted by the \@pointtable macro
\ifutx@Crowdmark
\def\MakePointTable{% See example on p. 246 of TeXbook. Note ## instead of # here, because this is a macro
\vtop{\offinterlineskip%
\hrule
\halign{
&\vrule##&\strut\quad\hfil##\hfil\quad\cr%
height2pt&\omit&&\omit&\cr% extend rules to meet properly
&Question\hfil&&Points&\cr% row of text
height2pt&\omit&&\omit&\cr% extend rules to meet properly
\noalign{\hrule}% put a horizontal rule
height2pt&\omit&&\omit&\cr% extend rules to meet properly
\enoughrows\cr% the set of rows below the header (\enoughrows is defined when \MakePointTable is run)
height0pt&\omit&&\omit&\cr
}
\hrule
}
}
\else
\def\MakePointTable{%
\vtop{\offinterlineskip%
\halign{%
\vrule##\tabskip 8pt&%
\strut\hfil##&% no of question
\strut\hfil##&% no of points
\vrule##&%
\strut\hfil##\hfil&% space for score
\vrule##\tabskip=0pt\cr%
\noalign{\hrule}\cr
&&&&Score&\cr
\noalign{\hrule}\cr
height2pt&\omit&\omit&&\omit&\cr
\enoughrows\cr
\noalign{\hrule height1.3pt}\cr
height2pt&\omit&\omit&&\omit&\cr
\ifnum\theNoCols=1
&Total&(\protect\ref{pointtotal})&&&\cr\noalign{\hrule}\egroup\egroup%
\else
&\multispan2\hfil{\normalsize Subtotal}&&&\cr\noalign{\hrule}
}
}
\fi
}
\fi
\def\PointTable{\@ifnextchar [{\@pointtableo}{\@pointtable{1}}}
%\def\PointTable{\ifutx@Solutions\else\ifutx@Draft\else{\@ifnextchar [{\@pointtableo}{\@pointtable{1}}}\fi}
\ifutx@Solutions
\def\@pointtableo[#1]{}
\else
\ifutx@Draft
\def\@pointtableo[#1]{}
\else
\def\@pointtableo[#1]{\@pointtable{#1}}
\fi
\fi
% If lastquestion not yet defined (no AUX file, because this is first run)
% then make \@pointtable null. (If not, will get TeX error when run before
% AUX file exists.)
\ifutx@Solutions
\def\@pointtable#1{}
\else
\ifutx@Draft
\def\@pointtable#1{}
\else
\ifutx@Crowdmark
\def\@pointtable#1{\@ifundefined{r@lastquestion}{}%
{%
\newcounter{NoCols}\setcounter{NoCols}{#1}%
\newcounter{NoColsLeft}\setcounter{NoColsLeft}{#1}%
\newcounter{NoOfQPerCol}
\newcounter{NoOfQ}
\newcounter{QLeft}
\newcounter{QLimit}\setcounter{QLimit}{0}
\hskip 0pt% attempt to correct vertical spacing (messes up horiz spacing)
% first set NoOfQ equal to number of questions on test
% (\setcounter doesn't seem to work with \ref{lastquestion})
\loop\ifnum\theNoOfQ<\ref{lastquestion}\addtocounter{NoOfQ}{1}\repeat
\setcounter{QLeft}{\value{NoOfQ}}
{\ifnum\theNoCols<4\large\fi% for crowdmark, use \large in all cases
\ifnum\theNoCols=4\large\fi%
\loop\ifnum\theNoColsLeft>0%
\setcounter{NoOfQPerCol}{\value{QLeft}}%
% divide NoOfQ by number of columns left to get NoOfQPerCol
\divide\value{NoOfQPerCol} by\value{NoColsLeft}%
\addtocounter{QLimit}{\value{NoOfQPerCol}}%
\xdef\enoughrows{}% see p. 373 of TeXbook re. next few lines
{\loop% must be within group (TeXbook example bottom p. 218)
\ifnum\theqnumber<\theQLimit%
\xdef\enoughrows{%
\enoughrows%
&\theqnumber&&\protect\ref{Q\theqnumber}&\cr%
height2pt&\omit&&\omit&\cr%
}%
\addtocounter{qnumber}{1}%
\repeat}%
\xdef\enoughrows% add last row
{%
\enoughrows
&\theqnumber&&\protect\ref{Q\theqnumber}&\cr%
}%
\hfil\MakePointTable\hfil%
\addtocounter{qnumber}{1}%
\addtocounter{NoColsLeft}{-1}%
\addtocounter{QLeft}{-\value{NoOfQPerCol}}%
\repeat%
\ifnum\theNoCols>1{%
\par\vskip 8mm\par\hfill\begin{tabular}{|c|c|}\hline\large Total&\protect\ref{pointtotal}\\\hline%
\end{tabular}\hfill%
}\fi%
}% end of scope of \Large
}% end of second argument of \@ifundefined
}% end of @pointtable
\else
\def\@pointtable#1{\@ifundefined{r@lastquestion}{}%
{%
\vspace{5mm}\hspace*{\fill}For graders' use:\hspace*{\fill}\par
\newcounter{NoCols}\setcounter{NoCols}{#1}%
\newcounter{NoColsLeft}\setcounter{NoColsLeft}{#1}%
\newcounter{NoOfQPerCol}
\newcounter{NoOfQ}
\newcounter{QLeft}
\newcounter{QLimit}\setcounter{QLimit}{0}
\hskip 0pt% attempt to correct vertical spacing (messes up horiz spacing)
% first set NoOfQ equal to number of questions on test
% (\setcounter doesn't seem to work with \ref{lastquestion})
\loop\ifnum\theNoOfQ<\ref{lastquestion}\addtocounter{NoOfQ}{1}\repeat
\setcounter{QLeft}{\value{NoOfQ}}
{\ifnum\theNoCols<4\Large\fi% if 4 or more cols, \Large doesn't fit
\ifnum\theNoCols=4\large\fi%
\loop\ifnum\theNoColsLeft>0%
\setcounter{NoOfQPerCol}{\value{QLeft}}%
% divide NoOfQ by number of columns left to get NoOfQPerCol
\divide\value{NoOfQPerCol} by\value{NoColsLeft}%
\addtocounter{QLimit}{\value{NoOfQPerCol}}%
\xdef\enoughrows{}% see p. 373 of TeXbook re. next few lines
{\loop% must be within group (TeXbook example bottom p. 218)
\ifnum\theqnumber<\theQLimit%
\xdef\enoughrows{%
\enoughrows%
&\theqnumber&(\protect\ref{Q\theqnumber})&&&\cr%
\noalign{\hrule}%
height2pt&\omit&\omit&&\omit&\cr%
}%
\addtocounter{qnumber}{1}%
\repeat}%
\xdef\enoughrows% add last row
{%
\enoughrows &\theqnumber&(\protect\ref{Q\theqnumber})&&&\cr%
}%
\hfil\MakePointTable\hfil%
\addtocounter{qnumber}{1}%
\addtocounter{NoColsLeft}{-1}%
\addtocounter{QLeft}{-\value{NoOfQPerCol}}%
\repeat%
\ifnum\theNoCols>1{%
\par\vskip 8mm\par\hfill\begin{tabular}{|c|c|}\hline\Large Total
(\protect\ref{pointtotal})&\phantom{XXXX}\\\hline%
\end{tabular}\hfill%
}\fi%
}% end of scope of \Large
}% end of second argument of \@ifundefined
}% end of @pointtable
\fi
\fi
\fi
% Miscellaneous commands unconnected with exam format
\renewcommand{\descriptionlabel}[1]{\hspace\labelsep
\normalfont\bfseries #1\phantom{.}}
\setlength\tabcolsep{12\p@}
\long\def\@makecaption#1#2{%
\vskip\abovecaptionskip
\sbox\@tempboxa{\footnotesize{\bf #1}. #2}%
\ifdim \wd\@tempboxa >\hsize
\footnotesize{\bf #1}. #2\par
\else
\global \@minipagefalse
\hbox to\hsize{\hfil\box\@tempboxa\hfil}%
\fi
\vskip\belowcaptionskip}
\def\argmax{\mathop{\rm arg\,max}}
\def\argmin{\mathop{\rm arg\,min}}
\def\realR{\mathbb{R}}
\renewcommand{\section}{\@startsection {section}{1}{\z@}%
{-3.5ex \@plus -1ex \@minus -.2ex}%
{2.3ex \@plus.2ex}%
{\reset@font\bfseries}}
\renewcommand{\subsection}{\@startsection{subsection}{2}{\z@}%
{-3.25ex\@plus -1ex \@minus -.2ex}%
{1.5ex \@plus .2ex}%
{\reset@font\itshape}}
\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{\z@}%
{-3.25ex\@plus -1ex \@minus -.2ex}%
{-1em}%
{\reset@font\normalsize\itshape}}
\renewcommand{\paragraph}{\@startsection{paragraph}{4}{\z@}%
{3.25ex \@plus1ex \@minus.2ex}%
{-1em}%
{\reset@font\normalsize\itshape}}
\renewcommand{\subparagraph}{\@startsection{subparagraph}{5}{\parindent}%
{3.25ex \@plus1ex \@minus .2ex}%
{-1em}%
{\reset@font\normalsize\bfseries}}