% \iffalse % This is exam-n.dtx, which supports formatting exam papers. % % Generated file : DO NOT EDIT % %% Release version exam-n-1.4.0, 2022 October 10. %% See https://purl.org/nxg/dist/exam-n %% and https://heptapod.host/nxg/exam-n %% and https://www.ctan.org/pkg/exam-n %% %%%% File: exam-n.dtx %%%% Copyright 2005--2022, Norman Gray %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% http://www.latex-project.org/lppl.txt %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status `maintained'. %% %% The Current Maintainer of this work is Norman Gray %% %% This work consists of the files exam-n.dtx and exam-n.ins, %% the derived file exam-n.cls, %% and the associated *.clo files. %<+package|driver|example>%%%% Source: a91e9cff7cac, 2022-10-10T13:33:17+01:00 %% %<*package|driver> % %<+package>\NeedsTeXFormat{LaTeX2e} %<+package>\ProvidesClass{exam-n}[2022/10/10 exam-n-1.4.0] %<+package>\typeout{Class: `exam-n-1.4.0 <2022/10/10>} % %<*driver> \documentclass{ltxdoc} \title{exam-n: exam papers} \author{Norman Gray\\(\texttt{norman.gray@glasgow.ac.uk})} \date{Version exam-n-1.4.0, 2022 October 10}% ...rather than exam-n-1.4.0, which isn't reader-focused \usepackage{url} \newcommand\Lopt[1]{\textsf {#1}} % options \newcommand\file[1]{\texttt {#1}} \newcommand\Lcount[1]{\textsl {\small#1}} \newcommand\Lenv[1]{\texttt{\{#1\}}} %environments \newcommand\Lpackage[1]{[\textsf{#1}]} %packages %Make command strings easier to write, with \cmd|\foo| %{\catcode`\<=\active \gdef<#1>{\meta{#1}}} {\catcode`\<=\active \gdef<#1>{{\ensuremath\langle\normalfont\textsl{#1}\ensuremath\rangle}}} \def\cmd{\begingroup \catcode`\\=12 \catcode`\{=12 \catcode`\}=12 \catcode`\#=12 \catcode`\<=\active \catcode`\|=12 \docmd} \def\docmd|#1|{\texttt{#1}\endgroup} \def\secref#1{Sect.~\ref{#1}} % Various definitions of this package, so we can document them. \usepackage{examndefs} % Uncomment \OnlyDescription to skip the implementation %\OnlyDescription \begin{document} \maketitle \tableofcontents \bigskip \DocInput{exam-n.dtx} \end{document} % % % \fi % % \noindent This class file supports creating exam papers. % This is intended as part of a slightly larger system for assembling % and managing the papers, by combining questions from multiple authors. % % This document is addressed to the exams convener, or someone % responsible for the overall exam; it goes into complete detail about % the class file, and how to customise it. There is more compact % documentation for the class, addressed to the authors of individual % questions, in the companion document `Notes for Authors'. % % The most up-to-date version of this class can be found at % \url{http://purl.org/nxg/dist/exam-n}. % % \newpage % % \section{Description} % % Usage: % \begin{verbatim} % \documentclass[options...]{exam-n} % % \begin{document} % \maketitle % \begin{question}...\end{question} % ... % \end{document} % \end{verbatim} % % \subsection{Class options} % \label{s:options} % % The class takes the following options. Note that these options are % processed in order, so if an option changes a default % (for example, \Lopt{draft} sets \Lopt{showsolutions} by default), % then it can be overridden by an option later in the list. % \begin{description} % \item[\Lopt{compose}, \Lopt{draft}, \Lopt{final}] % When composing questions, you should give % the \Lopt{compose} option to \Lenv{exam-n}; when assembling the paper, you % should use \Lopt{draft}; and you should use \Lopt{final} only for % the final version. % The \Lopt{draft} option switches on the \Lopt{showsolutions} % option (below), displays |\comment| remarks, % and makes some mild layout changes. % The \Lopt{compose} option implies the \Lopt{showsolutions} option, % causes questions to be formatted one per page, and turns off % various checks on the number of questions; the \Lopt{draft} option % should have the same pagination as the final paper and shifts the % body of the paper to the left so that marginal comments are % easier to write and read; the \Lopt{final} option turns off the % |\comment| command. % % \item[\Lopt{cmfonts}, \Lopt{psfonts}, \Lopt{mathptm}, % \Lopt{mathtime}, \Lopt{mtpro2}, \Lopt{stix2}] % The \Lopt{cmfonts} option (the default) uses the Computer Modern fonts for the % document, and the other options use PostScript or OpenType fonts. % % The \Lopt{mathtime} or \Lopt{mtpro2} options select PostScript % Times Roman, Helvetica and Courier for the body text, plus either Mathtime or % Mathtime Professional~2 to typeset maths (this is commercially % distributed by % PC\TeX\footnote{\url{https://www.pctex.com/mtpro2.html}}, and % designed to be compatible with Times Roman). A broadly % compatible alternative to this is to use the \Lopt{mathptm} % option, but although this is free, the results aren't impressive. % % A final option is to use the \Lopt{stix2} option to choose % specifically and exclusively the % (free) STIX2 font set\footnote{\url{https://www.stixfonts.org}} % for both text and maths. % On this site, you will need to download and install % the files in the \url{static_otf.zip} bundle. % Note that the support for this option is somewhat experimental, and % at present, this package simply uses (serif) STIX2 roman % for all font shapes. Since the exam style doesn't use any sans serif by % default, this doesn't matter, at some level. The % \Lopt{sansserif} option is not compatible with this option (the option % won't produce any error, but neither will it produce any effect). % % \textbf{FIXME: remove this when unicode-math is working.} % \textbf{Note:} because of an unfortunate interaction between packages, the % \Lpackage{stix2} and \Lpackage{siunitx} packages can produce unexpected % results with some combinations of \TeX\ engine and package version % (specifically, \Lpackage{stix2} plus \Lpackage{siunitx} % and \cmd|\micro| or \cmd|\circ| can produce garbled characters % without \LaTeX\ reporting an error). Before \TeX Live 2021, this % worked correctly with Xe\LaTeX\ and Lua\LaTeX, but not with % pdf\LaTeX; from \TeX Live 2021 this works as expected with % pdf\LaTeX, but works with the other two \emph{only} if you load % the \Lpackage{siunitx} package with % \cmd|\usepackage{siunitx}[=v2]|. I hope that future versions of % one or other of these packages will make clear how this package % should handle them, in a way which avoids this special-casing. % \iffalse See % https://github.com/josephwright/siunitx/issues/550 % https://github.com/josephwright/siunitx/issues/547 % https://github.com/stipub/stixfonts/issues/235 % \fi % % The handling of non-standard fonts has always been slightly % fragile in \LaTeX. % The \Lopt{mtpro2} and \Lopt{stix2} options are those currently % most used by the author, and are therefore the ones most likely % to get the various font nuances correct. % % \item[\Lopt{uprightpi}]By default $\pi$ is set slanted, as is the % usual \LaTeX\ default. When this is referring to the circular % constant, however, this should (in some typesetting styles) be set as an upright letter, in % fonts which support this. If the option \Lopt{uprightpi} is % present, then |\pi| is defined to produce an upright letter, and % the command |\italicpi| is defined to produce the slanted version. % Whether this option is supplied or not, the macro |\uppi| will % produce a single upright~$\pi$. % Note: this is at present implemented % only for the \Lopt{mtpro2} and \Lopt{stix2} options, % and the combination of pdflatex+stix2 does not support |\uppi| at present. % % \item[\Lopt{(no)siunitx}] Load the \Lpackage{siunitx} package, or % not. The default is yes. The |\units| macro, described below, % still exists as an alternative, but will be removed in a % forthcoming release (probably after 1.4.x). % % \item[\Lopt{(no)showsolutions}] % These control whether the solutions to % the questions are shown on the paper or not. \Lopt{showsolutions} is the % default when the either \Lopt{draft} or \Lopt{compose} options is % present, and \Lopt{noshowsolutions} in \Lopt{final} case, % though this will be overridden by one of the % \Lopt{\{no\}showsolutions} options later in the list. % % \item[\Lopt{(no)perquestionmarks} and \Lopt{(no)showmarktotals}] % These control whether mark totals and subtotals are tracked within % the question (perquestionmarks), and whether the total available % marks are displayed at the end of the question (showmarktotals). % See \secref{s:question} for more discussion (this % option was called \Lopt{showmarks} up to release 0.15). % % \item[\Lopt{(no)pageperquestion}] % If the option \Lopt{pageperquestion} is present, then each % question is on a separate page. Option \Lopt{nopageperquestion} % is the default. This is most often set by default by one of the % other options, or by a \file{.clo} file. % % \item[\Lopt{oneside}, \Lopt{twoside}] % These control whether the document is formatted for % one- or twosided printing. This is a standard option, which is % redundant in this case, since in this document style there is no % difference in formatting. You may in principle use other % {article} options, though you are encouraged not to. % % \item[\Lopt{fleqn}] % Display equations flush-left, rather than centred. You generally % won't set this in the |\documentclass| options -- it's here so % that it can be set in a |.clo| file. % % \item[\Lopt{sloppydescription}] % Disables the requirement that all exam metadata be present. See % the discussion of |\universitycoursecode| below. % % \item[\Lopt{mono}, \Lopt{colour}] % The university logo is typeset in colour by default, as is the % solution text; the \Lopt{mono} option causes everything to be in % mono instead. The \Lopt{colour} option does nothing, but is % present for symmetry. % % \item[\Lopt{sansserif}] % Use a sans serif font for the body text. This is plug-ugly, not % least because it doesn't match the maths font; also, it may be % easier or harder for dyslexic students to read (there seems to be % a variety of advice here, in both directions, ranging from % confident to dogmatic, but remarkably little solid evidence % either way). % % \item[\Lopt{largefont}, or \Lopt{hugefont}] % Produce a version of the paper in a `big' font (18pt) or `huge' font (36pt) for % the benefit of students with visual impairments. See notes below. % % \end{description} % % Any other options are interpreted as an instruction to read in a % \file{.clo} file, containing course-, department- or group-specific style % modifications. Most typically, these changes will affect the % rubric, and the sheet of physical constants. % The only generic style option is \Lopt{myclass} % (which is included as an example of how such a file is written). % See \secref{s:custom} below. % % In some circumstances -- for example when processing exam scripts % under the control of a Makefile or script -- it can be convenient to % control package options from outside the package. If there is a % file called \texttt{exam-n.config} in the input path (most likely in % the same directory as the exam paper), then this is read in when any % exam script is processed, and will supplement any % options in the |\documentclass| line. For example, if this file were present % and contained the line |\ExecuteOptions{showsolutions}|, then the % typeset exam would include the solutions. Note that this will % supplement, \emph{but not override}, options in the input file's |\documentclass|; % it is therefore useful only for switching options away from the default. % % The exam-n class includes the \Lpackage{amsmath} package, so you can % make immediate use of amsmath features if you wish (see % \texttt{\small http://www.ams.org/tex/amslatex.html} for discussion). % % The change of font size with the \Lopt{hugefont} option requires a % couple of minor layout changes. You may need to force some similar % changes in the exam paper, in this case. You can do that by bracketing the % adjusted text in \cmd|\ifbigfont\else\fi|; the |\ifbigfont| flag is true in the case of % \Lopt{hugefont}, but not \Lopt{largefont}. If you want the % |\ifbigfont| flag to apply to \Lopt{largefont}, too, then you may % set |\bigfonttrue| in a suitable place. The \Lpackage{amsmath} % \texttt{multline} environment can be useful here. The exams % convener should review the result carefully: a few judicious % \cmd|\ifbigfont\newpage\fi| insertions can make the result look less % awful. The \Lopt{largefont} and \Lopt{hugefont} options apply to % the content of solutions if the \Lopt{showsolutions} option is % present; this may or may not be the optimal choice. % % At the bottom of each page, you see a faint identification code, such % as `QM/123-456'. This consists of an exam identifier, extracted from % the exam preamble, plus a code which changes each time \LaTeX\ is % run. This helps you avoid collation accidents, and to distinguish % between slightly different versions of the printed document. % The identifier is based on the date and time, so changes each time % you run \LaTeX\ on the file (that is, it identifies a printing, % rather than a source-file version). % % \subsection{The Question environment} % \label{s:question} % % Within the document, you include questions within a \Lenv{question} % environment, within which you may further have % \Lenv{questiondata} and \Lenv{solution} environments. % % \DescribeEnv{question} % The \Lenv{question} environment delimits a single exam question. % % Usage, with \Lopt{perquestionmarks}: % \begin{quotation} % \noindent % |\begin{question}|\oarg{questionnumber}\marg{marks}\\ % \dots\\ % |\end{question}| % \end{quotation} % Or, with \Lopt{noperquestionmarks}: % \begin{quotation} % \noindent % |\begin{question}|\oarg{questionnumber}\\ % \dots\\ % |\end{question}| % \end{quotation} % % There are two variants of this environment, depending on whether the % \Lopt{perquestionmarks} option is present or not. If it is present % (the default) then the \Lenv{question} environment takes a non-empty % argument showing the total marks available for a question. % In addition, the class checks that the |\partmarks| commands within the % question (see below) add up to this declared goal mark. % If the \Lopt{showmarktotals} option is present, then this (expected and % checked) total is displayed at the end of the question. % % If the \Lopt{perquestionmarks} option is \emph{not} present, % then questions have no individual marks, the % environment takes no marks argument, and no marks are shown (this is usual % in essay-question exams, which typically comprise a sequence of % short equal-valued questions with an explanatory rubric). % Also, in this case the |\partmarks| command cannot be used within the question. % % The \Lenv{question} environment takes an optional argument, giving % the expected question number. In \Lopt{compose} mode, this is used % as the question number (unsurprisingly). In the two other modes, % this is compared with the question number which would be generated based on the % position in the sequence of \Lenv{question} environments in the file, so % that the first \Lenv{question} environment is for question one, the % second for question two, and so on. If these do not match, the exam % class displays a warning in \Lopt{draft} mode, and produces a fatal % error in \Lopt{final} mode. % The intention is that this can act as a check that all expected % questions are present; see also the |\numquestions| command. % \iffalse XXX How useful is this in fact? Should I just discard this, % especially since includequestion has a similar features? \fi % % \DescribeMacro{\QuestionNumberChecksOff} % In some cases, the questions are not numbered in this % straightforward fashion, so that you might have questions~`2A' % and~`2B'. In this case, the check is not meaningful, and you must % suppress it by calling the macro |\QuestionNumberChecksOff| in the % preamble. After that, you must provide a question-number argument % (in square brackets) for every question. % % Using |\label| within a question sets a label for the question number; % using it within a |\part| (see below) labels the part number. % % In some odder circumstances, you might not want to have any question % numbers at all; for example, you might want to require examinees to % attempt \emph{all} of the questions, and so simply have a mark for % the whole exam. There isn't a mode for this as such, but if you use % the \cs{QuestionNumberChecksOff} macro, and give |[\space]| as the % optional `question number' at the beginning of the \Lenv{question} % environment, then this will have the desired effect. % % \DescribeEnv{solution} % The \Lenv{solution} environment, contained within the \Lenv{question} % environment, contains the solution to the question, or other % notes. It is displayed by default in \Lopt{compose} mode, and % suppressed by default in the others, though this behaviour may be % overridden in either case with the \Lopt{(no)showsolutions} % option. You can have one \Lenv{solution} at the end of your % question, or have multiple ones scattered throughout it. You may % use the |\partmarks| macro within the solution, to indicate the % distribution of marks within (this part of) the solution -- % these, of course, do not count towards the total mark for the % question. You must not have a solution inside a solution. % % \DescribeEnv{questiondata} % At the end of a question, it is frequently useful to include further % information, such as extra equations, or numerical data. These % should be included within a \Lenv{questiondata} environment, in % order for them to be formatted appropriately. You may include % multiple paragraphs, equations, and displays in this environment, as % appropriate. Typically, you will have only one such environment per % question, appearing at the end, but may have several of them if you % really wish to. % % \DescribeEnv{mcq} % Some exams include multiple-choice questions rather than % extended-answer ones. These are numbered in the same sequence as % the other questions, but are formatted and marked-up differently. % \begin{verbatim} % \begin{mcq} % In 1908, where was there an airburst `impact'? % \answer Tunguska % \item Arizona % \item Off the Mexican coast % \item Egypt % \end{mcq} % \end{verbatim} % That is, the \Lenv{mcq} environment contains a list of possible % answers, all of which are indicated by |\item|, except precisely one % correct answer, indicated by |\answer|. % \DescribeMacro{\multiplechoiceanswers} % All multiple-choice questions must have the same number of possible % answers, which is declared with the command \cmd|\multiplechoiceanswers{}| % The \Lenv{mcq} environment is permitted only after |\multiplechoiceanswers|. % It's OK to have a \Lenv{solution} within an \Lenv{mcq} environment, % which might provide further commentary on the correct answer. % % There are various other commands which you may or should use within % the document. % % \DescribeMacro{\includequestion} % It may be convenient to split your exam into a number of separate % source files, such as having one \texttt{.tex} file for each % question. You can include these various source files using the % usual |\input| command. % % If the separate source files have the simple form:\label{s:includequestion} % \begin{verbatim} % \documentclass[compose]{exam-n} % \usepackage{graphicx} % for example % \begin{document} % \begin{question} % ... % \end{question} % \end{document} % \end{verbatim} % then they can be \LaTeX ed separately, for example by the authors of % different questions, but cannot be |\input| % unedited, as described above. If, however, they have \emph{only} % these structures (that is, only the |\documentclass| command, % the \Lenv{document} environment, and zero or more |\usepackage| % or |\RequirePackage| commands), % then you can most conveniently import them unedited using the % |\includequestion| command. % \begin{verbatim} % \includequestion{dynamics2} % \end{verbatim} % This acts like the |\input| command, but disables the listed structures. % It also puts the included command into a group, so that any % (re)definitions of commands are made local-only. % % Recall that the definition of the |\includequestion| command means % that any |\usepackage| commands will be ignored. If you, as a % question author, need certain packages to be present for your % question, you will have to make sure that whoever is assembling the % master file includes those packages there, too. % % That is, we don't try too hard to support including just any old \LaTeX, here: % any complicated preamble requirements in an included file should % probably be managed by the exams convener transplanting them into % the preamble of the main document. This may be an overly % simple-minded approach, and may change in future versions. % % The |\includequestion| command takes an optional argument which % overrides the question number. This caters for the case where % question authors have (unhelpfully) included question numbers in the % files' \Lenv{question} environments, and the case where questions % are not numbered in a straightforward sequence, for example `1', % `2A', `2B', and so on. % % \DescribeMacro{\section} % \DescribeMacro{\subsection} % Some exams are divided into sections, or have other structure which % needs to be spelled out. These are described with the |\section| % command, in a form such as |\section{II}|. You can also add smaller % headers before individual questions with something like % |\subsection{Second semester questions}|. These can appear only % between questions; it is an error to include one of these commands % within a \Lenv{question} or \Lenv{mcq} environment. % % \DescribeMacro{\part} % Questions may be subdivided into parts, such as (a), (b), % (c)..., or (i), (ii), (iii), and so on. Precede each of these with % this |\part| command. The formatting of the part numbers is % controlled by the exam style, as customised in % \secref{s:custom}. This macro starts a new paragraph. % % You can use the |\part| macro within solutions: this is useful if % you have the entire \Lenv{solution} environment at the end of the % question, but distracting if you intersperse the \Lenv{solution} % environments between question parts. The |\part| macro within % solutions increments separately from the increments within the question, % so if you use this in the solutions, you must have as many % |\part|s in the solution as there are parts in the question. % % In some (rare) cases, you may want to force a particular part % number. You can do that with an optional argument |\part[99]| % which overrides the auto-incremented numbering. Note that this % skips the auto-increment of the number but doesn't cancel it, so % if you do this for one part number you should probably do it for % all of them. % % \DescribeMacro{\partmarks} % \DescribeMacro{\partmarks*} % Macros \cmd|\partmarks{}| and \cmd|\partmarks*{}| announce % the number of marks associated with the current part of a question. % The class checks that the number of marks here does add up to the % number declared at the beginning of the {question} environment. % You will typically have just one |\partmarks| per |\part|, but % you can have more if you want. % % The |\partmarks| command will most typically go at the end of a % paragraph, but it may also appear inside an equation (that is, in % |\[...\]|; don't use |$$...$$|), inside one or other % \Lpackage{amsmath} display or \Lenv{equation} environments, or in % a list or other environment. If it appears % inside an environment, the indicator will appear at the % \emph{end} of the environment, independent of where in the % environment the command was typed (which implies that you can't % have more than one inside an environment). The alignment of % the partmarks indicator is not currently as good as I'd like it % to be, in the case of \Lpackage{amsmath} alignments, but this % turns out to be hard to improve. % % The starred version is similar, but budges its indicator upwards % a little, and is a heuristic alternative which is useful in some % cases \emph{after} a list or display, if the placement of the % indicator is otherwise inaesthetic % (if the style of the part-marks indicators happens to be such % that the indicator may be mistaken for an equation number, then % it would be wise to use either |\partmarks| or |\partmarks*| % after the equation, instead). If you use |\partmarks*| within a % display, you might be confronted by an error message, talking % about |\eqno| in maths mode, which is even more incomprehensible % than most \LaTeX\ messages. % % The unstarred version should only be used at the end of a % paragraph, and in fact forces a paragraph end; the starred % version should on stylistic grounds generally be used only at the % end of a paragraph, but it doesn't force one. % % The |\partmarks| command has an optional argument which % indicates the category of the question, thus `bookwork', `unseen', % and so on. If this is present, then the category is included in the % marks indicator. % % The |\partmarks| category/comment will typically be only one or two words % long, and can sit comfortably in the margin. If an author wants to % write more here, then it will be turned into a footnote on the % page. This will obviously change the layout of the page, though % since this text appears only in \Lopt{showsolutions} mode, that % shouldn't be a problem. % % \DescribeMacro{\defaultpartmarkscategory} % If the exams convener wishes to \emph{oblige} people to % include such a category, then they might call % |\defaultpartmarkscategory{category?}| in a package-options (|.clo|) % file, to default the category with a highlighted remark to the question setter. % % \DescribeMacro{\comment} % \cmd|\comment{}| associates a comment with a part of the text. % This is ignored in \Lopt{final} mode, but appears in the margin in the % other modes. % % \DescribeMacro{\author} % The |\author| command is a convenience. Used within a % \Lenv{question} environment -- most naturally just after the % |\begin{question}| -- it creates a comment with the author's % name. Its functionality may be expanded in future, so you should % use this command, rather than a generic |\comment|, when noting % the authorship of a question. % % \DescribeMacro{\shout} % If there is part of a question which is, for example, incomplete, % and which needs a more prominent callout than `comment', then you % should |\shout{...}| it. Shouts appear in all modes (\emph{including} % \Lopt{final}) and appear whether or not the class is showing solutions. % This makes a prominent remark in the text, and also in a list of % shouts at the end of the text. Your co-authors, or the exam % proof-checker, really have no excuse for missing it after that. % % \DescribeMacro{\leftnudge} % For various reasons, most often because of printing problems, it can % be useful to nudge the textblock left or right a little. You should % call the |\leftnudge| command to do this, rather than fiddling with % the underlying \LaTeX\ dimensions yourself. Give the command a dimension % argument such as |\leftnudge{1cm}| to nudge the textblock leftwards % by 1cm. You can give a negative dimension to nudge it rightwards % instead. The \Lopt{draft} option automatically nudges the text % block leftwards, to create a larger right-hand margin for notes. % % \DescribeMacro{\questionpreamble} % If |\questionpreamble| is called, then its contents are displayed % just before the start of the next question. This is useful for text like % |\questionpreamble{And one of\dots}| which might reinforce information in % the examination rubric. % % \subsection{Preamble} % \label{s:preamble} % % \DescribeMacro{\exambanner} % The |\exambanner| macro supplies text like `Examination for the % degrees of\dots'. % Since the contents of this command is automatically uppercased in % some styles, and there are per-department specifics about the punctuation % of abbreviations, you should use the commands |\BSc|, |\MSci|, and % friends (see \secref{s:othercommands}) to set the degree names % appropriately. % % \DescribeMacro{\universitycoursecode} % \DescribeMacro{\degreedescriptions} % \DescribeMacro{\coursetitle} % Declare the identity of the exam with % |\universitycoursecode|, |\schoolcoursecode|, |\coursetitle| and % |\degreedescriptions|. The distinction between these is as follows: % \begin{description} % \item[University course code] % This is the code for the course (and thus for the paper) as it % appears in university information systems, and is a % university-unique code such as `PHYS3031'. % \item[Course title] % This is just a textual name for the course, for example `Quantum Mechanics'. % \item[Degree descriptions] % This is a textual description of the qualifications that the % students doing this exam are heading for. This text has little % formal weight, but might help a lost student realise they're in % completely the wrong exam room\dots. This is something like % |{Physics 3\\Chemical Physics 3}| (separate each description % using |\\|). % \end{description} % All of these are required elements, and the \LaTeX\ compilation will % halt if they are absent. If for some reason the exam % paper does not need these to be present -- perhaps it is a class % test, for example -- then give the class option % \Lopt{sloppydescription}, and the checks for these elements (and for % |\rubric|) are suppressed. The layout may end up looking a little % funny. % % \DescribeMacro{\schoolcoursecode} % There is also a command |\schoolcoursecode|, which is a more % informal, but possibly more recognisable, code for the course/paper, % as it is generally recognised within the school; for example, the % honours Quantum Mechanics course is known within the school as % P304H. Its use is optional. % % \DescribeMacro{\paperident} % It can be convenient to add some identification to each page, if for % no other reason than to double-check that you haven't inserted a % field theory question into an `astronomy for poets' exam. The command |\paperident| % allows you to declare some text which appears at the bottom of each % page of the exam. It will typically repeat some of the text in the % |\schoolcoursecode| or |\degreedescriptions| arguments. % This is generally not necessary, however, as in its absence the % class generates an identifier. This identifier contains the name of % the exam, plus a pair of counters (for example \emph{QM2/98-1177}). The % function is two-fold: (i) since the counters increase monotonically % (they actually encode the date and time when the document % was \LaTeX ed), you can tell which of two superficially similar % documents is the later; and (ii) if you drop a sheaf of papers on the % photocopier floor, you can work out which one is which. % % \DescribeMacro{\examdate} % \DescribeMacro{\examtime} % Give the date and time of the exam with |\examdate| and |\examtime|. % Sometimes an exam may % have different time limits for different qualifications: this case, % separate the various times with |\\|, as in % \cmd|\examtime{9.30am -- 12 noon\\ (or) 9.30am -- 1.45am}|. % % \DescribeMacro{\rubric} % \DescribeMacro{\norubric} % The rubric, provided unsurprisingly by the command |\rubric|, may % contain more than one paragraph, % delimited by the usual blank line. Any emphasised words should be % marked with |\emph| -- they are typically % emphasised with a bold font. The class checks that a rubric has % been specified (unless \Lopt{sloppydescription} is present); if you % really wish to suppress this rubric -- perhaps because the % |\baserubric| is sufficient -- then give the command |\norubric|. % \DescribeMacro{\baserubric} % As well as this exam-specific rubric, the style produces an additional % boilerplate rubric, containing the usual material such as `Do not on % any account attempt to write on both sides of the paper at once. % Calculations may be done on the fingers, but candidates should avoid % counting on their toes unless special permission has been obtained beforehand.' % You will typically not have to change this, but if you do for some % reason, you can override it with the |\baserubric| command. % % Note that the |\baserubric| command is typically used within a |.clo| % file, within the argument to |\OverrideFormatting|. If you wish to % further override this on a per-exam basis, then you will need to do % so after |\OverrideFormatting| has done its work, and thus % immediately after the |\begin{document}|. % % \DescribeMacro{\numquestions} % Finally, declare the number of questions which are to be in the % paper with |\numquestions|. % The class issues a warning if we don't have this number, in draft or % final mode. This is optional -- no check is done if this isn't present. % % % \subsection{Other useful commands} % \label{s:othercommands} % % \DescribeMacro{\BSc\ and friends} % Macros |\BSc|, |\MSci|, |\MSc|, |\MA|, |\MEng| and |\BEng| are used % within the preamble macros to give appropriately capitalised and punctuated % versions of the degree types. % % \DescribeMacro{\vec} % Macro |\vec| is redefined to give bold-font vectors, rather than % vectors with arrows, which is the (weird) \LaTeX\ default. This % should work for bold greek as well as roman. % % \DescribeMacro{\dd} % Macros |\dd| and |\ddd|: |\dd| is a roman d, as used for % differentials; |\ddd| is the same with a preceding thinspace, % as used within integrals; for example % \[ % |\int f(x)\ddd x = \int f(x)\,\dd x| = \int f(x)\ddd x % \] % % \DescribeMacro{\Diffl} % You can typeset derivatives neatly: % \begin{center} % \def\dd{\mathrm{d}} % \begin{tabular}{ll} % |\Diffl{a}{b}| & $\displaystyle \Diffl ab$ \\[2ex] % |\Diffl[2]{a}{b}| & $\displaystyle \Diffl[2]ab$\\[2ex] % |\Diffl*{a}{b}| & $\Diffl* ab$ \\ % |\Diffl*[2]{a}{b}| & $\Diffl*[2]ab$\\ % \end{tabular} % \end{center} % The unstarred versions are for displayed equations, the starred % ones for inline maths. % \DescribeMacro{\Partial} % There is analogous support for partial derivatives with |\Partial|. % % \DescribeMacro{\units} % You should generally type units, and numbers with units, using % the \Lpackage{siunitx} package, which is loaded by the % \Lopt{siunitx} option (which is now enabled by default). However % this class currently also supports a basic |\units| command, % described below. This macro will be removed in a future version % of the class. % % Macros |\units|, |\units*|: you can typeset physical units in % |\rm|, with tilde or dot % acting as a separator between units. Since this is typeset in maths mode, all % other spacing is ignored. The unstarred version includes % leading |\thinspace|, as in |$v=10\units{m.s^{-1}}$|, giving % $v=10\units{m.s^{-1}}$. The starred % version can be used when referring to the unit by itself % (eg axis is |$B/\units*T$|, or $B/\units*T$), and is not % qualifying a number. % % \def\cs#1{$\backslash$\texttt{#1}} % For other useful symbols, see table~\ref{t:symbols}.\footnote{The % package used to support an \cs{au} macro, for astronomical % unit, and \cs{lambdabar} for Compton wavelength, but these have % since been removed. The former is available via % \Lpackage{siunitx}.} % % \begin{table} % \hrule \medskip % \begin{tabular}{rlp{8cm}} % |\e|&$\e^{i\pi}=-1$& the exponential is typeset in an upright rather than % italic shape, as in |$\e^{i\pi}=-1$|.\\ % \end{tabular} % \caption{\label{t:symbols}Miscellaneous symbols} % \medskip\hrule % \end{table} % % % \section{Customising the exam style} % \label{s:custom} % % As described in \secref{s:options} above, any unrecognised % options are interpreted as an instruction to search for and include % a class options file, formed from the name of the unrecognised % option, suffixed with \file{.clo}, which can be anywhere in the % \TeX\ include path. This options file has a fair amount of leeway % to override and adjust the layout of the exam. % % The most typical changes here will be to adjust the exam rubric for % a particular class, with the command |\baserubric|, and to change the % sheet of physical constants, with the command |\constantssheet|. % See the sample file |myclass.clo| for examples. % % Examine this sample \file{SpecialExam.clo} file: % \begin{verbatim} % \typeout{Physics Special exam options, for Special people} % \ExecuteOptions{pageperquestion} % % \OverrideFormatting{ % \renewcommand\FormatPartMarks[1]{\{#1\}} % \renewcommand\FormatPartNumber % {\hbox to 0pt{\hss (\StylePartNumber{partnumber})\hskip1em}} % \let\StylePartNumber\roman % as opposed to \alph % \renewcommand\FormatQuestionNumber % {\hbox to 0pt{\hss \textbf{\@currentquestion}\hskip2.5em}} % } % % \constantssheet{ % \begin{center} % $E=mc^2$ and $c=3\times10^8 {\rm m\,s^{-1}}$ % \end{center} % } % \end{verbatim} % This announces itself, then invokes the exam style's \Lopt{pageperquestion} % option. % % It then includes a number of formatting adjustments, % enclosed within the |\OverrideFormatting| command; the formatting % hooks are described below. % % Then it declares a `constants sheet', which is a display of % constants or equations, or indeed anything else, which is to be % displayed on the second page of the exam. % % The available formatting hooks are as follows: % \begin{description} % % \item[FormatPartMarks] % This formats the indication of the marks carried by a particular % part of a question. In this case, we have chosen to have the marks % contains inside curly brackets, rather than the default square % brackets. By default, the part-marks text will be placed at the end % of the paragraph it completes, flush right, and with at least 2em of % space before it. You can change this default space with % |\@partmarksspace|; as a special case, you can have the text sitting % in the margin instead, by having |\FormatPartMarks| generate a % zero-width box, and setting |\@partmarksspace=0pt|. % % \item[FormatPartNumber] % This overrides how to format the various |\part| markers within a % question, using the \texttt{partnumber} counter. In this case, the % markers will jut into the left-hand margin, rather than being % run-in. % % \item[StylePartNumber] % This overrides how to style the |\part| markers. The default is % |\alph|, but you might prefer, for example, |\Roman| or |\arabic|. % Override this with |\let\StylePartNumber\Roman|. % % \item[FormatQuestionNumber] % If you adjust the part marks, you should probably adjust the % formatting of the question number also. % \end{description} % % If you really want to go to town on reformatting, you can redefine % the command |\maketitle|, which formats the front-page title. When % formatting this, you have access to each of the fragments of text % described in \secref{s:preamble}, via a macro named after the % corresponding command. Thus the argument of the |\exambanner| command % is available in the macro |\@exambanner|. The exception is % |\numquestions|. If you find yourself needing to do this, it might % be worth having a discussion with the style's maintainer -- there % may be a simpler way to get what you want. % % \DescribeMacro{\CheckExamMetadata} % One of the things you may change within the |\maketitle| is the % checking of exam metadata -- which fields are required and which are % optional. You can change these from the default (in % \secref{s:preamble}) by defining a command |\CheckExamMetadata|. % \DescribeMacro{\RequiredMetadata} % This macro takes no arguments, and should use the command % \cmd|\RequiredMetadata{}{}{}| to % perform its tests. % {\catcode`\<=\active Here is the metadata key, such as % |{examdate}|, which corresponds to the macro |\examdate|, is % a brief description of the field, such as |{exam date}|, and % is a longer bit of explanation. If the corresponding % data is missing, then \LaTeX\ stops with an error, and the user can % examine the by pressing the \texttt h key. You can % adjust the test by examining the value of % |\iffussydescription ... \fi|, which is set to |\false| if the \Lopt{sloppydescription} % option was provided.} % % No more clues. If you want to hack at this, see the definition of % |\maketitle| in the class file \file{exam-n.cls}. % Aspire not to break things. % \iffalse %%%CONFIGURE%%% change the following to iffalse for a locally-distributed version\fi % \iftrue % \section{A work-flow} % This class file was developed as part of a move to `\LaTeX ify' the % production of exams in the School of Physics and Astronomy, in the % University of Glasgow. The work-flow which emerged was, roughly, as % follows: % \begin{enumerate} % \item The exam convener (the person in charge of assembling the exam % for a given course or lecture series) creates a Sharepoint directory % which contains a master file % (which consists mostly of |\includequestion| macros), % plus subdirectories each containing a short template file for the % benefit of question authors, and a copy of the % \texttt{notes-for-authors.pdf} instructions. % \item Each of those `question' directories is made visible to, and % read-writable by, the lecturer responsible for that question. They % write and \LaTeX ed their question, and upload it back to % Sharepoint. % \item The exam convener, who has access to the whole tree of % questions, downloads or network-mounts the Sharepoint folder, and % either edits the questions or negotiates with the authors, until % the exam \LaTeX s successfully. The result can then be % snapshotted, and sent off to the external examiner. % \end{enumerate} % This provides a centralised and easily manageable repository % for a previously fiddly and error-prone process. % % In step one, the template file is just one with a \texttt{[compose]} % option, following the brief example on p.\pageref{s:includequestion}. % We had excellent secretarial help to manage this step; it was fiddly the % first couple of times, but largely mechanical thereafter. In Sharepoint, % this step can in principle be automated, though we concluded this % was unnecessary in our case. % % Sharepoint (possibly slightly surprisingly) worked smoothly for us; % in other circumstances a group-writable source code repository, or % an institutional CMS, or even just a shared drive, would work just % as well. The advantage of Sharepoint, from our point of view, was % that it integrated with the university's existing authentication % framework, and was (axiomatically) acceptably secure for the process % of creating exams. % % The majority of our authors were habitual users of \LaTeX\ for % writing journal articles, and with subsequently submitting them to % journals or the arXiv; and when the process was presented in % those terms, with the same advantages, it was readily accepted. % % Thanks to Graham Woan and Rachael MacLaughlan for the numerous % iterations of this process until both it and the class file were stable. % \fi % \section{Example} % % Here is a short example file. There are further examples in the % \texttt{sample/} directory of the distribution. % \begin{macrocode} %<*example> %%%START example (Makefile strips out this block) \documentclass{exam-n} % standard final version %%\documentclass[draft,showsolutions]{exam-n} % draft style, showing solutions %%\documentclass[compose]{exam-n} % compose (author's) style \examdate{Wednesday, 18 May 2005} \examtime{9.30am -- 12 noon\\(or) 9.30am -- 1.45am} \exambanner{Examination for the Degrees of \BSc(Science) and \MSci\ on the Honours Standard} \schoolcoursecode{P304D and P304H} \universitycoursecode{PHYS3031 and PHYS4025} \coursetitle{Quantum Mechanics} %\degreedescriptions{Physics 3, Chemical Physics 3, Physics with % Astrophysics 3, Theoretical Physics 3M, Joint Physics 3} \degreedescriptions{Physics 3\\Chemical Physics 3\\Physics with Astrophysics 3\\Theoretical Physics 3M\\Joint Physics 3} \paperident{GR/P304} \rubric{Candidates for examination in \emph{Quantum Mechanics} should answer question 1 (16 marks) and \emph{either 2A or 2B} (24 marks each)} \numquestions{3} \begin{document} \maketitle \section{I} \begin{question}{20} \part At various points in the development of the mathematical theory of General Relativity, we pick a coordinate system in which differentiation is simple, and do a calculation using non-covariant differentiation, indicated by a comma. We then immediately deduce the covariant result, replacing this comma with a semicolon. Separately, the strong equivalence principle is sometimes referred to as the `comma goes to semicolon' rule. Explain the logic of each of these replacements of a comma with a semicolon, putting particular stress on the distinction between them.\partmarks{10} \part The radial and angular coordinates, $r$ and $\phi$ respectively, of a test particle moving in the Schwartzschild metric exterior to a star of mass $M\ll r$, are related by the equation \[ r = \frac{h^2}M \left( 1 + e\cos\phi + \frac{3M^2}{h^2}e\phi\sin\phi \right)^{-1}, \] where $h$ and $e$ are constants. Show that this equation takes the form of a precessing ellipse, of semi-latus rectum $l=h^2/M$, in which the pericentre line advances each orbit by an amount $\Delta=6\pi M^2/h^2$, stating clearly any assumptions that you make.\partmarks{6} The solar-mass star HD83443 has a 0.35 Jupiter-mass planet that follows a circular orbit of period 2.986 days and radius \SI{0.038}{\astronomicalunit}. Calculate the rate of precession, in arcseconds per year, of the pericentre line of the planet's orbit.\partmarks{4} [Schwartzschild radius of the Sun: \SI{3e3}m; $\SI1\astronomicalunit = \SI{1.5e11}m$] \begin{solution} In the first type of calculation, we do a calculation in the LIF, in which~$\Gamma^i_{jk}=0$, so that single partial differentiation is the same as covariant differentiation. If this process produces a geometrical object such as a scalar or a tensor, then we know that the result is frame-invariant. If the result involves only single partial differentiation -- that is, no second derivatives -- then since partial differentiation is the same as covariant differentiation in these coordinates, we cannot distinguish partial and covariant derivatives, and can replace the commas by semicolons. Since these are now manifestly covariant derivatives, so that the result is a tensor, and thus frame-invariant, the same expression would be true in any frame. The second situation is the statement that the expressions of physical laws in SR, such as the conservation equation $T^{\mu\nu}_{,\nu}=0$, must take the same \emph{form} when written as a covariant equation in GR, crucially without any curvature coupling. The slogan `comma goes to semicolon' is just a mnemonic for this. The distinction is that the first is a mathematical trick, of sorts, whereas the second is a version of the equivalence principle, and thus a statement with deep physical content. They don't have to explain things at this length or with this coherence (?) to get quite a few marks. They just have to show they have a clue. \end{solution} \end{question} \end{document} %%%END example % % \end{macrocode} % % \section{Release notes} % Recent release notes are below. For older notes, see the source % distribution. % % \input{release-notes.dtx} % % \subsection*{Acknowledgements} % \addcontentsline{toc}{subsection}{Acknowledgements} % % This class has greatly benefitted from comments and bug-reports from % Harry Ward, Graham Woan, and Nicolas Labrosse; % and it has received code contributions from Morag Casey. % % \StopEventually{} % \section{Implementation} % % \subsection{\LaTeX3 compatibility}\label{s:compatibility} % % As of release 1.4.0, we depend on the \LaTeX3 hooks mechanism, which % was introduced in 2020. We therefore cannot work with versions % older than that. % % Note that we can't use the (apparently preferable) % |\IfFormatAtLeastTF| command to do this test: we want to continue to % work even when we're using a \LaTeX\ which is too old for this % command to be defined. % \begin{macrocode} \@ifl@t@r\fmtversion{2020/10/01} {\typeout{Format is \fmtversion -- OK!}} {\ClassError{exam-n} {You need a more recent version of LaTeX} {This class now requires a LaTeX version at least 2020/10/01; version \fmtversion\ is too old}} % \end{macrocode} % % \subsection{Options} % % First, process the compose/draft/final option. % Flag |\@draftstatus| 0 represents the final version; 1 is a draft exam; 2 is a % single question being composed % \begin{macrocode} %<*package> \newcount\@draftstatus \@draftstatus=0 % default is final \DeclareOption{compose}{\@draftstatus=2 \@showsolutionstrue \@pageperquestiontrue} \DeclareOption{draft}{\@draftstatus=1 \@showsolutionstrue \@pageperquestionfalse} \DeclareOption{final}{\@draftstatus=0 \@showsolutionsfalse \@pageperquestionfalse} % \end{macrocode} % % Set true to use PostScript fonts % \begin{macrocode} \newif\if@psfonts\@psfontsfalse \DeclareOption{psfonts}{\@psfontstrue} \DeclareOption{cmfonts}{\@psfontsfalse} % \end{macrocode} % % Given that we're using PS fonts, should we use the mathtime fonts, % rather than just the mathptm ones (which aren't really ideal)? It % turns out that we can't test for the presence of the mathtime fonts % from within this class file -- the only reliable way of checking if % they're present is to look for something like rmtmi.pfa, but % |\IfFileExists| isn't able to search for any of those files, only ones % on the \texttt{TEXINPUTS} path such as \texttt{mathtime.sty}, which can be, and are % often, installed without the fonts themselves being present. % \begin{macrocode} \newcount\examn@mtselect \examn@mtselect=0 \DeclareOption{mathptm}{\@psfontstrue\examn@mtselect=0} \DeclareOption{mathtime}{\@psfontstrue\examn@mtselect=1} \DeclareOption{mtpro2}{\@psfontstrue\examn@mtselect=2} \DeclareOption{stix2}{\@psfontstrue\examn@mtselect=3} % \end{macrocode} % % The letter $\pi$ is usually the circular constant, and as such % should be set in an upright greek font. Don't this by default, % since that goes against the usual \LaTeX\ default, but instead % define the [uprightpi] option to support this, where possible. % Not all fonts make this easy. % \begin{macrocode} \newif\ifexamn@uprightpi \examn@uprightpifalse \DeclareOption{uprightpi}{\examn@uprightpitrue} % \end{macrocode} % % Load the \Lpackage{siunitx} package, or not, defaulting yes. % This is now preferred to the |\units| macro, and the latter will be % removed in a forthcoming release. % \begin{macrocode} \newif\ifexamn@siunitx \examn@siunitxtrue \DeclareOption{siunitx}{\examn@siunitxtrue} \DeclareOption{nosiunitx}{\examn@siunitxfalse} % \end{macrocode} % % Switch between serif and sans serif fonts. We make little attempt % to make the latter attractive; this is purely to conform to the % superstition (there seem no more grounds than that) that this is % better for dyslexic students. % \begin{macrocode} \newif\ifexamn@serif \examn@seriftrue \DeclareOption{serif}{\examn@seriftrue} \DeclareOption{sansserif}{\examn@seriffalse} % \end{macrocode} % % Set |\if@showsolutions| true if we are to show the contents of {solution} environments % \begin{macrocode} \newif\if@showsolutions \@showsolutionsfalse \DeclareOption{showsolutions}{\@showsolutionstrue} \DeclareOption{noshowsolutions}{\@showsolutionsfalse} % \end{macrocode} % % Set |\if@pageperquestion| true if we want a new page after each question % (set when printing solutions) % \begin{macrocode} \newif\if@pageperquestion \@pageperquestionfalse \DeclareOption{pageperquestion}{\@pageperquestiontrue} \DeclareOption{nopageperquestion}{\@pageperquestionfalse} % \end{macrocode} % % Set |\if@perquestionmarks| true if we are to expect a marks total to % be specified in the question, subtotals to be specified in the % question, and to include a check, at the end, that the two match up. % \begin{macrocode} \newif\if@perquestionmarks \@perquestionmarkstrue \DeclareOption{perquestionmarks}{\@perquestionmarkstrue} \DeclareOption{noperquestionmarks}{\@perquestionmarksfalse} % \end{macrocode} % % Set |\if@showmarktotals| true if we are to display the expected (and % checked to be actual) total marks at the end of the question. % \begin{macrocode} \newif\if@showmarktotals \@showmarktotalstrue \DeclareOption{showmarktotals}{\@showmarktotalstrue} \DeclareOption{noshowmarktotals}{\@showmarktotalsfalse} % \end{macrocode} % % Support the standard article oneside/twoside options, even though % they do nothing in this class. % \begin{macrocode} \newif\if@twosidepages \@twosidepagesfalse \DeclareOption{twoside}{\@twosidepagestrue} \DeclareOption{oneside}{\@twosidepagesfalse} % \end{macrocode} % % Some options styles want \Lopt{fleqn}, so make it an option to this % class, to be passed on to article and amsmath. % \begin{macrocode} \newif\if@fleqn \@fleqnfalse \DeclareOption{fleqn}{ \@fleqntrue \PassOptionsToPackage{fleqn}{amsmath} \PassOptionsToClass{fleqn}{article} } % \end{macrocode} % % If \Lopt{sloppydescription} is given, then we don't demand that all % the required exam metadata is provided. Failing this, we object, fatally, to % missing information. % \begin{macrocode} \newif\iffussydescription \fussydescriptiontrue \DeclareOption{sloppydescription}{\fussydescriptionfalse} % \end{macrocode} % % The university logo is typeset in colour by default; the \Lopt{mono} % option causes everything to be in mono instead. The \Lopt{colour} % option does nothing, but is present for symmetry. These have to be % |\def|s, by the way, not |\let|s, since the size macros aren't % defined until after \Lpackage{article} has been loaded. It seems % prudent to make the `showing solutions' text a bit more shouty in % this monochrome case. % \begin{macrocode} \def\examn@header@shoutformat#1{{\Large\bfseries #1}} \DeclareOption{mono}{ \PassOptionsToPackage{monochrome}{xcolor} \def\examn@header@shoutformat#1{{\Huge\bfseries #1}} } \DeclareOption{colour}{} % \end{macrocode} % % Options \Lopt{largefont} and \Lopt{hugefont} print versions of the % exam in `big' or `huge' font sizes, to help students with visual impairments. % The available font variants are represented as numbers. % Note: the |\examn@fontvariant| mechanism is in principle more % general than simply size variants, but some of the code below % assumes that |\examn@fontvariant| greater than zero means large % text, and so would need to be adjusted if this becomes untrue. % % The flag |\ifbigfont| is true if the font is `significantly large', % in the sense that exam text, or hyphenation or layout, may have to % be adjusted in this case: % option \Lopt{hugefont} sets it true, option \Lopt{largefont} does % not. It's intended to be a user-visible and -settable flag. % % \emph{Note:} the \Lopt{hugefont} option used to be \Lopt{bigfont}; % the latter is deprecated and may be removed in v1.2. % \begin{macrocode} \newcount\examn@fontvariant \examn@fontvariant=0 % the default \newif\ifbigfont \bigfontfalse \DeclareOption{largefont}{\examn@fontvariant=1 \bigfontfalse} % Deprecate [bigfont]; consider removing in v1.2 \DeclareOption{bigfont}{% \ClassWarning{exam-n}{OPTION [bigfont] HAS BEEN DEPRECATED; use [hugefont] instead} \examn@fontvariant=2 \bigfonttrue} \DeclareOption{hugefont}{\examn@fontvariant=2 \bigfonttrue} % \end{macrocode} % % This class is based on the article class. Load it, and pass the \texttt{a4paper} % option to it. % \begin{macrocode} \PassOptionsToClass{a4paper}{article} % \end{macrocode} % % We allow \file{.clo} files to override elements of the formatting, % such as |\maketitle| and the various |\Format...| hooks. They must % do this within a |\OverrideFormatting| command, using a sequence of % |\renewcommand|s. Carefully. % \begin{macrocode} \newtoks\@styleoverrides \@styleoverrides={} \def\OverrideFormatting{\@styleoverrides=} % \end{macrocode} % % There are a few other settings which may be defaulted within a % \file{.clo} file: % \begin{itemize} % \item |\constantsheet{...}|: is a table of, for example, physical % constants which should appear in exams associated with a particular % course. Despite the name, this can be any text which should appear % on the first non-cover sheet of the exam. % \item |\baserubric|: a modified `base rubric' -- see the % documentation of |\rubric| below. % \end{itemize} % % If \@constantssheet is defined (using |\constantsheet{...}| in a % .clo file), then display it on a page by itself. % \begin{macrocode} \newtoks\@constantstoks \def\@@displayconstants{% \clearpage \begingroup \the\@constantstoks \endgroup \clearpage } % \end{macrocode} % The macro |\constantssheet| has to be declared here, rather in the % more natural place below, with \@exambanner and friends, so that % it's usable within .clo files. % \begin{macrocode} \newtoks\@constantstoks \@constantstoks={} \let\@displayconstants\relax \def\constantssheet{\let\@displayconstants\@@displayconstants \@constantstoks=} % \end{macrocode} % % Similarly for the |\baserubric| and |\rubric| commands. % % The rubric is typically a per-exam thing. The `base rubric' is % more-or-less common to all exams, though it's possible to override % it in a .clo file. % \begin{macrocode} \def\@rubric{} \def\rubric{\long\def\@rubric} \def\norubric{\let\@rubric\@nnil} % \end{macrocode} % \dots and the base rubric: % \begin{macrocode} \def\@baserubric{% \textbf{Answer each question in a separate booklet}\par Candidates are reminded that devices able to store or display text or images may not be used in examinations without prior arrangement. \if@perquestionmarks \par Approximate marks are indicated in brackets as a guide for candidates. \fi } \def\baserubric{\long\def\@baserubric} % \end{macrocode} % % The |\defaultpartmarkscategory| macro creates a default partmarks % `category'. See below. This is declared here, so that it can be % used in a |.clo| file without error. % \begin{macrocode} \let\examn@defaultpartmarkscategory\relax \def\defaultpartmarkscategory#1{\def\examn@defaultpartmarkscategory{#1}} % \end{macrocode} % % Spit out the style overrides at the beginning of the document, % rather than here. % \begin{macrocode} \AtBeginDocument{\the\@styleoverrides} % \end{macrocode} % % Any remaining options are interpreted as filenames, and the % corresponding \file{.clo} file is read in. We do not permit any % other options, for example standard |{article}| options. % There's a complication here (which I haven't resolved, to my % puzzlement): if the .clo file includes for example % |\ExecuteOptions{pageperquestion}|, then a \Lopt{nopageperquestion} % appearing after the .clo option in the |\documentclass| line appears % to be ignored or overwritten, which is odd, since I thought that % options were executed in order; are these file options executed % later than others, perhaps? % \begin{macrocode} \DeclareOption*{\InputIfFileExists{\CurrentOption.clo}{} {\ClassError{exam-n} {Bad option \CurrentOption} {I don't understand the option \CurrentOption\MessageBreak (I didn't find file \CurrentOption.clo, if that's what you meant)}}} % \end{macrocode} % % The default options are set when the options are declared, above. % % If a file called \texttt{exam-n.config} exists, read it in. It may % usefully contain other |\ExecuteOptions{foo}| commands. Note that % these supplement but \emph{will not override} any options in the % |\documentclass| command; thus these are really only useful for % changing away from the default. This last behaviour is % unsatisfactory: it would be better if this would reliably override % any options supplied in |\documentclass|, but that turns out to be % hard to fix, given the \LaTeX\ option logic. % \begin{macrocode} \InputIfFileExists{exam-n.config}{}{} % \end{macrocode} % And finally process all the options marked so far. % \begin{macrocode} \ProcessOptions % \end{macrocode} % % \subsection{Dependencies} % % We depend on the \Lpackage{article} class. % % Note: we have to do this this way, so that % |\PassOptionsToClass{*side}{article}| is invoked only once -- % \Lenv{article} gets confused if both options are passed to it % \begin{macrocode} \if@twosidepages \PassOptionsToClass{twoside}{article} \else \PassOptionsToClass{oneside}{article} \fi \PassOptionsToClass{12pt}{article} % \end{macrocode} % % If the document includes % the \Lpackage{graphicx} or \Lpackage{pdfpages} packages, % then we don't want the \Lopt{draft} option to be passed on. % So explicitly pass the \Lopt{final} option to these packages. % \begin{macrocode} \PassOptionsToPackage{final}{graphicx} \PassOptionsToPackage{final}{pdfpages} % \end{macrocode} % % %%%CONFIGURE%%% % Define a logo for the University, which will appear in the exam header. % This should be a macro which takes a single argument giving the % required width of the logo, and which produces a |\vbox|. % \begin{macrocode} \def\UniLogo#1{\vbox to 15.5mm{% \hrule \vss\hbox to #1{% Aspect ratio of logo is 100x31 \hss no logo available\hss }% \vss \hrule}} % \end{macrocode} % % Other required packages. % \begin{macrocode} \RequirePackage[english]{babel} % UK hyphenation \RequirePackage{amsmath} \ifexamn@siunitx \RequirePackage{siunitx} \fi % \end{macrocode} % We use the \Lpackage{xcolor} package, in preference to % \Lpackage{color}, so that we are compatible with TikZ (TikZ loads % the \Lpackage{xcolor} package internally, and that isn't compatible % with \Lpackage{color}). We could probably work around this some % other way, but \Lpackage{xcolor} seems to be relatively standard, % and appears to be backward compatible with \Lpackage{color}, % so this change is harmless. % \begin{macrocode} \RequirePackage{xcolor} % \end{macrocode} % % I think flush-left equations look MUCH better than centred, but % Harry disagrees, so it's not the default. % \begin{macrocode} \LoadClass{article} % \end{macrocode} % % \subsection{Layout} % % \subsubsection{The \TeX\ engine} % Identify the \TeX\ engine we're using. If we are using pdf\TeX, % Xe\TeX, or Lua\TeX, we presume we're generating PDF. The % \Lpackage{ifpdf} package exists, and evaluates to true for Lua\TeX, % but doesn't distinguish between Xe- and Lua\TeX. % It would be nice to use a package such as \Lpackage{iftex}, but (as of late % 2017) this seems to do something sufficiently exotic with % respect to |\if| nesting, that it confuses the logic here. % It seems safer to do this test ourselves, so (a) we know what % we're getting, and (b) we have the result in a convenient integer form. % \begin{macrocode} \newcount\examn@engine \examn@engine=0 \expandafter\ifx\csname pdfmatch\endcsname\relax \expandafter\ifx\csname XeTeXinterchartoks\endcsname\relax \expandafter\ifx\csname directlua\endcsname\relax \examn@engine=0 % this is presumably original-TeX (how unutterably retro!) \else \examn@engine=3 \fi \else \examn@engine=2 \fi \else \ifnum\pdfoutput>0 \examn@engine=1 \else % this _is_ pdftex, but it's in generate-dvi mode % (we decide not to detect this case with the other engines) \examn@engine=0 \fi \fi % \end{macrocode} % % \subsubsection{Fonts} % % Choose the font set, based on |\if@psfonts| and |\examn@mtselect|. % The following is \emph{messy}, and it's not clear to me if it's % irreducibly so, or whether I'm just doing it the wrong way. % % Case |\examn@mtselect| is 0: the rather hacky \Lpackage{mathptm} solution. % \begin{macrocode} \def\ex@fontlabel{???} \if@psfonts \ifcase\examn@mtselect \def\ex@fontlabel{mathptm} \ifexamn@serif \RequirePackage{times} \else \RequirePackage{helvet} \fi \RequirePackage{mathptm} \ClassWarningNoLine{exam-n}{Using mathptm fonts} % \end{macrocode} % % Case |\examn@mtselect| is 1 or 2: use mathtime or Mathtime Pro 2 fonts % for maths. We use postscript Times and Helvetica for the body fonts % in both cases. % \begin{macrocode} \or \def\ex@fontlabel{mathtime} \RequirePackage[LY1]{fontenc} % specify text font encoding \RequirePackage[LY1,mtbold]{mathtime} % switch math fonts \ifexamn@serif \RequirePackage{times} \else \RequirePackage{helvet} \fi \ClassWarningNoLine{exam-n}{Using Mathtime fonts} \or % use mtpro2 fonts \def\ex@fontlabel{mtpro2} \RequirePackage[T1]{fontenc} \RequirePackage{textcomp} \ifexamn@serif \renewcommand\rmdefault{ptm} % the default \else \RequirePackage[scaled=0.9]{helvet} \renewcommand\rmdefault{phv} \fi \RequirePackage[mtpbb]{mtpro2} \ClassWarningNoLine{exam-n}{Using MTPro2 fonts} % \end{macrocode} % % Finally, case |\examn@mtselect| is 3: use STIX2 fonts: \url{http://www.stixfonts.org}. % Since this requires fontspec, it also requires either XeLaTeX or % LuaLaTeX. If we are in this branch, and not using either % engine, then fail with what we hope is a reasonably clear error. % % First off, refuse to work with original TeX. % \begin{macrocode} \or \def\ex@fontlabel{stix2} \ifcase\examn@engine \ClassError{exam-n} {You can't use STIX fonts with original/DVI LaTeX} {You must use either XeLaTeX or LuaLaTeX} % \end{macrocode} % % Use of the STIX fonts with pdflatex mostly works, but there is a % tricky current/legacy issue here. % The \Lpackage{stix2} package is intended to use the STIX2 % fonts with `legacy' \TeX\ engines. Does this apply to pdflatex, now % it defaults to unicode input? See the discussion of % \Lpackage{unicode-math} below. % % As of TeXLive 2022, this mostly works, in the sense that we do use STIX % fonts, but the upright-pi support below fails (no LaTeX errors, but % |\uppi| produces slanted pi). % \begin{macrocode} \or % pdflatex \RequirePackage{stix2} % \end{macrocode} % % We support only Xe\TeX\ and Lua\TeX\ here, since only these can use % `system' fonts. For Xe\LaTeX\ we use `system' Helvetica and Courier % fonts (slightly scaled) as the sans and mono fonts, respectively, for the sake of % completeness. % % Note: unicode-math is a little complicated. As I (unfortunately) % discovered via mistaken bug report % \url{https://github.com/stipub/stixfonts/issues/235}, % the \Lpackage{stix} package is intended to be used \emph{only} for % `legacy' \TeX\ engines, and \Lpackage{unicode-math} for current ones % such as Xe\LaTeX\ and Lua\LaTeX. % I'm fairly confident (as of 2022 July 11) that the following does % the right thing, but not yet 100% confident. % % Note that (as explained in the \Lpackage{unicode-math} manual, we % should use the STIX Two \emph{Math} font for symbols, and not the % text font. % \begin{macrocode} \or % XeLaTeX \RequirePackage[bold-style=ISO,math-style=ISO]{unicode-math} \setmathfont{STIX Two Math} \setmainfont{STIX Two Text} \or % LuaLaTeX: like XeLaTeX \RequirePackage[bold-style=ISO,math-style=ISO]{unicode-math} \setmathfont{STIX Two Math} \setmainfont{STIX Two Text} \fi % \end{macrocode} % The no-match case shouldn't happen. % \begin{macrocode} \else \def\ex@fontlabel{ERROR} \ClassError{exam-n} {Impossible value of mtselect: \examn@mtselect} {This shouldn't happen -- this is a class file bug} \fi % \end{macrocode} % % There are no font complications when using CM fonts. That's nice. % \begin{macrocode} \else \def\ex@fontlabel{CM} \ClassWarningNoLine{exam-n}{Using CM fonts} \fi % \end{macrocode} % % Report what engine and font configuration we're using. % \begin{macrocode} \typeout{Environment: engine: \ifcase\examn@engine original/DVI\or pdfTeX\or XeTeX\or LuaTeX\else ???\fi; fonts: \ex@fontlabel; options: % show any non-default options \ifexamn@uprightpi uprightpi, \fi \ifexamn@siunitx siunitx, \fi \ifexamn@serif\else noserif, \fi \if@pageperquestion pageperquestion, \fi \if@perquestionmarks\else noperquestionmarks, \fi \if@showmarktotals\else noshowmarktotals, \fi \if@twosidepages twoside, \fi \if@fleqn fleqn, \fi \iffussydescription\else sloppydescription, \fi \ifbigfont hugefont, \fi \if@showsolutions showsolutions\else noshowsolutions\fi} % \end{macrocode} % % If we're using a sans serif font, then redefine |\normalfont| appropriately. % The macro |\examn@bodyfontchange| stores up these font changes until % they're applied just after |\maketitle|. % \begin{macrocode} \def\examn@bodyfontchange{} \ifexamn@serif \else \ClassWarningNoLine{exam-n}{Using sans serif fonts} \DeclareRobustCommand\normalfont {\usefont\encodingdefault\sfdefault\seriesdefault\shapedefault \relax} \fi % \end{macrocode} % And similarly for the case where we want large fonts. % This (as it turns out) requires changing only |\normalsize| and not % |\normalfont|, so the two are in principle compatible; however we % implement both of them by redefining |\examn@bodyfontchange|, so % they're not in practice (a future fix, perhaps). % \begin{macrocode} \ifcase\examn@fontvariant % default: do nothing \def\examn@bodyfontchange{ % ...apart from redefine \small to be more clearly distinct from \normalsize \renewcommand\small{% \@setfontsize\normalsize{9}{11}% \abovedisplayskip 9\p@ \@plus1.5\p@ \@minus5\p@ \abovedisplayshortskip \z@ \@plus2.5\p@ \belowdisplayshortskip 5\p@ \@plus2.5\p@ \@minus2.5\p@ \belowdisplayskip \abovedisplayskip}} \or % font variant 1: 18pt \def\examn@bodyfontchange{ \renewcommand\normalsize{% \@setfontsize\normalsize{18}{24}% \abovedisplayskip 18\p@ \@plus3.5\p@ \@minus9\p@ \abovedisplayshortskip \z@ \@plus5\p@ \belowdisplayshortskip 10\p@ \@plus5\p@ \@minus5\p@ \belowdisplayskip \abovedisplayskip \let\@listi\@listI} \renewcommand\small{% \@setfontsize\normalsize{12}{16}% \abovedisplayskip 12\p@ \@plus2\p@ \@minus6\p@ \abovedisplayshortskip \z@ \@plus4\p@ \belowdisplayshortskip 6.5\p@ \@plus3\p@ \@minus3\p@ \belowdisplayskip \abovedisplayskip} \parindent=24pt \parskip=18pt % Redefine \FormatPartMarks so that it doesn't push the text off the paper \let\FormatPartMarks\examn@variantFormatPartMarks } \or % font variant 2: 36pt \def\examn@bodyfontchange{ \renewcommand\normalsize{% \@setfontsize\normalsize{36}{42}% \abovedisplayskip 36\p@ \@plus7\p@ \@minus17.5\p@ \abovedisplayshortskip \z@ \@plus10.5\p@ \belowdisplayshortskip 21\p@ \@plus10.5\p@ \@minus10.5\p@ \belowdisplayskip \abovedisplayskip \let\@listi\@listI} \renewcommand\small{% \@setfontsize\normalsize{24}{28}% \abovedisplayskip 24\p@ \@plus5\p@ \@minus12\p@ \abovedisplayshortskip \z@ \@plus8\p@ \belowdisplayshortskip 14\p@ \@plus8\p@ \@minus8\p@ \belowdisplayskip \abovedisplayskip} \parindent=48pt \parskip=36pt % Redefine \FormatPartMarks so that it doesn't push the text off the paper \let\FormatPartMarks\examn@variantFormatPartMarks } \else % Bad font variant \ClassError{exam-n} {Bad font variant \examn@fontvariant} {I didn't expect to see that number (broken style file re largefont/hugefont?)} \fi % \end{macrocode} % The above font variants require a |\FormatPartMarks| variant which % avoids being pushed off the edge of the page. % \begin{macrocode} \def\examn@variantFormatPartMarks#1{% \setbox0=\hbox{\hskip 1em \textbf{[#1]}}% \@tempdima=0.8\marginsize \ifdim\wd0>\@tempdima \advance\@tempdima -\wd0 \hbox to 0pt{\hskip\@tempdima \box0\hss}% \else \hbox to 0pt{\box0\hss}% \fi} % \end{macrocode} % % Adjust maths font sizes for the various cases: % \begin{macrocode} \DeclareMathSizes\@xiipt{12}{9}{7} \DeclareMathSizes\@xipt{10}{8}{6} % \end{macrocode} % % \subsubsection{PDF metadata, and other document identifiers} % % Generate an identifier, |\examn@docident| for this paper. This is obtained % from the university or school course code, followed by the % day-of-year, and the number of minutes since midnight (the goal here % is to produce an identifier which automatically increments in time, % but which isn't obviously a date. % % Yes, a big |\ifcase| would be more straightforward; % no, that wouldn't be any fun at all % (also it ends up looking messy and even tricksier). % \begin{macrocode} \def\examn@setdocident{% \begingroup \def\@step##1##2\@nil{\advance\@tempcnta##1 \def\@tempa{##2}} \def\@tempa{{31}{28}{31}{30}{31}{30}{31}{31}{30}{31}{30}{31}}% \@tempcnta=\day % day of month \@tempcntb=\month % month of year (unit-offset) \loop \advance\@tempcntb-1 \ifnum \@tempcntb>0 \expandafter\@step\@tempa\@nil \repeat \@tempcntb=\year % yes, do calculate leap years \divide\@tempcntb 4 \multiply\@tempcntb 4 \ifnum\@tempcntb=\year \ifnum\month>2 % but let's not worry about century years... \advance\@tempcnta 1 \fi \fi % remove any \\ or ~ in the coursecode fields \let\\\space \let~\space \xdef\examn@docident{% first element is based on uni/school course code \ifx\@coursetitle\@empty \ifx\@schoolcoursecode\@empty exam% \else \@schoolcoursecode \fi \else \@coursetitle \fi /\the\@tempcnta % day-of-year -\the\time} % minutes since midnight \endgroup } % \end{macrocode} % % Add information to the PDF document metadata. % \begin{macrocode} \ifcase\examn@engine \let\@SetDocumentInfo\relax % original TeX \or % pdfTeX \def\@SetDocumentInfo{\pdfinfo{/Title (\examn@docident)}}% % Don't put out an /Author(xxx) info entry -- there may be % multiple authors, and it isn't obviously useful \or % XeTeX % dvipdfm special -- see the dvipdfm manual \def\@SetDocumentInfo{\special{pdf: docinfo << /Title (\examn@docident) >>}}% \or % LuaTeX % from the LuaTeX manual \def\@SetDocumentInfo{\pdfextension info {/Title (\examn@docident)}}% \fi \AtBeginDocument{\examn@setdocident\@SetDocumentInfo} % \end{macrocode} % % \subsubsection{Exam metadata} % % \begin{macrocode} \def\@exambanner{} \def\exambanner{\def\@exambanner} \def\@schoolcoursecode{} \def\schoolcoursecode{\def\@schoolcoursecode} \def\@universitycoursecode{} \def\universitycoursecode{\def\@universitycoursecode} \def\@paperident{} \def\paperident{\def\@paperident} \def\@examdate{} \def\examdate{\def\@examdate} \def\@examtime{} \def\examtime{\def\@examtime} \def\@coursetitle{} \def\coursetitle{\def\@coursetitle} % \end{macrocode} % Display the degree descriptions, which are separated by |\\|. Put % each one in an |\hbox|, so it doesn't break over the line. % \begin{macrocode} \def\@degreedescriptions{} \def\degreedescriptions{\def\@degreedescriptions} \def\@displaydegreedescriptions{% \let\@tempb\leavevmode \def\dd##1\\{% \def\@tempa{##1}% \ifx\@tempa\@empty \let\next\relax \else \@tempb\hbox{##1}\let\next\dd \fi \def\@tempb{\discretionary{}{}{\kern0.5em--\kern0.5em}}% \next} \expandafter\dd\@degreedescriptions\\} % \end{macrocode} % % We can optionally check the total number of questions. Store this % if it is present, and add a check to the |\end{document}| to check % it at the end if it was indeed set at the beginning. Command % |\CheckTotalQuestions| is added to |\AtEndDocument| below. % \begin{macrocode} \def\@numquestions{} \def\numquestions{\def\@numquestions} \def\CheckTotalQuestions{% \ifnum\@draftstatus < 2 \ifx\@numquestions\@empty \else \ifnum\c@questionnumber=\@numquestions \else \ClassWarning{exam-n} {Expected \@numquestions\space questions, got \thequestionnumber!} \ifnum\@draftstatus > 0 % draft mode \begin{center} \textbf{\highlighted{Expected \@numquestions\space questions, got \thequestionnumber}} \end{center} \fi \fi \fi \fi } % \end{macrocode} % % % \subsection{Geometry and colours} % % Adjust the spacing for article and amsmath flush-left equations. % Amsmath doesn't use |\mathindent| in the same way \LaTeX\ does, and % this semi-workaround may break with early versions of amsmath. See % the amsmath FAQ at http://www.ams.org/tex/amsmath-faq.html for % some discussion. % \begin{macrocode} \if@fleqn \mathindent\parindent \@mathmargin=\parindent \fi % \end{macrocode} % % |\marginsize| is the size of the margin all round. Users shouldn't % change this in normal circumstances, but are free to if they have % some particular reason. Note that if all you want to do is move the % text to one side for printing reasons, use |\nudgeleft|. % \begin{macrocode} \newdimen\marginsize \marginsize=35mm \headheight=15pt \headsep=15pt % \end{macrocode} % % It's useful to colour-code material that's present in the compose % and draft modes but which won't appear in the final version; this % partly reassures question authors that this is `meta' material. % \begin{macrocode} \definecolor{meta}{rgb}{0.7,0.2,0.2} \def\highlighted{\textcolor{meta}} % \end{macrocode} % We (currently) want solutions to appear as coloured blocks. The % colour is this one: % \begin{macrocode} \definecolor{solutiontext}{rgb}{0.2,0.2,0.5} % \end{macrocode} % And finally a colour for `discreet' information, such as identifier % numbers. % \begin{macrocode} \definecolor{discreettext}{rgb}{0.6,0.6,0.6} % \end{macrocode} % % Set up the textblock in |\@settextblock|. % The argument is the amount by which the text block is to be nudged % to the left. % \begin{macrocode} \newcommand\@settextblock[1]{ \textwidth=\paperwidth \advance\textwidth -2\marginsize \textheight=\paperheight \advance\textheight -2\marginsize \oddsidemargin=\marginsize \advance\oddsidemargin -1in \advance\oddsidemargin -#1 \evensidemargin=\oddsidemargin \topmargin=\marginsize \advance\topmargin -\headheight \advance\topmargin -\headsep \advance\topmargin -1in \marginparwidth=\marginsize \advance\marginparwidth -1.5cm \advance\marginparwidth #1 %% \typeout{paperwidth=\the\paperwidth, paperheight=\the\paperheight, %% textwidth=\the\textwidth, textheight=\the\textheight, %% oddsidemargin=\the\oddsidemargin, %% headheight=\the\headheight, headsep=\the\headsep, topmargin=\the\topmargin} \marginparsep=0.5cm } % \end{macrocode} % In the \Lopt{draft} case, we nudge the text block to the side, to % give a larger margin. % \begin{macrocode} \ifnum\@draftstatus > 0 \@settextblock{2cm} \else \@settextblock{0pt} \fi % \end{macrocode} % |\leftnudge| is the amount by which the textblock is shifted % leftwards. This is usually zero, but is given a non-zero value in % draft modes, to give space for marginal comments, and may be given a % non-zero value by users, in the preamble, if that is required for % some reason by some limitation of the subsequent printing process. % It may be negative, to nudge the block rightwards. % \begin{macrocode} \let\leftnudge\@settextblock % \end{macrocode} % % Format the marginal paragraphs (ie, comments) % \begin{macrocode} \renewcommand\@marginparreset{% \reset@font \@setminipage \raggedright \small } % \end{macrocode} % % Add a few other formatting parameters. % % Note that the (default) layout of |\FormatPartNumber| depends on a % non-zero |\parindent|, so if the latter is changed, the former must % be, too. In fact, if |\parindent| is zero or otherwise small, % \begin{quotation} % \catcode`\|=0 % |begingroup |ttfamily % \catcode`\{=12 \catcode`\}=12 \catcode`\\=12 % |noindent \newcommand\FormatPartNumber{|linebreak % |noindent|null|quad\hbox to 2em{(\StylePartNumber{partnumber})\hss}} % |endgroup % \end{quotation} % works adequately as a part number, % though this does result in paragraphs being a little hard to make % out, unless there's a really generous |\parskip|. % \begin{macrocode} \setlength{\parindent}{2em} \setlength{\parskip}{\bigskipamount} % \end{macrocode} % % We must clear out any floats at the end of the paper, without % forcing a new page (figures and tables don't float, but there are % other packages which can generate floats, such as the % \Lenv{sidewaystable} from the \Lpackage{rotating} package). % This technique is simplified form Donald Arsenau's \Lpackage{placeins} package. % \begin{macrocode} \def\examn@flushfloats{\par \begingroup \edef\@tempa{\@deferlist\@dbldeferlist} \ifx\@tempa\@empty \else \clearpage \fi \endgroup } % \end{macrocode} % Text at the end of the paper. Command |\ClosingText| is added to % |\AtEndDocument|, below. % \begin{macrocode} \ifcase\@draftstatus % Final version \def\ClosingText{ \examn@flushfloats \begin{center}\textbf{End of Paper}\\\end{center} \mark{END}} \or % Draft version \def\ClosingText{ \examn@flushfloats \begin{center}\textbf{End of Draft Paper}\\\end{center} \mark{END}} \else % Compose version (nothing, because this would be on a page by itself) \def\ClosingText{ \examn@flushfloats \mark{END}} \fi % \end{macrocode} % % \subsection{Headings and marks} % % The headers and footers include continuation information. % \begin{macrocode} \RequirePackage{fancyhdr} \pagestyle{fancy} \setlength{\headwidth}{\textwidth} \renewcommand{\headrulewidth}{0pt} \renewcommand{\footrulewidth}{0pt} \fancyhead{} \fancyfoot{} % \end{macrocode} % Include an identifier in the footer, unless an identifier is present % in |\@paperident|. % \begin{macrocode} \fancyfoot[L]{{\tiny\textcolor{discreettext}{% \ifx\@paperident\@empty\examn@docident\else\@paperident\fi }}} % \end{macrocode} % We use marks to determine whether, at the top of the page, we're % continuing a question or starting a new one. Set |\mark{n}| at the % beginning of a question, and |\mark{}| at the end. In principle, if % |\topmark| is non-empty, then we're currently in the given question, % and if it's empty, we're not. Now, the \LaTeX\ floats mechanism % (which is involved in the handling of marginpars as well as floats) % interferes with this because it can call the output routine other % than at the end of a page. Thus |\topmark| is essentially useless % within \LaTeX, if there's any change of a float appearing. % % However, we can work around this by setting |\examn@topmark| in the % page footer, to be the value of |\botmark| there. I think this has % exactly the same semantics as |\topmark|, possibly apart from some % pathological situations. % % So, for the footer, we include a continuation mark if and only if % |\examn@topmark| is non-empty. We additionally store |\botmark| into |\examn@topmark|. % \begin{macrocode} \fancyfoot[R]{% \def\@tempa{END} \xdef\examn@topmark{\botmark} \ifx\examn@topmark\@empty \formatcontinuations{Paper continued over\dots}% \else\ifx\examn@topmark\@tempa \formatcontinuations{END} \else \formatcontinuations{Q\,\examn@topmark\ continued over\dots}% \fi\fi } \fancyfoot[C]{\thepage/\pageref{lastpage}} % \end{macrocode} % In the header, we perform essentially the same test, using the % |\examn@topmark| we saved in the previous page's footer. % \begin{macrocode} \def\examn@topmark{} \ifnum\@draftstatus=0 \fancyhead[L]{% \ifx\examn@topmark\@empty \else \formatcontinuations{Q\,\examn@topmark\ continued}% \fi } \fi % \end{macrocode} % We use the header to shout out the status of the paper, in % particular making it very clear if we're showing the exam answers: % we don't want this version to be accidentally distributed at the exam\dots. % The |\examn@bighead| macro sets its contents in a large box, but % without making the header any larger -- we want the headheight in % drafts to be the same as in the final version (because otherwise % we'd get different page breaks). % \begin{macrocode} \def\examn@bighead#1{\strut\vbox to 0pt{\vss\hbox{\examn@header@shoutformat{#1}}\vskip 10mm}} \ifnum\@draftstatus = 1 \if@showsolutions \fancyhead[C]{\examn@bighead{\highlighted{DRAFT + SOLUTIONS, p\thepage/\pageref{lastpage}}}} \else \fancyhead[C]{\examn@bighead{\highlighted{DRAFT, p\thepage/\pageref{lastpage}}}} \fi \else \if@showsolutions % Add a very prominent banner \fancyhead[C]{\examn@bighead{\highlighted{SHOWING SOLUTIONS}}} \fi \fi % \end{macrocode} % % Allow \texttt{.clo} files to override the formatting of the various % continuation markers. % \begin{macrocode} \def\formatcontinuations#1{\textbf{#1}} % \end{macrocode} % % Now define a command which writes out the page number of the last % page. This is added to |\AtEndDocument|, in the correct order, below. % \begin{macrocode} \def\WriteLastPageLabel{\label{lastpage}} % \end{macrocode} % % \subsubsection{The title page} % % Define a special page style for the title page. % % There is no header: all of the text on the page is handled by |\maketitle| % The first-page footer doesn't show anything, but it does have to set % |\examn@topmark| in case Q1 starts on this page. % \begin{macrocode} \def\ps@titlepage{ \def\@oddhead{} \def\@oddfoot{\xdef\examn@topmark{\botmark}} } % \end{macrocode} % % Create a custom maketitle. % Check all required information is present. % \begin{macrocode} \def\RequiredMetadata#1#2#3{ \expandafter\ifx\csname @#1\endcsname\@empty \ClassError{exam-n}{#2}{#3 (command \@backslashchar #1)} \else \typeout{#1 check OK} \fi} % \end{macrocode} % Define a |\CheckExamMetadata| test, but only if the macro wasn't defined in a |.clo| file. % \begin{macrocode} \@ifundefined{CheckExamMetadata}{ \def\CheckExamMetadata{ % First, data which is always required \RequiredMetadata{examdate} {No exam date given} {Specify an exam date} \RequiredMetadata{examtime} {No exam time given} {Specify an exam time} \RequiredMetadata{exambanner} {No exam banner given} {Specify an exam banner (eg Examination for the degree...)} \iffussydescription % The following tests can be skipped by using the option [sloppydescription] \RequiredMetadata{universitycoursecode} {No paper title given} {Specify a university course code (eg PHYS3031)} \RequiredMetadata{coursetitle} {No course title given} {Specify a course title (eg Quantum Mechanics)} \RequiredMetadata{degreedescriptions} {No paper subject given} {Specify a 'degree description' (eg Physics 3)} \RequiredMetadata{rubric} {No rubric given} {Specify a rubric, or declare its absence with \protect\norubric} \fi }}{} % \end{macrocode} % Start the |\maketitle| command. % First, handle the 'final' or 'draft' versions. % \begin{macrocode} \renewcommand\maketitle{ \ifnum\@draftstatus < 2 % final or draft version \CheckExamMetadata % \end{macrocode} % All OK so far\dots. Now produce the actual text. % \begin{macrocode} \thispagestyle{titlepage} \begin{center} \null \vskip -1.5cm % \end{macrocode} % Firse produce headers at the top, which highlight things which make % the paper non-distributable (eg, it includes the answers!). % Only highlight the number of shouts when we're not showing % solutions. The highlights above indicate clearly that the % paper is not in its distributable format; the purpose of % this output here is to highlight that the paper is still not % distributable, \emph{even though} it's not showing solutions. % \begin{macrocode} \if@showsolutions \nointerlineskip \vbox to 0pt{\vss \examn@header@shoutformat{\shout{SHOWING SOLUTIONS}} \vskip 1.5\bigskipamount} \else \ifnum\examn@shoutcounttotal>0 \typeout{SHOUTS: \the\examn@shoutcounttotal} \nointerlineskip \vbox to 0pt{\vss \examn@header@shoutformat {\highlighted{SHOUTS: \the\examn@shoutcounttotal\ (see end)}} \vskip 1.5\bigskipamount} \fi \fi \nointerlineskip % \end{macrocode} % The logo, in a zero-size box. % \begin{macrocode} \hbox to \textwidth{% date and time \vbox to 0pt{\vskip-2ex \UniLogo{50mm}\vss} \hss % \end{macrocode} % Make the |\@examtime| box have zero depth, or else fancyhead % complains that the size of the header isn't big enough, and % ups it for the whole document. In this position, it's OK that % it juts out of the bottom of the header line. % \begin{macrocode} \setbox0=\hbox{\vtop{% \vtop or \vbox here? % Opinions differ: % This week, Norman prefers \vtop because it gives a cleaner top line. \hsize=0.5\textwidth \leftskip=0pt plus1fil \rightskip=0pt \parfillskip=0pt \baselineskip=2.5ex \parskip=0.25ex \let\\\par \ifx\@examdate\@empty \shout{missing exam date} \else \@examdate \fi \par \ifx\@examtime\@empty \shout{missing exam time} \else \@examtime \fi \par}} \dp0=0pt \box0} \vskip4\bigskipamount %\UoGname\\[\medskipamount] {\uppercase\expandafter{\@exambanner}}\\[\medskipamount] \vbox{}\hrule \ifx\@degreedescriptions\@empty\else \@displaydegreedescriptions\\ \fi % \end{macrocode} % Exam identification. The |\@coursetitle| is the most important % item, so make that biggest. % Adjust the size of the course title so that it fits on to one line % (though if |\Large| is still too big, then we give up and go to multiple lines). % \begin{macrocode} \vskip 2\baselineskip plus 0.3fil \def\@tempa{\def\@tempa{\vskip 0.5\baselineskip}} \ifx\@schoolcoursecode\@empty\else \@tempa {\large\textbf{\@schoolcoursecode}} \fi \ifx\@universitycoursecode\@empty\else \@tempa {\large\textbf{[~\@universitycoursecode~]}} \fi \ifx\@coursetitle\@empty\else \setbox0=\hbox{\Huge\textbf{\@coursetitle}} \ifdim\wd0>\columnwidth \setbox0=\hbox{\LARGE\textbf{\@coursetitle}} \ifdim\wd0>\columnwidth % we're not going any smaller than this \setbox0=\vbox{\hsize\columnwidth \Large\bfseries \@coursetitle} \fi \fi \vskip 1.2\ht0 % generous vertical skip, size-dependent \ifhbox0 \hbox to \columnwidth{\hss\box0\hss} \else \box0 \fi \fi % \end{macrocode} % Rubric(s). The macros |\@empty| and |\@nnil| both have an empty % expansion. The difference between them is that |\@rubric| is set to % |\@nnil| by |\norubric| to indicate that |\@rubric| is deliberately % empty, whereas if |\@rubric| is |\@empty|, that's trapped in the % checks above as an error. % \begin{macrocode} \vskip 2\baselineskip plus 0.3fil \parindent=0pt \parskip=0.5\baselineskip \ifnum\examn@fontvariant > 0 % Don't put the rubric here (see below) {\LARGE Rubric: see overleaf} \else \ifx\@rubric\@empty\else \ifx\@rubric\@nnil\else % If there's a rubric, separate from the base rubric, then % separate the two with an hrule (the per-exam rubric % presumably represents special instructions for this exam, % so should be highlighted) \vbox{\let\emph\textbf \@rubric \par} \vskip2\baselineskip \hrule \vskip1.5\baselineskip \fi \fi % \end{macrocode} % Let the base rubric be a justified block of text near the bottom. % \begin{macrocode} \ifx\@baserubric\@empty \else \@baserubric \par \fi \fi % end \ifbigfont \else ... \end{center} % \end{macrocode} % These various fractions of fil glue don't add up as I'd expect % them to. No matter: the fractions here produce some spreading % out of the rubrics below the titles, which is what I'm after. % \begin{macrocode} \vskip 2\baselineskip plus 0.6fil % \newpage is {\vfil\penalty-\@M} \vbox to 0pt{\hbox to \textwidth{% \tiny \textcolor{discreettext} {\hfil\ifx\@paperident\@empty\examn@docident\else\@paperident\fi\hfil}}\vss} \penalty -\@M \@displayconstants % \end{macrocode} % The compose version is nice and simple, because we don't have to do % any checks. FIXME: Hmm: this is largely redundant, because we don't % document, and so don't really support, including the metadata in the % [compose] mode preamble. However we clearly did include this as one % point: was that just out of whim, or was there a requirement for that? % \begin{macrocode} \else % compose version \begin{tabular}{rl} \textbf{Exam}& {\def\\{ / }\@schoolcoursecode}\\ \textbf{Course codes}& \@universitycoursecode\\ %% \textbf{Subject}& %% {\def\and{and}\begin{tabular} %% {\@degreedescriptionstemplate}\@degreedescriptions %% \end{tabular}}\\ \textbf{Date \& time}& {\def\\{, }\@examdate, \@examtime}\\ \end{tabular} \fi % \end{macrocode} % And chatter about what decision we've made. % \begin{macrocode} \ifcase\@draftstatus % Final version \typeout{Exam \@schoolcoursecode: FINAL VERSION} \or % Draft version \typeout{Exam \@schoolcoursecode: DRAFT VERSION} \else % Compose version \typeout{Exam \@schoolcoursecode: COMPOSE VERSION} \fi % \examn@bodyfontchange \normalfont\normalsize \ifnum\examn@fontvariant>0 % Put the rubric on a second page, in the 'huge' size. \begin{center} \parskip=18pt \let\emph\textbf \@rubric\par \vskip\baselineskip \hrule \vskip\baselineskip \ifx\@baserubric\@empty \else \@baserubric \par \fi \end{center} \newpage \fi } % \end{macrocode} % % \subsection{Structuring commands} % % \subsubsection{Sections} % % Define simple sectioning commands. We also check that these aren't % inside questions. % \begin{macrocode} \setcounter{secnumdepth}{0} % \end{macrocode} % Redefine |\section|, to include a check that it's not being called % within a question (|\@currentquestion| is defined only inside the % \Lenv{question} or \Lenv{mcq} environments). % \begin{macrocode} \renewcommand\section{ \@ifundefined{@currentquestion}\@@section {\ClassError{exam-n}{Misplaced section} {You can't have a section inside a question;\MessageBreak move it before the {question} environment starts}}} \newcommand\@@section{\@startsection{section}{1}{\z@}% {-3.5ex \@plus -1ex \@minus -.2ex}% {1ex \@plus.1ex \@minus 0.5ex}% {\fmt@section}} \def\fmt@section#1{% \examn@prequestionspace{} \hbox to \textwidth{{\hfil\bfseries SECTION #1\hfil}}% } % \end{macrocode} % Redefine |\subsection| similarly. % \begin{macrocode} \renewcommand\subsection{ \@ifundefined{@currentquestion}\@@subsection {\ClassError{exam-n}{Misplaced subsection} {You can't have a subsection inside a question;\MessageBreak move it before the {question} environment starts}}} \newcommand\@@subsection{\@startsection{subsection}{2}{\z@} {-2ex \@plus -3ex \@minus -0.2ex} {0.5ex \@plus .1ex \@minus 0.1ex} {\fmt@subsection}} \def\fmt@subsection#1{% \examn@prequestionspace{} \noindent\textbf{#1}} % \end{macrocode} % We must redefine the section and subsection mark commands to gobble % their arguments. If we don't, then \LaTeX\ gets \emph{terribly} % confused about what the mark is. I don't quite follow what happens % in this case, but symptoms include Babel blowing up, and % \TeX\ running out of stack space. So: bad. % \begin{macrocode} \let\sectionmark\@gobble \let\subsectionmark\@gobble % \end{macrocode} % % Just to be safe, we should also disable the other sectioning % commands. % \begin{macrocode} \def\@badsection#1#2{\ClassError{guexam}{Bad section} {The exam class goes not support subdivisions like #1{#2}}} \def\subsubsection{\@badsection{subsubsection}} \def\paragraph{\@badsection{paragraph}} \def\subparagraph{\@badsection{subparagraph}} % \end{macrocode} % % The above redefinitions break the |\tableofcontents| macro. % It's unlikely but \emph{possibly} useful, in some cases, to have a % table of contents in an exam paper. Whether or not it is, we should % avoid breaking it, on a principle of least surprise. The following % makes the macro work again, even though it's not particularly % pretty. % \begin{macrocode} \renewcommand\tableofcontents{\bigskip \hbox to \textwidth{\hfil\textbf{\Large Contents}\hfil}% \@starttoc{toc}} % \end{macrocode} % % \subsubsection{Questions and solutions} % Counters: % \begin{macrocode} \newcount\marktotal % number of marks accumulated so far \newcount\markgoal % number of marks we should have in the end \newcounter{questionnumber} \setcounter{questionnumber}0 % \end{macrocode} % % Counter partnumber holds the number (i,ii,iii, etc) of the parts % within a question. It's a \LaTeX\ counter, so we can use |\roman|. % % We override the \Lenv{article} |\part| command. % % FIXME: % We would like to use |\StylePartNumber| here, but can't, because % that's defined as being eg |\alph|, and not |\@alph|. To change % this, we'll have to retire |\StylePartNumber|, in favour of saying % that, to change the formatting here, it's merely necessary to % redefine |\thepartnumber|. % \begin{macrocode} \newcounter{partnumber} \renewcommand\thepartnumber{\thequestionnumber\@alph\c@partnumber} \renewcommand\part[1][]{% \if@nobreak \else \par \@nobreakfalse \fi \ifvmode \vskip 0pt plus 4\bigskipamount \penalty-50 \fi \def\@tempa{#1}% \ifx\@tempa\@empty \refstepcounter{partnumber}% \noindent\FormatPartNumber \else \noindent\FormatPartNumber[#1]% \fi } % \end{macrocode} % The default |\FormatPartNumber| creates a box the same size as a % parindent. This therefore assumes that it's following a |\noindent|. % \begin{macrocode} \newcommand\FormatPartNumber[1][]{% \def\@tempa{#1}% \hbox to \parindent{(% \ifx\@tempa\@empty \StylePartNumber{partnumber}% \else \@tempa \fi )\hss}% } % \end{macrocode} % And by default we use alphanumeric counters for parts (we abstract % this, rather than simply including |\alph| in the definition of % |\FormatPartNumber|, so that we use the same style for the % `answerpartnumber' counter. % \begin{macrocode} \let\StylePartNumber\alph % \end{macrocode} % % A flag indicating whether we should start a new page before the next % question. This is manipulated by both |\section| and |\question|. % \begin{macrocode} \newif\if@newpagebeforequestion \if@pageperquestion \@newpagebeforequestiontrue \else \@newpagebeforequestionfalse \fi % \end{macrocode} % % The command |\examn@prequestionspace| is called just before we start a % new question, or before we start a header which precedes a % question. It adds some vertical space, given in the argument, % unless the |@pageperquestion| settings imply that this should be a % newpage instead, in which case the vertical space here is ignored. % \begin{macrocode} \def\examn@prequestionspace#1{% \if@pageperquestion \if@newpagebeforequestion % Add all the stretchability here, rather than stretching out % displays and lists above this on the page. \newpage % Clear the \@newpagebeforequestion flag, to suppress the action % of any following calls to \examn@prequestionspace, until the end % of the next question. \global\@newpagebeforequestionfalse \fi \else #1% \fi } % \end{macrocode} % % Macro |\examn@endquestion| gathers here a couple of checks shared % between end-of-question macros (see the \Lenv{mcq} environment and % the |\endquestion| macro). % The argument to the |\examn@endquestion| macro is material (such as the % mark-total) which should go at the end of the question, % and be surrounded by various spacing and resetting actions. % \begin{macrocode} \long\def\examn@endquestion#1{% \mark{} % the position of this call is slightly sensitive (but this works) \if@pageperquestion \global\@newpagebeforequestiontrue \fi #1 \@nobreakfalse \everypar{} } % \end{macrocode} % % \subsubsection{Partmarks} % % |\partmarks| is used at the end of a paragraph to indicate the % number of marks associated with this part. The starred variant % |\partmarks*| is used only when the end of a part is the end of a display % maths block which doesn't have an equation number. This moves the % part note up a bit, which looks nicer. % % It's also permissible to use |\partmarks| in the solution, to % indicate precisely where marks accrue. It's reasonable for this to % be more fine-grained than in the question. We don't check that the % partmarks in the solution add up to the mark goal. % % Manage the partmarks comments as the contents of a zero-width hbox, % which is sized to fit reasonably well in the margin. We insert this % into the output just before formatting the partmarks. % % The |\defaultpartmarkscategory| macro creates a default partmarks % `category'. If this is something like |{category?}|, then this % should prompt question authors to indicate the category in each call % to |\partmarks|. This can be declared within a |.clo| option file % (and is declared above, so that it can be read from there without error). % % Below, we must add the footnote text after the end of the paragraph, % otherwise this inserts vertical mode material, which causes a % linebreak, at least in the case where the last line is almost full. % Because we are using the hook mechanism, this package now depends on % the expl3 modules, and thus on TeXLive versions which aren't too old % (how old is too old? I'm not sure, but I expect TeXLive 2020 is new enough). % \begin{macrocode} \newbox\examn@partmarkscomment \def\examn@makepartmarkscomment#1{% \setbox0=\hbox{\small #1}% \ifdim\wd0 < 3\marginparwidth % let shortish comments wrap here \setbox\examn@partmarkscomment=\hbox to 0pt{\hbox{% \vtop to 0pt{% \hsize=\marginparwidth \parindent=0pt \parskip=0pt \leftskip=1em % 1em matches the hskip in default \FormatPartMarks \rightskip=0pt plus 0.5\marginsize \hangindent=2em \hangafter=-1 \small #1\vss}}\hss }% \else \stepcounter\@mpfn \protected@xdef\@thefnmark{\thempfn}% \@footnotetext{#1}% % 3em matches the \leftskip+\hangindent above \setbox\examn@partmarkscomment=\hbox to 0pt{% \hskip3em\highlighted{\small [comment \thempfn]}\hss}% \fi } \def\examn@getpartmarkscomment{% \ifhbox\examn@partmarkscomment \box\examn@partmarkscomment \fi} % \end{macrocode} % Now, finally, define the actual |\partmarks| command. % \begin{macrocode} \def\partmarks{% \@ifstar{\@tempswatrue \@partmarks}{\@tempswafalse \@partmarks}} \newdimen\@partmarksspace \@partmarksspace=2em % default value % \end{macrocode} % Check whether there's an optional (comment/category) argument, % enclosed in |[...]|. % \begin{macrocode} \def\@partmarks{% \@ifnextchar[%] \@@partmarks{\@@partmarks[]}} % \end{macrocode} % Implement the part marks indicator. First, check that % `perquestionmarks' is turned on; if it's not, then we shouldn't be % using |\partmarks|. % \begin{macrocode} \def\@@partmarks[#1]#2{% \if@perquestionmarks \if@insolution \@@partmarks@solution{#1}{#2}% \else \@@partmarks@question{#1}{#2}% \fi \else \ClassError{exam-n}{\string\partmarks\ is not compatible with noperquestionmarks}{Either remove \string\partmarks\ or remove the noperquestionmarks option} \fi } % \end{macrocode} % % Finally, implement the two partmarks variants for questions and solutions. % % The |\@@partmarks@endenv| command is called when |\partmarks| is % invoked within an environment, and is used to add a suitable vbox to % an after-environment hook. % % First prepare the vbox that's to be inserted, and then work out how % to place it. The |\vskip\baselineskip| in the |\@partmarksbox| is % to better position the box relative to where it ends up in the % vertical list, and the value has a large heuristic element. % \begin{macrocode} \newbox\@partmarksbox \def\@@partmarks@endenv@display{\@tempswatrue\@@partmarks@endenv@common} \def\@@partmarks@endenv@nodisplay{\@tempswafalse\@@partmarks@endenv@common} \def\@@partmarks@endenv@common#1{% \ifvbox\@partmarksbox % ooops -- been here before: two \partmarks in one env \ClassError{exam-n} {Two partmarks commands in one environment! First one IGNORED!} {You can (currently) have only one partmarks command per environment} \fi \global\setbox\@partmarksbox=\vbox to 0pt{\vss \hbox to \textwidth{% \strut\hfill \examn@getpartmarkscomment \FormatPartMarks{#1}}% \vskip\baselineskip}% %\dp\@partmarksbox=0pt % \end{macrocode} % Test whether we have the |{question}| environment as our immediate % container, as opposed to being in an inner environment. % \begin{macrocode} \def\@tempa{question}% \ifx\@tempa\@currenvir \setbox1=\vbox to 0pt{\vss\box\@partmarksbox}% \ifvmode \box1 \else \vadjust{\box1}% \fi \else % \end{macrocode} % Generally the \cmd|env//end| hook seems to % produce better results, in terms of positioning things at the end of % environments, but this does not work for environments % where the command is located inside a display (ie, in \TeX\ terms, % inside |$$...$$|); in these situations we have to use the % \texttt{.../after} hook instead. Such displays are most typically amsmath % alignment environments, but an \cmd|\halign| inside a display will % also qualify (see the discussion of `alignment displays' in \TeX % Book ch.19). There isn't a completely straightforward way of % detecting this situation (though amsmath's \cmd|\start@align| sets % \cmd|\xatlevel@| to be non-\cmd|\@empty|, which we take to indicate the % amsmath case), so we have to rely on the caller of this % command to invoke the \texttt{...@display} or \texttt{...@nodisplay} % variant appropriately. % \begin{macrocode} \if@tempswa % display variant \AddToHookNext{env/\@currenvir/after}{% %\typeout{hook:endenv/display #1}% \ifvmode\box\@partmarksbox \else\vadjust{\box\@partmarksbox}\fi}% \else \AddToHookNext{env/\@currenvir/end}{% %\typeout{hook:endenv/nodisplay: env/\@currenvir/end #1}% \ifvmode\box\@partmarksbox \else\vadjust{\box\@partmarksbox}\fi}% \fi \fi } % \end{macrocode} % % First, define the questions version, for appearing in the version candidates see. % Here, \cmd|#1| is the possibly empty `classification' text, and \cmd|#2| is the % number of marks. At this point |\if@tempswa| is true if we got here % via the \cmd|\partmarks*| variant, and false if it's the unstarred one. % % The argument |#2| must be a number: any non-number text will not % cause an error but will appear in the text. % % But first\dots! % % The |\partmarks| command increments a global counter, and we % \emph{don't} want to do this when an \Lpackage{amsmath} alignment is evaluating % the content in its `measuring' phase. Fortunately, % \Lpackage{amsmath} has an (internal) flag |\ifmeasuring@| which is % true in that phase, which it uses for this purpose, so make this macro a no-op in that case. % \begin{macrocode} \def\@@partmarks@question{% \ifmeasuring@ \let\@@partmarksnext\@gobbletwo \else \let\@@partmarksnext\@@partmarks@question@do \fi \@@partmarksnext } % \end{macrocode} % On with the main business. % \begin{macrocode} \def\@@partmarks@question@do#1#2{% \global\advance\marktotal #2 \let\@@partmarksnext\relax % base case % \end{macrocode} % Display the `part category', \emph{visible in the question}, % if \Lopt{showsolutions} is true, either % explicitly, or implicitly as a consequence of the % compose/draft/final mode. It's arguable that this should be % dependent on the mode only, but after some discussion, it ended up % seeming more reasonable to tie this to \Lopt{showsolutions} directly. % \begin{macrocode} \if@showsolutions \def\@tempa{#1}% \ifx\@tempa\@empty \ifx\examn@defaultpartmarkscategory\relax \let\examn@category\relax \else \examn@makepartmarkscomment{\highlighted{\examn@defaultpartmarkscategory}}% \fi \else \examn@makepartmarkscomment{\highlighted{#1}}% \fi \fi % \end{macrocode} % % If |\@tempswa|, then this is the starred form of |\partmarks|. % This is intended to be used only occasionally, after a display or % list environment, where for some reason the command can't go inside % the environment. % \begin{macrocode} \if@tempswa \ifdim\displaywidth>0pt \ClassError{exam-n} {Don't use \partmarks* inside a display} {Use \partmarks inside the display, or \partmarks* after it, if necessary} % \end{macrocode} % Else we are most likely just after an equation or just after a list % environment, or something similar. % (here and below we include some |{#2:n}| debugging code for when I, % inevitably, revisit this to worry about the spacing). % \begin{macrocode} \else \@@partmarks@endenv@nodisplay{#2}%{#2:1*}% \fi % \end{macrocode} % We've called the unstarred version of |\partmarks|. % This is the more usual mode. % \begin{macrocode} \else \ifdim\displaywidth>0pt % \end{macrocode} % We're in a display, after |$$|: \TeX\ is probably (but not certainly) in % maths mode just now; if we're in an amsmath alignment, we're in % specifically inner maths mode; there are other, rarer, ways of being % in an `alignment display'. Additionally, and commonly, if we're in % an \Lenv{equation} environment now -- which we can detect because % that, amongst other amsmath environments, sets |\eqnsw| to be true % -- then we're \emph{not} in an alignment, but we \emph{are} in a % case where the |\eqno| technique will fail (with `You can't use % `eqno' in math mode.'), so catch that. % % CONSIDER: is this |\@eqnsw| test in fact the only one I have to do % -- is the inner math mode test equivalent? That is, is this, when % it comes down to it, testing the actual thing I need to test here? % This will require another dive into the amsmath magic. % \begin{macrocode} \@tempswafalse \ifmmode\ifinner \else \@tempswatrue \fi\fi \if@tempswa \if@eqnsw % not so fast... we're in an {equation} \@tempswafalse \fi \fi \if@tempswa % \end{macrocode} % We're in outer maths mode, which we can take to mean a |\[...\]| equation. % In this case, we can very neatly position the partmarks indicator % using |\eqno|. % \begin{macrocode} \def\@@partmarksnext{\eqno \hbox to 1sp{% the \eqno argument must not be zero size \examn@getpartmarkscomment \FormatPartMarks{#2}%{#2:1} \hss}}% % \end{macrocode} % Or we're in one or other type of display. % \begin{macrocode} \else \def\@@partmarksnext{\@@partmarks@endenv@display{#2}}% %\def\@@partmarksnext{\@@partmarks@endenv@display{#2:2,\@currenvir}}% \fi % \end{macrocode} % % Otherwise, |\displaywidth=0pt|, and we're not in a display. % If we are in the |{question}| environment, as opposed to any sub-environment, % we end the paragraph here and put the partmarks indicator at the end % of the final line of the paragraph (this technique is filched from the TeXBook, p106). % Otherwise, we add a suitable box to an end-of-environment hook. % % Omitting the |{question}| test below, and handling all cases with % the end-of-paragraph technique, works in most case, in the sense of % looking fine. Where it fails is in the case of, eg, |{quote}|, % where the end-of-line ends up indented from the right. % % Using the hook has the additional advantage that |\partmarks| can be anywhere % within the environment and this locates it at the end. % % The dimension |\@partmarksspace| controls how much space the % partmarks-number takes up, the default is the special case of 0pt, % which puts it in the margin. % \begin{macrocode} \else \def\@tempa{question}% \ifx\@tempa\@currenvir \ifdim\@partmarksspace > 0pt {\unskip\nobreak\hfil\penalty50 \hskip\@partmarksspace \hbox{}\nobreak\hfil\examn@getpartmarkscomment\FormatPartMarks{#2}%{#2:3}% \parfillskip=0pt \finalhyphendemerits=0 \par} \else \unskip\nobreak\hfill\examn@getpartmarkscomment\FormatPartMarks{#2}\par%{#2:4}\par \fi \let\@@partmarksnext\relax \else \def\@@partmarksnext{\@@partmarks@endenv@nodisplay{#2}}% %\def\@@partmarksnext{\@@partmarks@endenv@nodisplay{#2:5,\@currenvir}}% \fi \fi \fi % \end{macrocode} % % The `question' variant of this macro includes an |\ignorespaces| at the % end, since that is generally the right thing to do (the command % almost always appears at the end of paragraphs, or after equations). % \begin{macrocode} \@@partmarksnext \ignorespaces } % \end{macrocode} % Then the solutions version, for the benefit of markers, which is % typically more finely itemized, and which isn't summed (ie, we don't % at present confirm that the marks here match the question's marks goal). % The solutions variant of this macro omits the |\ignorespaces| % (since in solutions this macro is scattered within the text). % Setting |\dp0=0pt| is probably unnecessary, but guarantees that box0 % has zero depth, so no extra vertical space appears because of % this new box. % \begin{macrocode} \def\@@partmarks@solution#1#2{% \setbox0=\vbox to 0pt{\vss \hbox to \textwidth{\hfil\hbox to 0pt{\quad\small[\dots #2]\hss}} \vskip0.25ex }% \dp0=0pt \ifvmode \box0 \else \vadjust{\nointerlineskip\box0}% \fi } % \end{macrocode} % % The code above permits page-breaks between lists and |\partmarks|. % That's because |\@endparenv|, which is called within |\endtrivlist|, % includes a negative |\@endparpenalty|. Override that here. This % applies to the whole document, but that's OK, since we want to % discourage inconvenient page-breaks generally. % \begin{macrocode} \@endparpenalty=\@M % \end{macrocode} % % The number of marks is formatted by the command |\FormatPartMarks|, which % may be overridden, using |\renewcommand| in a |.clo| file. % In this default case, |\FormatPartMarks| goes into the margin, so we % don't need to keep space for it, so set |\@partmarksspace| to zero. % \begin{macrocode} \newcommand\FormatPartMarks[1]{\hbox to 0pt{\hskip1em \textbf{[#1]}\hss}} \@partmarksspace=\z@ % \end{macrocode} % % \subsubsection{The question environments: normal questions} % % The \Lenv{question} environment. Implement % this using with a |\question| macro, rather than using % |\newenvironment|, so that we can define an optional argument. % \begin{macrocode} \newcommand\question{% \if@perquestionmarks \let\ex@next\@questionmarks \else \let\ex@next\@questionnomarks \fi \@ifnextchar[%] {\ex@next}{\ex@next[]}} % \end{macrocode} % Switch between the perquestionmarks and noperquestionmarks cases. % \begin{macrocode} \def\@questionmarks[#1]#2{% \def\@tempa{#2}% marks available for this question \ifx\@tempa\@empty \ClassError{exam-n} {Missing mark goal for question (using 0 instead)} {Missing mark goal for question (using 0 instead)} \def\@tempa{0} \fi \ifx\@includequestionoverridenumber\@empty \do@question{#1}{\@tempa}% \else \ClassWarning{exam-n}{Forcing question number \@includequestionoverridenumber, in included question #2} \do@question{\@includequestionoverridenumber}{\@tempa}% \fi } \def\@questionnomarks[#1]{% \do@question{#1}{0}% } % \end{macrocode} % % \subsubsection{The question environments: multiple-choice questions} % % And finally multiple-choice questions. The \Lenv{mcq} environment % contains a list of possible answers, numbered from one up, including % precisely one correct answer, indicated by |\answer|. These are % laid out in a compact itemized list. We do not indicate the number % of marks, since these are always the same. % % First, counters: % \begin{itemize} % \item |\ex@nmcq| is the number of answers which MCQs can have. If % this is less than 1, it's a flag that MCQs haven't been enabled by % |\multiplechoiceanswers|. % \item |\ex@mcqi| is the running index of answers. % \item |\ex@mcqnanswer| is the number of correct answers found % (which is checked to be one, at the end). % \end{itemize} % \begin{macrocode} \newcount\ex@nmcq \ex@nmcq=-1 \newcount\ex@mcqnanswer \def\multiplechoiceanswers#1{\ex@nmcq=#1} % \end{macrocode} % The \Lenv{mcq} environment takes a single argument indicating the % correct answer. The environment starts with the text question, % followed by a number of |\item| answers. % \begin{macrocode} \newenvironment{mcq} {\parindent=0pt \ifnum\ex@nmcq<1 \ClassError{exam-n} {mcq environment without preceding multiplechoiceanswers declaration} {The mcq environment may only be used if the number of permitted MCQ answers has been declared with \string\multiplechoiceanswers} \else % \end{macrocode} % Declare |\item| for the individual answers, and |\answer| for the % single correct answer. % \begin{macrocode} \def\item{\@tempswafalse\ex@mcqitem} \def\answer{\@tempswatrue\ex@mcqitem} % \end{macrocode} % Initialise counters, and invoke the common |\do@question| macro. % \begin{macrocode} \ex@mcqi=0 \ex@mcqnanswer=0 \do@question{}{1} \fi} % \end{macrocode} % At the end of the \Lenv{mcq} environment, check that we found % |\ex@nmcq| answers, and that the count of correct answers, % |\ex@nmcqanswer|, is exactly one. % \begin{macrocode} {\par \ifnum\ex@mcqi<\ex@nmcq \ClassWarning{exam-n}{Too few potential answers in MCQ \thequestionnumber} \@shout{Too few potential answers in MCQ \thequestionnumber} \ifnum\@draftstatus > 0 \highlighted{TOO FEW ANSWERS}\par \fi \fi \ifcase\ex@mcqnanswer \ClassWarning{exam-n} {No correct MCQ answer provided in question \thequestionnumber} \@shout{No correct MCQ answer provided in question \thequestionnumber} \ifnum\@draftstatus > 0 \highlighted{NO CORRECT ANSWER PROVIDED}\par \fi \or % ex@mcqanswer=1: correct -- do nothing \else \ClassWarning{exam-n} {Too many correct MCQ answers provided in question \thequestionnumber} \@shout{Too many correct MCQ answers provided in question \thequestionnumber} \ifnum\@draftstatus > 0 \highlighted{TOO MANY CORRECT ANSWERS}\par \fi \fi % \end{macrocode} % Other end-question tidyups (compare |\endquestion|). % \begin{macrocode} \examn@endquestion{\relax} } % \end{macrocode} % Each |\item| within the environment (implemented by |\ex@mcqitem|) % creates a new paragraph. % \begin{macrocode} \newcount\ex@mcqi \def\ex@mcqitem{% \par \ifnum\ex@mcqi=0 % first one \smallskip \parskip=0pt % nothing fancy -- we assume these won't spread % over more than one line \advance\leftskip by 2em \fi \advance\ex@mcqi by 1 \noindent \if@tempswa % the correct answer \advance\ex@mcqnanswer 1 \if@showsolutions \hbox to 0pt{\hss \highlighted{$\Longrightarrow$ \@Alph\ex@mcqi . }}% \else \hbox to 0pt{\hss \@Alph\ex@mcqi . }% \fi \else \hbox to 0pt{\hss \@Alph\ex@mcqi . }% \fi } % \end{macrocode} % % \subsubsection{The question environments: the common handler} % % The common question handler. This is the macro which does the work. % Argument |#1| is the overriding question number (empty indicates the % next one in sequence); argument |#2| is the mark goal, which must be % non-zero. % \begin{macrocode} \def\do@question#1#2{% \par % get that out of the way... \markgoal=#2 \marktotal=0 \ifx\examn@questionpreamble\@empty \else \vspace{2\baselineskip} \hbox to \textwidth{\hfil\textbf{\examn@questionpreamble}\hfil} \questionpreamble{} \fi \setcounter{partnumber}{0} \setcounter{answerpartnumber}{0} % \end{macrocode} % If the argument |#1| is non-empty, then it is a number, forcing the % question number. This is local, however -- don't use it to change % the sequence of questions, so don't set the `questionnumber' % counter, but only the current label. % \begin{macrocode} \refstepcounter{questionnumber} \def\@tempa{#1} \ifx\@tempa\@empty \else \edef\@currentlabel{#1} \fi % \end{macrocode} % % If |pageperquestion| is true, then start a new page here (unless % this is the first question). % \begin{macrocode} \examn@prequestionspace{% \if@nobreak % after a heading (or something like that) \else % we're not forcing a new page here, but this would be a good point to choose \vskip 2\baselineskip plus 8\baselineskip \penalty-200 \fi } % \end{macrocode} % % The optional argument specifies a question number. In compose mode, % this unequivocally specifies the question number -- end of story. % In the two other modes, this is expected to match the question % number implied by the count of questions so far, and we check this, % and warn if it is not so. % \begin{macrocode} \if@questionnumberchecks \def\@tempa{#1}% intended question number % \end{macrocode} % If there's no optional argument, we've got nothing to do % \begin{macrocode} \ifx\@tempa\@empty % no optional argument -- easy \def\@currentquestion{\thequestionnumber} % \end{macrocode} % % We have a non-null optional argument in |#1|. % Check the question number in the argument. If there's a % mismatch, warn in draft mode, and fail in final mode. First, % however, check that the argument |#1| is just a number (if it's not, % the author should have disabled this check in the preamble, and we % shouldn't be here at all). We do that check by setting a counter % inside a box. If |#1| is all number, then this will result in a % zero-width box; if not, then there will be unparsed characters and a % non-zero-width box (nifty, eh?). % \begin{macrocode} \else \setbox0=\hbox{\@tempcnta=#1} \ifdim\wd0>0pt \ClassWarning{exam-n}{Non-numeric question number, #1. You probably want to put \string\QuestionNumberChecksOff in the preamble} \par\textbf{Non-numeric question number, #1. You probably want to put \hbox{$\backslash$\ttfamily QuestionNumberChecksOff} in the preamble} (the formatting below may be messed up).\par \fi % \end{macrocode} % Switch on the draft status: in the final version, this mismatch is an error % \begin{macrocode} \ifcase\@draftstatus % Final version \@tempcnta=#1 \ifnum\c@questionnumber=\@tempcnta \def\@currentquestion{#1} \else \ifx\@includequestionoverridenumber\@empty \ClassError{exam-n} {\string\question[#1] is actually question \thequestionnumber!} {The question in {question} environment number \thequestionnumber\space is specified as \string\question[#1].\MessageBreak This is an error in 'final' mode.\MessageBreak Perhaps you need \string\QuestionNumberChecksOff?} \def\@currentquestion{???} \else \ClassWarning{exam-n}{Forcing question number \@includequestionoverridenumber, in {question} environment number \thequestionnumber} \edef\@currentquestion{\@includequestionoverridenumber}% this doesn't seem to expand in fact! \message{current question=\@currentquestion, override \@includequestionoverridenumber} \fi \fi % \end{macrocode} % In the other two modes, we simply need a warning. % \begin{macrocode} \or % Draft version -- let the given number override % \the\questionnumber, but warn if there's a difference. \@tempcnta=#1 \ifnum\c@questionnumber=\@tempcnta \else \ClassWarning{exam-n} {\string\question[#1] is actually question \thequestionnumber!} \fi \def\@currentquestion{#1} \else % compose mode -- argument overrides without question \def\@currentquestion{#1} \fi \fi \else % skip question-number checks \def\@tempa{#1}% intended question number \ifx\@tempa\@empty % no optional argument -- this is possibly an error, so warn \ClassWarning{exam-n}{\string\QuestionNumberChecksOff\ is in force, but this question has no [number]} \def\@currentquestion{\thequestionnumber} \else \typeout{Forcing question \thequestionnumber\space to be #1} \def\@currentquestion{#1} \fi \fi % \end{macrocode} % Format the question number, first removing and discarding any parindent % (the reason we don't just start with |\noindent| here is because % there may be a blank line between the |\begin{question}|, and the % text, so we'd (inadvertently) start another new paragraph when the % actual question starts). % The call to |\mark| should come \emph{after} setting the % question number: if it happens before, and there is a page-break % immediately before the new question, we can get a spurious % `Q?? continued' on the previous page. % % If a paragraph starts inside a level of grouping -- for example % |{\bf 1} text...| or even just |{T}ext| -- then the |\everypar| % tokens are expanded inside that group, which means that the % resetting of |\everypar| is local, with the result that the tokens % are reused for the next paragraph. Make the emptying of |\everypar| % global for that reason. % \begin{macrocode} \everypar{\setbox0=\lastbox % discard \box0 \FormatQuestionNumber \mark{\@currentquestion}% \global\everypar{}} } % \end{macrocode} % Format the question number. This command is documented as existing, % so that it can be potentially overridden in a \texttt{.clo} file. % \begin{macrocode} \newcommand\FormatQuestionNumber {\hbox to 0pt{\hss \textbf{\@currentquestion}\hskip1em}} % \end{macrocode} % % Finish off the question: % Format the indication of the total number % of marks, and do a few consistency checks. % \begin{macrocode} \def\endquestion{% \ifnum\marktotal=\markgoal \typeout{Question \@currentquestion\if@perquestionmarks, \the\marktotal\space marks\fi} \iffalse % all of this is redundant, and ends up too shouty \ifcase\@draftstatus % Final version -- do nothing \relax \or % draft version \relax % no, the above is too much; do nothing \else % compose version \par \hfil\textbf{\highlighted{[Q\,\@currentquestion\if@perquestionmarks, \the\marktotal\space marks\fi]}}% \break \fi \fi % \end{macrocode} % In the case where the mark total doesn't match, make a noise about it. % \begin{macrocode} \else \ClassWarning{exam-n} {Question \@currentquestion\space has a total of \the\marktotal\space marks, \MessageBreak when it should have \the\markgoal} \begin{center} \edef\@tempa{Question \@currentquestion\space has a total of \the\marktotal\space marks, when it should have \the\markgoal} \expandafter\shout\expandafter{\@tempa} \end{center} \fi % \end{macrocode} % Make a few tidyups in the end-question wrapper. % \begin{macrocode} \examn@endquestion{% \if@showmarktotals \par % into vertical mode \nobreak % keep the marks total with the question \vbox to 2\baselineskip{ \vss % this should be very similar to the call to % \FormatPartMarks in \@partmarks, above \hbox to \textwidth{\strut\hfill\FormatPartMarks{Total: \the\markgoal \ifnum\@draftstatus>0 % in draft modes, put a fairly discreet confirmation in the total \space \highlighted{\ifnum\marktotal=\markgoal OK\else X\fi}% \fi}}} \fi } } % \end{macrocode} % % \subsubsection{Other structures} % % The \Lenv{questiondata} environment allows the author to provide % some additional data or equations for the question. % This environment ends a preceding paragraph. % \begin{macrocode} \newenvironment{questiondata}{% \par \penalty50 % poor break \vbox\bgroup \slshape \parindent=0pt \parskip=\medskipamount \smallskip \hrule \nobreak \smallskip \noindent \ignorespaces }{% \par \nobreak \medskip \hrule width \textwidth \par \egroup % end of \vbox } % \end{macrocode} % % If |\questionpreamble| is called some time before the start of a % \Lenv{question} environment, then its contents will be printed at % the start of the next question. % \begin{macrocode} \newcommand\questionpreamble[1]{\gdef\examn@questionpreamble{#1}} \let\examn@questionpreamble\@empty % \end{macrocode} % % In those cases where the sequence of question numbers is not % supposed to match the sequence of question environments, declare % that we should turn off the corresponding checks within |\question|. % \begin{macrocode} \newif\if@questionnumberchecks \@questionnumbercheckstrue \newcommand\QuestionNumberChecksOff{\@questionnumberchecksfalse} % \end{macrocode} % % The underlying style (article) has enumerate and itemize % environments which have a rather generous amount of space. This % makes sense in an article, but within an exam, which already has a % lot of white space around, such lists end up looking unattractively % ragged. So redefine them slightly here, adjusting the spacing % appropriately. First `enumerate'\dots % \begin{macrocode} \def\enumerate{% \ifnum \@enumdepth >\thr@@\@toodeep\else \advance\@enumdepth\@ne \edef\@enumctr{enum\romannumeral\the\@enumdepth}% \expandafter \list \csname label\@enumctr\endcsname {\usecounter\@enumctr \topsep0pt \partopsep0pt %\parskip=5.0pt \parsep=\parskip \def\makelabel##1{\hss\llap{##1}}}% \fi} % \end{macrocode} % \dots then `itemize'. % \begin{macrocode} \def\itemize{% \ifnum \@itemdepth >\thr@@\@toodeep\else \advance\@itemdepth\@ne \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% \expandafter \list \csname\@itemitem\endcsname {\topsep0pt \partopsep0pt \def\makelabel##1{\hss\llap{##1}}}% \fi} % \end{macrocode} % To match the format of the question number above, we have to make % sure that the enumerate environment's counters are different. % \begin{macrocode} \renewcommand\theenumi{\@roman\c@enumi} % \end{macrocode} % % \subsection{Other useful commands} % % |\comment| creates a marginal comment in non-final modes. There is an % interaction with the marks mechanism -- see the discussion about % |\topmark| above. % \begin{macrocode} \newcommand\comment[1]{% \ifnum\@draftstatus > 0 \marginpar{\highlighted{#1}}% % should we \@shout this, too? \fi \ignorespaces } % \end{macrocode} % % The |\author| command is a convenience. Used within a % \Lenv{question} environment, it creates a comment with the author's % name. I may expand its functionality in future. % \begin{macrocode} \renewcommand\author[1]{\comment{Author: #1}} % \end{macrocode} % % The |\@shout| macro is intended for use in all modes: it appends a % remark to a list of exclamations which are highlighted at the end of % the document. % The argument to |\@shout| can have expandable things (such as % |\thequestionnumber|) in it. % Shouts appear in all modes and cannot be suppressed. % \begin{macrocode} \newtoks\@allshouts \@allshouts={} \def\@shout#1{\edef\@tempa{#1}\expandafter\@@shout\expandafter{\@tempa}} \def\@@shout#1{\global\@allshouts=\expandafter{\the\@allshouts\t{#1}}} \def\showthe@shouts{% {\def\t##1{{\LARGE\noindent\highlighted{NOTE: ##1}\par}}% \the\@allshouts}% % Remark on the number of shouts in the aux file {\@tempcnta=0 \def\t##1{\advance\@tempcnta1}\the\@allshouts \protected@write\@auxout{}% {\string\examn@shoutcount{\the\@tempcnta}}}} % \end{macrocode} % Define the user macro |\shout| % \begin{macrocode} \def\shout#1{\textbf{\highlighted{#1}}\@shout{#1}} % \end{macrocode} % Take note of the number of shouts, and write this information to the % \texttt{.aux} file, so that it can be read in next time. % \begin{macrocode} \newcount\examn@shoutcounttotal \examn@shoutcounttotal=0 \def\examn@shoutcount#1{\global\examn@shoutcounttotal=#1} % \end{macrocode} % % The |\includequestion| command includes a question from another % file. For convenience, we disable %|\documentclass|, |\usepackage|, |\RequirePackage|, and the % \Lenv{document} environment, so that the included file may be a % complete \LaTeX\ document. % We don't try too hard to support including just any old \LaTeX, here: % any complicated preamble requirements in an included file should % probably be managed by the exams convener transplanting them into % the preamble of the main document. This may be an overly % simple-minded approach, and may change in future versions. % \begin{macrocode} \def\dummy@documentclass{% \@ifnextchar[\dummy@@documentclass{\dummy@@documentclass[]}} \def\dummy@@documentclass[#1]#2{} \def\includequestion{ \@ifnextchar[%] {\@includequestion}{\@includequestion[]}} \def\@includequestion[#1]#2{% \begingroup \let\documentclass\dummy@documentclass \let\document\@empty % not \relax: makes \begin think {document} is undef'd \let\enddocument\endinput % stop reading, discarding any junk below \end{document} \def\@tempa{#1} \ifx\@tempa\@empty \else \def\@includequestionoverridenumber{#1} \message{includequestion override: \@includequestionoverridenumber} \fi \def\usepackage##1{\ClassWarning{exam-n} {Ignoring \string\usepackage{##1} in included question #2}} \let\RequirePackage\usepackage \input{#2} \endgroup } \let\@includequestionoverridenumber\@empty % \end{macrocode} % % \subsection{The solution environment} % % The solution environment is made somewhat complicated by the way we % implement it. Rather than using a verbatim-like technique to omit % the source lines (as done successfully by, for example, the % \Lpackage{comments} package) we set the contents of the environment % in a box, which we throw away. This technique is more robust in % principle, but it does mean we have to disable some things which % have global side-effects. % % Maintain a flag which indicates whether we're in a solution % environment or not. % \begin{macrocode} \newif\if@insolution \@insolutionfalse % \end{macrocode} % % We want to use |\part| within solutions. If we were to do so naively % however, we would end up incrementing the |partnumber| counter % which that macro uses, which either disturbs the numbering of the % parts in the question (if the solutions are interspersed in the % question) or starts out of sequence (if the solutions are at the % end). So we maintain a separate counter. Additionally, we want to % force the formatting of the solution parts, to be independent of the % formatting in the main question % \begin{macrocode} \newcounter{answerpartnumber} \newcommand{\examn@solutionpart}{% \par \stepcounter{answerpartnumber} \noindent\hbox to \parindent{(\StylePartNumber{answerpartnumber})\hss}} % \end{macrocode} % % Specify how solutions should be shown. The following makes them % ragged right, slightly smaller and slanted, with rules fore and aft. % This doesn't leap out, but the difference should be detectable. % Putting a box round the solution would be desirable (it keeps it all % together and would allow a coloured background), but that's rather % hard to arrange in practice. % % Solutions are shown in a slightly smaller size (namely |\small|). % It's debatable whether this is a good thing or not. Note that if % this is changed by removing the |\small|, then % |\examn@dummycaptions| will have to be adjusted, too. % % If either of the `enlarged font' options has been given, then we set % the solutions in the same large font, since these might be % distributed to students as model answers. % \begin{macrocode} \def\@formatsolution{\par \if@insolution \ClassError{exam-n}{Misplaced solution}{You can't have a solution within a solution} \else \@insolutiontrue % this happens within a group \fi \examn@dummycaptions % dummy captions within solutions \typeout{SHOWING SOLUTIONS} \let\part\examn@solutionpart % \end{macrocode} % Checks done; now get on with the layout % \begin{macrocode} \vskip 1ex plus 2\bigskipamount % add stretchable space... \penalty-\@lowpenalty % ...and encouragement to break here \parskip 0.5\baselineskip \raggedright \color{solutiontext}%\slshape \normalsize \hrule \hbox to \textwidth{\vrule height 1ex \hfil \vrule height 1ex} \nobreak \vskip -\parskip % cancel out the following parskip \textbf{\highlighted{Solution:}}\hskip2em \ignorespaces \parindent=2em } % \end{macrocode} % The end of the solution environment is simple, and simply matches % the box above. % \begin{macrocode} \def\end@formatsolution{% \par \nobreak \vskip -0.5ex \hbox to \textwidth{\vrule height 1ex \hfil \vrule height 1ex} \hrule } % \end{macrocode} % % The content of the \Lenv{solution} environment is balanced \LaTeX\ % text, and so does not have to be complicated; in particular, it does % not have to have the generality, and the consequent restrictions, of % for example Eijkhout's \Lpackage{comment} package. If we're including the % solutions, then we simply format them in the usual sort of way, % inside a group; otherwise we're skipping them, so put the contents in a % box and throw it away. Note that \Lenv{solution} is an environment, % so we're inside a group at this point. % \begin{macrocode} \if@showsolutions \let\solution\@formatsolution \let\endsolution\end@formatsolution % \end{macrocode} % In the case where we're not showing solutions, note that we % \emph{do} format the contents, so any |\global| effects will still % happen, unless we take action to avoid them. % % In particular, |\part|, which is normally redefined in solutions to % increment \texttt{answerpartnumber} rather than % \texttt{partnumber}, would increment \texttt{partnumber} in answers % unless we take action to stop it. % \begin{macrocode} \else \def\solution{% make a vbox... \par \if@insolution \ClassError{exam-n}{Misplaced solution}{You can't have a solution within a solution} \fi \let\endfigure\endfloat@skipsolutions \let\endtable\endfloat@skipsolutions \examn@dummycaptions % dummy captions avoid counter increments \let\part\relax % make \part a no-op in discarded {solution} \@ifundefined{includepdf}{}{\let\includepdf\examn@disabledpdfpages} \setbox\@tempboxa\vbox\bgroup \@insolutiontrue } \def\endsolution{%...and do nothing with this box \egroup } \fi % \end{macrocode} % % \subsubsection{Floats in solutions} % % Figures in solutions must be treated specially, since they mustn't % move outside the solution. The most straightforward thing seems to % be to avoid them floating at all. Additionally, this is probably true of % figures in the question as well (if a question refers to a figure, % it's probably civil to have the figure on the same page as the % text), so redefine {figure} so that in all cases figures are placed % `here', and never float. We also add generous amounts of vertical % space, to encourage figures to stay on the same page as the text % before them, if this is at all possible. % % \begin{macrocode} \def\examn@badfloat#1[#2]{ \ClassError{exam-n} {Bad #1 option #2 ignored} {In the exam-n class, the 'floating' environments take no argument,\MessageBreak and are always placed 'here'} \examn@float{#1}} \def\examn@float#1{% % re-using the standard LaTeX parameter means that \caption works \def\@captype{#1} \setbox\@tempboxa\vbox\bgroup} % \end{macrocode} % End both |{figure}| and |{table}| environments. % End the |\@tempboxa| and add some space and good breaks before displaying it. % We're typically in hmode here, but don't depend on it. % \begin{macrocode} \def\examn@endfloat{% \egroup % end \@tempboxa \ifvmode\else \unskip \fi % bare \unskip would can an error in vmode \nobreak % add lots of stretchability, but non-infinite, for the sake of tidiness \vskip 0pt plus 0.5\textheight \penalty50 % a pagebreak here discards following vskip % (cf TeXBook p106; or try \filbreak of p111) \vskip 2ex plus -0.5\textheight % negative stretch cancels previous vskip \box\@tempboxa %\vskip 1ex \nobreak } \def\endfloat@skipsolutions{% % variant when skipping solutions -- end the \@tempboxa and do nothing \egroup } % \end{macrocode} % Now, finally, redefine the figure and table environments in terms of % these new macros. % \begin{macrocode} \def\figure{% \@ifnextchar[{\examn@badfloat{figure}}{\examn@float{figure}}%] } \def\table{% \@ifnextchar[{\examn@badfloat{table}}{\examn@float{table}}%] } \let\endfigure\examn@endfloat \let\endtable\examn@endfloat % \end{macrocode} % And disable the \texttt{figure*} and \texttt{table*} environments. % \begin{macrocode} \expandafter\def\csname figure*\endcsname{% \ClassError{exam-n} {Bad environment figure* -- there is no figure* environment in exam-n} {Use plain {figure} instead. See the documentation for discussion}} \expandafter\def\csname table*\endcsname{% \ClassError{exam-n} {Bad environment table* -- there is no table* environment in exam-n} {Use plain {table} instead. See the documentation for discussion}} % \end{macrocode} % % Within these 'floats', we must redefine |\caption|, so that we don't % increment the float counters. One motivation for this is so that we don't have % table numbers changing depending on whether solutions are included % or not; but since we're implementing the solutions by setting the % content in a discarded box, it turns out that we get the counter % increments whether we include the solutions or not. The following % definition of |\caption| is just the standard one, with % |\refstepcounter| removed and `Table nnn' redefined appropriately. % \begin{macrocode} \def\examn@dummycaptions{% \def\fnum@figure{\figurename} % 'Figure nnn' changed to just 'Figure' \def\fnum@table{\tablename} \def\caption{% \ifx\@captype\@undefined \@latex@error{\noexpand\caption outside float}\@ehd \expandafter\@gobble \else %\refstepcounter\@captype % omit this line from the standard definition \expandafter\@firstofone \fi {\@dblarg{\@caption\@captype}}% } } % \end{macrocode} % % \subsubsection{Solutions and pdfpages} % % It appears that the \Lpackage{pdfpages} package is incompatible with % the way that I implement \Lopt{noshowsolutions}, largely because (I % think) it bypasses \LaTeX\ and fiddles with the generated PDF % directly. Therefore, we have to disable the \Lpackage{pdfpages} % support when we're skipping solutions. We mustn't do this globally, % since sometimes (for example in a .clo option file's % constants sheet) we do need pdfpages in the no-show-solutions case. % \begin{macrocode} \def\examn@disabledpdfpages{\@ifnextchar[% ] \examn@disabledpdfpages@ {\examn@disabledpdfpages@[]}} \def\examn@disabledpdfpages@[#1]#2{\relax} % \end{macrocode} % % \subsection{End-of-document actions} % % Add a number of actions to the end-of-document hook. Do them here, % rather than by calling |\AtEndDocument| multiple times, because the % order matters (in fact, the order here is the same as the order % they're defined in, but it's best to be explicit about this). % \begin{macrocode} \AtEndDocument{ \CheckTotalQuestions \ClosingText \showthe@shouts \WriteLastPageLabel} % \end{macrocode} % % \iffalse extradefs:start % This is a magic comment -- see Makefile. % these definitions are referred to, in order to document % them, both in this class's documentation, and in the % notes-for-authors. \fi % % \subsection{Other formatting niceties} % % Format vectors (the default for |\vec| is a symbol with an arrow % over it): % % Note: the STIX2+(XeLaTeX/LuaLaTeX) support depends on the LaTeX hook % mechanism released in 2020. It therefore does not work on versions of % LaTeX older than that. There is a check for this above (see % Sect~\ref{s:compatibility}). % \begin{macrocode} \if@psfonts \ifcase\examn@mtselect % mathptm fonts % This is a very clumsy version, but it appears to be our only option \def\vec#1{\mathchoice{\mbox{\boldmath $\displaystyle #1$}} {\mbox{\boldmath $ #1$}} {\mbox{\boldmath $\scriptstyle #1$}} {\mbox{\boldmath $\scriptscriptstyle #1$}}} \ifexamn@uprightpi \ClassWarning{exam-n}{Can't do uprightpi in [mathptm] -- sorry} \let\italicpi\pi \examn@uprightpifalse \fi \or % mathtime (should this be the same for mathtime as for mtpro2? \let\vec\mathbf \ifexamn@uprightpi \ClassWarning{exam-n}{Can't do uprightpi in [mathtime] -- sorry} \let\italicpi\pi \examn@uprightpifalse \fi \or % mtpro2 \let\vec\mathbold % \uppi is predefined in mtpro2 \ifexamn@uprightpi \let\italicpi\pi \let\pi\uppi \fi \else % STIX2: the unicode-math package provides a \symbf for bold math symbols, \ifnum\examn@engine<2 % pdflatex \let\vec\mathbf % pdftex (or original tex) % The following should, I think, create an upright pi, but doesn't \def\uppi{\mathrm{\pi}} \let\italicpi\pi %for consistency \let\symup\mathrm %not fully the right thing, but avoid errors below \else % xelatex or lualatex % This is where the dependence on a recent LaTeX enters. \let\vec\symbf \typeout{stix2: upright=\ifexamn@uprightpi true\else false\fi} \AddToHook{begindocument/end}{\gdef\uppi{\symup{𝜋}}} \ifexamn@uprightpi \AddToHook{begindocument/end}{\gdef\italicpi{\symit{𝜋}}\global\let\pi\uppi} \fi \fi \fi \else % CM fonts: \mathbf doesn't work with greek in CM \let\vec\mathbf \ifexamn@uprightpi % upright greek is hard to do portably, so give up % See eg https://tex.stackexchange.com/questions/145926/ for discussion \ClassWarning{exam-n}{Can't do uprightpi in [cmfonts] -- sorry} \let\italicpi\pi \let\uppi\pi %but avoid errors \examn@uprightpifalse \fi \fi % \end{macrocode} % % Abbreviations for various degrees. % \begin{macrocode} \newcommand\BSc{B.Sc.{}} \newcommand\MSci{M.Sci.{}} \newcommand\MSc{M.Sc.{}} \newcommand\MA{M.A.{}} \newcommand\MEng{M.Eng.{}} \newcommand\BEng{B.Eng.{}} % \end{macrocode} % % Formatting differentials, and the base of natural logs, % which should be in an upright font. % See section~\ref{s:othercommands}, or the `notes for authors', % for a description of these macros. % The macro |\ddd| is used inside an integral, and includes a leading thinspace % \begin{macrocode} \ifnum\examn@mtselect>2 % ie, STIX2, and thus using the unicode-math package (see above) \def\e{\symup{e}} \newcommand{\dd}{\symup{d}} \newcommand{\ddd}{\,\symup{d}} \else \def\e{\mathrm{e}} \newcommand{\dd}{\mathrm{d}} \newcommand{\ddd}{\,\mathrm{d}} \fi \def\Diffl{\@ifstar\@Difflflat\@Diffl} \def\Partial{\@ifstar\@Partialflat\@Partial} \def\@Partial{\@ifnextchar[{\@@Diffl\partial}{\@@Diffl\partial[]}} \def\@Partialflat{\@ifnextchar[{\@@Difflflat\partial}{\@@Difflflat\partial[]}} \def\@Diffl{\@ifnextchar[{\@@Diffl\dd}{\@@Diffl\dd[]}} \def\@Difflflat{\@ifnextchar[{\@@Difflflat\dd}{\@@Difflflat\dd[]}} \def\@@Diffl#1[#2]#3#4{% \def\@tempa{#2}% \ifx\@tempa\empty \frac{#1#3}{#1#4}% \else \frac{{#1}^{#2}#3}{#1{#4}^{#2}}% \fi} \def\@@Difflflat#1[#2]#3#4{% \def\@tempa{#2}% \ifx\@tempa\empty #1#3\mskip-0.8mu/\mskip-1.2mu #1#4% \else {#1}^{#2}#3\mskip-0.8mu /\mskip-1.2mu #1{#4}^{#2}% \fi} % \end{macrocode} % % Physical units in upright roman. This macro is now deprecated in % favour of use of the \Lopt{siunitx} option (which uses the % \Lpackage{siunitx} package, qv), and it will be removed in a % minor release after v1.4. % % The unstarred version includes leading % |\thinspace|. The starred version doesn't, and is used when referring to % the unit by itself (eg axis is |$B/\units*T$|), and is not qualifying % a number. % Separate units with either \texttt{.} or |~|, as in |\units{m~s^{-1}}| or % |\units{m.s^{-1}}|. % Note that although \texttt{.} and |~| are both possible unit separators in % general, the former won't work if used within a table (due to the timing of % token-reading). % % This is a rather simple-minded approach to unit formatting. For a much more % comprehensive treatment, see the \texttt{siunitx} package, % \url{https://ctan.org/pkg/siunitx}, which is now preferred, in place % of further use of this macro. % % Note: there are detailed prescriptions on the formatting of units and symbols in % ISO-80000-1:2009, Sect. 7. % \begin{macrocode} \def\units{\examn@unitswarning \begingroup \catcode`\.=\active \@ifstar{\let\un@tsspace\relax \un@ts}% {\let\un@tsspace\thinspace\un@ts}} \begingroup \catcode`\.=\active \gdef\un@ts#1{\let~\thinspace\let.\thinspace \ifmmode \un@tsspace\mathrm{#1}% \else \nobreak$\un@tsspace\mathrm{#1}$% \fi \endgroup} \endgroup \newif\ifexamn@warnunits \examn@warnunitstrue \def\examn@unitswarning{\ifexamn@warnunits \ClassWarning{exam-n}{The units macro will be removed in the next version; the [siunitx] option is now on by default, so you can use the macros in the siunits package}% \global\examn@warnunitsfalse \fi} % \end{macrocode} % \iffalse extradefs:end % magic comment -- see Makefile \fi % % All done. % \begin{macrocode} % % \end{macrocode} % \Finale % \endinput