% \iffalse meta-comment % An Infrastructure for Problems % $URL: https://svn.kwarc.info/repos/stex-content/sty/problem/problem.dtx $ % $Rev: 2674 $; last modified by $Author: deyan $ % $Date: 2010-03-24 04:09:39 +0100 (Wed, 24 Mar 2010) $ % Copyright (c) 2006-2008 Michael Kohlhase, all rights reserved % this file is released under the % LaTeX Project Public License (LPPL) % \fi % % \iffalse %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{problem}[2010/06/25 v0.9c Semantic Markup for Problems] % %<*driver> \documentclass{ltxdoc} \usepackage{url,float} \usepackage[show]{ed} \usepackage{latexml} \usepackage[solutions,hints,notes]{problem} \usepackage{hyperref} \makeindex \floatstyle{boxed} \newfloat{exfig}{thp}{lop} \floatname{exfig}{Example} \begin{document}\DocInput{problem.dtx}\end{document} % % \fi % % \CheckSum{365} % % \changes{v0.9}{2006/09/18}{First Version with Documentation} % \changes{v0.9a}{2007/01/02}{Renamed to \texttt{problem.sty}} % \changes{v0.9b}{2008/10/01}{added extraction} % \changes{v0.9c}{2010/01/03}{based on \texttt{omd.sty} now} % % \GetFileInfo{problem.sty} % % \MakeShortVerb{\|} % % \title{An Infrastructure for formatting Problems\thanks{Version {\fileversion} (last revised % {\filedate})}} % \author{Michael Kohlhase\\ % Jacobs University, Bremen\\ % \url{http://kwarc.info/kohlhase}} % \maketitle % % \begin{abstract} % The |problem| package supplies an infrastructure that allows specify problems and to % reuse them efficiently in multiple environments. % \end{abstract} % \setcounter{tocdepth}{2}\tableofcontents\newpage % %\section{Introduction}\label{sec:intro} % % The |problem| package supplies an infrastructure that allows specify problem. Problems % are text fragments that come with auxiliary functions: hints, notes, and % solutions\footnote{for the momenet multiple choice problems are not supported, but may % well be in a future version}. Furthermore, we can specify how long the solution to a % given problem is estimated to take and how many points will be awarded for a perfect % solution. % % Finally, the |problem| package facilitates the management of problems in small files, % so that problems can be re-used in multiple environment. % % \section{The User Interface}\label{sec:ui} % % \subsection{Package Options} % The |problem| package takes the options \DescribeMacro{solutions}|solutions| (should % solutions be output?), \DescribeMacro{notes}|notes| (should the problem notes be % presented?), \DescribeMacro{hints}|hints| (do we give the hints?), % \DescribeMacro{pts}|pts| (do we display the points awarded for solving the problem?), % \DescribeMacro{min}|min| (do we display the estimated minutes for problem soling). If % theses are specified, then the corresponding auxiliary parts of the problems are output, % otherwise, they remain invisible. % % The \DescribeMacro{boxed} option specifies that problems should be formatted in framed % boxes so that they are more visible in the text. Finally, the \DescribeMacro{test}|test| % option signifies that we are in a test sitution, so this option does not show the % solutions (of course), but leaves space for the students to solve them. % % The \DescribeMacro{extract}|extract| option can be set if we want to extract a problems % file, e.g. to display the solutions, see Section~\ref{sec:user:includeproblem} for a % discussion. % % \subsection{Problems and Solutions}\label{sec:user:probsols} % % \DescribeEnv{problem} The main enviornment provided by the |problem| package is % (surprise surprise) the |problem| environment. It is used to mark up problems and % excercises. The environment takes an optional KeyVal argument with the keys % \DescribeMacro{id}|id| as an identifier that can be reference later, % \DescribeMacro{pts}|pts| for the points to be gained from this exercise in homework or % quiz situations, \DescribeMacro{min}|min| for the estimated minutes needed to solve the % problem, and finally \DescribeMacro{title}|title| for an informative title of the % problem. For an example of a marked up problem see Figure~\ref{fig:problem} and the % resulting markup see Figure~\ref{fig:result}. % %\begin{exfig} % \begin{verbatim} % \usepackage[solutions,hints,pts,min]{problem} % \begin{document} % \begin{problem}[id=elefants,pts=10,min=2,title=Fitting Elefants] % How many Elefants can you fit into a Volkswagen beetle? % \begin{hint} Think positively, this is simple!\end{hint} % \begin{exnote}Justify your answer\end{exnote} % \begin{solution}[for=elefants,height=3cm] % Four, two in the front seats, and two in the back. % \end{solution} % \end{problem} % \end{document} % \end{verbatim} % \caption{A marked up Problem}\label{fig:problem} % \end{exfig} % % \DescribeEnv{solution} The |solution| environment can be to specify a solution to a % problem. If the \DescribeMacro{solutions}|solutions| option is set or |\solutionstrue| % is set in the text, then the solution will be presented in the output. The |solution| % environment takes an optional KeyVal argument with the keys \DescribeMacro{id}|id| for % an identifier that can be reference \DescribeMacro{for}|for| to specify which problem % this is a solution for, and \DescribeMacro{height}|height| that allows to specify the % amount of space to be left in test situations (i.e. if the \DescribeMacro{test}|test| % option is set in the |\usepackage| statement). % %\begin{exfig} % \begin{minipage}{.9\linewidth} % \begin{problem}[id=elefants.prob,title=Fitting Elefants] % How many Elefants can you fit into a Volkswagen beetle? % \begin{hint} Think positively, this is simple!\end{hint} % \begin{exnote}Justify your answer\end{exnote} % \begin{solution}%[for=elefants.prob,height=3cm] % Four, two in the front seats, and two in the back. % \end{solution} % \end{problem} % \end{minipage} % \caption{The Formmatted Problem from Figure~\ref{fig:problem}}\label{fig:result} % \end{exfig} % % \DescribeEnv{hint}\DescribeEnv{note}, the |hint| and |exnote| environments can be used % in a |problem| enviroment to give hints and to make notes that elaborate certain aspects % of the problem. % % \subsection{Including Problems}\label{sec:user:includeproblem} % % The \DescribeMacro{\includeproblem}|\includeproblem| macro can be used to include a % problem from another file. It takes an optional KeyVal argument and a second argument % which is a path to the file containing the problem (the macro assumes that there is only % one problem in the include file). The keys \DescribeMacro{title}|title|, % \DescribeMacro{min}|min|, and \DescribeMacro{pts}|pts| specify the problem title, the % estimated minutes for solving the problem and the points to be gained, and their values % (if given) overwrite the ones specified in the |problem| environment in the included % file. % % Sometimes we want to collect all the included problems into a separate file that can be % typeset independently. The main application is to have course notes into which the % problems are included (usually in boxed form to distinguish them from the rest of the % text and without solutions) and to have the problems with solutions in a separate file % (to encourage students to try and solve the problems before looking up solutions). In % this situation set the \DescribeMacro{extract}|extract| option on the notes file % \meta{notes}|.tex|, which causes a file \meta{notes}|-solutions.tex| to be generated % that has the |\includeproblem| statements with the respective numbers from the main % document. This can then be imported into a document with the respective front and % backmatter. In particular the frontmatter of the importing will ususlly specify the % \DescribeMacro{solutions}|solutions| option to generate solutions. % % \subsection{Reporting Metadata}\label{sec:user:reporting} % % The sum of the points and estimated minutes (that we specified in the |pts| and |min| % keys to the |problem| environment or the |\includeproblem| macro) to the log file and % the screen after each run. This is useful in preparing exams, where we want to make sure % that the students can indeed solve the problems in an alotted time period. % % The |\min| and |\pts| macros allow to specify (i.e. to print to the margin) the % distribution of time and reward to parts of a problem, if the |pts| and |pts| package % options are set. This allows to give students hints about the estimated time and the % points to be awarded. % % \StopEventually{\newpage\PrintChanges} % \newpage % % \section{The Implementation}\label{sec:implementation} % % \subsection{Package Options}\label{sec:impl:options} % % The first step is to declare (a few) package options that handle whether certain % information is printed or not. They all come with their own conditionals that are set by % the options. % % \begin{macrocode} %<*package> \newif\ifexnotes\exnotesfalse\DeclareOption{notes}{\exnotestrue} \newif\ifhints\hintsfalse\DeclareOption{hints}{\hintstrue} \newif\ifsolutions\solutionsfalse\DeclareOption{solutions}{\solutionstrue} \newif\ifpts\ptsfalse\DeclareOption{pts}{\ptstrue} \newif\ifmin\minfalse\DeclareOption{min}{\mintrue} \newif\ifboxed\boxedfalse\DeclareOption{boxed}{\boxedtrue} \newif\ifextract\extractfalse\DeclareOption{extract}{\extracttrue} \ProcessOptions % % \end{macrocode} % % Then we make sure that the necessary packages are loaded (in the right versions). % \begin{macrocode} %<*package> \RequirePackage{keyval}[1997/11/10] \RequirePackage{xcomment} \RequirePackage{sref} % % \end{macrocode} % % Here comes the equivalent header information for {\LaTeXML}, we also initialize the % package inclusions. Since {\LaTeXML} currently does not process package options, we have % nothing to do. % \begin{macrocode} %<*ltxml> # -*- CPERL -*- package LaTeXML::Package::Pool; use strict; use LaTeXML::Package; RequirePackage('sref'); % % \end{macrocode} % % Then we register the namespace of the requirements ontology % \begin{macrocode} %<*ltxml> RegisterNamespace('prob'=>"http://omdoc.org/ontology/problems#"); RegisterDocumentNamespace('prob'=>"http://omdoc.org/ontology/problems#"); % % \end{macrocode} % % \subsection{Problems and Solutions}\label{sec:impl:probsols} % % We now prepare the KeyVal support for problems. The key macros just set appropriate % internal macros. % % \begin{macrocode} %<*package> \srefaddidkey[prefix=prob.]{problem} \omdaddkey{problem}{pts} \omdaddkey{problem}{min} \omdaddkey{problem}{title} \omdaddkey{problem}{refnum} % \end{macrocode} % % Then we set up a box and a counter for problems % % \begin{macrocode} \newsavebox{\probbox} \newcounter{problem}[section] % \end{macrocode} % % \begin{macro}{\prob@number} % We consolidate the problem number into a reusable internal macro % \begin{macrocode} \def\prob@number{\ifx\inclprob@refnum\@empty \ifx\problem@refnum\@empty\thesection.\theproblem\else\problem@refnum\fi \inclprob@refnum\fi} % \end{macrocode} % \end{macro} % % We consolidate the problem header line into a separate internal macro that can be reused % in various settings. % % \begin{macro}{\prob@heading} % We consolidate the problem header line into a separate internal macro that can be % reused in various settings. % \begin{macrocode} \def\prob@heading{Problem \prob@number% \ifx\sref@id\@empty\else{\sref@label@id{Problem \thesection.\theproblem}}\fi% \ifx\inclprob@title\@empty% if there is no outside title \ifx\problem@title\@empty{:\quad}\else{\quad(\problem@title)\hfill\\}\fi \else\quad(\inclprob@title)\hfill\\\fi}% else show the outside title % \end{macrocode} % \end{macro} % % With this in place, we can now define the |problem| environment. It comes in two shapes, % depending on whether we are in boxed mode or not. In both cases we increment the problem % number and output the points and minutes (depending) on whehter the respective options % are set. % \begin{environment}{problem} % \begin{macrocode} \ifboxed \newenvironment{problem}[1][]{\omdsetkeys{problem}{#1}\sref@target% \stepcounter{problem}\show@pts\show@min\record@problem% \begin{lrbox}{\probbox}\begin{minipage}{.9\textwidth}} {\end{minipage}\end{lrbox} \setbox0=\hbox{\begin{minipage}{.9\textwidth}% \noindent\textbf\prob@heading\rm% \end{minipage}} \smallskip\noindent\fbox{\vbox{\box0\vspace*{.2em}\usebox\probbox}}\smallskip} \else \newenvironment{problem}[1][]{\omdsetkeys{problem}{#1}\sref@target% \stepcounter{problem}\show@pts\show@min\record@problem% \par\noindent\textbf\prob@heading\rm} {\smallskip} \fi%boxed % % \end{macrocode} % \end{environment} % % Note that we allow hints and solutions in the body of a |problem| environment so we have % to allow the |omdoc:CMP| and |omdoc:p| elements to autoclose. % % \begin{macrocode} %<*ltxml> DefCMPEnvironment('{problem} OptionalKeyVals:problem', "" . "?&KeyVal(#1,'title')(&KeyVal(#1,'title'))()" . "?&KeyVal(#1,'min')(&KeyVal(#1,'min'))()" . "?&KeyVal(#1,'pts')(&KeyVal(#1,'pts'))()" . "#body" ."\n"); % % \end{macrocode} % % \begin{macro}{\record@problem} % This macro records information about the problems in the |*.aux| file. % \begin{macrocode} %<*package> \def\record@problem{\protected@write\@auxout{}% {\string\@problem{\prob@number}% {\ifx\inclprob@pts\@empty\problem@pts\else\inclprob@pts\fi}% {\ifx\inclprob@min\@empty\problem@min\else\inclprob@min\fi}}} % % \end{macrocode} % \end{macro} % % \begin{macro}{\@problem} % This macro acts on a problem's record in the |*.aux| file. It does not have any % functionality here, but can be redefined elsewhere (e.g. in the |assignment| % package). % \begin{macrocode} %<*package> \def\@problem#1#2#3{} % % \end{macrocode} % \end{macro} % % The |solution| environment is similar to the |problem| environment, only that it is % independent of the boxed mode. It also has it's own keys that we need to define first. % % \begin{macrocode} %<*package> \define@key{soln}{id}{\def\soln@id{#1}} \define@key{soln}{for}{\def\soln@for{#1}} \define@key{soln}{height}{\def\soln@height{#1}} \ifsolutions \newenvironment{solution}[1][]% {\hrule\smallskip{\bf Solution: }\begin{small}}% {\hrule\end{small}} \else\newxcomment[]{solution}\fi % \newsavebox{\solution@box} % \newlength{\solution@width} % \setlength{\solution@width}{14cm} % \newenvironment{solution}[1][]% % {\begin{lrbox}{\solution@box}\begin{minipage}{\solution@width} % \hrule\smallskip{\bf Solution: }\small} % {\smallskip\hrule\end{minipage}\end{lrbox} % \ifsolutions\begin{center}\usebox{\solution@box}\end{center}\fi} % %<*ltxml> DefKeyVal('soln','id','Semiverbatim'); DefKeyVal('soln','height','Semiverbatim'); DefKeyVal('soln','for','Semiverbatim'); DefCMPEnvironment('{solution} OptionalKeyVals:soln', "" . "#body" . ""); % % \end{macrocode} % % \begin{macrocode} %<*package> \ifexnotes \newenvironment{exnote}[1][]% {\par\noindent\hrule\smallskip{\bf Note: }\small} {\smallskip\hrule} \else%ifexnotes \newxcomment[]{exnote} \fi%ifexnotes \ifhints \newenvironment{hint}[1][]% {\par\noindent\hrule\smallskip{\bf Hint: }\small} {\smallskip\hrule} \else%ifhints \newxcomment[]{hint} \fi%ifhints % %<*ltxml> DefCMPEnvironment('{exnote}', "" . "" . "#body" . "" .""); DefCMPEnvironment('{hint}', "" . "" . "#body" . "" .""); DefConstructor('\pts{}',""); DefConstructor('\min{}',""); % % \end{macrocode} % % \subsection{Including Problems}\label{sec:impl:includeproblem} % % The first action is to make a \meta{jobname}|-problems.tex| file, if the |extract| % option is set. % % \begin{macrocode} %<*package> \ifextract \newwrite\problem@file \immediate\openout\problem@file=\jobname-problems.tex \AtEndDocument{\closeout\problem@file} \fi % % \end{macrocode} % % \begin{macro}{\includeproblem} % The |\includeproblem| command is essentially a glorified |\input| statement, it sets % some internal macros first that overwrite the local points. After that (so that the % included problem had time to step the problem number) it writes the |\includeproblem| % statement to the problems file, if the |extract| option is set. Here we add a key % |refnum=\prob@num| to the inlcudeproblem, so that we can remember the number from the % main document.\ednote{do something about the overwriting of problem metadata in the % {\LaTeXML} binding.} % % \begin{macrocode} %<*package> \omdaddkey{inclprob}{pts} \omdaddkey{inclprob}{min} \omdaddkey{inclprob}{title} \omdaddkey{inclprob}{refnum} \clear@inclprob@keys \newcommand{\includeproblem}[2][]{% \bgroup\omdsetkeys{inclprob}{#1}\input{#2}\ifsolutions\newpage\fi\egroup \ifextract\def\@test{#1} \def\prob@num{\ifx\inclprob@refnum\@empty\thesection.\theproblem\else\inclprob@refnum\fi} \def\inclprob@keys{#1\ifx\@test\@empty\else,\fi refnum=\prob@num} \protected@write\problem@file{}{\string\includeproblem[\inclprob@keys]{#2}} \fi} % %<*ltxml> DefKeyVal('prob','pts','Semiverbatim'); DefKeyVal('prob','min','Semiverbatim'); DefKeyVal('prob','title','Semiverbatim'); DefConstructor('\includeproblem OptionalKeyVals:prob Semiverbatim', "" . "?&KeyVal(#1,'title')(&KeyVal(#1,'title'))()" . "?&KeyVal(#1,'min')(&KeyVal(#1,'min'))()" . "?&KeyVal(#1,'pts')(&KeyVal(#1,'pts'))()" .""); % % \end{macrocode} % \end{macro} % % \begin{macrocode} %<*ltxml> Tag('omdoc:exercise',afterOpen=>\&numberIt); Tag('omdoc:solution',afterOpen=>\&numberIt); Tag('omdoc:hint',afterOpen=>\&numberIt); % % \end{macrocode} % % \subsection{Reporting Metadata} % % \begin{macrocode} %<*package> \def\pts#1{\ifpts\marginpar{#1 pt}\fi} \def\min#1{\ifmin\marginpar{#1 min}\fi} % %<*ltxml> % % \end{macrocode} % % \begin{macrocode} %<*package> \AtEndDocument{\ifpts\message{Total: \arabic{pts} points}\fi \ifmin\message{Total: \arabic{min} minutes}\fi} % %<*ltxml> % % \end{macrocode} % % \begin{macro}{\show@pts} % The |\show@pts| shows the points: if no points are given from the outside and also no % points are given locally do nothing, else show and add. If there are outside points % then we show them in the margin. % \begin{macrocode} %<*package> \newcounter{pts} \def\show@pts{\ifx\inclprob@pts\@empty% \ifx\problem@pts\@empty\else% \ifpts\marginpar{\problem@pts pt\smallskip}\addtocounter{pts}{\problem@pts}\fi% \fi\else% \ifpts\marginpar{\inclprob@pts pt\smallskip}\addtocounter{pts}{\inclprob@pts}\fi% \fi} % \end{macrocode} % \end{macro} % and now the same for the minutes % \begin{macro}{\show@min} % \begin{macrocode} \newcounter{min} \def\show@min{\ifx\inclprob@min\@empty% \ifx\problem@min\@empty\else% \ifmin\marginpar{\problem@min min}\addtocounter{min}{\problem@min}\fi% \fi\else% \ifmin\marginpar{\inclprob@min min}\addtocounter{min}{\inclprob@min}\fi \fi} % % \end{macrocode} % \end{macro} % % \subsection{Finale} % Finally, we need to terminate the file with a success mark for perl. % \begin{macrocode} %1; % \end{macrocode} % \Finale \endinput % \iffalse % LocalWords: GPL structuresharing STR dtx pts keyval xcomment CPERL DefKeyVal %%% Local Variables: %%% mode: doctex %%% TeX-master: t %%% End: % \fi % LocalWords: RequirePackage Semiverbatim DefEnvironment OptionalKeyVals soln % LocalWords: exnote DefConstructor inclprob