summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/exframe
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/exframe
Initial commit
Diffstat (limited to 'macros/latex/contrib/exframe')
-rw-r--r--macros/latex/contrib/exframe/README.txt49
-rw-r--r--macros/latex/contrib/exframe/exframe.dtx6312
-rw-r--r--macros/latex/contrib/exframe/exframe.ins39
-rw-r--r--macros/latex/contrib/exframe/exframe.pdfbin0 -> 389785 bytes
4 files changed, 6400 insertions, 0 deletions
diff --git a/macros/latex/contrib/exframe/README.txt b/macros/latex/contrib/exframe/README.txt
new file mode 100644
index 0000000000..cea7a5c270
--- /dev/null
+++ b/macros/latex/contrib/exframe/README.txt
@@ -0,0 +1,49 @@
+exframe v3.3
+Copyright 2011-2019 Niklas Beisert
+
+exframe is a LaTeX2e package which provides a general purpose
+framework to describe and typeset exercises and exam questions
+along with their solutions. The package features mechanisms to
+hide or postpone solutions, to assign and handle points, to
+collect problems on exercise sheets, to store and use metadata
+and to implement a consistent numbering. It also provides a
+very flexible interface for configuring and customising the
+formatting, layout and representation of the exercise content.
+
+The package consists of the files
+
+ README.txt readme file
+ exframe.ins installation file
+ exframe.dtx source file
+ exframe.sty package file
+ exfsamp.tex standalone sample latex file
+ exfserm.tex multipart sample main file
+ exfser01.tex multipart sample sheet 1
+ exfser02.tex multipart sample sheet 2
+ exfser03.tex multipart sample sheet 3
+ exfseraa.tex multipart sample unused problems
+ exfserpe.tex multipart sample problem E
+ exfserpf.tex multipart sample problem F
+ exfsermk.sh multipart sample compile script
+ exfsermk.mak multipart sample makefile
+ exframe.pdf manual
+
+The distribution consists of the files
+README.txt, exframe.ins and exframe.dtx.
+
+Run "(pdf)latex exframe.dtx" to compile the manual exframe.pdf.
+
+Run "latex exframe.ins" to create the package exframe.sty
+and the samples consisting of exfsamp.tex, exfserm.tex,
+exfser01.tex, exfser02.tex, exfser03.tex, exfseraa.tex,
+exfserpe.tex, exfserpf.tex, exfsermk.sh, exfsermk.mak.
+Copy the file exframe.sty to an appropriate directory of your LaTeX
+distribution, e.g. texmf-root/tex/latex/exframe.
+
+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.
diff --git a/macros/latex/contrib/exframe/exframe.dtx b/macros/latex/contrib/exframe/exframe.dtx
new file mode 100644
index 0000000000..dd8e26e393
--- /dev/null
+++ b/macros/latex/contrib/exframe/exframe.dtx
@@ -0,0 +1,6312 @@
+% \iffalse
+%
+% exframe.dtx Copyright (C) 2011-2019 Niklas Beisert
+%
+% 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 Niklas Beisert.
+%
+% This work consists of the files exframe.dtx and exframe.ins
+% and the derived files exframe.sty and exfsamp.tex, exfserm.tex,
+% exfser01.tex, exfser02.tex, exfser03.tex, exfseraa.tex,
+% exfserpe.tex, exfserpf.tex, exfsermk.sh, exfsermk.mak.
+%
+%<package|samplesingle|samplemultimain>\NeedsTeXFormat{LaTeX2e}[1996/12/01]
+%<package>\ProvidesPackage{exframe}[2019/06/15 v3.3 Framework for Exercise Problems]
+%<samplesingle>\ProvidesFile{exfsamp.tex}[2019/06/15 v3.3 standalone sample for exframe]
+%<samplemultimain>\ProvidesFile{exfserm.tex}[2019/06/15 v3.3 multipart sample for exframe]
+%<*driver>
+\def\thedate#1{2019/06/15}\def\theversion#1{v3.3}
+\ProvidesFile{exframe.dtx}[\thedate{} \theversion{} exframe reference manual file]
+\PassOptionsToClass{10pt,a4paper}{article}
+\documentclass{ltxdoc}
+
+\usepackage[margin=35mm]{geometry}
+\usepackage{hyperref}
+\usepackage{hyperxmp}
+\usepackage[usenames]{color}
+
+\hypersetup{colorlinks=true}
+\hypersetup{pdfstartview=FitH}
+\hypersetup{pdfpagemode=UseNone}
+\hypersetup{pdfsource={}}
+\hypersetup{pdflang={en-UK}}
+\hypersetup{pdfcopyright={Copyright 2010-2019 Niklas Beisert.
+ 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.}}
+\hypersetup{pdflicenseurl={http://www.latex-project.org/lppl.txt}}
+\hypersetup{pdfcontactaddress={ETH Zurich, ITP, HIT K,
+ Wolfgang-Pauli-Strasse 27}}
+\hypersetup{pdfcontactpostcode={8093}}
+\hypersetup{pdfcontactcity={Zurich}}
+\hypersetup{pdfcontactcountry={Switzerland}}
+\hypersetup{pdfcontactemail={nbeisert@itp.phys.ethz.ch}}
+\hypersetup{pdfcontacturl={http://people.phys.ethz.ch/\xmptilde nbeisert/}}
+
+\newcommand{\secref}[1]{\hyperref[#1]{section \ref*{#1}}}
+
+\parskip1ex
+\parindent0pt
+\let\olditemize\itemize
+\def\itemize{\olditemize\parskip0pt}
+
+\begin{document}
+
+\title{The \textsf{exframe} Package}
+\hypersetup{pdftitle={The exframe Package}}
+\author{Niklas Beisert\\[2ex]
+ Institut f\"ur Theoretische Physik\\
+ Eidgen\"ossische Technische Hochschule Z\"urich\\
+ Wolfgang-Pauli-Strasse 27, 8093 Z\"urich, Switzerland\\[1ex]
+ \href{mailto:nbeisert@itp.phys.ethz.ch}
+ {\texttt{nbeisert@itp.phys.ethz.ch}}}
+\hypersetup{pdfauthor={Niklas Beisert}}
+\hypersetup{pdfsubject={Manual for the LaTeX2e Package exframe}}
+\date{\thedate{}, \theversion{}}
+\maketitle
+
+\begin{abstract}\noindent
+\textsf{exframe} is a \LaTeXe{} package
+which provides a general purpose framework to describe and typeset
+exercises and exam questions along with their solutions.
+The package features mechanisms
+to hide or postpone solutions,
+to assign and handle points,
+to collect problems on exercise sheets,
+to store and use metadata
+and to implement a consistent numbering.
+It also provides a very flexible interface for configuring and customising
+the formatting, layout and representation of the exercise content.
+\end{abstract}
+
+\begingroup
+\parskip0ex
+\tableofcontents
+\endgroup
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Introduction}
+
+This package provides a framework to describe and typeset
+exercises (homework problems, classroom exercises, quizzes, exam questions,
+exercise questions in books and lecture notes, \ldots)
+and their solutions or answers.
+The aim of this package is to set up a few \LaTeX{} environments
+into which questions and corresponding answers can be filled conveniently.
+The main task of the package is to manage the text and data
+that are provided in the source document,
+perform some common operations on them,
+and then output the content appropriately.
+The package has the following goals, tasks and features:
+%
+\begin{itemize}
+\item
+The package is designed with generality in mind.
+It is meant to be usable in many different situations.
+The primary target is science and education, but it may well
+be useful in other areas.
+
+\item
+The package defines a basic functional layout for the output
+and provides many options to reshape the layout and formatting
+according to the author's needs and wishes.
+
+\item
+The package can handle two layers of exercises:
+main problems and subproblems.
+The use of subproblems is optional.
+
+\item
+The display of solutions can be configured:
+Solutions can be hidden for a hand-out version of exercise sheets.
+When displayed, they may appear immediately,
+collectively after the problem,
+at the end of each sheet or at some manually defined location.
+
+\item
+The package can handle exercise sheets which combine several exercise problems:
+A \LaTeX{} document can consist of an individual sheet
+or of a collection of sheets (e.g.\ spanning a lecture course).
+In the latter case, the document files can be set up
+such that single sheets as well as a collection of all sheets
+can be compiled; the package \textsf{childdoc} may be of assistance.
+
+\item
+The package can handle points to be credited:
+Points will be displayed according to the layout.
+Overall points for a problem or a sheet can be added automatically.
+Points can also be stored and used elsewhere.
+
+\item
+The package provides an interface to specify exercise metadata
+(author, source, \ldots):
+Some basic types of metadata are predefined and more specific metadata
+categories can be added.
+
+\item
+The package can use alternative counters for equations
+within solutions (and problems). This is to ensure a consistent
+numbering independently of whether solutions are output or not.
+\end{itemize}
+
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Usage}
+\label{sec:usage}
+
+To use the package \textsf{exframe} add the command
+%
+\begin{center}
+|\usepackage{exframe}|
+\end{center}
+%
+to the preamble of the \LaTeX{} document.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Exercise Environments}
+\label{sec:environments}
+
+The package provides four environments
+to describe the main entities of exercise problems.
+Additional information on the exercises can be provided
+in the optional arguments to these environments
+which will be discussed in the following sections.
+Furthermore, a limited set of commands
+is provided for control and extra features,
+see the sections below for details.
+
+\DescribeEnv{problem}
+The |problem| environment describes
+an exercise problem:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{problem}[|\textit{opts}|]|\\
+| |\textit{problem text and subproblems}\\
+|\end{problem}|
+\end{tabular}
+\end{center}
+%
+As one of the many available options \textit{opts},
+one can provide a title for the exercise by
+specifying |title={|\textit{title}|}|.
+If no title is given, the problem number will be displayed instead.
+See \secref{sec:metadata} and \secref{sec:points}
+for a description of the available options.
+
+\DescribeEnv{subproblem}
+The |subproblem| environment describes
+a subproblem, part or an individual question of an exercise problem:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{subproblem}[|\textit{opts}|]|\\
+| |\textit{subproblem text}\\
+|\end{subproblem}|
+\end{tabular}
+\end{center}
+%
+A |subproblem| environment must be contained within a |problem| environment
+(however, a |problem| block need not contain |subproblem| blocks).
+
+\DescribeEnv{solution}
+The |solution| environment describes
+the solution to a problem or a subproblem:
+\begin{center}
+\begin{tabular}{l}
+|\begin{solution}[|\textit{opts}|]|\\
+| |\textit{solution text}\\
+|\end{solution}|
+\end{tabular}
+\end{center}
+%
+A |solution| environment should be
+at the end of a |subproblem| or |problem| environment
+(it is not mandatory to provide a |solution|).
+It can be contained within the corresponding environment or it can follow it.
+Depending on the choice of solution display, see \secref{sec:solutions},
+the output may have a slightly different layout.
+In terms of logic, it is preferred
+to define a solution \emph{within} the corresponding environment;
+this may also have some technical advantages and produce
+a slightly better result in terms of layout.
+
+\DescribeEnv{sheet}
+The |sheet| environment describes an exercise sheet:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{sheet}[|\textit{opts}|]|\\
+| |\textit{sheet text and problems}\\
+|\end{sheet}|
+\end{tabular}
+\end{center}
+%
+A sheet typically contains one or several problems
+(it is not mandatory to group problems into a |sheet|).
+There may or may not be additional auxiliary text introducing the problems.
+A header will be added to the sheet according to the specified layout.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Solution and Problem Display}
+\label{sec:solutions}
+
+There are several options to control the output of solutions
+and of problems.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutions}
+Most importantly, the display of solutions
+can be disabled or enabled altogether:
+%
+\begin{center}
+|\exercisesetup{solutions|[|=true|\textbar|false|]|}|
+\end{center}
+%
+Solutions are hidden by default,
+and their display needs to be activated explicitly
+(it suffices to specify the option |solutions| without the value |true|).
+It is also possible to control the display
+by an analogous package option |solutions|,
+see \secref{sec:options} for further information.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\ifsolutions}
+The display of solutions is reflected by the conditional |\ifsolutions|.
+As the hiding of solutions is performed automatically,
+the conditional would typically be used to change some details,
+e.g.\ for adjusting titles:
+%
+\begin{center}
+|\ifsolutions Solutions\||else Exercises\||fi|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutionequation}
+As solutions can contain numbered equations
+while the display of solutions can be switched on and off,
+it is important to assign a different counter for equations within solutions
+in order for the equation numbers to be stable.
+A separate counter for equations within solutions is enabled by default.
+It can be disabled by:
+%
+\begin{center}
+|\exercisestyle{solutionequation=false}|
+\end{center}
+%
+This option prepends the letter `S' to equation
+numbers within solutions which are counted separately;
+the display can be configured differently, see \secref{sec:layout}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutionbelow}
+\DescribeMacro{\insertsolutions}
+The package allows to collect solutions
+and defer their display to particular locations:
+%
+\begin{center}
+|\exercisestyle{solutionbelow=|\textit{pos}|}|
+\end{center}
+%
+The available choices for \textit{pos} are
+to display solutions where they are defined (|here|),
+defer them to the end of the current subproblem (|subproblem|),
+problem (|problem|) or sheet (|sheet|)
+or display them at a manually chosen location (|manual|).
+Note that typically solutions are defined at the end of a (sub)problem
+and therefore the choice |here| is similar to (|sub|)|problem|.
+The latter form, however, makes sure that a solution
+does not inherit the margin of the parent environment.
+The alternate modes |problem*| and |subproblem*|
+positions the solution \emph{after} the (sub)problem environment
+such that it does not inherit any layout,
+but also no definitions made in the parent environment.
+In |manual| mode, all solutions are collected (with appropriate headers)
+until they are output by the directive |\insertsolutions|.
+If no solutions are stored in the buffer
+(or if the mode is not |manual|), |\insertsolutions| has no effect.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\writesolutions}
+Another option to handle solutions is to write them to a file
+for later use.
+Writing to a file is initiated by:
+%
+\begin{center}
+|\writesolutions[|\textit{filename}|]|
+\end{center}
+%
+The optional argument describes the filename as \textit{filename}|.sol|;
+no argument defaults to the main tex filename as |\jobname.sol|;
+the extension |.sol| can be customised by the configuration |extsolutions|.
+This mode overrides the |solutionbelow| behaviour described above;
+all subsequent solutions are written to the file.
+The file is closed by |\closesolutions| and the display of solutions
+returns to manual mode.
+It is not necessary to close a file as it will be closed
+automatically by reading from a file, writing to another file
+or by the end of the document.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\readsolutions}
+Solutions are read from a file by:
+%
+\begin{center}
+|\readsolutions[|\textit{filename}|]|
+\end{center}
+%
+This command outputs a sectional title
+and reads the file via |\input{|\textit{filename}|.sol}|.
+
+\medskip
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{solutionbuf}
+\DescribeMacro{problembuf}
+The package offers similar functionality to control the display of problems.
+In order to have any control over the content of |problem| environments,
+the latter needs to be read into an internal buffer.
+Reading of solutions and problems to internal buffers is activated
+or deactivated by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exercisesetup{solutionbuf|[|=true|\textbar|false|]|}|\\
+|\exercisesetup{problembuf|[|=true|\textbar|false|]|}|
+\end{tabular}
+\end{center}
+%
+By default, |solution| environments are read to an internal buffer,
+while the content of |problem| environments is processed directly
+by the \TeX\ engine.
+Therefore, the following options to control the display
+of |problem| environments require the statement |\exercisesetup{problembuf}|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{problemmanual}
+\DescribeMacro{\insertproblems}
+The immediate display of |problem| environments is controlled by:
+%
+\begin{center}
+|\exercisestyle{problemmanual|[|=true|\textbar|false|]|}|
+\end{center}
+%
+In the default automatic mode, problems are displayed directly
+where they are declared.
+In manual mode, problems are collected to an internal buffer,
+and only displayed by issuing |\insertproblems|.
+
+Note that |solution| environments should be
+declared within the corresponding |problem| environment in order to
+preserve their appropriate association.
+The |solution| environment is then processed at the place
+where the |problem| environment is displayed,
+and it may (or may not) be deferred further.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\writeproblems}
+\DescribeMacro{\readproblems}
+Problems can be written out to an external file for later usage.
+The functionality is analogous to solutions
+and uses the macros:
+%
+\begin{center}
+\begin{tabular}{l}
+|\writeproblems[|\textit{filename}|]|\\
+|\readproblems[|\textit{filename}|]|
+\end{tabular}
+\end{center}
+%
+The optional argument describes the filename as \textit{filename}|.prb|;
+no argument defaults to the main tex filename as |\jobname.prb|;
+the extension |.prb| can be customised by the configuration |extproblems|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{disable}
+\DescribeMacro{insertproblemselect}
+The display of a particular |problem|
+can be suppressed altogether by an optional argument:
+%
+\begin{center}
+|\begin{problem}[disable]|
+\end{center}
+%
+
+This option can be exploited to automatically
+suppress certain classes of problems as follows:
+A hook function |insertproblemselect| declared by:
+%
+\begin{center}
+|\exerciseconfig{insertproblemselect}[1]{|\textit{code}|}|
+\end{center}
+%
+can call
+|\setproblemdata{disable}| whenever a problem is to be suppressed.
+In order to decide, the optional argument of the |problem| environment
+is passed on to the hook function as the single argument.
+Note that the argument needs to be processed manually.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Metadata}
+\label{sec:metadata}
+
+In a collection of exercise problems
+it makes sense to keep track of metadata
+for the overall collection as well as for individual problems
+and potentially display some of them.
+The framework defines a standard set of metadata fields
+and offers functionality to add more specialised metadata fields.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exercisedata}
+Global metadata is specified by the command:
+%
+\begin{center}
+|\exercisedata{|\textit{data}|}|
+\end{center}
+%
+The argument \textit{data}
+is a comma-separated list of metadata specifications
+in the form \textit{key}|={|\textit{value}|}|.
+The standard set of global metadata keys consists of:
+%
+\begin{itemize}
+\item |author|:
+principal author(s) of the exercise collection;
+also invokes the \LaTeX{} command |\author|;
+will be written to pdf documents.
+\item |title|:
+title of the exercise collection;
+also invokes the \LaTeX{} command |\title|;
+will be written to pdf documents.
+\item |date|:
+date of the exercise collection;
+also invokes the \LaTeX{} command |\date|;
+will be written to pdf documents.
+\item |subject|:
+subject area of the exercise collection;
+will be written to pdf documents.
+\item |keyword|:
+keyword(s) for the exercise collection;
+will be written to pdf documents.
+\item |course|:
+title of the course (class, lecture, module, \ldots)
+for the exercise collection.
+\item |institution|:
+institution (school, department, institute, university, \ldots)
+offering the course or exercise collection.
+\item |instructor|:
+instructor(s) for the course or exercise;
+this field refers to person(s) who organise
+the corresponding course or exercises
+whereas |author| refers to the principal creator of the material.
+\item |period|:
+period (year, season, date, term identifier, \ldots)
+of the corresponding course.
+\item |material|:
+type of material
+(exercises, homework assignments, exam, quizzes, solutions, \ldots).
+\end{itemize}
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defexercisedata}
+Additional custom fields for global metadata can be created with:
+%
+\begin{center}
+|\defexercisedata{|\textit{key}|}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getexercisedata}
+\DescribeMacro{\exercisedataempty}
+Global metadata should typically be specified
+somewhere at the top of the main document,
+and it can be inserted wherever needed.
+There are two commands to read and process metadata.
+To insert the value of metadata field \textit{key} use:
+%
+\begin{center}
+|\getexercisedata{|\textit{key}|}|
+\end{center}
+%
+In some situations the output should depend on whether
+a metadata has been filled
+(e.g.\ to fill a default value or to display something else instead).
+This can be checked with the conditional:
+%
+\begin{center}
+|\exercisedataempty{|\textit{key}|}|%
+ |{|\textit{empty code}|}{|\textit{filled code}|}|
+\end{center}
+%
+The \textit{empty code} is executed if no value
+or an empty value has been specified;
+otherwise the \textit{filled code} is executed.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{sheet}
+\DescribeMacro{problem}
+The package offers a similar mechanism to describe and use metadata
+for sheets and problems:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{sheet}[|\textit{opts}|]|\\
+|\begin{problem}[|\textit{opts}|]|
+\end{tabular}
+\end{center}
+%
+The argument \textit{opt}
+is a comma-separated list which can contain metadata specifications
+in the form \textit{key}|={|\textit{value}|}|.
+The standard set of metadata keys for sheets consists of:
+%
+\begin{itemize}
+\item |due|:
+indication of the due date for the exercise sheet.
+\item |handout|:
+indication of the handout date for the exercise sheet.
+\item |title|:
+specifies a title for the sheet;
+when reading value (see below), returns composed title;
+untitled sheets will be displayed by their number;
+title will be written to pdf documents.
+\item |rawtitle| (for reading only):
+contains the raw title as specified by |title|.
+\item |author|:
+author(s) of the sheet;
+will be written to pdf documents.
+\item |editor|:
+editor(s) of the sheet; this field refers to a person
+who makes adjustments to the sheet
+whereas |author| refers to the creator of the sheet.
+\item |editdate|:
+indication of the date when the sheet was last edited.
+\end{itemize}
+%
+The standard set of metadata keys for problems consists of:
+%
+\begin{itemize}
+\item |title|:
+specifies a title for the problem;
+when reading value (see below), returns composed title;
+untitled problems will be displayed by their number.
+\item |rawtitle| (for reading only):
+contains the raw title as specified by |title|.
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defsheetdata}
+\DescribeMacro{\setsheetdata}
+\DescribeMacro{\getsheetdata}
+\DescribeMacro{\sheetdataempty}
+\DescribeMacro{\defproblemdata}
+\DescribeMacro{\setproblemdata}
+\DescribeMacro{\getproblemdata}
+\DescribeMacro{\problemdataempty}
+Metadata for sheets can be used in the same way as the global metadata.
+The following directives are analogous to |\defexercisedata|,
+|\exercisedata|, |\getexercisedata| and |\exercisedataempty|:
+%
+\begin{center}
+\begin{tabular}{l}
+|\defsheetdata{|\textit{key}|}|\\
+|\setsheetdata{|\textit{data}|}|\\
+|\getsheetdata{|\textit{key}|}|\\
+|\sheetdataempty{|\textit{key}|}|%
+ |{|\textit{empty code}|}{|\textit{filled code}|}|\\[1ex]
+|\defproblemdata{|\textit{key}|}|\\
+|\setproblemdata{|\textit{data}|}|\\
+|\getproblemdata{|\textit{key}|}|\\
+|\problemdataempty{|\textit{key}|}|%
+ |{|\textit{empty code}|}{|\textit{filled code}|}|
+\end{tabular}
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{pdfdata}
+\DescribeMacro{\writeexercisedata}
+The most relevant metadata can be written to
+the metadata section of pdf files
+(using pdf\LaTeX{} and the package \textsf{hyperref}
+whenever loaded).
+This feature is configured by:
+%
+\begin{center}
+|\exercisesetup{pdfdata|[|=auto|\textbar|manual|%
+ \textbar|sheet|\textbar|off|]|}|
+\end{center}
+%
+The option |auto| writes the global metadata
+|title|, |author|, |subject| and |keyword|
+to the corresponding fields in the pdf file.
+To make this work, these must be defined before the
+|\begin{document}| directive.
+The option |manual| allows to manually write these metadata
+by the command |\writeexercisedata|.
+It should be issued after the metadata have been set,
+but before any content is written to the pdf file.
+In other words, it can be anywhere in the document preamble
+directly after |\begin{document}|,
+or following a couple of content-free definitions at the beginning
+of the document body (in case the metadata should be set
+within the document body for some reason).
+The option |sheet| writes out the metadata
+at the beginning of the first |sheet| environment
+(which should follow |\begin{document}| without any content in between).
+This option is primarily for filling the
+|author| and |title| fields with metadata
+of a sheet rather than a collection of exercises.
+Note that if no |author| is defined for the sheet,
+the global metadata |author| is used.
+The option |off| disables all writing of metadata.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{problem}
+\DescribeMacro{subproblem}
+\DescribeMacro{solution}
+There is an additional mechanism to keep track of metadata
+for problems, subproblems and solutions
+which can be displayed in the opening line of these entities.
+Displayed metadata serve two purposes:
+they are used to describe the quality of a problem
+or they are intended for internal documentation purposes.
+Their output can be controlled individually,
+e.g.\ only in development versions of a document.
+Note that specifying a key more than once
+will display the content multiple times
+in the order in which they are encountered.
+Displayed metadata are specified
+at the top of the corresponding environment:
+%
+\begin{center}
+\begin{tabular}{l}
+|\begin{problem}[|\textit{opts}|]|\\
+|\begin{subproblem}[|\textit{opts}|]|\\
+|\begin{solution}[|\textit{opts}|]|
+\end{tabular}
+\end{center}
+%
+
+The standard set of displayed metadata keys consists of:
+%
+\begin{itemize}
+\item |author|:
+author(s) of the problem (or subproblem, solution).
+\item |editor|:
+editor(s) of the problem; this field refers to a person
+who has made adjustments to the problem
+whereas |author| refers to the creator of the problem.
+\item |source|:
+source of the problem;
+in case the problem has been taken from elsewhere
+(conceptually or literally).
+\item |difficulty|:
+indication of the level of difficulty of the problem.
+\item |keyword|:
+keyword(s) for the problem;
+\item |comment|:
+some comment on the problem.
+\item |optional|
+(display enabled by default):
+whether addressing the problem is mandatory or optional;
+by default the text will be displayed after the title
+in italic shape.
+\end{itemize}
+%
+By default, only the |optional| items are displayed,
+all other types of items are hidden;
+controlling the display for each type of item is described below.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{extdata}
+Further displayed metadata keys
+are defined by the package option |extdata|, see \secref{sec:options}:
+%
+\begin{itemize}
+\item |review|:
+field to review the aspects of the problem
+(quality, length, appropriateness, difficulty, \ldots).
+\item |recycle|:
+indication of previous instances where this problem was used.
+\item |timesolve|:
+indication of the time needed to solve this problem (or subproblem).
+\item |timepresent|:
+indication of the time needed to present this problem
+(or subproblem, solution).
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\showprobleminfo}
+The display of the above metadata fields for a problem
+(or subproblem, solution) is controlled by:
+%
+\begin{center}
+|\showprobleminfo{|\textit{keys}|}|
+\end{center}
+%
+Here \textit{keys} is a comma-separated list of keys to
+be activated (\textit{key} or \textit{key}|=true|)
+or deactivated (\textit{key}|=false|).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defprobleminfo}
+Displayable metadata can be defined or adjusted by:
+%
+\begin{center}
+|\defprobleminfo{|\textit{key}|}{|\textit{code}|}|
+\end{center}
+%
+Here \textit{key} specifies the metadata field and
+\textit{code} the code to display this type of metadata
+where the argument |#1| represents the data to be displayed.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{insertprobleminfo}
+\DescribeMacro{insertsubprobleminfo}
+\DescribeMacro{insertsolutioninfo}
+\DescribeMacro{\addprobleminfo}
+\DescribeMacro{\addprobleminfo*}
+Additional information can be injected into the opening line
+of problems and solutions by the definitions:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseconfig{insertprobleminfo}{|\textit{code}|}|\\
+|\exerciseconfig{insertsubprobleminfo}{|\textit{code}|}|\\
+|\exerciseconfig{insertsolutioninfo}{|\textit{code}|}|
+\end{tabular}
+\end{center}
+%
+The hook code \textit{code} will be called after processing
+the environment arguments. Information can be added to the opening line by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\addprobleminfo{|\textit{info}|}|\\
+|\addprobleminfo*{|\textit{info}|}|
+\end{tabular}
+\end{center}
+%
+The unstarred command adds information at the end of the opening line,
+the starred version at the beginning (but after the title or identifier).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Points}
+\label{sec:points}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{points}
+Exercise problems or certain parts of them
+can be credited with points (credits, awards, \ldots).
+The package provides an interface to specify and manage such points.
+Points are declared by the option |points=|\textit{points}
+for the environments |sheet|, |problem| and |subproblem|.
+These numbers will be printed to the opening line of
+problems and subproblems.
+
+Note that the points should normally be integer numbers.
+Fractional points are permissible as well,
+but the internal storage by the \TeX{} engine is somewhat limited,
+so that only fractions with powers of two as denominators
+(.5, multiples of .25, .125, .0625, \ldots) are reliable.
+More general fractional decimal numbers such as multiples of 0.2
+will be subject to rounding errors and will not display nicely.
+
+Bonus points can be specified in the format
+|points=|[\textit{regular}][|+|\textit{bonus}].
+By default, such points will be printed as
+[\textit{regular}][|+|\textit{bonus}] where 0 components are omitted.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{problempointsat}
+\DescribeMacro{subproblempointsat}
+\DescribeMacro{solutionpointsat}
+The location where points of problems and subproblems
+shall be displayed can be adjusted individually by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exercisestyle{problempointsat=start|\textbar|start*|\textbar|margin|%
+ \textbar|end|\textbar|manual|\textbar|off}|\\
+|\exercisestyle{subproblempointsat=start|\textbar|start*|\textbar|margin|%
+ \textbar|end|\textbar|manual|\textbar|off}|\\
+|\exercisestyle{solutionpointsat=start|\textbar|start*|\textbar|margin|%
+ \textbar|end|\textbar|manual|\textbar|off}|
+\end{tabular}
+\end{center}
+%
+The default values are |start| and |end| for problems and subproblems,
+respectively.
+The option |start| displays points at
+the very end of the opening line;
+the option |start*| displays them at the start of it.
+The option |end| displays points at the end of the
+problem or subproblem text.
+The option |margin| displays points in the margin.
+The option |manual| displays points at a manually chosen location
+specified by the directive |\showpoints|.
+Note that |\showpoints| can also be used for the option |end|
+to display the points prematurely
+(e.g.\ if the text ends with a displayed equation,
+it may make sense to display the points just before the equation).
+The option |off| disables the display of points.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getsheetdata}
+Points for sheets are only stored by the package;
+they must displayed manually.
+Within the corresponding |sheet| environment
+the points can be accessed by:
+%
+\begin{center}
+|\getsheetdata{points}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getsheetpoints}
+\DescribeMacro{\getproblempoints}
+\DescribeMacro{\getsubproblempoints}
+\DescribeMacro{\getsolutionpoints}
+\DescribeMacro{\extractpoints}
+\DescribeMacro{\switchpoints}
+The package allows to read the point totals
+for other sheets and problems:
+%
+\begin{center}
+\begin{tabular}{l}
+|\getsheetpoints{|\textit{tag}|}|\\
+|\getproblempoints{|\textit{tag}|}|\\
+|\getsubproblempoints{}|\\
+|\getsolutionpoints{}|
+\end{tabular}
+\end{center}
+%
+Here \textit{tag} is the tag assigned to the corresponding sheet or problem,
+see \secref{sec:labels}.
+An empty argument \textit{tag} refers to the current
+sheet, (sub)problem or solution.
+If bonus points are used, the points will be returned
+in the format [\textit{regular}][|+|\textit{bonus}];
+the components \textit{regular} and \textit{bonus}
+can be extracted from the returned expression
+by |\extractpoints| and |\extractpoints*|, respectively.
+A convenient case switch of the returned value can be performed by:
+%
+\begin{center}
+|\switchpoints{|\textit{reg}|}{|\textit{bonus}|}{|\textit{both}|}{|%
+\textit{none}|}{|\textit{val}|}|
+\end{center}
+%
+Here \textit{val} is the value returned from the points register,
+\textit{reg} is displayed for purely regular points,
+\textit{bonus} is displayed for purely bonus points,
+\textit{both} is displayed for mixed points,
+\textit{none} is displayed for no points.
+In each of the four expressions,
+|#1| will be replaced by the regular points
+and |#2| by the bonus points.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\awardpoints}
+Grading instructions with points to be awarded
+can be specified in the solution text by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\awardpoints[|\textit{details}|]{|\textit{points}|}|\\
+|\awardpoints*[|\textit{details}|]{|\textit{points}|}|
+\end{tabular}
+\end{center}
+%
+Here \textit{details} is an optional text with further details,
+e.g.\ to explain under which conditions
+these points are to be awarded.
+The starred form is used to specify optional points or alternative paths
+with alternative grading instructions.
+These points will be marked and not be used for the computation of a total.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{warntext}
+The package attempts to add up
+the points of subproblems to the problem total
+and likewise the points of problems to the sheet total.
+The package also performs some sanity checks on the provided numbers:
+If points are specified for both subproblems and problems
+or for both problems and sheets, they will be compared.
+Also the points within solutions (excluding optional or alternative points)
+are added up and compared to the corresponding problem or subproblem.
+Furthermore the package checks whether points
+are defined for all subproblems within a problem
+or all problems within a sheet.
+Mismatches are reported as package warnings.
+As point mismatches can be rather severe,
+there is an option to write such warnings directly into
+the output document (to be removed before distribution):
+%
+\begin{center}
+|\exercisesetup{warntext|[|=true|\textbar|false|]|}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{fracpoints}
+The package offers pretty display of fractional points
+with denominators 2, 4 and 8 by writing the decimal part
+as a fraction, e.g.\ 1.75 $\to$ 1$^3\mskip-4mu/\mskip-2mu_4$.
+This feature is enabled by:
+%
+\begin{center}
+|\exercisestyle{fracpoints}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Labels and Tags}
+\label{sec:labels}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{label}
+\LaTeX{} provides labels to make references to remote parts of the text.
+Labels can be set as usual by |\label{|\textit{label}|}| within the
+|problem|, |subproblems| and |sheet| environments.
+Alternatively, they can be specified
+as the environment option:
+%
+\begin{center}
+|label={|\textit{label}|}|
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{tag}
+\DescribeMacro{\sheettag}
+\DescribeMacro{\problemtag}
+The package provides an additional mechanism to tag sheets and problems.
+Each |sheet| and each |problem| can be assigned a unique tag \textit{tag} by
+the environment option:
+%
+\begin{center}
+|tag={|\textit{tag}|}|
+\end{center}
+%
+This tag is used for reading point totals
+as described in \secref{sec:points}.
+Furthermore, the macro |\sheettag| or |\problemtag|
+is set to the tag \textit{tag} within the current environment.
+If no tag is specified it matches the number of the sheet or problem;
+note that this number can change by reordering sheets and problems
+and therefore it should not be used to identify the entity from
+other parts of the document.
+
+A useful application for tags is to encapsulate labels
+within individual sheets and problems
+which are part of a collection of exercises.
+Labels which are composed as
+|\sheettag-|\textit{label} or
+|\problemtag-|\textit{label}
+can be considered local and will not clash with labels
+defined within a different environment.
+Within the same sheet or problem, local labels can be accessed
+by the same construction.
+They can also be accessed from remote parts of the document by fully
+expanding |\sheettag| or |\problemtag| for the desired target environment.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{autolabelsheet}
+\DescribeMacro{autolabelproblem}
+If unique tags are specified, the package can automatically create labels
+for sheets (|sheet:|\textit{tag}) and problems (|prob:|\textit{tag}) by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exercisesetup{autolabelsheet|[|=true|\textbar|false|]|}|\\
+|\exercisesetup{autolabelproblem|[|=true|\textbar|false|]|}|
+\end{tabular}
+\end{center}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Layout}
+\label{sec:layout}
+
+The package provides a large number of parameters to adjust the
+display of exercises to a desired layout.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exerciseconfig}
+Configuration settings are declared and modified by the command:
+%
+\begin{center}
+|\exerciseconfig{|\textit{key}|}[|\textit{narg}|]{|\textit{value}|}|
+\end{center}
+%
+Here \textit{key} is a key and \textit{value} is its assigned value.
+Configuration options can also be macros with arguments in which case
+\textit{narg} is the number of arguments and \textit{value}
+is the macro definition using arguments |#|\textit{n}.
+The command |\exerciseconfig| therefore is analogous to
+|\|(|re|)|newcommand| except that the definitions are
+encapsulated by the package and any previous definition
+is overwritten without checking.
+
+\DescribeMacro{\exerciseconfigappend}
+\DescribeMacro{\exerciseconfigprepend}
+In some cases it may be useful to be able to
+append or prepend to a (parameterless) definition by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseconfigappend{|\textit{key}|}{|\textit{value}|}|\\
+|\exerciseconfigprepend{|\textit{key}|}{|\textit{value}|}|
+\end{tabular}
+\end{center}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\getexerciseconfig}
+\DescribeMacro{\exerciseconfigempty}
+Configuration definitions can be read by:
+%
+\begin{center}
+|\getexerciseconfig{|\textit{key}|}|[\textit{arguments}]
+\end{center}
+%
+The number of arguments after |{|\textit{key}|}|
+must match the optional argument \textit{nargs} of the definition.
+Furthermore, it can be checked whether a configuration definition
+is empty:
+%
+\begin{center}
+|\exerciseconfigempty{|\textit{key}|}|%
+ |{|\textit{empty code}|}{|\textit{filled code}|}|
+\end{center}
+%
+The \textit{empty code} is executed if no value
+or an empty value has been specified.
+Otherwise the \textit{filled code} is executed.
+
+The package defines numerous layout configuration options.
+They are listed along with their original definition
+and a brief description in \secref{sec:imp-config}.
+They include options to:
+%
+\begin{itemize}
+\item
+adjust the language for the principal entities of this package
+like `sheet(s)', `problem(s)', `solution(s)', `points(s)';
+\item
+adjust the fonts styles of various parts of the text;
+\item
+adjust the spacing above, below, between various elements;
+\item
+define code to process data and insert text at various locations;
+\item
+compose text to be used in various situations;
+\item
+adjust the appearance of counters;
+\item
+adjust some other behaviour of the package.
+\end{itemize}
+%
+The following will highlight only few examples.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{insertsheettitle}
+An important setting is:
+%
+\begin{center}
+|\exerciseconfig{insertsheettitle}{|\textit{code}|}|
+\end{center}
+%
+The code \textit{code} is meant to print the title
+or header of an exercise sheet.
+The minimalistic default code |\centerline{\getsheetdata{title}}|
+merely prints the sheet title ``Sheet \#'' at the centre of a line.
+Commonly, one would replace this by a more elaborate header
+(potentially with some more information,
+appealing layout, logos, \ldots).
+In order to design a header template,
+it makes sense to retrieve data
+via |\getexercisedata| and |\getsheetdata|
+described in \secref{sec:metadata}.
+Likewise |\exercisedataempty| and |\sheetdataempty|
+can be used to display default values or alternative data
+if some particular data is not provided.
+An example is given by the |plainheader| extended style option
+defined in \secref{sec:imp-styles}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{composetitleproblem}
+Another noteworthy example is |composetitleproblem|
+to compose the title for a problem. It takes two parameters,
+the number and the title.
+The (somewhat simplified) default declaration is:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseconfig{composetitleproblem}[2]{\exerciseifempty{#2}|\\
+| {\getexerciseconfig{termproblem}|\\
+| \getexerciseconfig{composeitemproblem}{#1}}|\\
+| {\getexerciseconfig{composeitemproblem}{#1} #2}}|
+\end{tabular}
+\end{center}
+%
+This checks whether the title is empty.
+If no title is given use ``Problem \#.'',
+otherwise use ``\#. \textit{title}''.
+Here the term ``Problem'' is made abstract
+by the configuration |termproblem|
+(e.g.\ to support internationalisation)
+and the problem number is further composed obtained by
+the configuration |composeitemproblem|
+which takes the bare number as argument
+and returns it followed by a dot.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exerciseifempty}
+\DescribeMacro{\exerciseifnotempty}
+Handy conditionals command to check
+whether an expression \textit{expr} is empty are:
+%
+\begin{center}
+\begin{tabular}{l}
+|\exerciseifempty{|\textit{expr}|}|%
+ |{|\textit{empty code}|}{|\textit{filled code}|}|\\
+|\exerciseifnotempty{|\textit{expr}|}|%
+ |{|\textit{filled code}|}|
+\end{tabular}
+\end{center}
+%
+Their main purpose is to test
+whether some provided expression \textit{expt} is empty.
+They expand to the common \TeX{} constructs
+|\if&#1&#2\else#3\fi| and |\if&#1&\else#2\fi|
+which work assuming that \textit{expr} is not too exotic
+(e.g.\ it should not start with the character `|&|'
+and other special \TeX{} characters or macros are potentially dangerous).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Exercise Styles}
+\label{sec:styles}
+
+The package provides a mechanism to define exercise styles
+which customise the display of exercises in some coordinated fashion.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exercisestyle}
+Style(s) are activated by the command:
+%
+\begin{center}
+|\exercisestyle{|\textit{styles}|}|
+\end{center}
+%
+Here \textit{styles} is a comma-separated list of styles,
+where each style is given by a pair \textit{style}[|={|\textit{argument}|}|].
+The package defines a couple of standard styles:
+%
+\begin{itemize}
+\item |solutionbelow=|\textit{pos}
+(can take values |here|, |subproblem|, |subproblem*|,
+|problem|, |problem*|, |sheet| and |manual|;
+initially set to |subproblem|) --
+positions the solutions below the indicated environments;
+see \secref{sec:solutions} for details.
+
+\item |problempointsat=|\textit{pos}
+(can take values |start|, |start*|, |margin|, |end| and |manual|;
+initially set to |start|) --
+displays points in problems at the indicated location;
+see \secref{sec:points} for details.
+
+\item |subproblempointsat=|\textit{pos}
+(can take values |start|, |start*|, |margin|, |end| and |manual|;
+initially set to |end|) --
+displays points in subproblems at the indicated location;
+see \secref{sec:points} for details.
+
+\item |solutionpointsat=|\textit{pos}
+(can take values |start|, |start*|, |margin|, |end| and |manual|;
+initially set to |end|) --
+displays points in solutions at the indicated location;
+see \secref{sec:points} for details.
+
+\item |problemby={|\textit{counter}|}| --
+number problems with the prefix \textit{counter},
+i.e.\ reset the problem counter whenever \textit{counter} increases
+and use a composite label \textit{counter}|.|\textit{problem}
+to identify problems.
+
+\item |equationby={|\textit{counter}|}| --
+number the dedicated equation counters for sheets, problems and solutions
+with the prefix \textit{counter}.
+
+\item |problembysheet| --
+number problems by sheet.
+
+\item |equationbysheet| --
+number dedicated equations for sheets, problems and solutions by sheet;
+note that the main equation counter is unaffected by this setting,
+it therefore makes sense to also activate the style |sheetequation|
+or use |\counterwithin{equation}{sheet}|.
+
+\item |pagebysheet| --
+number pages by sheet and denote pages by \textit{sheet}|.|\textit{page};
+this style is useful to generate stable page numbers for
+a collection of sheets.
+
+\item |sheetequation|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+use a dedicated equation counter within sheets.
+
+\item |problemequation|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+use a dedicated equation counter within problems.
+
+\item |solutionequation|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |true|) --
+use a dedicated equation counter within solutions.
+
+\item |fracpoints|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+display fractional points for denominators 2, 4, 8;
+see \secref{sec:points} for details.
+
+\item |twoside|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable two-sided layout;
+in two-sided layout, sheets will start on odd pages
+and empty pages are added at the end of sheets
+to produce an even number of pages.
+
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{extstyle}
+Further exercise styles
+are defined by the package option |extstyle|, see \secref{sec:options}:
+%
+\begin{itemize}
+\item |plainheader| --
+define a plain sheet header to display
+some essential exercise and sheet data:
+|course|, |institution|, |instructor|, |period| (optional), sheet |title|,
+see \secref{sec:metadata};
+the line below the header, font styles and spaces can be adjusted,
+see the definition in \secref{sec:imp-styles}.
+
+\item |contents| --
+display sheets and problems in the table of contents
+(as sections and subsections).
+
+\item |solutionsf| --
+display solutions in sans serif font family.
+
+\item |solutiondimproblem| --
+dim the problem text whenever solutions are displayed.
+
+\item |solutionsep| --
+separate the solutions from the remaining text by horizontal lines.
+
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\defexercisestyle}
+Custom styles can be defined by:
+%
+\begin{center}
+\begin{tabular}{l}
+|\defexercisestyle{|\textit{style}|}{|\textit{init}|}|\\
+|\defexercisestylearg[|\textit{default}|]{|\textit{style}|}{|\textit{init}|}|
+\end{tabular}
+\end{center}
+%
+This feature can be used to predefine certain aspects of
+the exercises layout.
+For example, different default page layouts could be declared in this way.
+The first version declares a style which is
+initialised by the code \textit{item} upon activation by
+|\exercisestyle{|\textit{style}[|=true|]|}|.
+Note that |\exercisestyle{|\textit{style}|=false}| does nothing.
+The second version declares a style which is activated by
+|\exercisestyle{|\textit{style}[|={|\textit{arg}|}|]|}|
+and which calls \textit{item} with the argument |#1| referring to \textit{arg}
+(or \textit{default} if no argument is given).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Package Options}
+\label{sec:options}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\DescribeMacro{\exercisesetup}
+Features and options of general nature can be selected by the commands:
+%
+\begin{center}
+\begin{tabular}{rl}
+&|\usepackage[|\textit{opts}|]{exframe}|
+\\
+or&|\PassOptionsToPackage{|\textit{opts}|}{exframe}|
+\\
+or&|\exercisesetup{|\textit{opts}|}|
+\end{tabular}
+\end{center}
+%
+|\PassOptionsToPackage| must be used before |\usepackage|;
+|\exercisesetup| must be used afterwards.
+\textit{opts} is a comma-separated list of options.
+
+The following options are available only when
+loading the package, i.e.\ they will not work
+within |\exercisesetup|:
+%
+\begin{itemize}
+\item |extdata|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+define some more advanced metadata entries.
+
+\item |extstyle|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+define some more advanced styles.
+
+\item |problemenv=|\textit{name} --
+redefine environment name |problem|.
+This and the following alike options may be useful in
+quickly adjusting existing sources to
+the \textsf{exframe} framework
+if the original framework works similarly
+and no special features are used.
+Otherwise, it is highly advisable to leave the
+names of environments and counters
+defined by the package untouched.
+
+\item |subproblemenv=|\textit{name} --
+redefine environment name |subproblem|.
+
+\item |solutionenv=|\textit{name} --
+redefine environment name |solution|.
+
+\item |sheetenv=|\textit{name} --
+redefine environment name |sheet|.
+
+\item |problemcounter=|\textit{name} --
+redefine counter name |problem|.
+
+\item |subproblemcounter=|\textit{name} --
+redefine counter name |subproblem|.
+
+\item |solutioncounter=|\textit{name} --
+redefine counter name |solution|.
+
+\item |sheetcounter=|\textit{name} --
+redefine counter name |sheet|.
+
+\end{itemize}
+%
+
+The following options can be specified by all three methods described above:
+%
+\begin{itemize}
+\item |solutions|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+Enable/disable display of solutions.
+Sets the conditional |\ifsolutions| accordingly.
+
+\item |pdfdata|[|=auto|\textbar|manual|\textbar|sheet|\textbar|off|]
+(no value implies |auto|, initially set to |auto|) --
+control writing most relevant metadata to pdf files;
+has no effect without package \textsf{hyperref}.
+
+\item |lineno|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable writing of line numbers as comments
+into solution files.
+
+\item |twoside|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable two-sided layout;
+see \secref{sec:styles} for details.
+
+\item |solutionhref|[|=true|\textbar|true|]
+(no value implies |true|, initially set to |false|) --
+enable/disable use of hyper-references from solutions
+to the corresponding problems;
+has no effect without package \textsf{hyperref}.
+
+\item |warntext|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable writing of relevant warning messages
+(points mismatch, point sums require update)
+into the document output for easier detection.
+
+\item |autolabelsheet|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable automatically assigning labels
+(|sheet:\sheettag|; can be adjusted)
+to sheets according to their tag |\sheettag|.
+
+\item |autolabelproblem|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable automatically assigning labels
+(|prob:\problemtag|; can be adjusted)
+to problems according to their tag |\problemtag|.
+
+\item |solutionbuf|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |true|) --
+enable/disable buffering for |solution| environments
+in order to control their display;
+disabling buffering can be helpful
+in debugging faulty |solution| environments;
+it might also resolve some tokenisation issues in special circumstances;
+note that the display of solutions cannot be suppressed
+with |\exercisesetup{solutions=false}| when buffering if disabled.
+
+\item |problembuf|[|=true|\textbar|false|]
+(no value implies |true|, initially set to |false|) --
+enable/disable buffering for |problem| environments
+in order to control their display.
+
+\end{itemize}
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{Information}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Copyright}
+
+Copyright \copyright{} 2011--2019 Niklas Beisert
+
+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
+ \url{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 Niklas Beisert.
+
+This work consists of the files |README.txt|, |exframe.ins| and |exframe.dtx|
+as well as the derived files |exframe.sty|, |exfsamp.tex|, |exfserm.tex|,
+|exfser|\textit{nn}|.tex| (\textit{nn}=|01|, |02|, |03|, |aa|),
+|exfserpe.tex|, |exfserpf.tex|, |exfsermk.sh|, |exfsermk.mak|
+and |exframe.pdf|.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Files and Installation}
+
+The package consists of the files:
+%
+\begin{center}
+\begin{tabular}{ll}
+ |README.txt| & readme file \\
+ |exframe.ins| & installation file \\
+ |exframe.dtx| & source file \\
+ |exframe.sty| & package file \\
+ |exfsamp.tex| & sample file \\
+ |exfserm.tex| & multipart sample main file \\
+ |exfser01.tex| & multipart sample sheet 1 \\
+ |exfser02.tex| & multipart sample sheet 2 \\
+ |exfser03.tex| & multipart sample sheet 3 \\
+ |exfseraa.tex| & multipart sample unused problems \\
+ |exfserpe.tex| & multipart sample problem E \\
+ |exfserpf.tex| & multipart sample problem F \\
+ |exfsermk.sh| & multipart sample compile script \\
+ |exfsermk.mak| & multipart sample makefile \\
+ |exframe.pdf| & manual
+\end{tabular}
+\end{center}
+%
+The distribution consists of the files
+|README.txt|, |exframe.ins| and |exframe.dtx|.
+%
+\begin{itemize}
+\item
+Run (pdf)\LaTeX{} on |exframe.dtx|
+to compile the manual |exframe.pdf| (this file).
+\item
+Run \LaTeX{} on |exframe.ins| to create the package |exframe.sty|
+and the samples consisting of |exfsamp.tex|, |exfserm.tex|,
+|exfser01.tex|, |exfser02.tex|, |exfser03.tex|, |exfseraa.tex|,
+|exfserpe.tex|, |exfserpf.tex|, |exfsermk.sh|, |exfsermk.mak|.
+Copy the file |exframe.sty| to an appropriate directory of your \LaTeX{}
+distribution, e.g.\ \textit{texmf-root}|/tex/latex/exframe|.
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Related Packages}
+
+The package makes use of other packages available at CTAN:
+\begin{itemize}
+\item
+This package relies on some functionality of the package \textsf{verbatim}
+to read verbatim code from the \LaTeX{} source without expansion of macros.
+Compatibility with the \textsf{verbatim} package
+has been tested with v1.5q (2014/10/28).
+\item
+This package uses the package
+\href{http://ctan.org/pkg/xkeyval}{\textsf{xkeyval}}
+to process the options for the package, environments and macros.
+Compatibility with the \textsf{xkeyval} package
+has been tested with v2.7a (2014/12/03).
+\item
+This package can use the package
+\href{http://ctan.org/pkg/hyperref}{\textsf{hyperref}}
+to include hyperlinks between problems and solutions.
+Compatibility with the \textsf{hyperref} package
+has been tested with v6.88e (2018/11/30).
+\item
+This package can use the package
+\href{http://ctan.org/pkg/amstext}{\textsf{amstext}}
+(which is automatically loaded by \textsf{amsmath})
+to display text within equations.
+Compatibility with the \textsf{amstext} package
+has been tested with v2.01 (2000/06/29).
+\item
+This package uses the command |\currfilename|
+provided by the package \textsf{currfile} (if available and loaded)
+to indicate the \LaTeX{} source file in the generated metapost file.
+Compatibility with the \textsf{currfile} package
+has been tested with v0.7c (2015/04/23).
+\end{itemize}
+
+There are several other \LaTeX{} packages
+which offer a similar functionality
+varying largely in scope and sophistication:
+%
+\begin{itemize}
+\item
+The package \href{http://ctan.org/pkg/exsheets}{\textsf{exsheets}}
+and its successor \href{http://ctan.org/pkg/xsim}{\textsf{xsim}}
+provide a \LaTeX{} 3 style for typesetting exercises with solutions.
+They offer options to
+hide or delay solutions,
+print only specific problems,
+deal with points,
+specify metadata,
+handle exercise collections,
+as well as some more specific options.
+They allow to adjust the layout and choose among predefined ones.
+\item
+The package \href{http://ctan.org/pkg/exercise}{\textsf{exercise}}
+provides a style for typesetting exercises with solutions.
+It offers many options to
+hide or delay solutions,
+print only specific problems,
+specify some metadata
+as well as some more specific options.
+It allows to customise the layout.
+\item
+The package \href{http://ctan.org/pkg/exercises}{\textsf{exercises}}
+provides a style for typesetting exercises with solutions.
+It offers options to hide solutions and deal with points.
+It allows basic customisation of the layout.
+\item
+The package \href{http://ctan.org/pkg/exam}{\textsf{exam}}
+provides a document class for typesetting exams conveniently.
+It offers many options to hide solutions, deal with points
+and deal with other exam-specific tasks.
+It allows to adjust the layout and choose among predefined ones.
+\item
+The package \href{http://ctan.org/pkg/probsoln}{\textsf{probsoln}}
+provides a style for typesetting exercises with solutions
+which are stored in a collection.
+It offers options to
+hide solutions
+and to assemble problems from an external collection.
+\item
+The packages
+\href{http://ctan.org/pkg/uebungsblatt}{\textsf{uebungsblatt}},
+\href{http://ctan.org/pkg/uassign}{\textsf{uassign}},
+\href{http://ctan.org/pkg/mathexam}{\textsf{mathexam}},
+\href{http://ctan.org/pkg/exsol}{\textsf{exsol}},
+\href{https://github.com/mbauman/homework}{\textsf{homework}},
+\href{https://gist.github.com/jhwilson/1278588}{\textsf{jhwhw}}
+provide basic functionality for somewhat more particular situations.
+\end{itemize}
+%
+See CTAN categories
+\href{http://ctan.org/topic/exercise}{\textsf{exercise}}
+and \href{http://ctan.org/topic/exam}{\textsf{exam}}
+for further up-to-date packages.
+
+The philosophy of the present package is to
+define a low-level framework to describe exercises with solutions
+to be used in various situations.
+The aim is to provide the means to describe the content
+(problems, solutions, sheets) in a simple fashion
+and separate it from the various layout definitions and choices
+which will define the appearance of the content.
+The interface was designed to reduce potential conflict
+with other packages and definitions.
+The package itself does not define an elaborate layout,
+but it provides means to adjust it in many ways and
+to predefine custom layout schemes.
+The package offers most of the functionality of the above packages,
+but (presently) misses out on some more advanced features,
+see \secref{sec:suggestions}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Feature Suggestions}
+\label{sec:suggestions}
+
+The following is a list of features which may be useful for future
+versions of this package:
+%
+\begin{itemize}
+\item
+Add a section on useful combinations of customisation settings
+to achieve specific goals. Please send suggestions.
+\item
+Option to hide problem text while maintaining access to embedded solutions
+(for a version containing only solutions):
+this is difficult to implement because the problem environment
+cannot simply be discarded, but would have to be scanned very carefully
+for the embedded solution;
+instead process problems to some document and save solutions to file,
+then read solutions from different document.
+\item
+Define structures for multiple-choice questions.
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\subsection{Revision History}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.3:} 2019/06/15
+
+\begin{itemize}
+\item
+control display of |problem| environments via
+package option |problembuf|:
+manual display, write to file, disable individual problems
+\item
+|solutionbelow| mode |here*| superseded by
+package option |solutionbuf|
+\item
+display total points within solution: |solutionpointsat|
+(thanks to Till Bargheer for suggestion)
+\item
+read points for current sheet, (sub)problem and solution
+(thanks to Johannes Hahn for suggestion)
+\item
+case switch for bonus points
+(thanks to Johannes Hahn for suggestion)
+\item
+option to |disable| particular problems,
+control by hook function
+(thanks to Manuel Benz for suggestion)
+\item
+provided interface |\showfracpoints| and |\exerciseconfig{frac}|
+for fractional points display
+\item
+filename extensions configurable
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.2:} 2019/05/01
+
+\begin{itemize}
+\item
+bonus points can be specified as
+|points=|[\textit{regular}][|+|\textit{bonus}]
+\item
+|solutionbelow| mode |here*| added
+for direct processing of the solution environment
+\item
+multipart sample added
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.11:} 2019/04/15
+
+\begin{itemize}
+\item
+fix interaction with
+package \href{http://ctan.org/pkg/calc}{\textsf{calc}}
+(thanks to Johannes Hahn for bug report)
+\item
+fix style |fracpoints| in combination
+with some [|sub|]|problempointsat| choices
+(thanks to Johannes Hahn for bug report)
+\item
+fix spacing for [|sub|]|problempointsat=margin|
+(thanks to Johannes Hahn for bug report)
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.1:} 2019/01/21
+
+\begin{itemize}
+\item
+alternate placement modes for solutions
+\item
+fixed expansion of problem title
+\item
+reset font size for problem text
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v3.0:} 2019/01/16
+
+\begin{itemize}
+\item
+renamed to |exframe.sty|
+\item
+first version published on CTAN
+\item
+overhaul and streamline interface
+\item
+solution processing remodelled
+\item
+changed metadata handling
+\item
+changed and generalised points handling
+\item
+generalised sectioning layout
+\item
+changed layout specification model
+\item
+insert hyperlinks using \textsf{hyperref}
+\item
+manual, example and installation package added
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v2.0 -- v2.6:} 2014/10/03 -- 2018/11/05
+
+\begin{itemize}
+\item
+changed metadata interface
+\item
+broadened scope
+\item
+added more layout options
+\item
+added more metadata
+\item
+added sheet and problem tags
+\item
+add and remember points
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v1.1 -- v1.6:} 2014/08/07 -- 2014/09/14
+
+\begin{itemize}
+\item
+renamed to |nbprob.sty|
+\item
+added metadata
+\item
+added points
+\item
+added layout configuration
+\item
+removed specific macros
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\paragraph{v1.0 -- v1.02:} 2011/09/23 -- 2013/03/17
+
+\begin{itemize}
+\item
+first version as |problems.cls|
+\item
+dedicated layout and macros for author's exercise sheets
+\end{itemize}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\appendix
+
+\settowidth\MacroIndent{\rmfamily\scriptsize 0000\ }
+
+ \DocInput{exframe.dtx}
+
+\end{document}
+%</driver>
+% \fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Standalone Sample}
+% \label{sec:samplesingle}
+%\iffalse
+%<*samplesingle>
+%\fi
+%
+% This section provides an example of how to use
+% some of the \textsf{exframe} features.
+% The resulting layout will be somewhat messy
+% due to a random selection of features.
+%
+% This example file describes a single exercise sheet.
+% The other sheet of the series would be declared
+% analogously in independent documents.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Preamble.}
+%
+% Standard document class:
+% \begin{macrocode}
+\documentclass[12pt]{article}
+% \end{macrocode}
+
+% Use package \textsf{geometry} to set the page layout;
+% adjust the paragraph shape:
+% \begin{macrocode}
+\usepackage{geometry}
+\geometry{layout=a4paper}
+\geometry{paper=a4paper}
+\geometry{margin=2.5cm}
+\parindent0pt
+\parskip0.5ex
+% \end{macrocode}
+
+% Include \textsf{amsmath}, \textsf{hyperref}
+% and the \textsf{exframe} package:
+% \begin{macrocode}
+\usepackage{amsmath}
+\usepackage{hyperref}
+\usepackage[extstyle]{exframe}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solutions Switch.}
+%
+% It will be useful to have the switch to turn on/off
+% the display of solutions near the top
+% of the source file, potentially with the opposite setting commented out:
+% \begin{macrocode}
+\exercisesetup{solutions=true}
+%%\exercisesetup{solutions=false}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Layout Declarations.}
+%
+% The following layout declarations adjust the general layout
+% of exercise sheets. They may as well be moved into an include file.
+%
+% Declare a header for exercise sheets
+% to display several relevant pieces of data;
+% display points total:
+% \begin{macrocode}
+\exercisestyle{plainheader}
+\exerciseconfig{composeheaderbelowright}{\getsheetdata{points}}%
+% \end{macrocode}
+
+% Redefine the appearance of some counters;
+% sheets should be labelled by capital roman numerals,
+% subproblems by lowercase roman numerals;
+% declare the widest subproblem item to be expected:
+% \begin{macrocode}
+\exerciseconfig{countersheet}{\Roman{sheet}}
+\exerciseconfig{countersubproblem}{\roman{subproblem})}
+\exerciseconfig{countersubproblemmax}{vii)}
+% \end{macrocode}
+
+% Automatically display an asterisk for all
+% subproblems with bonus points only;
+% remove space to separate items:
+% \begin{macrocode}
+\exerciseconfig{insertsubprobleminfo}{%
+ \switchpoints{}{\addprobleminfo*{%
+ \hspace{-\getexerciseconfig{skipsubprobleminfo}}*}}%
+ {}{}{\getsubproblempoints{}}}
+% \end{macrocode}
+
+% Redefine the terms to be used for sheet(s);
+% here, a German version:
+% \begin{macrocode}
+\exerciseconfig{termsheet}{\"Ubungsblatt}
+\exerciseconfig{termsheets}{\"Ubungsbl\"atter}
+% \end{macrocode}
+
+% Display points for problems in the margin;
+% change margin display to use the left margin;
+% use the abbreviated form `$n$p.':
+% \begin{macrocode}
+\exercisestyle{problempointsat=margin}
+\reversemarginpar
+\exerciseconfig{composepointsmargin}[1]{#1p.}
+\exerciseconfig{composepointspairmargin}[2]{
+ \ifdim#2pt=0pt#1p.%
+ \else\ifdim#1pt=0pt+#2p.%
+ \else#1+#2p.%
+ \fi\fi}
+% \end{macrocode}
+
+% Change the basic font style for all titles to be bold sans-serif:
+% \begin{macrocode}
+\exerciseconfig{styletitle}{\sffamily\bfseries}
+% \end{macrocode}
+
+% Add a significant amount of space below problems:
+% \begin{macrocode}
+\exerciseconfig{skipproblembelow}{1.5cm}
+% \end{macrocode}
+
+% Display half points as fractions:
+% \begin{macrocode}
+\exercisestyle{fracpoints}
+% \end{macrocode}
+% Show solutions below each problem
+% (may try alternatives |subproblem| or |sheet|):
+% \begin{macrocode}
+\exercisestyle{solutionbelow=problem}
+% \end{macrocode}
+% Separate solutions by horizontal lines (extended style):
+% \begin{macrocode}
+\exercisestyle{solutionsep}
+% \end{macrocode}
+
+% Add course name to sheet title metadata:
+% \begin{macrocode}
+\exerciseconfig{composemetasheet}[2]{\getexercisedata{course},
+ \exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+% \end{macrocode}
+
+% Set title and author for pdf metadata:
+% \begin{macrocode}
+\exercisesetup{pdfdata=sheet}
+\exercisedata{title=%
+ {\getexercisedata{course}, \getexercisedata{material}}}
+\exercisedata{author=%
+ {\getexercisedata{instructor}, \getexercisedata{institution}}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Exercise Series Data.}
+%
+% Set some data on the current series:
+% \begin{macrocode}
+\exercisedata{institution={Katharinen-Volksschule}}
+\exercisedata{course={Mathematik}}
+\exercisedata{instructor={J.\ G.\ B\"uttner}}
+\exercisedata{period={ca.\ 1786}}
+\exercisedata{material={\"Ubungsaufgaben}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Body.}
+%
+% \begin{macrocode}
+\begin{document}
+% \end{macrocode}
+
+% Start sheet number 5:
+% \begin{macrocode}
+\begin{sheet}[number=5]
+% \end{macrocode}
+
+% Start a problem with a title:
+% \begin{macrocode}
+\begin{problem}[title={Sums},points=99+4]
+% \end{macrocode}
+
+% Some introduction to the problem:
+% \begin{macrocode}
+This problem deals with sums and series.
+% \end{macrocode}
+
+% A subproblem with a local label:
+% \begin{macrocode}
+\begin{subproblem}[points=2,difficulty=simple,label={\problemtag-simplesum}]
+Compute the sum
+\showpoints
+\begin{equation}
+1+2+3.
+\end{equation}
+% \end{macrocode}
+
+% Provide a solution for the subproblem (within the subproblem environment):
+% \begin{macrocode}
+\begin{solution}
+The result is
+\begin{equation}
+1+2+3=6.
+\end{equation}
+\end{solution}
+% \end{macrocode}
+
+% End subproblem:
+% \begin{macrocode}
+\end{subproblem}
+% \end{macrocode}
+
+% Another subproblem:
+% \begin{macrocode}
+\begin{subproblem}[points=97+0.5,difficulty=lengthy]
+Compute the sum
+\begin{equation}
+1+2+3+\ldots+98+99+100.
+\end{equation}
+Keep calm and calculate!
+%%That ought to keep him occupied for a while
+\end{subproblem}
+% \end{macrocode}
+
+% Provide a solution for the previous subproblem
+% (layout may differ slightly from declaration within);
+% declare author:
+% \begin{macrocode}
+\begin{solution}[author={C.\ F.\ Gau\ss}]
+We use the result $1+2+3=6$ from part \ref{\problemtag-simplesum}
+to jumpstart the calculation. The remaining sums yield
+\awardpoints*[1 for each remaining sum]{97}
+\begin{equation}
+6+4+5+\ldots+99+100=5050.
+\end{equation}
+Alternatively the summands can be grouped into pairs as follows:
+\begin{align}
+1+100&=101,\\
+2+99&=101,\\
+3+98&=101,\\
+\ldots &\nonumber\\
+50+51&=101.
+\end{align}
+These amount to 50 times the same number 101.
+Therefore the sum equals
+\begin{equation}
+1+2+\ldots+99+100=50\cdot 101=5050.
+\end{equation}
+\textit{Ligget se!} \awardpoints{97+0.5}
+\end{solution}
+% \end{macrocode}
+
+% Some text between subproblems:
+% \begin{macrocode}
+You may give the final part a try:
+% \end{macrocode}
+
+% Final subproblem; this one is optional:
+% \begin{macrocode}
+\begin{subproblem}[optional={optional},
+ difficulty={requires inspiration},points={+3.5}]
+Compute the series
+\showpoints
+\begin{equation}
+1+2+3+\ldots
+\end{equation}
+% \end{macrocode}
+
+% Provide a solution:
+% \begin{macrocode}
+\begin{solution}
+The series is divergent, so the result is $\infty$ \awardpoints{+1}.
+\par
+However, after subtracting the divergent part,
+the result clearly is
+\begin{equation}
+\zeta(-1)=-\frac{1}{12}\,,
+\end{equation}
+where the zeta-function $\zeta(s)$ is defined by
+\begin{equation}
+\zeta(s):=\sum_{k=1}^\infty \frac{1}{k^s}\,.
+\end{equation}
+This definition holds only for $s>1$ where the sum is convergent,
+but one can continue the complex analytic function to $s<0$
+\awardpoints{+1.5}.
+\par
+Another way of understanding the result
+is to use the indefinite summation formula
+for arbitrary exponent $s$ in the summand
+(which also follows from the Euler--MacLaurin formula)
+\begin{equation}
+\sum_n n^s
+= \frac{n^{s+1}}{s+1}
+ -\sum_{j=0}^s \frac{\zeta(j-s)\,s!}{(s-j)!\,j!}\,n^j
+= \ldots - \zeta(-s)\,n^0.
+\end{equation}
+Curiously, the constant term with $j=0$ is just the desired result
+but with the wrong sign
+(in fact, the constant term of an indefinite sum is ambiguous;
+for the claim we merely set $j=0$
+in the expression which holds for others values of $j$)
+\awardpoints{+0.5}.
+In order to understand the sign,
+we propose that the above formula describes the regularised result
+for the sum with limits $+\infty$ and $n$
+\begin{equation}
+\sum_{k=+\infty}^n k^s
+\simeq \frac{n^{s+1}}{s+1}
+ -\sum_{j=0}^s \frac{\zeta(j-s)\,s!}{(s-j)!\,j!}\,n^j.
+\end{equation}
+Then we flip the summation limits of the desired sum
+to bring it into the above form
+\awardpoints{+0.5}
+\begin{equation}
+\sum_{k=1}^\infty k^s
+= -\sum_{k=\infty}^0 k^s
+\simeq \zeta(-s).
+\end{equation}
+\end{solution}
+% \end{macrocode}
+
+% End subproblem:
+% \begin{macrocode}
+\end{subproblem}
+% \end{macrocode}
+
+% End problem:
+% \begin{macrocode}
+\end{problem}
+% \end{macrocode}
+
+% Another problem; this one is untitled:
+% \begin{macrocode}
+\begin{problem}[points=1, difficulty=insane]
+Show that the equation
+\begin{equation}
+a^3+b^3=c^3
+\end{equation}
+has no positive integer solutions.
+\end{problem}
+% \end{macrocode}
+
+% A solution can also follow a problem
+% (but the layout may be slightly different,
+% e.g.\ here the space below the problem will
+% appear before the solution):
+% \begin{macrocode}
+\begin{solution}
+\normalmarginpar
+This is beyond the scope of this example.
+\marginpar{\footnotesize\raggedright does not fit here.\par}
+\end{solution}
+% \end{macrocode}
+
+% End sheet:
+% \begin{macrocode}
+\end{sheet}
+% \end{macrocode}
+
+% End of document body:
+% \begin{macrocode}
+\end{document}
+% \end{macrocode}
+%\iffalse
+%</samplesingle>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Multipart Sample}
+% \label{sec:samplemulti}
+%
+% The second example describes a series of exercise sheets
+% which can be compiled as a collection or as individual sheets.
+% This example describes a versatile setup
+% with several convenient features;
+% most of these features can be adjusted or removed easily as they
+% mostly enhance the setup and do not interact with each other strongly.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Main File}
+% \label{sec:samplemultimain}
+%\iffalse
+%<*samplemultimain>
+%\fi
+%
+% The main source file is called |exfserm.tex|.
+% It is referenced at several places within the setup,
+% and when changing the name they need to be adjusted accordingly.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{childdoc Mechanism.}
+%
+% The setup uses the package \textsf{childdoc} to allow compilation
+% of the series as a whole or in parts and with various sets of options:
+% \begin{macrocode}
+\input{childdoc.def}
+\childdocmain{exfserm}
+% \end{macrocode}
+% The parameter of |\childdocmain| must match the main file name |exfserm|.
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Compilation Switches.}
+%
+% Define compilation switches and declare their default settings.
+% |\printsol| controls whether solutions should be printed or not;
+% by default solutions are activated for compilation of a part,
+% but not for the complete document.
+% |\draftver| controls whether the final version of
+% the document is to be compiled;
+% concretely this affects the compilations of metapost figures, see below:
+% \begin{macrocode}
+\providecommand{\draftver}{y}
+\ifchilddoc
+\providecommand{\printsol}{y}
+\else
+\providecommand{\printsol}{n}
+\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Preamble.}
+%
+% Standard document class:
+% \begin{macrocode}
+\documentclass[12pt]{article}
+% \end{macrocode}
+
+% \begin{macrocode}
+% \textsf{graphicx} package to display license logo:
+\RequirePackage{graphicx}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{hyperref Package.}
+%
+% Use the \textsf{hyperref} package.
+% Declare some options, e.g.\ use bookmarks only for complete document:
+% \begin{macrocode}
+\PassOptionsToPackage{bookmarks=\ifchilddoc false\else true\fi}{hyperref}
+\PassOptionsToPackage{bookmarksopen=true}{hyperref}
+\RequirePackage{hyperref}
+% \end{macrocode}
+% Use the \textsf{hyperxmp} package for inclusion of
+% copyright metadata in the compiled pdf files:
+% \begin{macrocode}
+\IfFileExists{hyperxmp.sty}{\RequirePackage{hyperxmp}}{}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{exframe Package.}
+%
+% Invoke \textsf{exframe} with extended data and styles:
+% \begin{macrocode}
+\RequirePackage[extdata,extstyle]{exframe}
+% \end{macrocode}
+
+% Set solutions switch and declare two-sided layout only
+% if no solutions are printed:
+% \begin{macrocode}
+\if\printsol n
+\exercisesetup{solutions=false}
+\exercisesetup{twoside=true}
+\else
+\exercisesetup{solutions=true}
+\exercisesetup{twoside=false}
+\fi
+% \end{macrocode}
+
+% Might want to display some metadata (only for partial compile):
+% \begin{macrocode}
+%%\if\printsol n\else\showprobleminfo{author,source,recycle}\fi
+% \end{macrocode}
+
+% Set some options. Automatically assign labels to problems.
+% Include sheets and problems in table of contents.
+% Separate solutions by horizontal rules.
+% Count problems, equations and pages by sheet
+% (unless compiling single problem).
+% Collect solutions below each problem.
+% Write pdf metadata for sheet when compiling single sheet.
+% \begin{macrocode}
+\exercisesetup{autolabelproblem}
+\exercisestyle{contents,solutionsep}
+\ifchilddocmanual\else
+\exercisestyle{pagebysheet,problembysheet,equationbysheet,sheetequation}
+\fi
+\exercisestyle{solutionbelow={problem}}
+\ifchilddoc\ifchilddocmanual\else\exercisesetup{pdfdata=sheet}\fi\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Layout Definitions.}
+%
+% Set page dimensions and layout:
+% \begin{macrocode}
+\RequirePackage[a4paper,margin=2.5cm]{geometry}
+\pagestyle{plain}
+% \end{macrocode}
+% Remove paragraph indentation:
+% \begin{macrocode}
+\setlength\parindent{0pt}
+\setlength\parskip{\smallskipamount}
+% \end{macrocode}
+% Show overfull lines:
+% \begin{macrocode}
+\setlength\overfullrule{5pt}
+% \end{macrocode}
+% Define turn page over mark; hide when printing solutions:
+% \begin{macrocode}
+\newcommand{\turnover}{\ifsolutions\else\vfill%
+ \hfill{\mathversion{bold}$\longrightarrow$}\newpage\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Banner.}
+%
+% Use standard sheet banner;
+% show sheet |editdate| below banner (if declared);
+% when compiling single sheet, display sheet due date instead:
+% \begin{macrocode}
+\exercisestyle{plainheader}
+\exerciseconfig{composeheaderbelowright}
+ {\sheetdataempty{editdate}{}{version: \getsheetdata{editdate}}}
+\ifchilddoc\ifsolutions\else
+ \exerciseconfig{composeheaderbelowright}
+ {\sheetdataempty{due}{}{due: \getsheetdata{due}}}
+\fi\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Lorem.}
+%
+% Define a macro |\lorem| to write out some paragraph of text
+% for the example:
+% \begin{macrocode}
+\def\lorem{Lorem ipsum dolor sit amet, consectetur adipisici elit,
+ sed eiusmod tempor incidunt ut labore et dolore magna aliqua.
+ Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
+ nisi ut aliquid ex ea commodi consequat.
+ Quis aute iure reprehenderit in voluptate velit esse
+ cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint obcaecat cupiditat non proident,
+ sunt in culpa qui officia deserunt mollit anim id est laborum.\par}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{metapost Setup.}
+%
+% Use package \textsf{mpostinl} (if available)
+% to include some metapost figures within the source of the problems:
+% \begin{macrocode}
+\IfFileExists{mpostinl.sty}{\RequirePackage{mpostinl}}{}
+\ifdefined\mpostsetup
+% \end{macrocode}
+
+% Setup \textsf{mpostinl}.
+% Use checksums to invoke metapost only when figures change.
+% Process all figures individually and immediately when in
+% draft mode (avoids a second compilation pass).
+% Number figures within sheet to provide a stable numbering
+% upon insertion/deletion of new figures or partial compilation.
+% Do not warn about unused figures when preparing without solutions
+% (figures for solutions should be declared outside |solution| environments):
+% \begin{macrocode}
+\mpostsetup{checksum}
+\if\draftver y\mpostsetup{now,nowall}\fi
+\ifchilddocmanual\else\mpostsetup{numberwithin={sheet}}\fi
+\ifsolutions\else\mpostsetup{warnunused=false}\fi
+% \end{macrocode}
+
+% Global metapost definitions.
+% Define some latex macro to demonstrate
+% usage of latex for typesetting labels.
+% Define some global metapost variables,
+% |paths| is an array of path variables,
+% |xu| serves as a length unit to
+% scale individual figures
+% (use |interim xu:=...;| to set scale for local figure only):
+% \begin{macrocode}
+\mpostsetup{globaldef=true}
+\begin{mposttex}
+\def\figure{figure}
+\end{mposttex}
+\begin{mpostdef}
+path paths[];
+newinternal numeric xu;
+xu:=1cm;
+\end{mpostdef}
+\mpostsetup{globaldef=false}
+% \end{macrocode}
+
+% Close optional \textsf{mpostinl} processing:
+% \begin{macrocode}
+\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Document Data.}
+%
+% Set document data for series of problem sheets:
+% \begin{macrocode}
+\exercisedata{course={exframe package samples}}
+\exercisedata{instructor={N.\ Beisert}}
+\exercisedata{institution={exframe academy}}
+\exercisedata{period={spring 2019}}
+\exercisedata{date={2019}}
+% \end{macrocode}
+
+% Assemble some entries from given data:
+% \begin{macrocode}
+\exercisedata{material={\ifsolutions\getexerciseconfig{termsolutions}%
+ \else\getexerciseconfig{termsheets}\fi}}
+\exerciseconfig{composetitlesheet}[2]{\exerciseifempty{#2}%
+ {\ifsolutions\getexerciseconfig{termsolutions}\else%
+ \getexerciseconfig{termsheet}\fi\ #1}%
+ {\ifsolutions\getexerciseconfig{termsolutions}\fi\ #2}}
+\exerciseconfig{composemetasheet}[2]{\if\draftver yDRAFT: \fi%
+ \getexercisedata{course},
+ \getexerciseconfig{composetitlesheet}{#1}{#2}}
+% \end{macrocode}
+
+% Set general purpose metadata:
+% \begin{macrocode}
+\exercisedata{title={\if\draftver yDRAFT: \fi%
+ \getexercisedata{course}, \getexercisedata{material}}}
+\exercisedata{author={Niklas Beisert, \getexercisedata{institution}}}
+\exercisedata{subject={lecture series at \getexercisedata{institution},
+ \getexercisedata{period}}}
+% \end{macrocode}
+
+% Redefine some terms:
+% \begin{macrocode}
+\exerciseconfig{termsheet}{sheet}
+\exerciseconfig{termsheets}{sample sheets}
+\exerciseconfig{termsolution}{Solution}
+\exerciseconfig{termsolutions}{solutions}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{License.}
+%
+% It is always useful to specify a copyright line
+% and a license for the document.
+% Define some restrictive default text.
+% \begin{macrocode}
+\def\copyrightmessage
+ {This document as well as its parts is protected by copyright.}
+\def\licensemessage
+ {Reproduction of any part of this work in any form
+ without prior written consent of \getexercisedata{institution}
+ is not permissible.}
+% \end{macrocode}
+
+% Apply Creative Commons BY-SA license
+% under certain conditions (no solutions, final version):
+% \begin{macrocode}
+\ifsolutions\else\if\draftver y\else
+\def\licensecctype{by-sa}
+\def\licenseccname{Attribution-ShareAlike \licenseccver{} International}
+\fi\fi
+% \end{macrocode}
+
+% Write applicable Creative Commons license information.
+% Use Creative Commons logos included in package \textsf{doclicense}:
+% \begin{macrocode}
+\ifdefined\licensecctype
+\ifdefined\licenseccver\else\def\licenseccver{4.0}\fi
+\def\licenseurl
+ {https://creativecommons.org/licenses/\licensecctype/\licenseccver}
+\def\licensemessage{\texorpdfstring
+ {This work is licensed under the Creative Commons ``\licenseccname'' License
+ (CC \MakeUppercase{\licensecctype} \licenseccver).\par
+ \IfFileExists{doclicense.sty}{
+ \begin{center}\includegraphics{doclicense-CC-\licensecctype}\end{center}}{}
+ To view a copy of this license, visit: \url{\licenseurl}}
+ {This work is licensed under the Creative Commons \licenseccname{} License.}}
+\fi
+% \end{macrocode}
+
+% Write copyright and license as pdf metadata
+% (using package \textsf{hyperxmp} if available):
+% \begin{macrocode}
+\ifdefined\xmptilde
+\hypersetup{pdfcopyright={Copyright \getexercisedata{date}
+ \getexercisedata{author}. \copyrightmessage{} \licensemessage}}
+\ifdefined\sourceurl\hypersetup{pdflicenseurl={\sourceurl}}\else
+\ifdefined\licenseurl\hypersetup{pdflicenseurl={\licenseurl}}\fi\fi
+\ifdefined\XMPLangAlt
+\hypersetup{pdfsource={}}
+\XMPLangAlt{en}{pdfcopyright={Copyright \getexercisedata{date}
+ \getexercisedata{author}. \copyrightmessage{} \licensemessage}}
+\fi
+\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Body.}
+%
+% Start document body:
+% \begin{macrocode}
+\begin{document}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Single Problem Display.}
+%
+% The following code handles the compilation
+% of individual problems from their own source file.
+% Make sure to leave the conditional before issuing |\end{document}|:
+% \begin{macrocode}
+\def\tmp{}
+\ifchilddocmanual
+\def\tmp{\end{document}}
+\input{\childdocname}
+\fi\tmp
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Frontmatter.}
+%
+% Do not print frontmatter for individual sheets.
+% Define a plain page counter for frontmatter:
+% \begin{macrocode}
+\setcounter{section}{-1}
+\begingroup\ifchilddoc\else
+\renewcommand{\thepage}{\arabic{page}}
+% \end{macrocode}
+
+% Prepare a title page to display some relevant data:
+% \begin{macrocode}
+\pdfbookmark[1]{Title Page}{title}
+\thispagestyle{empty}
+\vspace*{\fill}
+\begin{center}
+\begingroup\bfseries\LARGE\getexercisedata{course}\par\endgroup
+\vspace{0.5cm}
+\begingroup\large\getexercisedata{material}\par\endgroup
+\vspace{0.5cm}
+\begingroup\large\getexercisedata{institution},
+ \getexercisedata{period}\par\endgroup
+\vspace{2cm}
+\begingroup\scshape\Large\getexercisedata{instructor}\par\endgroup
+\end{center}
+\vspace*{\fill}\vspace*{\fill}
+\newpage
+% \end{macrocode}
+
+% Prepare a copyright and license page using data specified above:
+% \begin{macrocode}
+\phantomsection\pdfbookmark[1]{Copyright}{copyright}
+\thispagestyle{empty}
+\vspace*{\fill}\vspace*{\fill}
+\begin{center}
+\begin{minipage}{11cm}\raggedright
+{\copyright} \getexercisedata{date} \getexercisedata{author}
+\par\medskip
+\copyrightmessage{}
+\licensemessage
+\ifdefined\sourcemessage\par\medskip\sourcemessage\fi
+\ifdefined\attributionmessage\par\medskip\attributionmessage\fi
+\end{minipage}\end{center}
+\vspace*{\fill}\vspace*{\fill}\vspace*{\fill}
+\newpage
+% \end{macrocode}
+
+% Print table of contents:
+% \begin{macrocode}
+\makeatletter\renewcommand\@pnumwidth{2.4em}\makeatother
+\setcounter{tocdepth}{2}
+\phantomsection\pdfbookmark[1]{Contents}{contents}
+{\parskip0pt\tableofcontents}
+\exercisecleardoublepage\setcounter{page}{1}
+% \end{macrocode}
+
+% End of frontmatter:
+% \begin{macrocode}
+\fi\endgroup
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Include Sheets.}
+%
+% Include problem sheets:
+% \begin{macrocode}
+\include{exfser01}
+\include{exfser02}
+\include{exfser03}
+% \end{macrocode}
+
+% Include sheet to collect unused problems
+% (only process for individual sheets, i.e.\ itself):
+% \begin{macrocode}
+\def\jobnameunused{exfseraa}
+\ifx\childdocname\jobnameunused\include{\jobnameunused}\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{End.}
+%
+% End of document body:
+% \begin{macrocode}
+\end{document}
+% \end{macrocode}
+%
+%\iffalse
+%</samplemultimain>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Sheet File}
+% \label{sec:samplemultisheets}
+%\iffalse
+%<*samplemultisheet1|samplemultisheet2|samplemultisheet3|samplemultisheeta>
+%\fi
+%
+% Provide some source files
+% |exfser01.tex|, |exfser02.tex|, |exfser03.tex|, |exfseraa.tex|
+% for problem sheets.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{childdoc Mechanism.}
+%
+% Instruct the package \textsf{childdoc} to compile
+% only the present sheet if source is compiled by latex:
+% \begin{macrocode}
+%%\providecommand{\printsol}{n}
+\input{childdoc.def}
+\childdocof{exfserm}
+% \end{macrocode}
+%\iffalse
+%</samplemultisheet1|samplemultisheet2|samplemultisheet3|samplemultisheeta>
+%<samplemultiprobleme|samplemultiproblemf>%%\providecommand{\printsol}{n}
+%<samplemultiprobleme|samplemultiproblemf>\input{childdoc.def}
+%<samplemultiprobleme|samplemultiproblemf>\childdocby{exfserm}
+%<*samplemultisheet1>
+%\fi
+% The parameter of |\childdocof| must match the main file name |exfserm|.
+% Uncommenting the commented line suppressed printing of the solution.
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Environment.}
+%
+% Declare a sheet with intended due date:
+% \begin{macrocode}
+\begin{sheet}[due={2019-04-29}]
+% \end{macrocode}
+% Adjust due date for each sheet.
+% For sheet containing unused problems |exfseraa.tex|,
+% declare a sheet |title={unused problems}| instead of due date.
+%\iffalse
+%</samplemultisheet1>
+%<samplemultisheet2>\begin{sheet}[due={2019-05-06}]
+%<samplemultisheet3>\begin{sheet}[due={2019-05-13}]
+%<samplemultisheeta>\begin{sheet}[title={unused problems}]
+%<*samplemultisheet1>
+%\fi
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problems.}
+%
+% Start a problem:
+% \begin{macrocode}
+\begin{problem}[title={Sample A}]
+% \end{macrocode}
+%
+%\iffalse
+%</samplemultisheet1>
+%<samplemultisheet2>\begin{problem}[title={Sample C}]
+%<samplemultisheet3>\input{exfserpe}
+%<samplemultisheeta>\begin{problem}[title={Sample X}]
+%<samplemultiprobleme>\begin{problem}[title={Sample E}]
+%<*samplemultisheet1|samplemultisheet2|samplemultisheeta|samplemultiprobleme>
+%\fi
+
+% Let us declare a figure using \textsf{mpostinl} (if available).
+% Denote it by the label \textit{tag}|-fig|,
+% where \textit{tag} is the tag of the problem
+% (in order to avoid potential conflicts with other problems;
+% \textit{tag} is assigned automatically or by specifying
+% the option |tag| for the |problem| environment):
+% \begin{macrocode}
+\ifdefined\mpostuse
+\begin{mpostfig}[label={\problemtag-fig}]
+interim xu:=1.5cm;
+paths[1]:=fullcircle scaled 1xu;
+fill paths[1] withgreyscale 0.7;
+draw paths[1] withpen pencircle scaled 1pt;
+label(btex \figure etex, center(paths[1]));
+\end{mpostfig}
+\fi
+% \end{macrocode}
+
+% Write a problem body with figure, some subproblems and a solution:
+% \begin{macrocode}
+\lorem
+
+\begin{subproblem}
+\lorem
+\begin{center}
+\ifdefined\mpostuse\mpostuse{\problemtag-fig}\else figure\fi
+\end{center}
+\lorem
+\end{subproblem}
+
+\begin{solution}
+\lorem
+\end{solution}
+
+\begin{subproblem}
+\lorem
+\end{subproblem}
+
+\begin{solution}
+\lorem
+\end{solution}
+
+\lorem
+
+\begin{subproblem}
+\lorem
+\end{subproblem}
+
+\begin{solution}
+\lorem
+\end{solution}
+% \end{macrocode}
+
+% End the problem:
+% \begin{macrocode}
+\end{problem}
+% \end{macrocode}
+%\iffalse
+%</samplemultisheet1|samplemultisheet2|samplemultisheeta|samplemultiprobleme>
+%<*samplemultisheet1|samplemultisheet2|samplemultisheet3|samplemultisheeta>
+%\fi
+
+% Start new page:
+% \begin{macrocode}
+\turnover
+% \end{macrocode}
+
+%\iffalse
+%</samplemultisheet1|samplemultisheet2|samplemultisheet3|samplemultisheeta>
+%<*samplemultisheet1>
+%\fi
+% Write a second problem to accompany the first one:
+% \begin{macrocode}
+\begin{problem}[title={Sample B}]
+% \end{macrocode}
+%
+%\iffalse
+%</samplemultisheet1>
+%<samplemultisheet2>\begin{problem}[title={Sample D}]
+%<samplemultisheet3>\input{exfserpf}
+%<samplemultisheeta>\begin{problem}[title={Sample Y}]
+%<samplemultiproblemf>\begin{problem}[title={Sample F}]
+%<*samplemultisheet1|samplemultisheet2|samplemultisheeta|samplemultiproblemf>
+%\fi
+
+% Problem body without a figure;
+% this time the |solution| environments are
+% included in the |subproblem| environments:
+% \begin{macrocode}
+\lorem
+
+\begin{subproblem}
+\lorem
+\begin{solution}
+\lorem
+\end{solution}
+\end{subproblem}
+
+\begin{subproblem}
+\lorem
+\begin{solution}
+\lorem
+\end{solution}
+\end{subproblem}
+% \end{macrocode}
+
+% End the problem:
+% \begin{macrocode}
+\end{problem}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{End Sheet.}
+%\iffalse
+%</samplemultisheet1|samplemultisheet2|samplemultisheeta|samplemultiproblemf>
+%<*samplemultisheet1|samplemultisheet2|samplemultisheet3|samplemultisheeta>
+%\fi
+% End the sheet:
+% \begin{macrocode}
+\end{sheet}
+% \end{macrocode}
+
+%\iffalse
+%</samplemultisheet1|samplemultisheet2|samplemultisheet3|samplemultisheeta>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Individual Problem Files}
+% \label{sec:samplemultisheet3}
+%\iffalse
+%<*discard>
+%\fi
+%
+% It may be more convenient to define each problem in an individual file,
+% so that a sheet can be composed by including the appropriate
+% problem files.
+% In such a setup, the \textsf{childdoc} mechanism
+% allows to compile each problem individually.
+%
+% To that end, prepare a file |exfserp|\textit{nn}|.tex|
+% containing the |problem| environment.
+% This file should start with:
+% \begin{macrocode}
+%%\providecommand{\printsol}{n}
+\input{childdoc.def}
+\childdocby{exfserm}
+% \end{macrocode}
+% and end with |\endinput|.
+% Then compose the problem sheet
+% by including the appropriate set of problem files
+% via |\input{exfserp|\textit{nn}|}|.
+%
+% In the example, a sheet file |exfser03.tex|
+% includes two problem files |exfserpe.tex| and |exfserpf.tex|.
+%
+%\iffalse
+%</discard>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Make Scripts}
+% \label{sec:samplemultimake}
+%\iffalse
+%<*samplemultiscript>
+%\fi
+%
+% The setup allows the compilation in various modes for editing purposes.
+% In order to generate and update a complete set of documents for distribution
+% (all individual sheets and a collection of sheets;
+% with and without solutions),
+% it makes sense to use the software development utility |make|.
+% The compilation of individual components is simplified
+% by a |bash| shell script.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Compile Script.}
+%
+% The |bash| shell script |exfsermk.sh| compiles one part of
+% the collection of problem sheets in a given mode.
+%
+% Shebang for |bash| script:
+% \begin{macrocode}
+#!/bin/bash
+% \end{macrocode}
+
+% Display usage:
+% \begin{macrocode}
+if [ -z $1 ]
+then
+ echo "Usage:
+ $0 number [version]
+ number: number of sheet, 0 for combined document
+ version: 1 for problems, 2 for solutions
+ $0 filename
+ filename: target file to be compiled"
+ exit 1
+fi
+% \end{macrocode}
+%\iffalse$\fi
+
+% Configure and declare variables with default values.
+% |num| takes the sheet number;
+% |ver| takes the compile mode;
+% |main| defines the name of the main source file;
+% |source|\textit{nn} defines the name of the sheet source file;
+% |target1|[\textit{nn}] defines the target file name in mode 1;
+% |target2|[\textit{nn}] defines the target file name in mode 2;
+% |sheets| is a list of allowable sheet identifiers \textit{nn}:
+% \begin{macrocode}
+num="$1"
+ver="$2"
+main="exfserm"
+source="exfser"
+target1="Problems"
+target2="Solutions"
+sheets="01 02 03 aa"
+nl=$'\n'
+sheetokay=""
+make=".pdf"
+% \end{macrocode}
+%\iffalse$\fi
+
+% Check if the parameter matches any of the acceptable output file names:
+% \begin{macrocode}
+for v in $target1 $target2
+do
+ if [[ $num =~ ^$v ]]
+ then
+ ver=$v
+ num=${num#$v}
+ if [[ $num =~ ^.*\.tex$ ]]; then make=".tex"; fi
+ num=${num%%.*}
+ fi
+done
+% \end{macrocode}
+
+% Ensure that |num| is a two-digit number, prepend `0' otherwise:
+% \begin{macrocode}
+if [[ $num =~ ^[0-9]$ ]]; then num="0$num"; fi
+if [[ $num == "00" ]]; then num=""; fi
+% \end{macrocode}
+
+% Check whether |num| is acceptable:
+% \begin{macrocode}
+if [[ -z $num ]]; then sheetokay="okay"; fi
+for v in $sheets
+do
+ if [[ "$num" == "$v" ]]; then sheetokay="okay"; fi
+done
+% \end{macrocode}
+
+% Otherwise display error message and exit:
+% \begin{macrocode}
+if [[ -z $sheetokay ]]
+then
+ echo "error: unknown sheet"
+ exit 1
+fi
+% \end{macrocode}
+%\iffalse$\fi
+
+% Function to compile a component.
+% Set up \textsf{childdoc} mechanism according to desired component.
+% Compile two passes, first in |-draftmode|.
+% Suppress messages by |mpost|.
+% Display warning messages in log file:
+% \begin{macrocode}
+function docompile
+{
+ if [[ -z $num ]]; then job=$main; else job=$source$num; fi
+ for par in -draftmode ""
+ do
+ body="\\def\\jobname{$job}\\def\\draftver{n}\\def\\printsol{$sol}"
+ body="$body\\input{childdoc.def}"
+ if [[ -z $num ]]
+ then
+ body="$body\\childdocforward{$main}"
+ else
+ body="$body\\childdocforward[$main]{$source$num}"
+ fi
+ drop="This is|entering extended mode|\\write18"
+ drop="$drop|Preloading the plain mem file|mpost\.mp|plain\.mp"
+ pdflatex -shell-escape -interaction=batchmode $par \
+ -jobname "$target$num" "$body" | grep -vE "$drop"
+ done
+ grep -E "Warning|Error|Undefined|Overfull|Underfull" "$target$num.log"
+}
+% \end{macrocode}
+%\iffalse$\fi
+
+% Function to generate a \textsf{childdoc} compile file with specific options:
+% \begin{macrocode}
+function writesource
+{
+ body="\\def\\draftver{n}$nl\\def\\printsol{$sol}$nl"
+ body="$body\\input{childdoc.def}$nl"
+ if [[ -z $num ]]
+ then
+ body="$body\\childdocforward{$main}"
+ else
+ body="$body\\childdocforwardprefix[$main]{$target}{$source}"
+ fi
+ echo "$body" > $target$num.tex
+}
+% \end{macrocode}
+
+% Configure variables and select appropriate function for intended task:
+% \begin{macrocode}
+function process
+{
+ target=$1
+ sol=$2
+ if [[ "$make" == ".pdf" ]]; then docompile; else writesource; fi
+}
+% \end{macrocode}
+%\iffalse$\fi
+
+% Translate versions to parameter values:
+% \begin{macrocode}
+if [[ -z $ver || "$ver" == "$target1" || $ver = 1 ]]
+then
+ process $target1 n
+fi
+if [[ -z $ver || "$ver" == "$target2" || $ver = 2 ]]
+then
+ process $target2 y
+fi
+% \end{macrocode}
+
+% Finish with blank line:
+% \begin{macrocode}
+echo
+% \end{macrocode}
+%
+%\iffalse
+%</samplemultiscript>
+%\fi
+%
+%\iffalse
+%<*samplemultimake>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Makefile.}
+%
+% \catcode9=13\def^^I{~~~~~~~~}
+%
+% Define a make file |exfsermk.mak| for the project.
+% The compilation is then started by
+% |make -f exfsermk.mak| \ldots.
+% More conveniently, in a single-project setup within the directory,
+% this file would be called |Makefile| in which case it suffices
+% to just run |make| \ldots.
+%
+% Configuration definitions:
+% \begin{macrocode}
+MAIN = exfserm
+SOURCE = exfser
+PROBLEM = exfserp
+SCRIPT = exfsermk.sh
+MAKEFILE = exfsermk.mak
+TARGETLIST = Problems Solutions
+SHEETNUM = 01 02 03 aa
+PREREQS = $(MAIN).tex
+SOURCES = $(SHEETNUM:%=$(SOURCE)%.tex)
+SHEETS = $(foreach trg,$(TARGETLIST),$(trg).pdf $(SHEETNUM:%=$(trg)%.pdf))
+TARGETS = $(foreach trg,$(TARGETLIST),$(trg).pdf)
+GENFILES = $(foreach trg,$(TARGETLIST),$(trg).tex $(SHEETNUM:%=$(trg)%.tex))
+BAKFILES = $(SOURCES) $(MAIN).tex $(MAKEFILE) $(SCRIPT) $(PROBLEM)*
+% \end{macrocode}
+%\iffalse$\fi
+
+% Define some abstract targets;
+% |default| is the default target when no parameters are given:
+% \begin{macrocode}
+default: sheets ;
+sheets: $(SHEETS) ;
+main: $(TARGETS) ;
+sheet%: $(foreach trg,$(TARGETLIST),$(trg)%.pdf) ;
+all: main sheets ;
+sources: $(GENFILES) ;
+% \end{macrocode}
+%\iffalse$\fi
+
+% Compile particular files via |exfsermk.sh| bash script.
+% Note that command lines have to start with a tab character
+% (represented by 8 spaces here):
+% \begin{macrocode}
+$(TARGETS): $(SOURCES) $(PREREQS)
+ bash ./$(SCRIPT) $@
+$(word 1,$(TARGETLIST))%.pdf: $(SOURCE)%.tex $(PREREQS)
+ bash ./$(SCRIPT) $@
+$(word 2,$(TARGETLIST))%.pdf: $(SOURCE)%.tex $(PREREQS)
+ bash ./$(SCRIPT) $@
+$(GENFILES):
+ bash ./$(SCRIPT) $@
+% \end{macrocode}
+%\iffalse$\fi
+
+% Touch main file for recompile:
+% \begin{macrocode}
+touch:
+ touch $(MAIN).tex
+% \end{macrocode}
+%\iffalse$\fi
+% Define |clean| target to remove all intermediate compilation files:
+% \begin{macrocode}
+clean:
+ rm -f $(SHEETNUM:%=$(SOURCE)%.aux)
+ rm -f $(SHEETNUM:%=$(SOURCE)%.log)
+ rm -f $(foreach trg,$(TARGETLIST),$(SHEETNUM:%=$(trg)%.log) $(trg).log)
+ rm -f $(patsubst %,$(MAIN)%,.aux .log .out .toc)
+ rm -f $(patsubst %,$(MAIN)%,.mp .mpx -*.mps -tmp.log -tmp.mp -tmp.mpx)
+ rm -f mpxerr.tex mpxerr.log mpxerr.dvi texput.log
+ rm -f $(patsubst %,$(PROBLEM)*%,.aux .log .mp .mpx -*.mps)
+ rm -f $(patsubst %,$(PROBLEM)*%,-tmp.log -tmp.mp -tmp.mpx)
+% \end{macrocode}
+%\iffalse$\fi
+% Define |clean-bak| target to remove all backup files
+% ending in `|~|' or `|.bak|':
+% \begin{macrocode}
+clean-bak:
+ rm -f $(BAKFILES:%=%~) $(BAKFILES:%=%.bak)
+% \end{macrocode}
+% Define |clean-all| target to remove all generated files
+% for a clean source directory:
+% \begin{macrocode}
+clean-all: clean
+ rm -f $(SHEETS) $(TARGETS)
+ rm -f $(SHEETNUM:%=$(SOURCE)%.pdf) $(MAIN).pdf
+ rm -f $(foreach trg,$(TARGETLIST),$(SHEETNUM:%=$(trg)%.tex) $(trg).tex)
+ rm -f $(PROBLEM)*.pdf
+% \end{macrocode}
+%\iffalse$\fi
+% \catcode9=9
+%
+%\iffalse
+%</samplemultimake>
+%\fi
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \section{Implementation}
+% \label{sec:implementation}
+%\iffalse
+%<*package>
+%\fi
+%
+% This section describes the package |exframe.sty|.
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{General Definitions}
+% \label{sec:imp-def}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Required Packages.}
+%
+% The package loads the package
+% \textsf{verbatim} and \textsf{xkeyval}
+% if not yet present.
+% \textsf{verbatim} is used for solution environment reading
+% and \textsf{xkeyval} is used for extended options processing:
+% \begin{macrocode}
+\RequirePackage{verbatim}
+\RequirePackage{xkeyval}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{General Definitions.}
+%
+% \macro{\exf@empty}
+% Define an empty macro for comparison by |\ifx|:
+% \begin{macrocode}
+\def\exf@empty{}
+% \end{macrocode}
+
+% \macro{\exf@tmpdim}
+% Define a length for temporary storage:
+% \begin{macrocode}
+\newlength\exf@tmpdim
+% \end{macrocode}
+
+% \macro{\exf@exptwo}
+% A macro to conveniently expand the third token in line:
+% \begin{macrocode}
+\def\exf@exptwo#1{\expandafter#1\expandafter}
+% \end{macrocode}
+% \macro{\exf@exparg}
+% A macro to conveniently expand the first token
+% of an argument following arbitrary code:
+% \begin{macrocode}
+\long\def\exf@expswitch#1#2{#2{#1}}
+\long\def\exf@exparg#1#2{\exf@exptwo\exf@expswitch{#2}{#1}}
+% \end{macrocode}
+% \macro{\exf@csdo}
+% \macro{\exf@csdotwo}
+% Some macros to conveniently expand |\csname| arguments
+% before expanding the macro:
+% \begin{macrocode}
+\def\exf@csdo#1#2{\expandafter#1\csname#2\endcsname}
+\def\exf@csdotwo#1#2#3{\exf@exptwo#1#2\csname#3\endcsname}
+% \end{macrocode}
+
+% \macro{\exf@append@def}
+% \macro{\exf@prepend@def}
+% Add definitions to macros (after or before original content):
+% \begin{macrocode}
+\long\def\exf@append@def#1#2{\exf@exptwo\def#1\expandafter{#1#2}}
+\long\def\exf@prepend@switch#1#2#3{#2{#3#1}}
+\long\def\exf@prepend@def#1#2{\exf@exptwo\exf@prepend@switch{#1}{\def#1}{#2}}
+% \end{macrocode}
+
+% \macro{\exf@expsetkeys}
+% A version of |\setkeys| from \textsf{xkeyval} which expands first:
+% \begin{macrocode}
+\newcommand{\exf@expsetkeys}[2]{\edef\exf@tmp{#2}%
+ \exf@exparg{\setkeys{#1}}{\exf@tmp}}
+% \end{macrocode}
+
+% \macro{\exf@isif}
+% Execute |#3| if content of macro |#1| equals |#2|:
+% \begin{macrocode}
+\newcommand{\exf@ifis}[3]%
+ {\def\exf@tmp{#2}\ifx#1\exf@tmp#3\fi}
+% \end{macrocode}
+
+% \macro{\exf@href}
+% Display text with hyperreference passed by macro |#1|
+% (in case \textsf{hyperref} is loaded
+% and the reference is defined and not empty):
+% \begin{macrocode}
+\newcommand{\exf@href}[2]{%
+ \ifdefined#1\ifx#1\exf@empty#2\else%
+ \ifdefined\hyperlink\protect\hyperlink{#1}{#2}\else#2\fi\fi\else#2\fi}
+% \end{macrocode}
+
+% \macro{\exf@text}
+% \macro{\exf@ensuretext}
+% Two macros to display text in math mode.
+% |exf@text| is a wrapper for |\text| of \textsf{amstext}
+% in case the latter package is loaded.
+% |exf@ensuretext| makes sure the text is set in text mode
+% or within an |\mbox| in math math:
+% \begin{macrocode}
+\newcommand{\exf@text}[1]{\ifdefined\text\text{#1}\else#1\fi}
+\newcommand{\exf@ensuretext}[1]{\ifmmode\mbox{#1}\else#1\fi}
+% \end{macrocode}
+
+% \macro{\exf@addcontentsline}
+% Add a line to the table of contents unless macro in argument |#1| is empty:
+% \begin{macrocode}
+\newcommand{\exf@addcontentsline}[2]{%
+ \ifx#1\exf@empty\else\addcontentsline{toc}{#1}{#2}\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Package Setup}
+% \label{sec:imp-setup}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Initialisation Options.}
+%
+% \macro{exframe.sty}
+% Some setup options are available while loading the package only.
+%
+% Configure names of main environments and counters:
+% \begin{macrocode}
+\def\exf@problemname{problem}
+\def\exf@subproblemname{sub\exf@problemname}
+\def\exf@solutionname{solution}
+\def\exf@sheetname{sheet}
+\def\exf@problemcounter{problem}
+\def\exf@subproblemcounter{sub\exf@problemcounter}
+\def\exf@solutioncounter{solution}
+\def\exf@sheetcounter{sheet}
+\define@key{exframe.sty}{problemenv}{\def\exf@problemname{#1}}
+\define@key{exframe.sty}{subproblemenv}{\def\exf@subproblemname{#1}}
+\define@key{exframe.sty}{solutionenv}{\def\exf@solutionname{#1}}
+\define@key{exframe.sty}{sheetenv}{\def\exf@sheetname{#1}}
+\define@key{exframe.sty}{problemcounter}{\def\exf@problemcounter{#1}}
+\define@key{exframe.sty}{subproblemcounter}{\def\exf@subproblemcounter{#1}}
+\define@key{exframe.sty}{solutioncounter}{\def\exf@solutioncounter{#1}}
+\define@key{exframe.sty}{sheetcounter}{\def\exf@sheetcounter{#1}}
+% \end{macrocode}
+
+% Whether to provide some extended configuration options
+% (available while loading only):
+% \begin{macrocode}
+\define@boolkey{exframe.sty}[exf@]{extdata}[true]{}
+\define@boolkey{exframe.sty}[exf@]{extstyle}[true]{}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Setup Options.}
+%
+% \macro{exf@setup}
+% All remaining setup options are available
+% also when the package is already loaded.
+%
+% Main switch for solutions:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[]{solutions}[true]{}
+% \end{macrocode}
+% Switch for writing pdf metadata:
+% \begin{macrocode}
+\define@choicekey{exf@setup}{pdfdata}%
+ {auto,manual,sheet,off}[auto]{\def\exf@metadata{#1}}
+\def\exf@metadata{auto}
+% \end{macrocode}
+% Write line number indicators to output file:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{lineno}[true]{}
+% \end{macrocode}
+% Prepare two-sided sheets:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{twoside}[true]{}
+% \end{macrocode}
+% Generate hyperreferences from solutions to corresponding problems:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{solutionhref}[true]{}
+\exf@solutionhreftrue
+% \end{macrocode}
+% Automatically generate labels for sheets and problems:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{autolabelsheet}[true]{}
+\define@boolkey{exf@setup}[exf@]{autolabelproblem}[true]{}
+% \end{macrocode}
+% Write warning message to document for better detection of inconsistencies:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{warntext}[true]{}
+% \end{macrocode}
+% Activate buffering of solutions:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{solutionbuf}[true]{}
+\exf@solutionbuftrue
+% \end{macrocode}
+% Activate buffering of problems:
+% \begin{macrocode}
+\define@boolkey{exf@setup}[exf@]{problembuf}[true]{}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Processing.}
+%
+% Process global options while loading package:
+% \begin{macrocode}
+\ProcessOptionsX<exframe.sty,exf@setup>
+% \end{macrocode}
+
+% \macro{\exercisesetup}
+% Configure package when package is already loaded:
+% \begin{macrocode}
+\newcommand{\exercisesetup}[1]{\exf@expsetkeys{exf@setup}{#1}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Configuration}
+% \label{sec:imp-config}
+%
+% This section defines and describes the various configuration options
+% provided by the package. It also serves as a manual,
+% and most code can be recycled and adjusted for individual configurations:
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Definitions.}
+%
+% \macro{\exerciseconfig}
+% Set a configuration macro;
+% store definition in |exf@config@#2|;
+% use |\newcommand| for macros with arguments,
+% but (non-long) |\def| for plain definitions:
+% \begin{macrocode}
+\newcommand{\exerciseconfig}[1]{%
+ \@ifnextchar[{\exf@configopt{#1}}{\exf@confignoopt{#1}}}
+\long\def\exf@configopt#1[#2]#3{%
+ \exf@csdo\def{exf@config@#1}{}%
+ \exf@csdo\renewcommand{exf@config@#1}[#2]{#3}}%
+\long\def\exf@confignoopt#1#2{\exf@csdo\def{exf@config@#1}{#2}}
+% \end{macrocode}
+% \macro{\exerciseconfigappend}
+% \macro{\exerciseconfigprepend}
+% Append to a (parameterless) configuration macro:
+% \begin{macrocode}
+\newcommand{\exerciseconfigappend}[2]{%
+ \exf@csdo\exf@append@def{exf@config@#1}{#2}}
+\newcommand{\exerciseconfigprepend}[2]{%
+ \exf@csdo\exf@prepend@def{exf@config@#1}{#2}}
+% \end{macrocode}
+% \macro{\getexerciseconfig}
+% Get configuration macro:
+% \begin{macrocode}
+\newcommand{\getexerciseconfig}[1]{\csname exf@config@#1\endcsname}
+% \end{macrocode}
+% \macro{\exerciseconfigempty}
+% Test whether configuration macro |#1| is empty;
+% execute |#2| if empty, otherwise execute |#3|:
+% \begin{macrocode}
+\newcommand{\exerciseconfigempty}[3]{\exf@csdo\ifx{exf@config@#1}\exf@empty%
+ #2\else#3\fi}
+% \end{macrocode}
+
+% \macro{\exerciseifemtpy}
+% \macro{\exerciseifnotempty}
+% Code to test whether |#1| (expanded) is empty;
+% execute |#2| if empty, otherwise execute |#3|:
+% \begin{macrocode}
+\long\def\exerciseifempty#1#2#3{\if&#1&#2\else#3\fi}
+\long\def\exerciseifnotempty#1#2{\if&#1&\else#2\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Terms.}
+%
+% \macro{term...}
+% Terms for sheet, problem, solution and points
+% (for adjustment or internationalisation):
+% \begin{macrocode}
+\exerciseconfig{termsheet}{Sheet}
+\exerciseconfig{termsheets}{Sheets}
+\exerciseconfig{termproblem}{Problem}
+\exerciseconfig{termproblems}{Problems}
+\exerciseconfig{termsolution}{Solution}
+\exerciseconfig{termsolutions}{Solutions}
+\exerciseconfig{termpoint}{point}
+\exerciseconfig{termpoints}{points}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Formatting Styles.}
+%
+% \macro{style...}
+% Formatting styles to be applied for various parts of text.
+% Different styles will be applied in sequence from more general
+% to more specific.
+%
+% Basic style for all exercise text:
+% \begin{macrocode}
+\exerciseconfig{styletext}{\normalsize\normalfont}
+% \end{macrocode}
+% Style for problems:
+% \begin{macrocode}
+\exerciseconfig{styletextproblem}{}
+% \end{macrocode}
+% Style for solutions:
+% \begin{macrocode}
+\exerciseconfig{styletextsolution}{\footnotesize}
+% \end{macrocode}
+% Basic style for titles:
+% \begin{macrocode}
+\exerciseconfig{styletitle}{\bfseries}
+% \end{macrocode}
+% Style for problem titles:
+% \begin{macrocode}
+\exerciseconfig{styletitleproblem}{\large}
+% \end{macrocode}
+% Style for subproblem titles:
+% \begin{macrocode}
+\exerciseconfig{styletitlesubproblem}{}
+% \end{macrocode}
+% Style for solution titles:
+% \begin{macrocode}
+\exerciseconfig{styletitlesolution}{}
+% \end{macrocode}
+% Style for problem section title in solution block:
+% \begin{macrocode}
+\exerciseconfig{styletitlesolutionsproblem}{\small}
+% \end{macrocode}
+% Style for solution block title:
+% \begin{macrocode}
+\exerciseconfig{styletitlesolutions}{\normalsize}
+% \end{macrocode}
+% Style for problem block title:
+% \begin{macrocode}
+\exerciseconfig{styletitleproblems}{\Large}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Spacing.}
+%
+% \macro{skip...}
+% Spaces related to various elements.
+% Vertical space is typically combined with space declared elsewhere
+% using |\addvspace|.
+%
+% Space above problem environment:
+% \begin{macrocode}
+\exerciseconfig{skipproblemabove}{3.25ex plus 1ex minus 1.5ex}
+% \end{macrocode}
+% Space below problem environment:
+% \begin{macrocode}
+\exerciseconfig{skipproblembelow}{3pt plus 1pt minus 1pt}
+% \end{macrocode}
+% Space below or after problem title;
+% positive numbers generate vertical space
+% (problem body is started in new paragraph),
+% negative numbers generate horizontal space
+% (problem body continues on opening line):
+% \begin{macrocode}
+\exerciseconfig{skipproblemtitle}{3pt plus 1pt minus 1pt}
+% \end{macrocode}
+% Horizontal space between items in the problem opening line:
+% \begin{macrocode}
+\exerciseconfig{skipprobleminfo}{0.5em}
+% \end{macrocode}
+% Space for problem item and indentation;
+% |0pt| means no indentation and direct display of title;
+% positive numbers define an absolute amount;
+% |-1pt| (or any negative number) computes the amount of indentation
+% from the width of (standard) item plus separator:
+% \begin{macrocode}
+\exerciseconfig{skipproblemitem}{0pt}
+% \end{macrocode}
+
+% Spaces related to subproblem environment;
+% analogous to spaces related to problem environment,
+% see above:
+% \begin{macrocode}
+\exerciseconfig{skipsubproblemabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsubproblembelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsubproblemtitle}{-1em}
+\exerciseconfig{skipsubprobleminfo}{0.25em}
+\exerciseconfig{skipsubproblemitem}{-1pt}
+% \end{macrocode}
+
+% Spaces related to solution environment;
+% analogous to spaces related to problem environment,
+% \begin{macrocode}
+\exerciseconfig{skipsolutionabove}{0ex}
+\exerciseconfig{skipsolutionbelow}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutiontitle}{-0.5em}
+\exerciseconfig{skipsolutioninfo}{0.25em}
+% \end{macrocode}
+% |skipsolutionitem| and |skipsolutionitemsub|
+% are analogous to |skipproblemitem| described above;
+% they apply to solutions corresponding to problems and subproblems,
+% respectively:
+% \begin{macrocode}
+\exerciseconfig{skipsolutionitem}{0pt}
+\exerciseconfig{skipsolutionitemsub}{0pt}
+% \end{macrocode}
+
+% Spaces related to solution blocks;
+% space above and below a solution block:
+% \begin{macrocode}
+\exerciseconfig{skipsolutionsabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipsolutionsbelow}{1.5ex plus 0.5ex minus 1ex}
+% \end{macrocode}
+% Space above problem titles in a solution block:
+% \begin{macrocode}
+\exerciseconfig{skipsolutionsproblemabove}{1.0ex plus 0ex minus 0.5ex}
+% \end{macrocode}
+% Space following problem titles in a solution block
+% (with legacy definition):
+% \begin{macrocode}
+\exerciseconfig{skipsolutionsproblemtitle}{1.0ex plus 0ex minus 0.5ex}
+\exerciseconfig{skipsolutionsproblem}{\exf@config@skipsolutionsproblemtitle}
+% \end{macrocode}
+% Space following title of a solution block:
+% \begin{macrocode}
+\exerciseconfig{skipsolutionstitle}{1.0ex plus 0ex minus 0.5ex}
+% \end{macrocode}
+
+% Spaces related to problem blocks;
+% space above and below a problem block:
+% \begin{macrocode}
+\exerciseconfig{skipproblemsabove}{1.5ex plus 0.5ex minus 1ex}
+\exerciseconfig{skipproblemsbelow}{1.5ex plus 0.5ex minus 1ex}
+% \end{macrocode}
+% Space following title of a problem block:
+% \begin{macrocode}
+\exerciseconfig{skipproblemstitle}{1.0ex plus 0ex minus 0.5ex}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Hook Code.}
+%
+% \macro{insert...}
+% Code to process data and to insert text at various points of processing.
+%
+% Code to generate the title for a sheet;
+% minimalistic default to display the sheet title:
+% \begin{macrocode}
+\exerciseconfig{insertsheettitle}{\centerline{\getsheetdata{title}}}
+% \end{macrocode}
+% Code to clear the page at the start and at the end of a new sheet:
+% \begin{macrocode}
+\exerciseconfig{insertsheetclearpage}{\exercisecleardoublepage}
+% \end{macrocode}
+% Code to insert before a sheet is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertsheetbefore}{}
+% \end{macrocode}
+% Code to insert after a sheet is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertsheetafter}{}
+% \end{macrocode}
+% Code to insert before a solution block is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertsolutionsbefore}{}
+% \end{macrocode}
+% Code to insert after a solution block is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertsolutionsafter}{}
+% \end{macrocode}
+% Code to insert before a problem block is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertproblemsbefore}{}
+% \end{macrocode}
+% Code to insert after a problem block is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertproblemsafter}{}
+% \end{macrocode}
+% Code to insert before a problem is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertproblembefore}{}
+% \end{macrocode}
+% Code to insert after a problem is displayed:
+% \begin{macrocode}
+\exerciseconfig{insertproblemafter}{}
+% \end{macrocode}
+% Code to insert between a problem and its solution
+% (if style |solutionbelow| is |problem|):
+% \begin{macrocode}
+\exerciseconfig{insertproblemsolution}{}
+% \end{macrocode}
+% Code to insert text into the problem opening line
+% by means of |\addprobleminfo|:
+% \begin{macrocode}
+\exerciseconfig{insertprobleminfo}{}
+% \end{macrocode}
+% Code to determine the display of problems:
+% \begin{macrocode}
+\exerciseconfig{insertproblemselect}[1]{}
+% \end{macrocode}
+% Analogous definitions for subproblems:
+% \begin{macrocode}
+\exerciseconfig{insertsubproblembefore}{}
+\exerciseconfig{insertsubproblemafter}{}
+\exerciseconfig{insertsubprobleminfo}{}
+\exerciseconfig{insertsubproblemsolution}{}
+% \end{macrocode}
+% Analogous definitions for solutions:
+% \begin{macrocode}
+\exerciseconfig{insertsolutionbefore}{}
+\exerciseconfig{insertsolutionafter}{}
+\exerciseconfig{insertsolutioninfo}{}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Text Composition for Environments.}
+%
+% \macro{compose...}
+% Macros to generate text for various situations.
+% Preferably the output is plain text without formatting,
+% but in some situations it may be required to
+% address formatting in these macros.
+%
+% Default separator for items:
+% \begin{macrocode}
+\exerciseconfig{composeitemsep}{\ }
+% \end{macrocode}
+% Compose sheet title;
+% arguments are sheet number and raw title (empty if not specified);
+% default is ``Sheet |#1|'' or given title ``|#2|'':
+% \begin{macrocode}
+\exerciseconfig{composetitlesheet}[2]%
+ {\exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#2}}
+% \end{macrocode}
+% Compose sheet title for pdf metadata;
+% arguments are sheet number and raw title:
+% \begin{macrocode}
+\exerciseconfig{composemetasheet}[2]%
+ {\getexerciseconfig{composetitlesheet}{#1}{#2}}
+% \end{macrocode}
+% Compose sheet title for table of contents;
+% arguments are sheet number and raw title:
+% \begin{macrocode}
+\exerciseconfig{composetocsheet}[2]%
+ {\exerciseifempty{#2}{\getexerciseconfig{termsheet} #1}{#1. #2}}
+% \end{macrocode}
+% Compose problem item; argument is problem number:
+% \begin{macrocode}
+\exerciseconfig{composeitemproblem}[1]{#1.}
+% \end{macrocode}
+% Problem item separator:
+% \begin{macrocode}
+\exerciseconfig{composeitemproblemsep}%
+ {\getexerciseconfig{composeitemsep}}
+% \end{macrocode}
+% Compose problem title;
+% arguments are problem number (empty if item is split off)
+% and raw title (empty if not specified);
+% default is ``Problem |#1|.'' or ``|#1|. |#2|'':
+% \begin{macrocode}
+\exerciseconfig{composetitleproblem}[2]{\exerciseifempty{#1}%
+ {\exerciseifempty{#2}{}{#2}}%
+ {\exerciseifempty{#2}{\getexerciseconfig{termproblem}\ %
+ \getexerciseconfig{composeitemproblem}{#1}}%
+ {\getexerciseconfig{composeitemproblem}{#1} #2}}}
+% \end{macrocode}
+% Compose problem title for table of contents;
+% arguments are problem number and raw title:
+% \begin{macrocode}
+\exerciseconfig{composetocproblem}[2]%
+ {\exerciseifempty{#2}{\getexerciseconfig{termproblem} #1}{#1. #2}}
+% \end{macrocode}
+% Compose subproblem item; argument is subproblem number:
+% \begin{macrocode}
+\exerciseconfig{composeitemsubproblem}[1]{#1}
+% \end{macrocode}
+% Subproblem item separator:
+% \begin{macrocode}
+\exerciseconfig{composeitemsubproblemsep}%
+ {\getexerciseconfig{composeitemsep}}
+% \end{macrocode}
+% Compose subproblem title;
+% argument is subproblem number:
+% \begin{macrocode}
+\exerciseconfig{composetitlesubproblem}[1]{#1}
+% \end{macrocode}
+% Compose solution item; arguments are problem and subproblem number:
+% \begin{macrocode}
+\exerciseconfig{composeitemsolution}[2]{#1.}
+\exerciseconfig{composeitemsolutionsub}[2]{#2}
+% \end{macrocode}
+% Solution item separator:
+% \begin{macrocode}
+\exerciseconfig{composeitemsolutionsep}%
+ {\getexerciseconfig{composeitemsep}}
+% \end{macrocode}
+% Compose title for single solution;
+% arguments are corresponding problem and subproblem number:
+% \begin{macrocode}
+\exerciseconfig{composetitlesolutionsingle}[2]%
+ {\getexerciseconfig{termsolution}:}
+% \end{macrocode}
+% Compose title for one out of several solutions;
+% arguments are corresponding problem and subproblem number:
+% \begin{macrocode}
+\exerciseconfig{composetitlesolutionmulti}[2]{#2}
+% \end{macrocode}
+% Compose table of contents line for solution;
+% arguments are problem number and raw title:
+% \begin{macrocode}
+\exerciseconfig{composetocsolution}[2]%
+ {\getexerciseconfig{composetocproblem}{#1}{#2}}
+% \end{macrocode}
+% Compose title for solution block:
+% \begin{macrocode}
+\exerciseconfig{composetitlesolutions}%
+ {\getexerciseconfig{termsolutions}}
+% \end{macrocode}
+% Compose title for problem block:
+% \begin{macrocode}
+\exerciseconfig{composetitleproblems}%
+ {\getexerciseconfig{termproblems}}
+% \end{macrocode}
+% Compose table of contents line for solution block:
+% \begin{macrocode}
+\exerciseconfig{composetocsolutions}%
+ {\getexerciseconfig{composetitlesolutions}}
+% \end{macrocode}
+% Compose table of contents line for problem block:
+% \begin{macrocode}
+\exerciseconfig{composetocproblems}%
+ {\getexerciseconfig{composetitleproblems}}
+% \end{macrocode}
+% Compose sectional title for solution following a single problem;
+% arguments are problem number and raw title:
+% \begin{macrocode}
+\exerciseconfig{composetitlesolutionsproblemsingle}[2]%
+ {\getexerciseconfig{termsolution}}
+% \end{macrocode}
+% Compose sectional title for solution of one problem within a solution block;
+% arguments are problem number and raw title:
+% \begin{macrocode}
+\exerciseconfig{composetitlesolutionsproblemmulti}[2]%
+ {\exerciseifempty{#2}{\getexerciseconfig{termproblem} #1}{#1. #2}}
+% \end{macrocode}
+% Compose label:
+% \begin{macrocode}
+\exerciseconfig{composeitemsolutionlabel}[2]{#1#2}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Points.}
+%
+% Compose number of points:
+% \begin{macrocode}
+\exerciseconfig{composepointsnum}[1]{#1}
+% \end{macrocode}
+% Compose number of points followed by `points';
+% use singular `point' for $1$:
+% \begin{macrocode}
+\exerciseconfig{composepoints}[1]{\getexerciseconfig{composepointsnum}{#1}~%
+ \ifdim #1pt=1pt\getexerciseconfig{termpoint}%
+ \else\getexerciseconfig{termpoints}\fi}
+% \end{macrocode}
+% Compose points declaration for use in opening line:
+% \begin{macrocode}
+\exerciseconfig{composepointsstart}[1]{(\getexerciseconfig{composepoints}{#1})}
+% \end{macrocode}
+% Compose points declaration for use in margin:
+% \begin{macrocode}
+\exerciseconfig{composepointsmargin}[1]{\getexerciseconfig{composepoints}{#1}}
+% \end{macrocode}
+% Compose points declaration for use in text:
+% \begin{macrocode}
+\exerciseconfig{composepointsbody}[1]{(\getexerciseconfig{composepoints}{#1})}
+% \end{macrocode}
+% Compose points declaration for use in sheet data:
+% \begin{macrocode}
+\exerciseconfig{composepointssheet}[1]{%
+ \exerciseifnotempty{#1}{\getexerciseconfig{composepoints}{#1}}}
+% \end{macrocode}
+% Compose points declaration for solution with comment:
+% \begin{macrocode}
+\exerciseconfig{composepointsaward}[2]%
+ {(\getexerciseconfig{composepoints}{#1}\exerciseifnotempty{#2}{; #2})}
+% \end{macrocode}
+% Compose alternative points for solution declaration with comment:
+% \begin{macrocode}
+\exerciseconfig{composepointsawardalt}[2]%
+ {(\getexerciseconfig{composepoints}{#1}*\exerciseifnotempty{#2}{; #2})}
+% \end{macrocode}
+
+% Compose pairs of points; omit 0 components:
+% \begin{macrocode}
+\exerciseconfig{composepointspair}[2]{%
+ \ifdim#2pt=0pt%
+ \getexerciseconfig{composepoints}{#1}%
+ \else\ifdim#1pt=0pt%
+ +\getexerciseconfig{composepoints}{#2}%
+ \else%
+ \getexerciseconfig{composepointsnum}{#1}+%
+ \getexerciseconfig{composepointsnum}{#2}~%
+ \getexerciseconfig{termpoints}%
+ \fi\fi}
+% \end{macrocode}
+% Compose pairs of points for designated use;
+% recycle plain definition if no bonus points given:
+% \begin{macrocode}
+\exerciseconfig{composepointspairbody}[2]{%
+ \ifdim#2pt=0pt\getexerciseconfig{composepointsbody}{#1}\else%
+ (\getexerciseconfig{composepointspair}{#1}{#2})\fi}
+\exerciseconfig{composepointspairstart}[2]{%
+ \ifdim#2pt=0pt\getexerciseconfig{composepointsstart}{#1}\else%
+ (\getexerciseconfig{composepointspair}{#1}{#2})\fi}
+\exerciseconfig{composepointspairmargin}[2]{%
+ \ifdim#2pt=0pt\getexerciseconfig{composepointsmargin}{#1}\else%
+ \getexerciseconfig{composepointspair}{#1}{#2}\fi}
+\exerciseconfig{composepointspairsheet}[2]{%
+ \ifdim#2pt=0pt\getexerciseconfig{composepointssheet}{#1}\else%
+ \getexerciseconfig{composepointspair}{#1}{#2}\fi}
+\exerciseconfig{composepointspairaward}[3]{%
+ \ifdim#2pt=0pt\getexerciseconfig{composepointsaward}{#1}{#3}\else%
+ (\getexerciseconfig{composepointspair}{#1}{#2}%
+ \exerciseifnotempty{#3}{; #3})\fi}
+\exerciseconfig{composepointspairawardalt}[3]{%
+ \ifdim#2pt=0pt\getexerciseconfig{composepointsawardalt}{#1}{#3}\else%
+ (\getexerciseconfig{composepointspair}{#1}{#2}*%
+ \exerciseifnotempty{#3}{; #3})\fi}
+% \end{macrocode}
+% Compose pairs of points for designated situations:
+% \begin{macrocode}
+\exerciseconfig{composepointspairbodyproblem}[2]{%
+ \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairbodysubproblem}[2]{%
+ \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairbodysolution}[2]{%
+ \getexerciseconfig{composepointspairbody}{#1}{#2}}
+\exerciseconfig{composepointspairstartproblem}[2]{%
+ \getexerciseconfig{composepointspairstart}{#1}{#2}}
+\exerciseconfig{composepointspairstartsubproblem}[2]{%
+ \getexerciseconfig{composepointspairstart}{#1}{#2}}
+\exerciseconfig{composepointspairstartsolution}[2]{%
+ \getexerciseconfig{composepointspairstart}{#1}{#2}}
+% \end{macrocode}
+
+% Display points in the margin:
+% \begin{macrocode}
+\exerciseconfig{insertpointsmargin}[1]{\marginpar{\footnotesize #1}}
+% \end{macrocode}
+
+% Display warning about points mismatch:
+% \begin{macrocode}
+\exerciseconfig{insertwarnpoints}[3]
+ {\textbf{points mismatch for #1 (#2 determined vs.\ #3 given)}}
+% \end{macrocode}
+% Display warning about points changed:
+% \begin{macrocode}
+\exerciseconfig{insertwarnpointsrerun}[1]
+ {\textbf{points changed for #1 (please recompile)}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Counters.}
+%
+% Define counter display via configuration interface:
+% \begin{macrocode}
+\exerciseconfig{countersheet}{\arabic{\exf@sheetcounter}}
+\exerciseconfig{counterproblem}{\arabic{\exf@problemcounter}}
+\exerciseconfig{counterproblemmax}{10}
+\exerciseconfig{countersubproblem}{\alph{\exf@subproblemcounter})}
+\exerciseconfig{countersubproblemmax}{m)}
+\exerciseconfig{countersheetequation}{\arabic{equation}}
+\exerciseconfig{counterproblemequation}{P\arabic{equation}}
+\exerciseconfig{countersolutionequation}{S\arabic{equation}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Further Definitions.}
+%
+% \macro{labelsheet}
+% \macro{labelproblem}
+% Templates for automatic generation of labels from tags:
+% \begin{macrocode}
+\exerciseconfig{labelsheet}[1]{sheet:#1}
+\exerciseconfig{labelproblem}[1]{prob:#1}
+% \end{macrocode}
+
+% \macro{toclevel...}
+% Table of contents levels for sheets, problems,
+% solutions of problems and solution blocks;
+% empty means no writing to table of contents:
+% \begin{macrocode}
+\exerciseconfig{toclevelsheet}{}
+\exerciseconfig{toclevelproblem}{}
+\exerciseconfig{toclevelproblems}{}
+\exerciseconfig{toclevelsolution}{}
+\exerciseconfig{toclevelsolutions}{}
+% \end{macrocode}
+
+% \macro{extsolutions}
+% \macro{extproblems}
+% Filename extension for solution and problem blocks:
+% \begin{macrocode}
+\exerciseconfig{extsolutions}{.sol}
+\exerciseconfig{extproblems}{.prb}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Styles}
+% \label{sec:imp-styles}
+%
+% Styles are meant as a way to adjust
+% several configuration options at the same time
+% to achieve a consistent layout in some regard.
+% Useful examples can be found among the
+% extended exercise styles.
+% They can serve a starting point for further
+% custom styles.
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Exercise Styles Code.}
+%
+% \macro{\defexercisestylearg}
+% Define a style with an argument:
+% \begin{macrocode}
+\newcommand{\defexercisestylearg}[3][]{%
+ \def\exf@tmp{#1}\ifx\exf@tmp\exf@empty%
+ \define@key{exf@style}{#2}{#3}\else%
+ \define@key{exf@style}{#2}[#1]{#3}\fi}
+% \end{macrocode}
+% \macro{\defexercisestyle}
+% Define a style with a boolean argument;
+% execute code onlf if true:
+% \begin{macrocode}
+\newcommand{\defexercisestyle}[2]{%
+ \exf@csdotwo\long\def{exf@style@code@#1}{#2}%
+ \exf@exparg{\define@boolkey{exf@style}[exf@style@]{#1}[true]}%
+ {\csname ifexf@style@#1\endcsname\csname exf@style@code@#1\endcsname\fi}}
+% \end{macrocode}
+% \macro{\exercisestyle}
+% Process styles:
+% \begin{macrocode}
+\newcommand{\exercisestyle}[1]{\exf@expsetkeys{exf@style}{#1}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Default Exercise Styles.}
+%
+% \macro{problemmanual}
+% Delay display of problems:
+% \begin{macrocode}
+\define@boolkey{exf@style}[exf@]{problemmanual}[true]{}
+\exf@problemmanualfalse
+% \end{macrocode}
+%
+% \macro{solutionbelow}
+% Choose location for solutions:
+% \begin{macrocode}
+\def\exf@solutionbelow{subproblem}
+\define@choicekey{exf@style}{solutionbelow}%
+ {here,subproblem,subproblem*,problem,problem*,sheet,manual}%
+ {\ifexf@solfile@open\else\gdef\exf@solutionbelow{#1}\fi}
+% \end{macrocode}
+%
+% \macro{sheetequation}
+% \macro{problemequation}
+% \macro{solutionequation}
+% Use separate equation counters for sheets, problems and solutions:
+% \begin{macrocode}
+\defexercisestyle{sheetequation}{}
+\defexercisestyle{problemequation}{}
+\defexercisestyle{solutionequation}{}
+\exf@style@solutionequationtrue
+% \end{macrocode}
+%
+% \macro{problempointsat}
+% \macro{subproblempointsat}
+% \macro{solutionpointsat}
+% Choose where points of (sub)problems and solutions are displayed:
+% \begin{macrocode}
+\def\exf@pointsat{start}
+\define@choicekey{exf@style}{problempointsat}%
+ {start,start*,margin,end,manual,off}{\def\exf@pointsat{#1}}
+\define@choicekey{exf@style}{pointsat}%
+ {start,start*,margin,end,manual,off}{\def\exf@pointsat{#1}}
+\def\exf@subpointsat{end}
+\define@choicekey{exf@style}{subproblempointsat}%
+ {start,start*,margin,end,manual,off}{\def\exf@subpointsat{#1}}
+\define@choicekey{exf@style}{subpointsat}%
+ {start,start*,margin,end,manual,off}{\def\exf@subpointsat{#1}}
+\def\exf@solpointsat{off}
+\define@choicekey{exf@style}{solutionpointsat}%
+ {start,start*,margin,end,manual,off}{\def\exf@solpointsat{#1}}
+\define@choicekey{exf@style}{solpointsat}%
+ {start,start*,margin,end,manual,off}{\def\exf@solpointsat{#1}}
+% \end{macrocode}
+%
+% \macro{problemby}
+% \macro{equationby}
+% Declare problems or equations as subcounter of other counter:
+% \begin{macrocode}
+\defexercisestylearg{problemby}{\exf@numberproblemwithin{#1}}
+\defexercisestylearg{equationby}{\exf@numberequationwithin{#1}}
+% \end{macrocode}
+%
+% \macro{pagebysheet}
+% \macro{problembysheet}
+% \macro{equationbysheet}
+% Number pages, problems or equations by sheet:
+% \begin{macrocode}
+\defexercisestyle{pagebysheet}{%
+ \def\thepage{\csname the\exf@sheetcounter\endcsname.\arabic{page}}%
+ \def\theHpage{\csname theH\exf@sheetcounter\endcsname.\arabic{page}}%
+ \exerciseconfigappend{insertsheetbefore}{\setcounter{page}{1}}}
+\defexercisestyle{problembysheet}%
+ {\exf@numberproblemwithin{\exf@sheetcounter}}
+\defexercisestyle{equationbysheet}%
+ {\exf@numberequationwithin{\exf@sheetcounter}}
+% \end{macrocode}
+%
+% \macro{fracpoints}
+% Use vulgar fractions to display binary fractional points:
+% \begin{macrocode}
+\defexercisestyle{fracpoints}%
+ {\exerciseconfig{composepointsnum}[1]{\protect\showfracpoints{##1}}}
+% \end{macrocode}
+%
+% \macro{twoside}
+% Use two-sided layout for sheets:
+% \begin{macrocode}
+\defexercisestylearg[true]{twoside}{\exercisesetup{twoside={#1}}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Extended Exercise Styles.}
+%
+% Declare more specific styles:
+% \begin{macrocode}
+\ifexf@extstyle
+% \end{macrocode}
+%
+% \macro{contents}
+% Add sheets and problems to table of contents:
+% \begin{macrocode}
+\defexercisestyle{contents}{%
+ \exerciseconfig{toclevelsheet}{section}%
+ \exerciseconfig{toclevelproblem}{subsection}}
+% \end{macrocode}
+% \macro{solutionsf}
+% Use sans serif font for solutions:
+% \begin{macrocode}
+\defexercisestyle{solutionsf}{%
+ \exerciseconfigappend{styletextsolution}{\sffamily\let\itshape\slshape}}
+% \end{macrocode}
+% \macro{solutiondimproblem}
+% Dim problem text if solutions are displayed:
+% \begin{macrocode}
+\defexercisestyle{solutiondimproblem}{%
+ \RequirePackage{color}%
+ \exerciseconfigappend{styletextsolution}{\color[gray]{0}}%
+ \exerciseconfigappend{styletextproblem}{\color[gray]{0.2}}}
+% \end{macrocode}
+% \macro{solutionsep}
+% Separate solutions by horizontal lines:
+% \begin{macrocode}
+\defexercisestyle{solutionsep}{%
+ \exerciseconfig{insertsolutionsbefore}{\hrule\nopagebreak[3]\vspace{0.5ex}}%
+ \exerciseconfig{insertsolutionsafter}%
+ {\removelastskip\nopagebreak[3]\vspace{1.0ex}\hrule}}
+% \end{macrocode}
+% \macro{plainheader}
+% Declare a simple sheet header with some configurable options;
+% the configuration options |styleheader...| define font styles,
+% |skipheaderbelow| the space below the header and
+% |composeheaderbelow...| some auxiliary text to be displayed
+% on the line below the header:
+% \begin{macrocode}
+\defexercisestyle{plainheader}{%
+ \exerciseconfig{styleheadertitle}{\Large\bfseries}%
+ \exerciseconfig{styleheadercourse}{\sffamily}%
+ \exerciseconfig{styleheaderbelow}{\footnotesize}%
+ \exerciseconfig{skipheaderbelow}{3ex}%
+ \exerciseconfig{composeheaderbelowleft}{}%
+ \exerciseconfig{composeheaderbelowright}{}%
+ \exerciseconfig{composeheaderbelowcenter}{}%
+ \exerciseconfig{insertsheettitle}{\noindent%
+ \begin{minipage}{\textwidth}%
+ {\getexerciseconfig{styleheadertitle}%
+ \makebox[0pt][l]{\getexercisedata{course}}%
+ \hfill\makebox[0pt][r]{\getsheetdata{title}}\par}%
+ {\getexerciseconfig{styleheadercourse}%
+ \makebox[0pt][l]{\getexercisedata{institution}%
+ \exercisedataempty{period}{}{, \getexercisedata{period}}}%
+ \hfill\makebox[0pt][r]{\getexercisedata{instructor}}%
+ \vphantom{g}\par}%
+ \hrule%
+ {\def\tmp{}%
+ \exerciseconfigempty{composeheaderbelowleft}{}{\def\tmp{.}}%
+ \exerciseconfigempty{composeheaderbelowcenter}{}{\def\tmp{.}}%
+ \exerciseconfigempty{composeheaderbelowright}{}{\def\tmp{.}}%
+ \exerciseifnotempty{\tmp}%
+ {\getexerciseconfig{styleheaderbelow}\vphantom{\^A}%
+ \makebox[0pt][l]{\getexerciseconfig{composeheaderbelowleft}}%
+ \hfill\makebox[0pt][c]{\getexerciseconfig{composeheaderbelowcenter}}%
+ \hfill\makebox[0pt][r]{\getexerciseconfig{composeheaderbelowright}}%
+ \vspace*{-\baselineskip}\vspace*{-\parskip}\par}}%
+ \end{minipage}%
+ \par\addvspace{\getexerciseconfig{skipheaderbelow}}}}
+% \end{macrocode}
+%
+% Done with extended styles:
+% \begin{macrocode}
+\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Metadata}
+% \label{sec:imp-metadata}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Global Metadata Code.}
+%
+% \macro{\defexercisedata}
+% Declare global metadata field
+% by defining a key \textit{key} in category |exf@data|
+% that stores the chosen value in |\exf@data@|\textit{key}:
+% \begin{macrocode}
+\newcommand{\defexercisedata}[1]{%
+ \exf@csdo\def{exf@data@#1}{}%
+ \define@key{exf@data}{#1}%
+ {\exf@csdo\gdef{exf@data@#1}{##1}}}
+% \end{macrocode}
+% \macro{\exercisedata}
+% Process key-value pairs:
+% \begin{macrocode}
+\newcommand{\exercisedata}[1]{\setkeys{exf@data}{#1}}
+% \end{macrocode}
+% \macro{\getexercisedata}
+% Read global metadata:
+% \begin{macrocode}
+\newcommand{\getexercisedata}[1]{\csname exf@data@#1\endcsname}
+% \end{macrocode}
+% \macro{\exercisedataempty}
+% Check whether the field is empty:
+% \begin{macrocode}
+\newcommand{\exercisedataempty}[3]{\exf@csdo\ifx{exf@data@#1}\exf@empty%
+ #2\else#3\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Global Metadata Declarations.}
+%
+% Declare fields corresponding to standard pdf metadata:
+% \begin{macrocode}
+\defexercisedata{author}
+\defexercisedata{title}
+\defexercisedata{subject}
+\defexercisedata{keyword}
+% \end{macrocode}
+% Declare additional general purpose fields:
+% \begin{macrocode}
+\defexercisedata{date}
+% \end{macrocode}
+% Declare metadata related to courses:
+% \begin{macrocode}
+\defexercisedata{instructor}
+\defexercisedata{course}
+\defexercisedata{institution}
+\defexercisedata{period}
+\defexercisedata{material}
+% \end{macrocode}
+% Overwrite standard definitions for |author|, |title|, |date|
+% to also fill ordinary \LaTeX{} structures:
+% \begin{macrocode}
+\define@key{exf@data}{author}{\gdef\exf@data@author{#1}\author{#1}}
+\define@key{exf@data}{title}{\gdef\exf@data@title{#1}\title{#1}}
+\define@key{exf@data}{date}{\gdef\exf@data@date{#1}\date{#1}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Metadata.}
+%
+% \macro{\defsheetdata}
+% Declare sheet metadata field
+% by defining a key \textit{key} in category |exf@sheet|
+% that stores the chosen value in |\exf@data@sheet@|\textit{key}:
+% \begin{macrocode}
+\newcommand{\defsheetdata}[1]{%
+ \exf@csdo\def{exf@data@sheet@#1}{}%
+ \define@key{exf@sheet}{#1}%
+ {\exf@csdo\def{exf@data@sheet@#1}{##1}}}
+% \end{macrocode}
+% \macro{\setsheetdata}
+% Set sheet metadata:
+% \begin{macrocode}
+\newcommand{\setsheetdata}[1]{\setkeys{exf@sheet}{#1}}
+% \end{macrocode}
+% \macro{\getsheetdata}
+% Read sheet metadata:
+% \begin{macrocode}
+\newcommand{\getsheetdata}[1]{\csname exf@data@sheet@#1\endcsname}
+% \end{macrocode}
+% \macro{\sheetdataempty}
+% Check whether the field is empty:
+% \begin{macrocode}
+\newcommand{\sheetdataempty}[3]{\exf@csdo\ifx{exf@data@sheet@#1}\exf@empty%
+ #2\else#3\fi}
+% \end{macrocode}
+
+% Declare general purpose fields:
+% \begin{macrocode}
+\defsheetdata{due}
+\defsheetdata{handout}
+\defsheetdata{editdate}
+\defsheetdata{author}
+\defsheetdata{editor}
+% \end{macrocode}
+
+% Special title processing:
+% \begin{macrocode}
+\def\exf@data@sheet@rawtitle{}
+\define@key{exf@sheet}{title}{\def\exf@data@sheet@rawtitle{#1}}
+\def\exf@data@sheet@title{\exf@config@composetitlesheet%
+ {\csname the\exf@sheetcounter\endcsname}{\exf@data@sheet@rawtitle}}%
+% \end{macrocode}
+% Special points processing:
+% \begin{macrocode}
+\def\exf@data@sheet@points{\ifdefined\exf@sheet@points%
+ \expandafter\exf@config@composepointspairsheet\exf@sheet@points\fi}%
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Metadata.}
+%
+% \macro{\defproblemdata}
+% Declare problem metadata field
+% by defining a key \textit{key} in category |exf@problem|
+% that stores the chosen value in |\exf@data@problem@|\textit{key}:
+% \begin{macrocode}
+\newcommand{\defproblemdata}[1]{%
+ \exf@csdo\def{exf@data@problem@#1}{}%
+ \define@key{exf@problem}{#1}%
+ {\exf@csdo\def{exf@data@problem@#1}{##1}}}
+% \end{macrocode}
+% \macro{\setproblemdata}
+% Set problem metadata:
+% \begin{macrocode}
+\newcommand{\setproblemdata}[1]{\setkeys{exf@problem,exf@scanproblem}{#1}}
+% \end{macrocode}
+% \macro{\getproblemdata}
+% Read problem metadata:
+% \begin{macrocode}
+\newcommand{\getproblemdata}[1]{\csname exf@data@problem@#1\endcsname}
+% \end{macrocode}
+% \macro{\problemdataempty}
+% Check whether the field is empty:
+% \begin{macrocode}
+\newcommand{\problemdataempty}[3]{\exf@csdo\ifx{exf@data@problem@#1}\exf@empty%
+ #2\else#3\fi}
+% \end{macrocode}
+
+% Special title processing:
+% \begin{macrocode}
+\def\exf@data@problem@rawtitle{}
+\define@key{exf@problem}{title}{\def\exf@data@problem@rawtitle{#1}}
+\def\exf@data@problem@title{\exf@config@composetitleproblem{%
+ \csname the\exf@problemcounter\endcsname}{\exf@data@problem@rawtitle}}%
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Environment Code.}
+%
+% \macro{\exf@addmargin}
+% Define a length for environment margin:
+% \begin{macrocode}
+\newlength\exf@addmargin
+% \end{macrocode}
+
+% \macro{\exf@section}
+% Write out problem opening line followed by some amount of skip
+% (positive dimensions add vertical space,
+% negative dimensions add horizontal space);
+% protected expand argument if in horizontal mode
+% (because it will be held until text is output
+% and some definitions may become invalid):
+% \begin{macrocode}
+\newcommand{\exf@section}[2]{\setlength\exf@tmpdim{#1}%
+ \ifdim\exf@tmpdim<0pt%
+ \protected@edef\exf@tmp{#2}%
+ \else%
+ \def\exf@tmp{#2}%
+ \fi%
+ \exf@exparg{\@startsection{}{}{0pt}{0pt}{#1}{}*}{\exf@tmp}}
+% \end{macrocode}
+
+% \macro{\exf@init@block}
+% Clean info buffer, define amount of skip between items:
+% \begin{macrocode}
+\newcommand{\exf@init@block}[1]{%
+ \def\exf@intro{}\def\exf@intro@skip{#1}%
+ \exf@addmargin0pt\def\exf@introitem{}}
+% \end{macrocode}
+% \macro{\exf@append@intro}
+% Append to info buffer:
+% \begin{macrocode}
+\newcommand{\exf@append@intro}[1]%
+ {\exf@append@def\exf@intro{#1\hspace{\exf@intro@skip}}}
+% \end{macrocode}
+% \macro{\exf@prepend@intro}
+% Prepend to info buffer:
+% \begin{macrocode}
+\newcommand{\exf@prepend@intro}[1]%
+ {\exf@prepend@def\exf@intro{#1\hspace{\exf@intro@skip}}}
+% \end{macrocode}
+% \macro{\exf@open@block}
+% Open environment, set margin, compose opening line:
+% \begin{macrocode}
+\newcommand{\exf@open@block}[1]{%
+ \advance\leftskip\exf@addmargin%
+ \advance\linewidth-\exf@addmargin%
+ \advance\@totalleftmargin\exf@addmargin%
+ \ifx\exf@intro\exf@empty%
+ \exf@section{0pt}{\exf@introitem}%
+ \else%
+ \exf@section{#1}{\exf@introitem\exf@intro\unskip}%
+ \fi}%
+% \end{macrocode}
+% \macro{\exf@close@block}
+% Close environment, undo margin:
+% \begin{macrocode}
+\newcommand{\exf@close@block}{%
+ \advance\leftskip-\exf@addmargin%
+ \advance\linewidth\exf@addmargin%
+ \advance\@totalleftmargin-\exf@addmargin}%
+% \end{macrocode}
+
+% \macro{\addprobleminfo}
+% Interface to append or prepend to info buffer:
+% \begin{macrocode}
+\newcommand{\addprobleminfo}{\@ifstar\exf@prepend@intro\exf@append@intro}
+% \end{macrocode}
+
+% \macro{\exf@addinfoswitch}
+% Add a switch for displaying problem info:
+% \begin{macrocode}
+\newcommand{\exf@addinfoswitch}[1]%
+ {\define@boolkey{exf@infoswitch}[exf@showdata@]{#1}[true]{}}
+% \end{macrocode}
+% \macro{\defprobleminfo}
+% Declare a problem info field,
+% add corresponding info switch,
+% process key-value pair if switch activated:
+% \begin{macrocode}
+\newcommand{\defprobleminfo}[2]{%
+ \exf@addinfoswitch{#1}%
+ \exerciseconfig{compose@probleminfo@#1}[1]{#2}%
+ \exf@exparg{\define@key{exf@probleminfo}{#1}}%
+ {\csname ifexf@showdata@#1\endcsname\exf@append@intro{%
+ \csname exf@config@compose@probleminfo@#1\endcsname{##1}}\fi}}
+% \end{macrocode}
+% \macro{\showprobleminfo}
+% Process info switches, expand argument first:
+% \begin{macrocode}
+\newcommand{\showprobleminfo}[1]{\exf@expsetkeys{exf@infoswitch}{#1}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Info Declarations.}
+%
+% Declare general purpose fields:
+% \begin{macrocode}
+\defprobleminfo{optional}{\emph{#1:}}
+\showprobleminfo{optional}
+\defprobleminfo{difficulty}{(#1)}
+% \end{macrocode}
+
+% Declare fields for internal information (mostly):
+% \begin{macrocode}
+\defprobleminfo{comment}{#1}
+\defprobleminfo{author}{$\langle$#1$\rangle$}
+\defprobleminfo{editor}{$\{$#1$\}$}
+\defprobleminfo{source}{[#1]}
+\defprobleminfo{keyword}{\#(#1)}
+% \end{macrocode}
+
+% Declare more specific fields:
+% \begin{macrocode}
+\ifexf@extdata
+\defprobleminfo{review}{#1}
+\defprobleminfo{recycle}{[[#1]]}
+\defprobleminfo{timesolve}{\{#1\}}
+\defprobleminfo{timepresent}{\{\!\{#1\}\!\}}
+\fi
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Write Metadata to PDF Files.}
+%
+% \macro{\exf@writemetadata}
+% Write Metadata to PDF Files in case \textsf{hyperref} is available,
+% choose between global and sheet version, pass through unfilled values:
+% \begin{macrocode}
+\newcommand{\exf@writemetadata}[1]{%
+ \ifdefined\hypersetup%
+ \def\exf@tmp{#1}\ifx\exf@tmp\exf@empty%
+% \end{macrocode}
+% Write global author and title:
+% \begin{macrocode}
+ \ifx\exf@data@author\exf@empty\else%
+ \hypersetup{pdfauthor={\exf@data@author}}\fi%
+ \ifx\exf@data@title\exf@empty\else%
+ \hypersetup{pdftitle={\exf@data@title}}\fi%
+ \else%
+% \end{macrocode}
+% Write sheet author (if available) and compose sheet title:
+% \begin{macrocode}
+ \ifx\exf@data@sheet@author\exf@empty%
+ \ifx\exf@data@author\exf@empty\else%
+ \hypersetup{pdfauthor={\exf@data@author}}\fi%
+ \else\hypersetup{pdfauthor={\exf@data@sheet@author}}\fi%
+ \hypersetup{pdftitle={\exf@config@composemetasheet%
+ {\csname the\exf@sheetcounter\endcsname}{\exf@data@sheet@rawtitle}}}%
+ \fi%
+% \end{macrocode}
+% Write subject and keywords:
+% \begin{macrocode}
+ \ifx\exf@data@subject\exf@empty\else%
+ \hypersetup{pdfsubject={\exf@data@subject}}\fi%
+ \ifx\exf@data@keyword\exf@empty\else%
+ \hypersetup{pdfkeywords={\exf@data@keyword}}\fi%
+ \fi%
+% \end{macrocode}
+% Do not write again:
+% \begin{macrocode}
+ \gdef\exf@metadata{off}}
+% \end{macrocode}
+
+% Automatic writing at |\begin{document}|:
+% \begin{macrocode}
+\AtBeginDocument{\exf@ifis\exf@metadata{auto}{\exf@writemetadata{}}}
+% \end{macrocode}
+
+% \macro{\writeexercisedata}
+% Write metadata manually:
+% \begin{macrocode}
+\newcommand{\writeexercisedata}{%
+ \exf@ifis\exf@metadata{manual}{\exf@writemetadata{}}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Counters}
+% \label{sec:imp-counter}
+%
+% \macro{sheet}
+% \macro{problem}
+% \macro{subproblem}
+% \macro{solution}
+% Define main counters (with customised names if necessary)
+% and equation counters:
+% \begin{macrocode}
+\newcounter{\exf@sheetcounter}
+\newcounter{\exf@problemcounter}
+\newcounter{\exf@subproblemcounter}[\exf@problemcounter]
+\newcounter{\exf@solutioncounter}[\exf@problemcounter]
+\newcount\exf@eqsav
+\newcounter{exf@sheetequation}
+\newcounter{exf@problemequation}
+\newcounter{exf@solutionequation}
+% \end{macrocode}
+
+% Implement counter display;
+% take care of corresponding \textsf{hyperref} labels:
+% \begin{macrocode}
+\exf@csdo\def{the\exf@sheetcounter}{\exf@config@countersheet}
+\exf@csdo\def{the\exf@problemcounter}{\exf@config@counterproblem}
+\exf@csdo\def{the\exf@subproblemcounter}{\exf@config@countersubproblem}
+\def\theexf@sheetequation{\exf@config@countersheetequation}
+\def\theHexf@sheetequation{sheet.\arabic{equation}}
+\def\theexf@problemequation{\exf@config@counterproblemequation}
+\def\theHexf@problemequation{prob.\arabic{equation}}
+\def\theexf@solutionequation{\exf@config@countersolutionequation}
+\def\theHexf@solutionequation{sol.\arabic{equation}}
+% \end{macrocode}
+
+% \macro{\exf@numberproblemwithin}
+% Declare problem counter as subcounter of |#1|:
+% \begin{macrocode}
+\newcommand{\exf@numberproblemwithin}[1]{%
+ \@addtoreset{\exf@problemcounter}{#1}%
+ \exf@csdo\def{the\exf@problemcounter}%
+ {\csname the#1\endcsname.\exf@config@counterproblem}}
+% \end{macrocode}
+
+% \macro{\exf@numberequationwithin}
+% Declare various new equation counters as subcounter of |#1|;
+% take care of corresponding \textsf{hyperref} labels:
+% \begin{macrocode}
+\newcommand{\exf@numberequationwithin}[1]{%
+ \@addtoreset{exf@sheetequation}{#1}%
+ \def\theexf@sheetequation%
+ {\csname the#1\endcsname.\exf@config@countersheetequation}%
+ \def\theHexf@sheetequation%
+ {\csname theH#1\endcsname.sheet.\arabic{equation}}%
+ \@addtoreset{exf@problemequation}{#1}%
+ \def\theexf@problemequation%
+ {\csname the#1\endcsname.\exf@config@counterproblemequation}%
+ \def\theHexf@problemequation%
+ {\csname theH#1\endcsname.prob.\arabic{equation}}%
+ \@addtoreset{exf@solutionequation}{#1}%
+ \def\theexf@solutionequation%
+ {\csname the#1\endcsname.\exf@config@countersolutionequation}%
+ \def\theHexf@solutionequation%
+ {\csname theH#1\endcsname.sol.\arabic{equation}}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Buffers}
+% \label{sec:imp-buffer}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{File Output.}
+%
+% \macro{\ifexf@solfile@open}
+% Conditional whether output files are presently in use:
+% \begin{macrocode}
+\newif\ifexf@solfile@open\exf@solfile@openfalse
+\newif\ifexf@probfile@open\exf@probfile@openfalse
+% \end{macrocode}
+% \macro{\exf@solfile}
+% Reserve file handles:
+% \begin{macrocode}
+\newwrite\exf@solfile
+\newwrite\exf@probfile
+% \end{macrocode}
+
+% \macro{\exf@writeline}
+% Write a line to the file:
+% \begin{macrocode}
+\newcommand{\exf@writeline}[2]{\immediate\write#1{#2}}
+% \end{macrocode}
+
+% \macro{\exf@linesep}
+% Return a separator line:
+% \begin{macrocode}
+\newcommand{\exf@linesep}%
+ {\@percentchar---------------------------------------}
+% \end{macrocode}
+% \macro{\exf@lineno}
+% Return current position in source file;
+% display line number and source file name
+% (if available via package \textsf{currfile}):
+% \begin{macrocode}
+\newcommand{\exf@lineno}{\@percentchar%
+ \ifdefined\currfilename\currfilename\space\fi%
+ l.\the\inputlineno}
+% \end{macrocode}
+
+% \macro{\exf@start@solfile}
+% Open a new solution file |#1.sol| (do nothing if already open);
+% indicate source, switch to manual solution display mode:
+% \begin{macrocode}
+\newcommand{\exf@start@solfile}[1]{%
+ \ifexf@solfile@open\else%
+ \exercisestyle{solutionbelow=manual}%
+ \global\exf@solfile@opentrue%
+ \edef\exf@tmp{#1}%
+ \immediate\openout\exf@solfile\exf@tmp\exf@config@extsolutions\relax%
+ \exf@writeline\exf@solfile{\@percentchar%
+ generated from file `\jobname' by exframe.sty}%
+ \ifexf@lineno\exf@writeline\exf@solfile{\exf@lineno}\fi%
+ \exf@writeline\exf@solfile{}%
+ \fi}
+% \end{macrocode}
+
+% \macro{\exf@close@solfile}
+% Close solution file (if open);
+% indicate position, close and reset variables:
+% \begin{macrocode}
+\newcommand{\exf@close@solfile}{%
+ \ifexf@solfile@open%
+ \ifexf@lineno\exf@writeline\exf@solfile{\exf@linesep}%
+ \exf@writeline\exf@solfile{\exf@lineno}\fi%
+ \exf@writeline\exf@solfile{\@backslashchar endinput}%
+ \immediate\closeout\exf@solfile%
+ \global\exf@solfile@openfalse%
+ \fi}
+% \end{macrocode}
+
+% \macro{\exf@start@probfile}
+% Open a new problem file |#1.prb| (do nothing if already open);
+% indicate source, switch to manual problem display mode:
+% \begin{macrocode}
+\newcommand{\exf@start@probfile}[1]{%
+ \ifexf@probfile@open\else%
+ \global\exf@probfile@opentrue%
+ \edef\exf@tmp{#1}%
+ \immediate\openout\exf@probfile\exf@tmp\exf@config@extproblems\relax%
+ \exf@writeline\exf@probfile{\@percentchar%
+ generated from file `\jobname' by exframe.sty}%
+ \ifexf@lineno\exf@writeline\exf@probfile{\exf@lineno}\fi%
+ \exf@writeline\exf@probfile{}%
+ \fi}
+% \end{macrocode}
+
+% \macro{\exf@close@probfile}
+% Close problem file (if open);
+% indicate position, close and reset variables:
+% \begin{macrocode}
+\newcommand{\exf@close@probfile}{%
+ \ifexf@probfile@open%
+ \ifexf@lineno\exf@writeline\exf@probfile{\exf@linesep}%
+ \exf@writeline\exf@probfile{\exf@lineno}\fi%
+ \exf@writeline\exf@probfile{\@backslashchar endinput}%
+ \immediate\closeout\exf@probfile%
+ \global\exf@probfile@openfalse%
+ \fi}
+% \end{macrocode}
+
+% Make sure to properly close files at the end:
+% \begin{macrocode}
+\AtEndDocument{\exf@close@solfile\exf@close@probfile}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Buffers.}
+%
+% \macro{\exf@solbuf}
+% \macro{\exf@probbuf}
+% \macro{\ifexf@solbuf@clean}
+% \macro{\ifexf@probbuf@clean}
+% Declare token buffers for storing problems and solutions
+% and conditionals indicating whether the buffers have been used:
+% \begin{macrocode}
+\newtoks\exf@solbuf
+\newtoks\exf@probbuf
+\newif\ifexf@solbuf@clean\exf@solbuf@cleantrue
+\newif\ifexf@probbuf@clean\exf@probbuf@cleantrue
+% \end{macrocode}
+% \macro{\exf@clear@solbuf}
+% \macro{\exf@clear@probbuf}
+% Clear a buffer and mark clean:
+% \begin{macrocode}
+\def\exf@clear@solbuf{\global\exf@solbuf@cleantrue\global\exf@solbuf={}}
+\def\exf@clear@probbuf{\global\exf@probbuf@cleantrue\global\exf@probbuf={}}
+% \end{macrocode}
+
+% \macro{\exf@append@buf}
+% Append tokens to buffer:
+% \begin{macrocode}
+\def\exf@append@buf#1#2{\global#1=\expandafter{\the#1#2}}
+% \end{macrocode}
+% \macro{\exf@addline}
+% Add a protected expanded line to the buffer:
+% \begin{macrocode}
+\def\exf@addline#1#2{{\protected@edef\exf@tmp{#2}%
+ \exf@exparg{\exf@append@buf#1}{\exf@tmp^^J}}}
+% \end{macrocode}
+% \macro{\exf@source@buf}
+% Source a buffer into the document:
+% \begin{macrocode}
+\def\exf@source@buf#1{\exf@exptwo\scantokens{\the#1}}
+% \end{macrocode}
+% \macro{\exf@write@buf}
+% Write the buffer into the solution file:
+% \begin{macrocode}
+\def\exf@write@buf#1#2{\exf@writeline#1{\the#2}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Verbatim Processing.}
+%
+% \macro{\exf@verbatim}
+% Start reading the buffer from the environment body:
+% \begin{macrocode}
+\newcommand{\exf@verbatim}{%
+ \begingroup%
+ \@bsphack%
+ \let\do\@makeother\dospecials%
+ \catcode`\^^M\active%
+ \def\verbatim@processline{\exf@exptwo\exf@verbatim@process%
+ {\the\verbatim@line^^J}}%
+ \verbatim@start}
+% \end{macrocode}
+
+% \macro{\exf@endverbatim}
+% Stop reading the buffer:
+% \begin{macrocode}
+\newcommand{\exf@endverbatim}{\@esphack\endgroup}
+% \end{macrocode}
+
+% \macro{\exf@scanblock}
+% Scan an optional argument from a verbatim environment;
+% allow for an empty environment and an empty first line;
+% argument |#1| is macro to be called eventually:
+% \begin{macrocode}
+\def\exf@scanblock#1{%
+% \end{macrocode}
+% Check for empty first line:
+% \begin{macrocode}
+ \@ifnextchar\par{\exf@scanblock@par{#1}}{\exf@scanblock@sel{#1}}}
+% \end{macrocode}
+% Handle empty first line, implies no optional argument:
+% \begin{macrocode}
+\long\def\exf@scanblock@par#1\par{\exf@scanblock@sel{#1}[]}
+% \end{macrocode}
+% Check for optional argument (|[|) and for environment ending (|\end|):
+% \begin{macrocode}
+\def\exf@scanblock@sel#1{\@ifnextchar[{\exf@scanblock@opt{#1}}%
+ {\@ifnextchar\end{\exf@scanblock@end{#1}}{\exf@scanblock@noopt{#1}}}}
+% \end{macrocode}
+% Handle empty environment, hopefully environment matches (otherwise?!):
+% \begin{macrocode}
+\def\exf@scanblock@end#1\end#2{%
+ \def\exf@tmp{#2}\ifx\exf@tmp\@currenvir%
+ \def\exf@verbatim{}\def\exf@endverbatim{}%
+ \fi%
+ #1{}{\scantokens{\end{#2}}}}
+% \end{macrocode}
+% Pass on without and with optional argument;
+% pass on optional argument and any token scanned prematurely:
+% \begin{macrocode}
+\def\exf@scanblock@noopt#1#2{#1{}{\scantokens#2}}
+\def\exf@scanblock@opt#1[#2]{#1{#2}{}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Points}
+% \label{sec:imp-points}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Points Arithmetic.}
+%
+% \macro{\exf@addtopoints}
+% Add points |#2|+|#3| to macro |#1| using metric register:
+% \begin{macrocode}
+\newcommand{\exf@addtopoints}[3]{%
+ \ifdefined#1\else\def#1{{0}{0}}\fi%
+ \setlength\exf@tmpdim{\expandafter\@firstoftwo#1pt}%
+ \addtolength\exf@tmpdim{#2pt}%
+ \edef\exf@tmp{\strip@pt\exf@tmpdim}%
+ \setlength\exf@tmpdim{\expandafter\@secondoftwo#1pt}%
+ \addtolength\exf@tmpdim{#3pt}%
+ \xdef#1{{\exf@tmp}{\strip@pt\exf@tmpdim}}}
+% \end{macrocode}
+%
+% \macro{\exf@pointsmismatch}
+% Execute |#3| if points disagree:
+% \begin{macrocode}
+\newcommand{\exf@pointsmismatch}[3]{%
+ \let\exf@tmp\@undefined%
+ \ifdim\expandafter\@firstoftwo#1pt=\expandafter\@firstoftwo#2pt\else%
+ \def\exf@tmp{}\fi%
+ \ifdim\expandafter\@secondoftwo#1pt=\expandafter\@secondoftwo#2pt\else%
+ \def\exf@tmp{}\fi%
+ \ifdefined\exf@tmp#3\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Points Expansion.}
+%
+% \macro{\exf@outpoints}
+% If points macro |#3| is set,
+% expand |#3|, pass on as |#1{\protect#2}#3| and clear |#3| globally:
+% \begin{macrocode}
+\def\exf@outpoints#1#2#3{\ifdefined#3%
+ \exf@exptwo\exf@outpoints@switch{#3}{#1}{#2}%
+ \global\let#3\@undefined\fi}
+\def\exf@outpoints@switch#1#2#3{#2{\protect#3#1}}
+% \end{macrocode}
+
+% \macro{\exf@scanpoints}
+% Call as |\exf@scanpoints#1|[\textit{regular}][|+|\textit{bonus}]|++&| to
+% write |{|\textit{regular}|}{|\textit{bonus}|}| into |#1|;
+% fill with 0 if empty:
+% \begin{macrocode}
+\def\exf@scanpoints#1#2+#3+#4&{%
+ \edef#1{\if&#2&0\else#2\fi}%
+ \edef#1{{#1}{\if&#3&0\else#3\fi}}}
+% \end{macrocode}
+% \macro{\exf@formatpoints}
+% Format as [|#1|][|+#2|]; remove 0 components:
+% \begin{macrocode}
+\def\exf@formatpoints#1#2{\ifdim#2pt=0pt#1\else%
+ \ifdim#1pt=0pt+#2\else#1+#2\fi\fi}
+% \end{macrocode}
+
+% \macro{\extractpoints}
+% Extract main (plain) or bonus (starred) part from saved points register:
+% \begin{macrocode}
+\newcommand{\extractpoints}{\@ifstar{\exf@extractpoints\@secondoftwo}%
+ {\exf@extractpoints\@firstoftwo}}
+\newcommand{\exf@extractpoints}[2]{\edef\exf@tmp{#2}%
+ \exf@exptwo\exf@scanpoints\exf@tmp\exf@tmp++&%
+ \expandafter#1\exf@tmp}
+% \end{macrocode}
+
+% \macro{\switchpoints}
+% Extract main (plain) and bonus (starred) part from points,
+% and execute one of three:
+% \begin{macrocode}
+\newcommand{\switchpoints}[5]{\edef\exf@tmp{#5}%
+ \exf@exptwo\exf@scanpoints\exf@tmp\exf@tmp++&%
+ \expandafter\exf@switchpoints\exf@tmp{#1}{#2}{#3}{#4}}
+\newcommand{\exf@switchpoints}[6]{%
+ \ifdim#2pt=0pt\ifdim#1pt=0pt\def\exf@tmp##1##2{#6}%
+ \else\def\exf@tmp##1##2{#3}\fi%
+ \else\ifdim#1pt=0pt\def\exf@tmp##1##2{#4}%
+ \else\def\exf@tmp##1##2{#5}\fi\fi\exf@tmp{#1}{#2}}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Tools.}
+%
+% \macro{\exf@makepointsmargin}
+% Combination to typeset points in margin:
+% \begin{macrocode}
+\newcommand{\exf@makepointsmargin}[2]{%
+ \exf@config@insertpointsmargin{\exf@config@composepointspairmargin{#1}{#2}}}
+% \end{macrocode}
+
+% \macro{\exf@warnmismatch}
+% If points |#3| and |#4| are defined and disagree,
+% issue a warning message:
+% \begin{macrocode}
+\newcommand{\exf@warnmismatch}[4]{%
+ \ifdefined#4\ifdefined#3\exf@pointsmismatch#3#4{%
+ \let\exf@tmp\PackageWarning%
+ \ifx#1\exf@solutionname\let\exf@tmp\PackageWarningNoLine\fi%
+ \exf@tmp{exframe}{points mismatch %
+ (\expandafter\exf@formatpoints#3 determined %
+ vs. \expandafter\exf@formatpoints#4 given) %
+ for #1 \csname the#2\endcsname}%
+ \ifexf@warntext\edef\exf@tmp{%
+ {\expandafter\exf@formatpoints#3}{\expandafter\exf@formatpoints#4}}%
+ \exf@exptwo\exf@config@insertwarnpoints#1\exf@tmp\fi}%
+ \fi\fi}
+% \end{macrocode}
+%
+% \macro{\exf@warnrerun}
+% If points |#3| and |#4| are defined and disagree,
+% issue advice to recompile:
+% \begin{macrocode}
+\newcommand{\exf@warnrerun}[4]{%
+ \ifdefined#4\ifdefined#3\exf@pointsmismatch#3#4{%
+ \PackageWarning{exframe}{points changed %
+ for #1 \csname the#2\endcsname; rerun to fix}%
+ \ifexf@warntext\exf@config@insertwarnpointsrerun#1\fi}%
+ \fi\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Binary Rational Numbers.}
+%
+% \macro{\exf@splitsign}
+% \macro{\exf@splitdecimal}
+% Split a decimal float number into sign, integer and fractional part:
+% \begin{macrocode}
+\def\exf@splitsign#1-#2-#3&{\def\exf@splitnum{#1#2}\def\exf@splitminus{#3}}
+\def\exf@splitdecimal#1.#2.#3&{\def\exf@splitint{#1}\def\exf@splitdec{#2}}
+% \end{macrocode}
+
+% \macro{\showfracpoints}
+% Display a float number as a fraction
+% with denominators 2, 4 or 8 when possible;
+% first split number, complete missing zeros and handle cases:
+% \begin{macrocode}
+\newcommand{\showfracpoints}[1]{%
+ \edef\exf@tmp{#1}%
+ \expandafter\exf@splitsign\exf@tmp--&%
+ \expandafter\exf@splitdecimal\exf@splitnum..&%
+ \if&\exf@splitint&\def\exf@splitint{0}\fi%
+ \if&\exf@splitdec&\def\exf@splitdec{0}\fi%
+ \def\exf@tmp{\exf@splitint.\exf@splitdec}%
+ \ifnum\exf@splitdec=0\def\exf@tmp{\exf@splitint}\fi%
+ \ifnum\exf@splitdec=5\def\exf@tmp{\exf@config@frac{\exf@splitint}{1}{2}}\fi%
+ \ifnum\exf@splitdec=25\def\exf@tmp{\exf@config@frac{\exf@splitint}{1}{4}}\fi%
+ \ifnum\exf@splitdec=75\def\exf@tmp{\exf@config@frac{\exf@splitint}{3}{4}}\fi%
+ \ifnum\exf@splitdec=125\def\exf@tmp{\exf@config@frac{\exf@splitint}{1}{8}}\fi%
+ \ifnum\exf@splitdec=375\def\exf@tmp{\exf@config@frac{\exf@splitint}{3}{8}}\fi%
+ \ifnum\exf@splitdec=625\def\exf@tmp{\exf@config@frac{\exf@splitint}{5}{8}}\fi%
+ \ifnum\exf@splitdec=875\def\exf@tmp{\exf@config@frac{\exf@splitint}{7}{8}}\fi%
+ \ifx\exf@splitminus\exf@empty\else$\exf@splitminus$\fi\exf@tmp%
+}
+% \end{macrocode}
+
+% \macro{\exf@config@frac}
+% Display a vulgar fraction
+% such as 12$^3\mskip-4mu/\mskip-2mu_4$:
+% \begin{macrocode}
+\newcommand{\exf@config@frac}[3]{%
+ \ifnum#1=0\else#1\fi%
+ \ifnum#2=0\else$%
+ ^{\exf@text{#2}}%
+ \mskip-4mu/\mskip-2mu%
+ _{\exf@text{#3}}$\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Sheet Points Code.}
+%
+% \macro{\exf@notesheetpoints}
+% Store a sheet point number in a macro:
+% \begin{macrocode}
+\newcommand{\exf@notesheetpoints}[2]{%
+ \exf@csdo\gdef{exf@sheetpoints@#1}{#2}}
+% \end{macrocode}
+% Make sure the macros in code written to the |.aux| file exist:
+% \begin{macrocode}
+\AtBeginDocument{\immediate\write\@auxout{%
+ \string\providecommand{\string\exf@notesheetpoints}[2]{}}}
+% \end{macrocode}
+% \macro{\exf@writesheetpoints}
+% Write sheet points to the |.aux| file:
+% \begin{macrocode}
+\newcommand{\exf@writesheetpoints}[2]%
+ {\immediate\write\@auxout{\string\exf@notesheetpoints{\sheettag}%
+ {\exf@formatpoints{#1}{#2}}}}
+% \end{macrocode}
+% \macro{\getsheetpoints}
+% Read points for current sheet or from |.aux| file:
+% \begin{macrocode}
+\newcommand{\getsheetpoints}[1]{\if&#1&%
+ \ifdefined\exf@sheet@points%
+ \expandafter\exf@formatpoints\exf@sheet@points\else 0\fi%
+ \else\ifcsname exf@sheetpoints@#1\endcsname%
+ \csname exf@sheetpoints@#1\endcsname\else 0\fi\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Points Code.}
+%
+% \macro{\exf@noteproblempoints}
+% Store a problem point number in a macro:
+% \begin{macrocode}
+\newcommand{\exf@noteproblempoints}[2]{%
+ \exf@csdo\gdef{exf@problempoints@#1}{#2}}
+% \end{macrocode}
+% Make sure the macros written to the |.aux| file exist:
+% \begin{macrocode}
+\AtBeginDocument{\immediate\write\@auxout{%
+ \string\providecommand{\string\exf@noteproblempoints}[2]{}}}
+% \end{macrocode}
+% \macro{\exf@writeproblempoints}
+% Write problem points to the |.aux| file:
+% \begin{macrocode}
+\newcommand{\exf@writeproblempoints}[2]%
+ {\immediate\write\@auxout{\string\exf@noteproblempoints{\problemtag}%
+ {\exf@formatpoints{#1}{#2}}}}
+% \end{macrocode}
+% \macro{\getproblempoints}
+% Read points for current problem or from |.aux| file:
+% \begin{macrocode}
+\newcommand{\getproblempoints}[1]{\if&#1&%
+ \ifdefined\exf@problem@points%
+ \expandafter\exf@formatpoints\exf@problem@points\else 0\fi%
+ \else\ifcsname exf@problempoints@#1\endcsname%
+ \csname exf@problempoints@#1\endcsname\else 0\fi\fi}
+% \end{macrocode}
+% \macro{\getsubproblempoints}
+% Read points for current subproblem:
+% \begin{macrocode}
+\newcommand{\getsubproblempoints}[1]{\if&#1&%
+ \ifdefined\exf@subproblem@points%
+ \expandafter\exf@formatpoints\exf@subproblem@points\else 0\fi%
+ \else 0\fi}
+% \end{macrocode}
+
+% \macro{\showpoints}
+% Show points within a problem or subproblem:
+% \begin{macrocode}
+\newcommand{\showpoints}{%
+ \ifdefined\exf@in@solution\exf@outpoints{\exf@ensuretext}%
+ {\exf@config@composepointspairbodysolution}{\exf@solution@points@show}%
+ \else\ifdefined\exf@in@subproblem\exf@outpoints{\exf@ensuretext}%
+ {\exf@config@composepointspairbodysubproblem}{\exf@subproblem@points@show}%
+ \else\ifdefined\exf@in@problem\exf@outpoints{\exf@ensuretext}%
+ {\exf@config@composepointspairbodyproblem}{\exf@problem@points@show}%
+ \fi\fi\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solution Points Code.}
+%
+% \macro{\exf@awardpointsalt}
+% Award points for alternative or optional solution;
+% does not count towards solution total:
+% \begin{macrocode}
+\newcommand{\exf@awardpointsalt}[2][]{\exf@scanpoints\exf@tmp#2++&%
+ \exf@exptwo\exf@ensuretext{%
+ \expandafter\exf@config@composepointspairawardalt\exf@tmp{#1}}}
+% \end{macrocode}
+% \macro{\exf@awardpointsreg}
+% Award points for regular solution;
+% counts towards solution total:
+% \begin{macrocode}
+\newcommand{\exf@awardpointsreg}[2][]{\exf@scanpoints\exf@tmp#2++&%
+ \exf@exptwo\exf@addtopoints\exf@solution@points@total\exf@tmp%
+ \exf@scanpoints\exf@tmp#2++&%
+ \exf@exptwo\exf@ensuretext{%
+ \expandafter\exf@config@composepointspairaward\exf@tmp{#1}}}
+% \end{macrocode}
+% \macro{\awardpoints}
+% Award points within solution with optional starred form:
+% \begin{macrocode}
+\newcommand{\awardpoints}{\@ifstar\exf@awardpointsalt\exf@awardpointsreg}
+% \end{macrocode}
+
+% \macro{\getsolutionpoints}
+% Read points for current solution:
+% \begin{macrocode}
+\newcommand{\getsolutionpoints}[1]{\if&#1&%
+ \ifdefined\exf@solution@points%
+ \expandafter\exf@formatpoints\exf@solution@points\else 0\fi%
+ \else 0\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Sheet Environment}
+% \label{sec:imp-sheet}
+%
+% \macro{exf@sheet}
+% Define options for |sheet| environment:
+% \begin{macrocode}
+\define@key{exf@sheet}{points}{\exf@scanpoints\exf@sheet@points#1++&}
+\define@key{exf@sheet}{number}{\setcounter{\exf@sheetcounter}{#1}}
+\define@key{exf@sheet}{label}{\def\exf@label{#1}}
+\define@key{exf@sheet}{tag}{\def\sheettag{#1}}
+% \end{macrocode}
+
+% \macro{sheet}
+% Define |sheet| environment (potentially using custom name):
+% \begin{macrocode}
+\newenvironment{\exf@sheetname}[1][]{%
+% \end{macrocode}
+% Insert hook code to clear page, step counter:
+% \begin{macrocode}
+ \exf@config@insertsheetclearpage%
+ \refstepcounter{\exf@sheetcounter}%
+% \end{macrocode}
+% Use equation counter for sheets:
+% \begin{macrocode}
+ \ifexf@style@sheetequation%
+ \exf@eqsav\value{equation}\relax%
+ \setcounter{equation}{\value{exf@sheetequation}}%
+ \let\theequation\theexf@sheetequation%
+ \let\theHequation\theHexf@sheetequation%
+ \fi%
+% \end{macrocode}
+% Reset optional arguments, process arguments:
+% \begin{macrocode}
+ \let\exf@sheet@points\@undefined%
+ \def\sheettag{\csname the\exf@sheetcounter\endcsname}%
+ \let\exf@sheet@points@total\@undefined%
+ \let\exf@label\@undefined%
+ \setkeys{exf@sheet}{#1}%
+% \end{macrocode}
+% Process automatic and manual labels:
+% \begin{macrocode}
+ \ifexf@autolabelsheet\label{\exf@config@labelsheet{\sheettag}}\fi%
+ \ifdefined\exf@label\label{\exf@label}\fi%
+% \end{macrocode}
+% Set points from explicit input or from |.aux| storage:
+% \begin{macrocode}
+ \ifdefined\exf@sheet@points%
+ \let\exf@sheet@points@given\exf@empty%
+ \else%
+ \let\exf@sheet@points@given\@undefined%
+ \ifcsname exf@sheetpoints@\sheettag\endcsname%
+ \exf@csdotwo\let\exf@tmp{exf@sheetpoints@\sheettag}%
+ \exf@exptwo\exf@scanpoints\exf@sheet@points\exf@tmp++&%
+ \fi\fi%
+% \end{macrocode}
+% Process metadata:
+% \begin{macrocode}
+ \exf@ifis\exf@metadata{sheet}{\exf@writemetadata{sheet}}%
+% \end{macrocode}
+% Insert hook code:
+% \begin{macrocode}
+ \exf@config@insertsheetbefore%
+% \end{macrocode}
+% Add table of contents line:
+% \begin{macrocode}
+ \ifx\exf@config@toclevelsheet\exf@empty\else%
+ \ifdefined\phantomsection\phantomsection\fi\fi%
+ \exf@addcontentsline{\exf@config@toclevelsheet}%
+ {\exf@config@composetocsheet{\csname the\exf@sheetcounter\endcsname}%
+ {\exf@data@sheet@rawtitle}}%
+% \end{macrocode}
+% Write sheet title:
+% \begin{macrocode}
+ \exf@config@insertsheettitle}%
+% \end{macrocode}
+% End of environment;
+% perform sanity check on total points if given explicitly:
+% \begin{macrocode}
+ {\ifdefined\exf@sheet@points@given%
+ \exf@warnmismatch{\exf@sheetname}{\exf@sheetcounter}%
+ {\exf@sheet@points@total}{\exf@sheet@points}%
+% \end{macrocode}
+% Test whether points have changed since last compile:
+% \begin{macrocode}
+ \else%
+ \exf@warnrerun{\exf@sheetname}{\exf@sheetcounter}%
+ {\exf@sheet@points@total}{\exf@sheet@points}%
+% \end{macrocode}
+% Store points:
+% \begin{macrocode}
+ \let\exf@sheet@points\exf@sheet@points@total%
+ \fi%
+% \end{macrocode}
+% Write sheet points to |.aux| file:
+% \begin{macrocode}
+ \ifdefined\exf@sheet@points%
+ \expandafter\exf@writesheetpoints\exf@sheet@points%
+ \fi%
+% \end{macrocode}
+% Insert solutions:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{sheet}{\insertsolutions}%
+% \end{macrocode}
+% Insert hook code:
+% \begin{macrocode}
+ \exf@config@insertsheetafter%
+ \exf@config@insertsheetclearpage%
+% \end{macrocode}
+% Restore original equation counter:
+% \begin{macrocode}
+ \ifexf@style@sheetequation%
+ \setcounter{exf@sheetequation}{\value{equation}}%
+ \setcounter{equation}{\exf@eqsav}%
+ \fi%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \ignorespacesafterend}
+% \end{macrocode}
+
+% \macro{\exercisecleardoublepage}
+% Clear the current page, clear even page with a totally empty page:
+% \begin{macrocode}
+\newcommand{\exercisecleardoublepage}{%
+ \clearpage\ifexf@twoside\ifodd\value{page}\else%
+ \thispagestyle{empty}\hbox{}\newpage\fi\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Problem Environment}
+% \label{sec:imp-problem}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Print Problems.}
+%
+% \macro{exf@problem}
+% Define options for |problem| environment:
+% \begin{macrocode}
+\define@key{exf@problem}{points}{\exf@scanpoints\exf@problem@points#1++&}
+\define@key{exf@problem}{label}{\def\exf@label{#1}}
+\define@key{exf@problem}{tag}{\def\problemtag{#1}}
+\define@key{exf@problem}{sollabel}{\xdef\exf@sollabel{#1}}
+% \end{macrocode}
+
+% \macro{printproblem}
+% Define |printproblem| environment:
+% \begin{macrocode}
+\newenvironment{printproblem}[1]{%
+% \end{macrocode}
+% Start with new paragraph, set text style, add vspace:
+% \begin{macrocode}
+ \par\exf@config@styletext\addvspace{\exf@config@skipproblemabove}%
+% \end{macrocode}
+% Step problem counter:
+% \begin{macrocode}
+ \refstepcounter{\exf@problemcounter}%
+% \end{macrocode}
+% Insert hook code:
+% \begin{macrocode}
+ \exf@config@insertproblembefore%
+% \end{macrocode}
+% Begin inner group, mark in problem:
+% \begin{macrocode}
+ \begingroup%
+ \def\exf@in@problem{}%
+% \end{macrocode}
+% Use equation counter for problems:
+% \begin{macrocode}
+ \ifexf@style@problemequation%
+ \exf@eqsav\value{equation}\relax%
+ \setcounter{equation}{\value{exf@problemequation}}%
+ \let\theequation\theexf@problemequation%
+ \let\theHequation\theHexf@problemequation%
+ \fi%
+% \end{macrocode}
+% Initialise variables, process arguments:
+% \begin{macrocode}
+ \exf@init@block{\exf@config@skipprobleminfo}%
+ \def\problemtag{\csname the\exf@problemcounter\endcsname}%
+ \let\exf@problem@points\@undefined%
+ \let\exf@label\@undefined%
+ \global\let\exf@sollabel\@undefined%
+ \let\exf@problem@points@total\@undefined%
+ \setkeys{exf@problem,exf@probleminfo,exf@scanproblem}{#1}%
+% \end{macrocode}
+% Process automatic and manual labels:
+% \begin{macrocode}
+ \ifexf@autolabelproblem\label{\exf@config@labelproblem{\problemtag}}\fi%
+ \ifdefined\exf@label\label{\exf@label}\fi%
+% \end{macrocode}
+% Mark for new solution section; remember problem counter, title:
+% \begin{macrocode}
+ \gdef\exf@problem@solnewsec{}%
+ \xdef\exf@prevprob{\csname the\exf@problemcounter\endcsname}%
+ \ifcsname theH\exf@problemcounter\endcsname%
+ \xdef\exf@prevprobhref{\exf@problemcounter.%
+ \csname theH\exf@problemcounter\endcsname}%
+ \fi%
+ \ifx\exf@data@problem@rawtitle\exf@empty%
+ \global\let\exf@prevprobtitle\@undefined%
+ \else%
+ \protected@xdef\exf@prevprobtitle{\exf@data@problem@rawtitle}%
+ \fi%
+ \global\let\exf@prevsubprob\@undefined%
+ \global\let\exf@prevsubprobhref\@undefined%
+% \end{macrocode}
+% Set points from explicit input or from |.aux| storage:
+% \begin{macrocode}
+ \ifdefined\exf@problem@points%
+ \let\exf@problem@points@given\exf@empty%
+ \else%
+ \let\exf@problem@points@given\@undefined%
+ \ifcsname exf@problempoints@\problemtag\endcsname%
+ \exf@csdotwo\let\exf@tmp{exf@problempoints@\problemtag}%
+ \exf@exptwo\exf@scanpoints\exf@problem@points\exf@tmp++&%
+ \fi\fi%
+ \global\let\exf@prevpoints\exf@problem@points%
+ \let\exf@problem@points@show\@undefined%
+ \ifdefined\exf@problem@points%
+ \let\exf@problem@points@show\exf@problem@points%
+ \fi%
+% \end{macrocode}
+% Disable points display if desired:
+% \begin{macrocode}
+ \exf@ifis\exf@pointsat{off}{\let\exf@problem@points@show\@undefined}%
+% \end{macrocode}
+% Display points in opening line if desired;
+% expand points into argument and remove points:
+% \begin{macrocode}
+ \exf@ifis\exf@pointsat{start}{\exf@outpoints{\exf@append@intro}%
+ {\exf@config@composepointspairstartproblem}{\exf@problem@points@show}}%
+ \exf@ifis\exf@pointsat{start*}{\exf@outpoints{\exf@prepend@intro}%
+ {\exf@config@composepointspairstartproblem}{\exf@problem@points@show}}%
+% \end{macrocode}
+% Insert hook code, set problem body style:
+% \begin{macrocode}
+ \exf@config@insertprobleminfo%
+ \exf@config@styletextproblem%
+% \end{macrocode}
+% Write title without item:
+% \begin{macrocode}
+ \ifdim\exf@config@skipproblemitem=0pt%
+ \exf@prepend@intro{{%
+ \exf@config@styletitle\exf@config@styletitleproblem%
+ \exf@config@composetitleproblem{\csname the\exf@problemcounter\endcsname}%
+ {\exf@data@problem@rawtitle}}}%
+% \end{macrocode}
+% Write item with fixed total width or item width plus space:
+% \begin{macrocode}
+ \else%
+ \ifdim\exf@config@skipproblemitem>0pt%
+ \setlength\exf@addmargin{\exf@config@skipproblemitem}%
+ \else%
+ \settowidth\exf@addmargin{%
+ \exf@config@styletitle\exf@config@styletitleproblem%
+ \exf@config@composeitemproblem{\exf@config@counterproblemmax}%
+ \exf@config@composeitemproblemsep}%
+ \fi%
+% \end{macrocode}
+% Define item label:
+% \begin{macrocode}
+ \def\exf@introitem{\makebox[0cm][r]{%
+ \exf@config@styletitle\exf@config@styletitleproblem%
+ \exf@config@composeitemproblem{\csname the\exf@problemcounter\endcsname}%
+ \exf@config@composeitemproblemsep}}%
+% \end{macrocode}
+% Compose title:
+% \begin{macrocode}
+ \ifx\exf@data@problem@rawtitle\exf@empty\else%
+ \exf@prepend@intro{{%
+ \exf@config@styletitle\exf@config@styletitleproblem%
+ \exf@config@composetitleproblem{\exf@empty}{\exf@data@problem@rawtitle}}}%
+ \fi%
+ \fi%
+% \end{macrocode}
+% Write points into margin if desired;
+% expand points into argument and remove points:
+% \begin{macrocode}
+ \exf@ifis\exf@pointsat{margin}{%
+ \exf@outpoints{\exf@prepend@def\exf@introitem}%
+ {\exf@makepointsmargin}{\exf@problem@points@show}}%
+% \end{macrocode}
+% Write out opening line:
+% \begin{macrocode}
+ \exf@open@block{\exf@config@skipproblemtitle}%
+% \end{macrocode}
+% Add table of contents line:
+% \begin{macrocode}
+ \exf@addcontentsline{\exf@config@toclevelproblem}%
+ {\exf@config@composetocproblem{\csname the\exf@problemcounter\endcsname}%
+ {\exf@data@problem@rawtitle}}%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \@afterindentfalse}%
+% \end{macrocode}
+% End environment, show points if desired:
+% \begin{macrocode}
+ {\exf@ifis\exf@pointsat{end}{\showpoints}%
+% \end{macrocode}
+% Perform sanity checks on total points if given explicitly:
+% \begin{macrocode}
+ \ifdefined\exf@problem@points@given%
+ \exf@warnmismatch{\exf@problemname}{\exf@problemcounter}%
+ {\exf@problem@points@total}{\exf@problem@points}%
+% \end{macrocode}
+% Warn if calculated total points have changed:
+% \begin{macrocode}
+ \else%
+ \exf@warnrerun{\exf@problemname}{\exf@problemcounter}%
+ {\exf@problem@points@total}{\exf@problem@points}%
+% \end{macrocode}
+% Read computed total points:
+% \begin{macrocode}
+ \let\exf@problem@points\exf@problem@points@total%
+ \fi%
+% \end{macrocode}
+% Write points to |.aux| file; add to sheet total:
+% \begin{macrocode}
+ \ifdefined\exf@problem@points%
+ \expandafter\exf@writeproblempoints\exf@problem@points%
+ \exf@exptwo\exf@addtopoints\exf@sheet@points@total\exf@problem@points%
+ \fi%
+ \ifdefined\exf@problem@points\else\ifdefined\exf@sheet@points@total%
+ \PackageWarning{exframe}{no points defined for \exf@problemname}%
+ \fi\fi%
+% \end{macrocode}
+% Solutions to subproblems must be declared within problem environment:
+% \begin{macrocode}
+ \global\let\exf@prevsubprob\@undefined%
+ \global\let\exf@prevsubprobhref\@undefined%
+% \end{macrocode}
+% End paragraph and environment:
+% \begin{macrocode}
+ \par\exf@close@block%
+% \end{macrocode}
+% Display solution if desired:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{problem}{%
+ \exf@config@insertproblemsolution%
+ \exf@showsolutions{\exf@config@composetitlesolutionmulti}{}}%
+% \end{macrocode}
+% Restore original equation counter:
+% \begin{macrocode}
+ \ifexf@style@problemequation%
+ \setcounter{exf@problemequation}{\value{equation}}%
+ \setcounter{equation}{\exf@eqsav}%
+ \fi%
+% \end{macrocode}
+% End inner group:
+% \begin{macrocode}
+ \endgroup%
+% \end{macrocode}
+% Insert hook code, vertical skip:
+% \begin{macrocode}
+ \exf@config@insertproblemafter%
+ \addvspace{\exf@config@skipproblembelow}%
+% \end{macrocode}
+% Display solution if desired:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{problem*}{%
+ \exf@showsolutions{\exf@config@composetitlesolutionmulti}{}}%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \ignorespacesafterend}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Read Problem Environment.}
+%
+% \macro{exf@scanproblem}
+% Define options for |problem| environment:
+% \begin{macrocode}
+\define@boolkey{exf@scanproblem}[exf@scanproblem@]{disable}[true]{}
+% \end{macrocode}
+
+% \macro{exf@problem@direct}
+% Define direct output version of |problem| environment;
+% pass on to |printproblem| environment:
+% \begin{macrocode}
+\newenvironment{exf@problem@direct}[1][]%
+ {\printproblem{#1}}{\endprintproblem\ignorespacesafterend}
+% \end{macrocode}
+
+% \macro{exf@problem@scan}
+% \macro{exf@scanproblem}
+% Define scan version of |problem| environment;
+% use |\exf@scanblock| to properly parse optional argument
+% and pass on to |exf@scanproblem|:
+% \begin{macrocode}
+\newenvironment{exf@problem@scan}%
+ {\exf@scanblock{\exf@scanproblem}}{\endexf@scanproblem}%
+\newenvironment{exf@scanproblem}[2]{%
+% \end{macrocode}
+% Determine problem display:
+% \begin{macrocode}
+ \exf@scanproblem@disablefalse%
+ \setkeys*{exf@scanproblem}{#1}%
+ \exf@config@insertproblemselect{#1}%
+% \end{macrocode}
+% Write separator and |printproblem| environment to buffer:
+% \begin{macrocode}
+ \ifexf@scanproblem@disable%
+ \def\exf@verbatim@process{\@gobble}%
+ \else%
+ \ifexf@lineno\exf@addline\exf@probbuf{\exf@linesep}%
+ \exf@addline\exf@probbuf{\exf@lineno}\fi%
+ \exf@addline\exf@probbuf%
+ {\@backslashchar begin{printproblem}{#1}}%
+ \def\exf@verbatim@process{\exf@append@buf\exf@probbuf}%
+ \fi%
+% \end{macrocode}
+% Start verbatim processing:
+% \begin{macrocode}
+ \exf@verbatim#2}%
+% \end{macrocode}
+% End verbatim processing; close |printproblem| environment:
+% \begin{macrocode}
+ {\exf@endverbatim%
+ \ifexf@scanproblem@disable\else%
+ \exf@addline\exf@probbuf{\@backslashchar end{printproblem}}%
+ \global\exf@probbuf@cleanfalse%
+ \fi%
+% \end{macrocode}
+% Write buffer to file if output file open:
+% \begin{macrocode}
+ \ifexf@probfile@open%
+ \exf@write@buf\exf@probfile\exf@probbuf%
+ \exf@clear@probbuf%
+ \fi%
+% \end{macrocode}
+% Output buffer immediately:
+% \begin{macrocode}
+ \ifexf@problemmanual\else%
+ \exf@source@buf\exf@probbuf%
+ \exf@clear@probbuf%
+ \fi%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \ignorespacesafterend}
+% \end{macrocode}
+
+% \macro{problem}
+% Define |problem| environment
+% (potentially using custom name)
+% to choose between direct and buffered version:
+% \begin{macrocode}
+\newenvironment{\exf@problemname}%
+ {\ifexf@problembuf\let\exf@tmp\exf@problem@scan%
+ \else\let\exf@tmp\exf@problem@direct\fi%
+ \exf@tmp}%
+ {\ifexf@problembuf\let\exf@tmp\endexf@problem@scan%
+ \else\let\exf@tmp\endexf@problem@direct\fi%
+ \exf@tmp}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Problem Blocks}
+% \label{sec:imp-problems}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problem Block Handling.}
+%
+% \macro{\exf@problemstitle}
+% Compose the title for a problem block section:
+% \begin{macrocode}
+\newcommand{\exf@problemstitle}{%
+% \end{macrocode}
+% Check whether title is empty:
+% \begin{macrocode}
+ \protected@edef\exf@problemstitleexp{\exf@config@composetitleproblems}%
+ \ifx\exf@problemstitleexp\exf@empty\else%
+% \end{macrocode}
+% Output section line:
+% \begin{macrocode}
+ \exf@section{\exf@config@skipproblemstitle}%
+ {\exf@config@styletitle\exf@config@styletitleproblems%
+ \exf@problemstitleexp}%
+ \exf@addcontentsline{\exf@config@toclevelproblems}%
+ {\exf@config@composetocproblems}%
+ \fi}
+% \end{macrocode}
+
+% \macro{\exf@showproblemsin}
+% Output problem block intro:
+% \begin{macrocode}
+\newcommand{\exf@showproblemsin}{%
+% \end{macrocode}
+% Set problem body style; add vertical space; insert hook code:
+% \begin{macrocode}
+ \par\exf@config@styletext\addvspace{\exf@config@skipproblemsabove}%
+ \exf@config@insertproblemsbefore}
+% \end{macrocode}
+
+% \macro{\exf@showproblemsout}
+% Output problem block outro:
+% \begin{macrocode}
+\newcommand{\exf@showproblemsout}{%
+% \end{macrocode}
+% Insert hook code; close paragraph; add vertical space:
+% \begin{macrocode}
+ \exf@config@insertproblemsafter%
+ \par\exf@config@styletext\addvspace{\exf@config@skipproblemsbelow}}
+% \end{macrocode}
+
+% \macro{\exf@showproblems}
+% Output problem block in buffer:
+% \begin{macrocode}
+\newcommand{\exf@showproblems}{%
+% \end{macrocode}
+% Do nothing if buffer is empty (avoid titles):
+% \begin{macrocode}
+ \ifexf@probbuf@clean\else\begingroup%
+% \end{macrocode}
+% Execute output problem block intro:
+% \begin{macrocode}
+ \exf@showproblemsin%
+ \exf@problemstitle%
+% \end{macrocode}
+% Source and clear buffer:
+% \begin{macrocode}
+ \exf@source@buf\exf@probbuf%
+ \exf@clear@probbuf%
+% \end{macrocode}
+% Execute output problem block outro:
+% \begin{macrocode}
+ \exf@showproblemsout%
+ \endgroup\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Problems Buffer Interface.}
+%
+% \macro{\writeproblems}
+% Open a file |#1.prb| for writing problems;
+% default is present main file name:
+% \begin{macrocode}
+\newcommand{\writeproblems}[1][\jobname]{%
+ \exf@close@probfile\exf@start@probfile{#1}}
+% \end{macrocode}
+
+% \macro{\closeproblems}
+% Close problems output file (if open):
+% \begin{macrocode}
+\newcommand{\closeproblems}{\exf@close@probfile}
+% \end{macrocode}
+
+% \macro{\readproblems}
+% Read problems from file |#1.prb|;
+% default is present main file name;
+% switch layout and add heading:
+% \begin{macrocode}
+\newcommand{\readproblems}[1][\jobname]{\exf@close@probfile%
+ \begingroup%
+ \exf@config@styletext\exf@config@styletextproblem%
+ \exf@problemstitle%
+ \input{#1\exf@config@extproblems}%
+ \endgroup}
+% \end{macrocode}
+
+% \macro{\insertproblems}
+% Show problems buffer:
+% \begin{macrocode}
+\newcommand{\insertproblems}{\exf@showproblems}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Subproblem Environment}
+% \label{sec:imp-subproblem}
+%
+% \macro{exf@subproblem}
+% Define options for |subproblem| environment:
+% \begin{macrocode}
+\define@key{exf@subproblem}{points}{\exf@scanpoints\exf@subproblem@points#1++&}
+\define@key{exf@subproblem}{label}{\def\exf@label{#1}}
+% \end{macrocode}
+
+% \macro{subproblem}
+% Define |subproblem| environment (potentially using custom name):
+% \begin{macrocode}
+\newenvironment{\exf@subproblemname}[1][]{%
+% \end{macrocode}
+% Start with new paragraph, set text style, add vspace and step counter:
+% \begin{macrocode}
+ \par{\exf@config@styletext\addvspace{\exf@config@skipsubproblemabove}}%
+ \refstepcounter{\exf@subproblemcounter}%
+% \end{macrocode}
+% Insert hook code:
+% \begin{macrocode}
+ \exf@config@insertsubproblembefore%
+% \end{macrocode}
+% Start inner group, mark in subproblem:
+% \begin{macrocode}
+ \begingroup%
+ \def\exf@in@subproblem{}%
+% \end{macrocode}
+% Initialise variables, process arguments:
+% \begin{macrocode}
+ \exf@init@block{\exf@config@skipsubprobleminfo}%
+ \let\exf@subproblem@points\@undefined%
+ \let\exf@label\@undefined%
+ \setkeys{exf@subproblem,exf@probleminfo}{#1}%
+% \end{macrocode}
+% Process manual label:
+% \begin{macrocode}
+ \ifdefined\exf@label\label{\exf@label}\fi%
+% \end{macrocode}
+% Remember subproblem counter for solution:
+% \begin{macrocode}
+ \xdef\exf@prevsubprob{\csname the\exf@subproblemcounter\endcsname}%
+ \ifcsname theH\exf@subproblemcounter\endcsname%
+ \xdef\exf@prevsubprobhref{\exf@subproblemcounter.%
+ \csname theH\exf@subproblemcounter\endcsname}%
+ \fi%
+% \end{macrocode}
+% Remeber points for display;
+% disable points display if desired:
+% \begin{macrocode}
+ \let\exf@subproblem@points@show\@undefined%
+ \ifdefined\exf@subproblem@points%
+ \let\exf@subproblem@points@show\exf@subproblem@points\fi%
+ \exf@ifis\exf@subpointsat{off}{\let\exf@subproblem@points@show\@undefined}%
+% \end{macrocode}
+% Add given points to problem total:
+% \begin{macrocode}
+ \ifdefined\exf@subproblem@points%
+ \global\let\exf@prevpoints\exf@subproblem@points%
+ \exf@exptwo\exf@addtopoints\exf@problem@points@total\exf@subproblem@points%
+% \end{macrocode}
+% Warn if no points given for present subproblem but previously:
+% \begin{macrocode}
+ \else%
+ \ifdefined\exf@problem@points@total%
+ \PackageWarning{exframe}{no points defined for \exf@subproblemname}%
+ \fi%
+ \fi%
+% \end{macrocode}
+% Display points in opening line if desired;
+% expand points into argument and remove points:
+% \begin{macrocode}
+ \exf@ifis\exf@subpointsat{start}{\exf@outpoints{\exf@append@intro}%
+ {\exf@config@composepointspairstartsubproblem}{\exf@subproblem@points@show}}%
+ \exf@ifis\exf@subpointsat{start*}{\exf@outpoints{\exf@prepend@intro}%
+ {\exf@config@composepointspairstartsubproblem}{\exf@subproblem@points@show}}%
+% \end{macrocode}
+% Insert hook code:
+% \begin{macrocode}
+ \exf@config@insertsubprobleminfo%
+% \end{macrocode}
+% Write opening line without item:
+% \begin{macrocode}
+ \ifdim\exf@config@skipsubproblemitem=0pt%
+ \exf@prepend@intro{{%
+ \exf@config@styletitle\exf@config@styletitlesubproblem%
+ \exf@config@composetitlesubproblem{%
+ \csname the\exf@subproblemcounter\endcsname}}}%
+% \end{macrocode}
+% Write item with fixed total width or item width plus space:
+% \begin{macrocode}
+ \else%
+ \ifdim\exf@config@skipsubproblemitem>0pt%
+ \setlength\exf@addmargin{\exf@config@skipsubproblemitem}%
+ \else%
+ \settowidth\exf@addmargin{%
+ \exf@config@styletitle\exf@config@styletitlesubproblem%
+ \exf@config@composeitemsubproblem{\exf@config@countersubproblemmax}%
+ \exf@config@composeitemsubproblemsep}%
+ \fi%
+% \end{macrocode}
+% Define item label:
+% \begin{macrocode}
+ \def\exf@introitem{\makebox[0cm][r]{%
+ \exf@config@styletitle\exf@config@styletitlesubproblem%
+ \exf@config@composeitemsubproblem%
+ {\csname the\exf@subproblemcounter\endcsname}%
+ \exf@config@composeitemsubproblemsep}}%
+ \fi%
+% \end{macrocode}
+% Write points into margin if desired;
+% expand points into argument and remove points:
+% \begin{macrocode}
+ \exf@ifis\exf@subpointsat{margin}{%
+ \exf@outpoints{\exf@prepend@def\exf@introitem}%
+ {\exf@makepointsmargin}{\exf@subproblem@points@show}}%
+% \end{macrocode}
+% Write out opening line:
+% \begin{macrocode}
+ \exf@open@block{\exf@config@skipsubproblemtitle}%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \@afterindentfalse}%
+% \end{macrocode}
+% End environment, show points if desired:
+% \begin{macrocode}
+ {\exf@ifis\exf@subpointsat{end}{\showpoints}%
+% \end{macrocode}
+% End paragraph and environment:
+% \begin{macrocode}
+ \par\exf@close@block%
+% \end{macrocode}
+% Display solution if desired:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{subproblem*}{%
+ \exf@config@insertsubproblemsolution%
+ \exf@showsolutions{\exf@config@composetitlesolutionsingle}{}}%
+% \end{macrocode}
+% End inner group:
+% \begin{macrocode}
+ \endgroup%
+% \end{macrocode}
+% Insert hook code, vertical skip:
+% \begin{macrocode}
+ \exf@config@insertsubproblemafter%
+ {\exf@config@styletext\addvspace{\exf@config@skipsubproblembelow}}%
+% \end{macrocode}
+% Display solution if desired:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{subproblem}{%
+ \exf@showsolutions{\exf@config@composetitlesolutionsingle}{}}%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \ignorespacesafterend}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Solution Environment}
+% \label{sec:imp-solution}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Print Solutions.}
+%
+% \macro{exf@solution}
+% Define options for |solution| environment:
+% \begin{macrocode}
+\define@key{exf@solution}{prob}{\def\exf@solprob{#1}}
+\define@key{exf@solution}{subprob}{\def\exf@solsubprob{#1}}
+\define@key{exf@solution}{problemtag}{\def\problemtag{#1}}
+\define@key{exf@solution}{sheettag}{\def\sheettag{#1}}
+\define@key{exf@solution}{href}{\def\exf@solhref{#1}}
+\define@key{exf@solution}{label}{\def\exf@label{#1}}
+\define@key{exf@solution}{points}{\exf@scanpoints\exf@solution@points#1++&}
+\define@key{exf@solution}{probtitle}{\def\exf@solprobtitle{#1}}
+% \end{macrocode}
+
+% \macro{printsolution}
+% Define |printsolution| environment
+% to display a previously read |solution| environment;
+% this works analogously to |problem| and |subproblem|:
+% \begin{macrocode}
+\newenvironment{printsolution}[1]{%
+% \end{macrocode}
+% Start new paragraph, add vertical space:
+% \begin{macrocode}
+ \par{\exf@config@styletext\addvspace{\exf@config@skipsolutionabove}}%
+% \end{macrocode}
+% Insert hook code:
+% \begin{macrocode}
+ \exf@config@insertsolutionbefore%
+% \end{macrocode}
+% Use equation counter for solutions:
+% \begin{macrocode}
+ \ifexf@style@solutionequation%
+ \exf@eqsav\value{equation}\relax%
+ \setcounter{equation}{\value{exf@solutionequation}}%
+ \let\theequation\theexf@solutionequation%
+ \let\theHequation\theHexf@solutionequation%
+ \fi%
+% \end{macrocode}
+% Start a group, initialise variables, process arguments:
+% \begin{macrocode}
+ \begingroup%
+ \def\exf@in@solution{}%
+ \def\exf@solprob{}%
+ \def\exf@solsubprob{}%
+ \let\exf@label\@undefined%
+ \let\exf@solution@points\@undefined%
+ \let\exf@solution@points@total\@undefined%
+ \def\exf@solhref{}%
+ \exf@init@block{\exf@config@skipsolutioninfo}%
+ \setkeys{exf@solution,exf@probleminfo}{#1}%
+% \end{macrocode}
+% Set solution counter to reflect associated problem:
+% \begin{macrocode}
+ \exf@csdo\def{the\exf@solutioncounter}%
+ {\exf@config@composeitemsolutionlabel{\exf@solprob}{\exf@solsubprob}}%
+ \refstepcounter{\exf@solutioncounter}%
+% \end{macrocode}
+% Set label:
+% \begin{macrocode}
+ \ifdefined\exf@label\label{\exf@label}\fi%
+% \end{macrocode}
+% Remeber points for display;
+% disable points display if desired:
+% \begin{macrocode}
+ \let\exf@solution@points@show\@undefined%
+ \ifdefined\exf@solution@points%
+ \let\exf@solution@points@show\exf@solution@points\fi%
+ \exf@ifis\exf@solpointsat{off}{\let\exf@solution@points@show\@undefined}%
+% \end{macrocode}
+% Display points in opening line if desired;
+% expand points into argument and remove points:
+% \begin{macrocode}
+ \exf@ifis\exf@solpointsat{start}{\exf@outpoints{\exf@append@intro}%
+ {\exf@config@composepointspairstartsolution}{\exf@solution@points@show}}%
+ \exf@ifis\exf@solpointsat{start*}{\exf@outpoints{\exf@prepend@intro}%
+ {\exf@config@composepointspairstartsolution}{\exf@solution@points@show}}%
+% \end{macrocode}
+% Insert hook code, set solution body style:
+% \begin{macrocode}
+ \exf@config@insertsolutioninfo%
+ \exf@config@styletext\exf@config@styletextsolution%
+% \end{macrocode}
+% Determine solution for problem or subproblem:
+% \begin{macrocode}
+ \ifx\exf@solsubprob\exf@empty%
+ \let\exf@tmp\exf@config@skipsolutionitem%
+ \else%
+ \let\exf@tmp\exf@config@skipsolutionitemsub%
+ \fi%
+% \end{macrocode}
+% Write title without item:
+% \begin{macrocode}
+ \ifdim\exf@tmp=0pt%
+ \protected@edef\exf@solution@title{%
+ \exf@composetitle{\exf@solprob}{\exf@solsubprob}}%
+ \ifx\exf@solution@title\exf@empty\else%
+ \exf@prepend@intro{{%
+ \exf@config@styletitle\exf@config@styletitlesolution%
+ \ifexf@solutionhref\exf@href{\exf@solhref}%
+ {\exf@solution@title}\else\exf@solution@title\fi}}%
+ \fi%
+% \end{macrocode}
+% Write item with fixed total width or item width plus space:
+% \begin{macrocode}
+ \else%
+ \ifdim\exf@tmp>0pt%
+ \setlength\exf@addmargin{\exf@tmp}%
+ \else%
+ \settowidth\exf@addmargin{%
+ \exf@config@styletitle\exf@config@styletitlesolution%
+ \ifx\exf@solsubprob\exf@empty%
+ \exf@config@composeitemsolution{\exf@config@counterproblemmax}%
+ {\exf@config@countersubproblemmax}%
+ \else%
+ \exf@config@composeitemsolutionsub{\exf@config@counterproblemmax}%
+ {\exf@config@countersubproblemmax}%
+ \fi\exf@config@composeitemsolutionsep}%
+ \fi%
+% \end{macrocode}
+% Set item label depending on problem or subproblem:
+% \begin{macrocode}
+ \ifx\exf@solsubprob\exf@empty%
+ \protected@edef\exf@solution@item%
+ {\exf@config@composeitemsolution{\exf@solprob}{\exf@empty}}%
+ \else%
+ \protected@edef\exf@solution@item%
+ {\exf@config@composeitemsolutionsub{\exf@solprob}{\exf@solsubprob}}%
+ \fi%
+% \end{macrocode}
+% Define item label:
+% \begin{macrocode}
+ \def\exf@introitem{\makebox[0cm][r]{%
+ \exf@config@styletitle\exf@config@styletitlesubproblem%
+ \ifexf@solutionhref\exf@href{\exf@solhref}{\exf@solution@item}%
+ \else\exf@solution@item\fi%
+ \exf@config@composeitemproblemsep}}%
+ \fi%
+% \end{macrocode}
+% Write points into margin if desired;
+% expand points into argument and remove points:
+% \begin{macrocode}
+ \exf@ifis\exf@solpointsat{margin}{%
+ \exf@outpoints{\exf@prepend@def\exf@introitem}%
+ {\exf@makepointsmargin}{\exf@solution@points@show}}%
+% \end{macrocode}
+% Write out opening line:
+% \begin{macrocode}
+ \exf@open@block{\exf@config@skipsolutiontitle}%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \@afterindentfalse}%
+% \end{macrocode}
+% End environment, show points if desired, perform sanity check:
+% \begin{macrocode}
+ {\exf@ifis\exf@solpointsat{end}{\showpoints}%
+ \exf@warnmismatch{\exf@solutionname}{\exf@solutioncounter}%
+ {\exf@solution@points@total}{\exf@solution@points}%
+% \end{macrocode}
+% End paragraph and envionment:
+% \begin{macrocode}
+ \par\exf@close@block%
+% \end{macrocode}
+% Restore original equation counter:
+% \begin{macrocode}
+ \ifexf@style@solutionequation%
+ \setcounter{exf@solutionequation}{\value{equation}}%
+ \setcounter{equation}{\exf@eqsav}%
+ \fi%
+% \end{macrocode}
+% End inner group:
+% \begin{macrocode}
+ \endgroup%
+% \end{macrocode}
+% Vertical skip, insert hook code:
+% \begin{macrocode}
+ {\exf@config@styletext\addvspace{\exf@config@skipsolutionbelow}}%
+ \exf@config@insertsolutionafter%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \ignorespacesafterend}
+% \end{macrocode}
+
+% \macro{\solutionssection}
+% Define a section for a problem within a solution block:
+% \begin{macrocode}
+\newcommand{\solutionssection}[1]{\begingroup%
+% \end{macrocode}
+% Initialise variables, process arguments:
+% \begin{macrocode}
+ \def\exf@solprob{}%
+ \def\exf@solsubprob{}%
+ \def\exf@solprobtitle{}%
+ \let\exf@label\@undefined%
+ \let\exf@solhref\@undefined%
+ \setkeys{exf@solution}{#1}%
+% \end{macrocode}
+% Select title (and table of contents entry)
+% corresponding to multiple problems vs.\ single problem:
+% \begin{macrocode}
+ \let\exf@composetitle\exf@config@composetitlesolutionsproblemmulti%
+ \exf@ifis\exf@solutionbelow{problem}{\let\exf@composetitle%
+ \exf@config@composetitlesolutionsproblemsingle}%
+ \exf@ifis\exf@solutionbelow{problem*}{\let\exf@composetitle%
+ \exf@config@composetitlesolutionsproblemsingle}%
+ \def\exf@solutionstoc{\exf@addcontentsline{\exf@config@toclevelsolution}%
+ {\exf@config@composetocsolution{\exf@solprob}{\exf@solprobtitle}}}%
+% \end{macrocode}
+% Write section line:
+% \begin{macrocode}
+ \addvspace{\exf@config@skipsolutionsproblemabove}%
+ \exf@solutionssection{\exf@config@styletitlesolutionsproblem}%
+ {\exf@composetitle{\exf@solprob}{\exf@solprobtitle}}%
+ {\exf@config@skipsolutionsproblemtitle}%
+ {\exf@solutionstoc}{\exf@label}{\exf@solhref}%
+ \endgroup}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Read Solution Environment.}
+%
+% \macro{\exf@process@solnewsec}
+% If this is the first solution within a new section,
+% write section heading to buffer:
+% \begin{macrocode}
+\newcommand{\exf@process@solnewsec}{%
+ \ifdefined\exf@problem@solnewsec%
+ \def\exf@probarg{\ifdefined\exf@prevprob prob={\exf@prevprob}\fi%
+ \ifdefined\exf@prevprobtitle,probtitle={\exf@prevprobtitle}\fi%
+ \ifdefined\exf@prevprobhref,href={\exf@prevprobhref}\fi%
+ \ifdefined\exf@sollabel,label={\exf@sollabel}\fi}%
+ \exf@ifis\exf@solutionbelow{here}{\let\exf@probarg\@undefined}%
+ \exf@ifis\exf@solutionbelow{subproblem}{\let\exf@probarg\@undefined}%
+ \exf@ifis\exf@solutionbelow{subproblem*}{\let\exf@probarg\@undefined}%
+ \ifdefined\exf@probarg%
+ \ifexf@lineno\exf@addline\exf@solbuf{\exf@linesep}%
+ \exf@addline\exf@solbuf{\exf@lineno}\fi%
+ \exf@addline\exf@solbuf{\@backslashchar solutionssection{\exf@probarg}}%
+ \exf@addline\exf@solbuf{}%
+ \fi%
+ \global\let\exf@problem@solnewsec\@undefined%
+ \fi}%
+% \end{macrocode}
+
+% \macro{\exf@process@solnewsec}
+% Declare additional arguments to |printsolution|
+% to describe corresponding problem and tags:
+% \begin{macrocode}
+\newcommand{\exf@generate@solprobarg}{%
+ \edef\exf@solprobarg{%
+ \ifdefined\exf@prevprob prob={\exf@prevprob},\fi%
+ \ifdefined\exf@prevsubprob subprob={\exf@prevsubprob},%
+ \ifdefined\exf@prevsubprobhref href={\exf@prevsubprobhref},\fi%
+ \else%
+ \ifdefined\exf@prevprobhref href={\exf@prevprobhref},\fi%
+ \fi%
+ \ifdefined\exf@prevpoints points=%
+ {\expandafter\exf@formatpoints\exf@prevpoints},\fi%
+ \ifdefined\sheettag sheettag={\sheettag},\fi%
+ \ifdefined\problemtag problemtag={\problemtag},\fi}%
+% \end{macrocode}
+% Clean up:
+% \begin{macrocode}
+ \global\let\exf@prevsubprob\@undefined%
+ \global\let\exf@prevsubprobhref\@undefined%
+ \global\let\exf@prevpoints\@undefined}%
+% \end{macrocode}
+
+% \macro{exf@solution@direct}
+% Define direct output version of |solution| environment;
+% pass on to |printsolution| environment:
+% \begin{macrocode}
+\newenvironment{exf@solution@direct}[1][]%
+ {\showpoints%
+ \global\let\exf@problem@solnewsec\@undefined%
+ \exf@generate@solprobarg%
+ \exf@showsolutionsin%
+ \let\exf@composetitle\exf@config@composetitlesolutionsingle%
+ \exf@exptwo\printsolution{\exf@solprobarg#1}}%
+ {\endprintsolution%
+ \exf@showsolutionsout%
+ \ignorespacesafterend}%
+% \end{macrocode}
+
+% \macro{exf@solution@scan}
+% \macro{exf@scansolution}
+% Define scan version of |solution| environment;
+% use |\exf@scanblock| to properly parse optional argument
+% and pass on to |exf@scansolution|:
+% \begin{macrocode}
+\newenvironment{exf@solution@scan}%
+ {\exf@scanblock{\exf@scansolution}}{\endexf@scansolution}%
+\newenvironment{exf@scansolution}[2]{%
+% \end{macrocode}
+% If solution is to be displayed immediately,
+% make sure to display points first;
+% insert solution section heading in buffer;
+% compose additional arguments to |printsolution|:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{here}{\showpoints}%
+ \exf@process@solnewsec%
+ \exf@generate@solprobarg%
+% \end{macrocode}
+% Write separator and |printsolution| environment to buffer:
+% \begin{macrocode}
+ \ifexf@lineno\exf@addline\exf@solbuf{\exf@linesep}%
+ \exf@addline\exf@solbuf{\exf@lineno}\fi%
+ \exf@addline\exf@solbuf%
+ {\@backslashchar begin{printsolution}{\exf@solprobarg#1}}%
+% \end{macrocode}
+% Start verbatim processing:
+% \begin{macrocode}
+ \def\exf@verbatim@process{\exf@append@buf\exf@solbuf}%
+ \exf@verbatim#2}%
+% \end{macrocode}
+% End verbatim processing; close |printsolution| environment:
+% \begin{macrocode}
+ {\exf@endverbatim%
+ \exf@addline\exf@solbuf{\@backslashchar end{printsolution}}%
+ \global\exf@solbuf@cleanfalse%
+% \end{macrocode}
+% Write buffer to file if output file open:
+% \begin{macrocode}
+ \ifexf@solfile@open%
+ \exf@write@buf\exf@solfile\exf@solbuf%
+ \exf@clear@solbuf%
+ \fi%
+% \end{macrocode}
+% Drop buffer if solutions not to be displayed:
+% \begin{macrocode}
+ \ifsolutions\else\exf@clear@solbuf\fi%
+% \end{macrocode}
+% Display solution immediately in various cases:
+% \begin{macrocode}
+ \exf@ifis\exf@solutionbelow{here}{\exf@showsolutions%
+ {\exf@config@composetitlesolutionsingle}{}}%
+ \ifdefined\exf@in@subproblem\else%
+ \exf@ifis\exf@solutionbelow{subproblem}{%
+ \exf@showsolutions{\exf@config@composetitlesolutionsingle}{}}%
+ \exf@ifis\exf@solutionbelow{subproblem*}{%
+ \exf@showsolutions{\exf@config@composetitlesolutionsingle}{}}\fi%
+ \ifdefined\exf@in@problem\else%
+ \exf@ifis\exf@solutionbelow{problem}{%
+ \exf@showsolutions{\exf@config@composetitlesolutionmulti}{}}%
+ \exf@ifis\exf@solutionbelow{problem*}{%
+ \exf@showsolutions{\exf@config@composetitlesolutionmulti}{}}\fi%
+% \end{macrocode}
+% Done:
+% \begin{macrocode}
+ \ignorespacesafterend}
+% \end{macrocode}
+
+% \macro{solution}
+% Define |solution| environment
+% (potentially using custom name)
+% to choose between direct and buffered version:
+% \begin{macrocode}
+\newenvironment{\exf@solutionname}%
+ {\ifexf@solutionbuf\let\exf@tmp\exf@solution@scan%
+ \else\let\exf@tmp\exf@solution@direct\fi%
+ \exf@tmp}%
+ {\ifexf@solutionbuf\let\exf@tmp\endexf@solution@scan%
+ \else\let\exf@tmp\endexf@solution@direct\fi%
+ \exf@tmp}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \subsection{Solution Blocks}
+% \label{sec:imp-solutions}
+%
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solution Block Handling.}
+%
+% \macro{\exf@solutionssection}
+% Output solution block section:
+% \begin{macrocode}
+\newcommand{\exf@solutionssection}[6]{%
+% \end{macrocode}
+% Check whether title is empty:
+% \begin{macrocode}
+ \protected@edef\exf@solutionstitleexp{#2}%
+ \ifx\exf@solutionstitleexp\exf@empty\else%
+% \end{macrocode}
+% Define a label:
+% \begin{macrocode}
+ \ifdefined#5%
+ \exf@csdo\def{the\exf@solutioncounter}%
+ {\exf@config@composeitemsolutionlabel{\exf@solprob}{\exf@solsubprob}}%
+ \refstepcounter{\exf@solutioncounter}\label{#5}%
+ \fi%
+% \end{macrocode}
+% Output section line:
+% \begin{macrocode}
+ \exf@section{#3}{\exf@config@styletitle\exf@config@styletitlesolution#1%
+ \ifexf@solutionhref\exf@href{#6}{\exf@solutionstitleexp}%
+ \else\exf@solutionstitleexp\fi}#4%
+ \fi}
+% \end{macrocode}
+
+% \macro{\exf@solutionstitle}
+% Compose the title for a solution block:
+% \begin{macrocode}
+\newcommand{\exf@solutionstitle}{\exf@solutionssection%
+ {\exf@config@styletitlesolutions}{%
+ \exf@config@composetitlesolutions}{\exf@config@skipsolutionstitle}%
+ {\exf@addcontentsline{\exf@config@toclevelsolutions}%
+ {\exf@config@composetocsolutions}}{\@undefined}{\@undefined}}
+% \end{macrocode}
+
+% \macro{\exf@showsolutionsin}
+% Output solution block intro:
+% \begin{macrocode}
+\newcommand{\exf@showsolutionsin}{%
+% \end{macrocode}
+% Set solution body style; add vertical space; insert hook code:
+% \begin{macrocode}
+ \par\exf@config@styletext\addvspace{\exf@config@skipsolutionsabove}%
+ \exf@config@styletextsolution%
+ \exf@config@insertsolutionsbefore}
+% \end{macrocode}
+
+% \macro{\exf@showsolutionsout}
+% Output solution block outro:
+% \begin{macrocode}
+\newcommand{\exf@showsolutionsout}{%
+% \end{macrocode}
+% Insert hook code; close paragraph; add vertical space:
+% \begin{macrocode}
+ \exf@config@insertsolutionsafter%
+ \par\exf@config@styletext\addvspace{\exf@config@skipsolutionsbelow}}
+% \end{macrocode}
+
+% \macro{\exf@showsolutions}
+% Output solution block in buffer:
+% \begin{macrocode}
+\newcommand{\exf@showsolutions}[2]{%
+% \end{macrocode}
+% Do nothing if buffer is empty (avoid titles):
+% \begin{macrocode}
+ \ifexf@solbuf@clean\else\begingroup%
+% \end{macrocode}
+% Execute output solution block intro:
+% \begin{macrocode}
+ \exf@showsolutionsin%
+ \let\exf@composetitle#1%
+ #2%
+% \end{macrocode}
+% Source and clear buffer:
+% \begin{macrocode}
+ \exf@source@buf\exf@solbuf%
+ \exf@clear@solbuf%
+% \end{macrocode}
+% Execute output solution block outro:
+% \begin{macrocode}
+ \exf@showsolutionsout%
+ \endgroup\fi}
+% \end{macrocode}
+
+% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% \paragraph{Solutions Buffer Interface.}
+%
+% \macro{\writesolutions}
+% Open a file |#1.sol| for writing solutions;
+% default is present main file name:
+% \begin{macrocode}
+\newcommand{\writesolutions}[1][\jobname]{%
+ \exf@close@solfile\exf@start@solfile{#1}}
+% \end{macrocode}
+
+% \macro{\closesolutions}
+% Close solutions output file (if open):
+% \begin{macrocode}
+\newcommand{\closesolutions}{\exf@close@solfile}
+% \end{macrocode}
+
+% \macro{\readsolutions}
+% Read solutions from file |#1.sol|;
+% default is present main file name;
+% switch layout and add heading:
+% \begin{macrocode}
+\newcommand{\readsolutions}[1][\jobname]{\exf@close@solfile%
+ \ifsolutions\begingroup%
+ \exf@config@styletext\exf@config@styletextsolution%
+ \let\exf@composetitle\exf@config@composetitlesolutionmulti%
+ \exf@solutionstitle%
+ \input{#1\exf@config@extsolutions}%
+ \endgroup\fi}
+% \end{macrocode}
+
+% \macro{\insertsolutions}
+% Show solutions buffer:
+% \begin{macrocode}
+\newcommand{\insertsolutions}{\exf@showsolutions%
+ {\exf@config@composetitlesolutionmulti}{\exf@solutionstitle}}
+% \end{macrocode}
+
+%\iffalse
+%</package>
+%\fi
+%
+\endinput
diff --git a/macros/latex/contrib/exframe/exframe.ins b/macros/latex/contrib/exframe/exframe.ins
new file mode 100644
index 0000000000..621d7e434d
--- /dev/null
+++ b/macros/latex/contrib/exframe/exframe.ins
@@ -0,0 +1,39 @@
+\def\batchfile{exframe.ins}
+\input docstrip.tex
+
+\keepsilent
+\preamble
+
+Copyright (C) 2011-2019 Niklas Beisert
+
+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.
+
+\endpreamble
+
+% the style and sample files
+\generate{\askforoverwritefalse
+\file{exframe.sty}{\from{exframe.dtx}{package}}
+\file{exfsamp.tex}{\from{exframe.dtx}{samplesingle}}
+\file{exfserm.tex}{\from{exframe.dtx}{samplemultimain}}
+\file{exfser01.tex}{\from{exframe.dtx}{samplemultisheet1}}
+\file{exfser02.tex}{\from{exframe.dtx}{samplemultisheet2}}
+\file{exfser03.tex}{\from{exframe.dtx}{samplemultisheet3}}
+\file{exfseraa.tex}{\from{exframe.dtx}{samplemultisheeta}}
+\file{exfserpe.tex}{\from{exframe.dtx}{samplemultiprobleme}}
+\file{exfserpf.tex}{\from{exframe.dtx}{samplemultiproblemf}}
+\nopreamble\nopostamble
+\file{exfsermk.sh}{\from{exframe.dtx}{samplemultiscript}}
+\catcode9=12\file{exfsermk.mak}{\from{exframe.dtx}{samplemultimake}}
+}
+
+\Msg{***********************************************************************}
+\Msg{* Done. Please copy the file exframe.sty to an appropriate directory *}
+\Msg{* of your LaTeX distribution, e.g. texmf-root/tex/latex/exframe. *}
+\Msg{***********************************************************************}
+\endbatchfile
diff --git a/macros/latex/contrib/exframe/exframe.pdf b/macros/latex/contrib/exframe/exframe.pdf
new file mode 100644
index 0000000000..84e39f432b
--- /dev/null
+++ b/macros/latex/contrib/exframe/exframe.pdf
Binary files differ