From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- macros/latex/contrib/exframe/README.txt | 49 + macros/latex/contrib/exframe/exframe.dtx | 6312 ++++++++++++++++++++++++++++++ macros/latex/contrib/exframe/exframe.ins | 39 + macros/latex/contrib/exframe/exframe.pdf | Bin 0 -> 389785 bytes 4 files changed, 6400 insertions(+) create mode 100644 macros/latex/contrib/exframe/README.txt create mode 100644 macros/latex/contrib/exframe/exframe.dtx create mode 100644 macros/latex/contrib/exframe/exframe.ins create mode 100644 macros/latex/contrib/exframe/exframe.pdf (limited to 'macros/latex/contrib/exframe') 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. +% +%\NeedsTeXFormat{LaTeX2e}[1996/12/01] +%\ProvidesPackage{exframe}[2019/06/15 v3.3 Framework for Exercise Problems] +%\ProvidesFile{exfsamp.tex}[2019/06/15 v3.3 standalone sample for exframe] +%\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\else#3\fi| and |\if&\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} +% +% \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 +% +%\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 +% +%\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 +% +%%%\providecommand{\printsol}{n} +%\input{childdoc.def} +%\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 +% +%\begin{sheet}[due={2019-05-06}] +%\begin{sheet}[due={2019-05-13}] +%\begin{sheet}[title={unused problems}] +%<*samplemultisheet1> +%\fi + +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \paragraph{Problems.} +% +% Start a problem: +% \begin{macrocode} +\begin{problem}[title={Sample A}] +% \end{macrocode} +% +%\iffalse +% +%\begin{problem}[title={Sample C}] +%\input{exfserpe} +%\begin{problem}[title={Sample X}] +%\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|samplemultisheet3|samplemultisheeta> +%\fi + +% Start new page: +% \begin{macrocode} +\turnover +% \end{macrocode} + +%\iffalse +% +%<*samplemultisheet1> +%\fi +% Write a second problem to accompany the first one: +% \begin{macrocode} +\begin{problem}[title={Sample B}] +% \end{macrocode} +% +%\iffalse +% +%\begin{problem}[title={Sample D}] +%\input{exfserpf} +%\begin{problem}[title={Sample Y}] +%\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|samplemultisheet3|samplemultisheeta> +%\fi +% End the sheet: +% \begin{macrocode} +\end{sheet} +% \end{macrocode} + +%\iffalse +% +%\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 +% +%\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 +% +%\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 +% +%\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 +% \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\else#3\fi} +\long\def\exerciseifnotempty#1#2{\if&\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&0\else#2\fi}% + \edef#1{{#1}{\if&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&% + \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&% + \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&% + \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&% + \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 +% +%\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 Binary files /dev/null and b/macros/latex/contrib/exframe/exframe.pdf differ -- cgit v1.2.3