% livexam.cls

% A customisation of exam.cls, intended for use in preparing
% University of Liverpool exam papers.  

% Ian Thompson 03 May 2013

\NeedsTeXFormat{LaTeX2e}

\ProvidesClass{livexam}[2013/05/03 \space\space Ian Thompson]

\typeout{+++++++++++++++++++++}
\typeout{+ BETA TEST VERSION +}
\typeout{+++++++++++++++++++++}

\RequirePackage[final]{graphicx} %Needed for the logo
\RequirePackage{amsmath}  %Needed for the definition of \emarks

%Option for final or draft mode
\newif\if@final
\@finalfalse %Default to draft mode
\DeclareOption{final}{\@finaltrue}
\DeclareOption{draft}{\@finalfalse}

%Ultimately, exam.cls depends on article.cls. Here we gobble up any
%article options that would mess with the format of the exam.
\DeclareOption{a5paper}{\ClassWarning{livexam}{Exams use a4 paper; option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{b5paper}{\ClassWarning{livexam}{Exams use a4 paper; option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{letterpaper}{\ClassWarning{livexam}{Exams use a4 paper; option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{legalpaper}{\ClassWarning{livexam}{Exams use a4 paper; option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{executivepaper}{\ClassWarning{livexam}{Exams use a4 paper; option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{landscape}{\ClassWarning{livexam}{option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{twoside}{\ClassWarning{livexam}{option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{titlepage}{\ClassWarning{livexam}{option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{twocolumn}{\ClassWarning{livexam}{option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{8pt}{\ClassWarning{livexam}{Font size too small! Option '\CurrentOption' ignored\MessageBreak}}
\DeclareOption{9pt}{\ClassWarning{livexam}{Font size too small! Option '\CurrentOption' ignored\MessageBreak}}

\DeclareOption{a4paper}{\OptionNotUsed}

\DeclareOption*{%
  \PassOptionsToClass{\CurrentOption}{exam}%
}
\ProcessOptions\relax

\typeout{**************}
\if@final
  \typeout{* FINAL MODE *}
\else
  \typeout{* DRAFT MODE *}
\fi
\typeout{**************}

%A despicable hack. This tricks exam.cls into loading extarticle.cls 
%rather than article.cls, thereby enabling large font sizes. 
\let\oldloadclass\LoadClass
\let\oldpassoptionstoclass\PassOptionsToClass
\def\LoadClass#1{\oldloadclass{extarticle}}
\def\PassOptionsToClass#1#2{\oldpassoptionstoclass{\CurrentOption}{extarticle}}
\oldloadclass{exam}
\let\LoadClass\oldloadclass
\let\PassOptionsToClass\oldpassoptionstoclass

%In 17pt and 20pt mode, we will reduce the size of the headers and footers
\def\hf@size{\normalsize}

\ifnum\@ptsize = 17
  \def\hf@size{\small}
\fi

\ifnum\@ptsize = 20
  \def\hf@size{\footnotesize}
\fi

%Put margin notes on the left
\reversemarginpar

%Set page geometry. The title page is slightly wider than the rest.

\if@final
  \ifnum\@ptsize > 12
    \typeout{* Narrowing margins for large font mode. *}
    \RequirePackage[a4paper,headheight=4em,voffset=43pt,textwidth=471pt,textheight=622pt,headsep=30pt,marginparwidth=45pt]{geometry} 
  \else
    \RequirePackage[a4paper,headheight=4em,voffset=43pt,textwidth=441pt,textheight=622pt,headsep=30pt,marginparwidth=45pt]{geometry} 
  \fi
\else
  \ifnum\@ptsize > 12
    \RequirePackage[a4paper,headheight=4em,voffset=43pt,textwidth=452pt,textheight=622pt,headsep=30pt,marginparwidth=45pt]{geometry}
  \else
    \RequirePackage[a4paper,headheight=4em,voffset=43pt,textwidth=420pt,textheight=622pt,headsep=30pt,marginparwidth=45pt]{geometry}
  \fi
\fi

%Enable testing for hyperref later on.
\newif\if@lbhyperrefloaded
\AtBeginDocument{\@ifpackageloaded{hyperref}{\@lbhyperrefloadedtrue}{\@lbhyperrefloadedfalse}}

%Set up commands for gathering information about the exam.
\let\@papercode\relax
\let\@papertitle\relax
\let\@examiner\relax
\let\@phone\relax
\let\@examlength\relax
\let\@rubric\relax
\let\@paperyear\relax
%\let\@examperiod\relax
\let\@exammonth\relax
\let\@paperdescription\relax
\let\@papernote\relax

\newcommand\modulecode[1]{\def\@papercode{#1}}
\newcommand\moduletitle[1]{\def\@papertitle{#1}}
\newcommand\examiner[1]{\def\@examiner{#1}}
\newcommand\phone[1]{\def\@phone{#1}}
\newcommand\timeallowed[1]{\def\@examlength{#1}}
\newcommand\rubric[1]{\def\@rubric{#1}}
\newcommand\paperyear[1]{\def\@paperyear{#1}}
\newcommand\papermonth[1]{\def\@exammonth{#1}}
\newcommand\paperdescription[1]{\def\@paperdescription{#1}}
\newcommand\papernote[1]{\def\@papernote{#1}}

\newif\if@specialpaper
\@specialpaperfalse
\newcommand\specialpaper{\@specialpapertrue}

%Set footers
\pagestyle{headandfoot}
\lfoot{\hf@size Paper Code \, \textbf{\@papercode}}
\cfoot{\hf@size Page \thepage\ of \numpages}
\rfoot{\hf@size \iflastpage{END}{CONTINUED}}

%Set headers
\if@final
  \firstpageheader{%
  \framebox{\begin{tabular}{l@{}} 
    \hf@size PAPER CODE NO.\\ 
      \hf@size \textbf{\@papercode} 
  \end{tabular}}}
  {}{%
  \begin{tabular}{l@{}ll@{}}
      \hf@size EXAMINER: \space& \hf@size\textbf{\@examiner}    & TEL.NO. \@phone \\
      \hf@size DEPARTMENT: \space & \hf@size{}Mathematical Sciences &
  \end{tabular}
  }
  \runningheader{}{\includegraphics[height=48pt]{bwlogo}}{}
\else
  \lhead{\hf@size Draft version}
  \rhead{\hf@size \today}
\fi

%Final version will test for \maketitle
\newif\ifmaketitle
\maketitlefalse

\if@final
  \AtEndDocument{%
    \ifmaketitle\relax\else
    \ClassError{livexam}{Final version requires maketitle}{I have helped you enough already}
  \fi}
%
% Set up title page for final mode 
  \renewcommand\maketitle{%
%
  \maketitletrue

  %Helpful reminders for anyone who forgets the required information
  \ifx\@papertitle\relax
    \ClassError{livexam}{No paper title provided}{I have helped you enough already}
    \def\@papertitle{\fbox{TITLE MISSING!}}
  \fi

  \ifx\@examlength\relax
    \ClassError{livexam}{No exam length provided}{I have helped you enough already}
    \def\@examlength{\fbox{EXAM LENGTH MISSING!}}
  \fi

  \ifx\@rubric\relax
    \ClassError{livexam}{No rubric provided}{I have helped you enough already}
    \def\@rubric{\fbox{RUBRIC MISSING!}}
  \fi

  \ifx\@examiner\relax 
    \ClassError{livexam}{No examiner name provided}{I have helped you enough already}
    \def\@examiner{\fbox{EXAMINER NAME MISSING!}}
  \fi

  \ifx\@phone\relax
    \ClassError{livexam}{No telephone extension provided}{I have helped you enough already}
    \def\@phone{\fbox{TELEPHONE EXTENSION MISSING!}}
  \fi

  \ifx\@papercode\relax
    \ClassError{livexam}{No exam paper code provided}{I have helped you enough already}
    \def\@papercode{\fbox{PAPER CODE MISSING!}}
  \fi

  %Only check month and year for standard paper types
  \if@specialpaper\else

    \ifx\@exammonth\relax
      \ClassError{livexam}{No exam month provided}{I have helped you enough already}
      \def\@exammonth{\fbox{MONTH MISSING!}}
    \fi

    \ifx\@paperyear\relax
      \ClassError{livexam}{No paper year provided}{I have helped you enough already}
      \def\@paperyear{\fbox{YEAR MISSING!}}
    \fi

    %The class builds its own description in this case
    \ifx\@paperdescription\relax\else\ClassWarning{livexam}{Exam description ignored}\fi
    \def\@paperdescription{\@exammonth\ \@paperyear\ Examinations}

  \fi

  %Now it's time to construct the front page
  \begin{center}
  \includegraphics[height=4em]{bwlogo}
  \vskip70pt
  \MakeUppercase{\textbf{\large \@paperdescription}}

  \if@specialpaper
    \par\vskip25pt
    \parbox{0.8\textwidth}{\@papernote}
    \par\vskip50pt
  \else
    \ifx\@papernote\relax\else\ClassWarning{livexam}{Paper note ignored}\fi
    \par\vskip70pt
  \fi

  \textbf{\large \@papertitle}

  \ifprintanswers
    \vskip20pt{ \Huge\bfseries SOLUTIONS\par } \vskip50pt
  \else
    \vskip80pt
  \fi

  \textsc{Time allowed:} \@examlength\par
  \rule{\textwidth}{1pt}
  \par\bigskip
  \parbox{0.79\textwidth}{INSTRUCTIONS TO CANDIDATES: \@rubric}
  \end{center}
  %Reset width to its standard value, and start a new page.
  \ifnum\@ptsize > 12
    \newgeometry{headheight=4em,voffset=43pt,textwidth=442pt,textheight=622pt,headsep=30pt,marginparwidth=45pt}
  \else
    \newgeometry{headheight=4em,voffset=43pt,textwidth=412pt,textheight=622pt,headsep=30pt,marginparwidth=45pt}
  \fi
  }
\else
  %No title page in draft mode
  \let\maketitle\relax
\fi

%Marks
\newcommand\markmsg[1]{\ifnum#1=1{mark}\else{marks}\fi}

%Marks following a displayed equation
\newcommand\emarks[1]{\tag*{[#1 \markmsg{#1}]}}

%Marks following text. \par ensures proper alignment, \vskip-\parskip cancels
%the \parskip glue, and \relax prevents the negative glue from appearing as
%the last item on a vertical list, so TeX won't remove it.
\newcommand\tmarks[1]{\hskip4em plus 4em minus 4em\penalty50\hspace*{\fill}~\mbox{[#1 \markmsg{#1}]}\par\vskip-\parskip\relax} 

%Bold numbering for questions
\renewcommand\thequestion{\arabic{question}}
\renewcommand\questionlabel{\textbf{\thequestion.}}

%Set up sectioning
\newcounter{@qsection}
\setcounter{@qsection}{0}
\renewcommand\the@qsection{\Alph{@qsection}}
\newcommand\qsection{%
  \refstepcounter{@qsection}
  \renewcommand\thequestion{\Alph{@qsection}\arabic{question}}
  \par\bigskip\hbox to\textwidth{\hfil\bfseries\Large Section \the@qsection\hfil}\par}

\def\questionshook{%
  \ifnum\value{@qsection}=0
    \settowidth{\leftmargin}{10.\hskip\labelsep}
  \else
    \settowidth{\leftmargin}{A10.\hskip\labelsep}
  \fi
  \labelwidth\leftmargin\advance\labelwidth-\labelsep
  \itemsep=15pt plus 5pt minus 4pt
}


%Redefine subparts: enclose subpart numbers in parentheses, and align
%labels so that the left edge of the widest label coincides with the
%left edge of the text at the next level up. Also set the initial 
%subpart number using the mastersubpart counter.
\newcounter{@widestlabel}
\renewenvironment{subparts}[1][3]
{\bgroup%Just in case anyone tries to be smart when starting the environment.
  \setcounter{@widestlabel}{#1}
  \def\@queslevel{subpart}%
  \list{\subpartlabel}%
    {%
    \usecounter{subpart}
    \def\makelabel##1{\hss\llap{##1}}%
    \settowidth{\leftmargin}{(\roman{@widestlabel})\hskip\labelsep}%
    \labelwidth\leftmargin\advance\labelwidth-\labelsep%
    \topsep=0pt%
    \partopsep=0pt%
    \subpartshook%
    %Old versions of exam.cls allowed the \part command to be used to
    %create subparts (probably not intentionally). A few chancers took
    %advantage of this curious 'feature', so we will reinstate it. 
    \let\part\subpart%
    }%
  }%
  {\endlist\egroup}

\renewcommand\subpartlabel{(\thesubpart)}

%Small subparts arranged in a row. The optional argument can be used
%to adjust spacing. The \item (or \H@item if hyperref is loaded) and
%\par commands are temporarily disabled so that we can call
%\process@subpart, and exam.cls will perform the book keeping that it
%normally does for a subpart.
\newenvironment{tinysubparts}[1][1.1em]%
{\def\@tstmp{#1}
 \gdef\ts@tmrk{\relax}
 \def\tmarks##1{\gdef\ts@tmrk{ \phantom{-}\penalty10000\hskip 0pt plus 1 fill\penalty10000\mbox{[##1 \markmsg{##1}]}\par}}
 \setcounter{subpart}{0}
 \def\@queslevel{subpart}
 \if@lbhyperrefloaded\let\H@item\relax\else\let\item\relax\fi
 \leavevmode\medskip\par\hskip 0pt plus 1 filll\hbox\bgroup}
{\egroup\hskip 0pt plus 1 filll\penalty0\ts@tmrk\par\smallskip}

\newcommand\tinysubpart{%
\refstepcounter{subpart}
\@bonusfalse
\let\@oldpar\par\let\par\relax
\process@subpart
\let\par\@oldpar
\ifnum\value{subpart}>1\hspace{\@tstmp}\fi%Put a space before each tinysubpart except the first. 
\mbox{(\roman{subpart}) }}

%Spacing around equations
\abovedisplayskip=1ex plus3pt minus2pt
\belowdisplayskip=1ex plus3pt minus2pt

%It is perferable to use enumerate (rather than parts and subparts)
%in solutions, because it does not upset the part counting mechanism.
%So...
\renewcommand\labelenumi{(\alph{enumi})}
\renewcommand\labelenumii{(\roman{enumii})}

%End of file livexam.cls
