texlive[57572] Master/texmf-dist: xsim (31jan21)
commits+karl at tug.org
commits+karl at tug.org
Sun Jan 31 22:33:37 CET 2021
Revision: 57572
http://tug.org/svn/texlive?view=revision&revision=57572
Author: karl
Date: 2021-01-31 22:33:37 +0100 (Sun, 31 Jan 2021)
Log Message:
-----------
xsim (31jan21)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/latex/xsim/README
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.blanks.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.blanks.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.boxed-headings.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.code-and-output.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.code-and-output.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.collections.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.collections.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.crossref.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.crossref.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.description-list.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.different-point-types.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.difficulties.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.floating.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-80640.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-80640.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-91339.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-91339.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.grade-distribution.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.hints.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.hints.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listings.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listings.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listofexercises.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.multiplechoice.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.pointsums.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.randomexercises.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.randomexercises.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-13635.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-13635.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-155630.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-155630.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-199360.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-299534.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-299534.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-305110.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-308883.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-338165.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-338165.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-350028.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-350028.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369065.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369065.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369636.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369636.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369803.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369803.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-370642.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-395273.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-498299.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-498299.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-15093.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-15093.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-23968.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-23968.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-6698.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-6698.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.various.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.various.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim-manual.cls
trunk/Master/texmf-dist/tex/latex/xsim/xsim.sty
trunk/Master/texmf-dist/tex/latex/xsim/xsimverb.sty
Added Paths:
-----------
trunk/Master/texmf-dist/doc/latex/xsim/HISTORY
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530-exercises.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.tex
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.pdf
trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.tex
trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.pdf
trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.tex
Removed Paths:
-------------
trunk/Master/texmf-dist/doc/latex/xsim/xsim.history
trunk/Master/texmf-dist/doc/latex/xsim/xsim.ideas
trunk/Master/texmf-dist/doc/latex/xsim/xsim_manual.pdf
trunk/Master/texmf-dist/doc/latex/xsim/xsim_manual.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.auxfile.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.base.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.blanks.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.collections.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.definitions.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.environments.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.goals.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.grades.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.interface.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.modules.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.solutions.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.style.layouts.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.tags.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.templates.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.translations.code.tex
trunk/Master/texmf-dist/tex/latex/xsim/xsim.verbwrite.code.tex
Added: trunk/Master/texmf-dist/doc/latex/xsim/HISTORY
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/HISTORY (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/HISTORY 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,178 @@
+--------------------------------------------------------------------------
+
+XSIM -- eXercise Sheets IMproved
+
+--------------------------------------------------------------------------
+Clemens Niederberger
+Web: https://github.com/cgnieder/xsim
+E-Mail: contact at mychemistry.eu
+--------------------------------------------------------------------------
+Copyright 2017--2020 Clemens Niederberger
+
+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 Clemens Niederberger.
+--------------------------------------------------------------------------
+
+HISTORY:
+
+ v0.0 2017/02/09 - start with coding the first ideas
+ v0.1 2017/03/19 - first draft which actually seems to do everything as
+ planned
+ v0.2 2017/03/21 - bugfix in the verbwrite module
+ - add `use!' and `print!' properties
+ - add the concepts of `noupdate' and `boolean' properties
+ v0.4 2017/03/24 - \IfExerciseBooleanPropertyTF
+ - \GetExercisePropertyTF, \PropertyValue
+ - \printallsolutions
+ - \UseExerciseTemplate
+ - bug fix in solution environments: now get printed again
+ when option `print=true' is used
+ - bug fix to the translations of the solution list headings:
+ exercise name instead of exercise type is now printed
+ - \AddtoExerciseTypeGoal, \AddtoExerciseGoal
+ \AddtoExerciseTypeGoalPrint, \AddtoExerciseGoalPrint,
+ \ExerciseGoalValuePrint
+ - \addpoints, \addbonus, \points, \printgoal
+ v0.5 2017/03/30 - add style file mechanism
+ - make solution print conditions `section' and `chapter'
+ combinable
+ v0.5a 2017/04/15 - fix wrong translation of the `default-heading'
+ v0.5b 2017/04/16 - add \SetExerciseProperty
+ v0.6 2017/04/27 - official interface for grade distributions
+ - refine hook management (environment module)
+ v0.6a 2017/04/28 - refine \blank command, add documentation for said command
+ v0.7 2017/05/09 - \xsim_list_length:n
+ - new boolean property `used'
+ - when an exercise is collected the counter isn't stepped
+ but only when the exercise is inserted for the first
+ time; when this happens the new property `used' is set to
+ `true'
+ - make setting boolean properties case insensitive
+ - add missing pieces to manual (eg `page' property...)
+ - \TotalExerciseGoals and \TotalExerciseTypeGoals
+ - \XSIMifchapterTF
+ - \xsim_if_goal_sum:nnnTF and friends,
+ \IfExerciseTypeGoalsSumTF and \IfExerciseGoalsSumTF
+ - some more hints in the manual regarding collections
+ v0.8 2017/05/18 - bug fix in \xsim_set_property:nnnn
+ - random exercise lists from collections
+ - \xsim_collection_count:n
+ - \GetExerciseIdForProperty and \GetExerciseTypeForProperty
+ for unique properties
+ - set property `print=false' during collection and only to
+ true when the corresponding exercises actually are
+ printed
+ - do not insert \par at the beginning and end of exercises
+ and solutions; this should be left to the templates!
+ - new option `print-collection/print' which allows to
+ choose between exercises, solutions, and both to be
+ printed
+ - new parameter `solution-counter' in order to avoid
+ possible conflicts with existing counters
+ v0.8a 2017/05/19 - \IfPrintSolutionTF
+ v0.8b 2017/05/23 - use \printgoal in default environment template
+ - \xsim_print_goal:nnn now expands input to a number
+ v0.9 2017/06/20 - \xsimstyle's behaviour now matches the description in
+ the manual
+ - add style file `layouts' which at the moment provides the
+ two exercise templates `runin' and `margin'
+ - \printforexercises , \xsim_print_type_code:nnnnn
+ - \IfExerciseParameterSetTF
+ - \GetExerciseParameterTF
+ - change syntax of \SetExerciseProperty
+ - \SetExpandedExerciseProperty
+ - \ExerciseSetProperty, \ExerciseSetExpandedProperty
+ - property `sectioning'
+ - \IfExistSolutionTF
+ v0.10 2017/09/19 - \xsim_input:nnn
+ - \GetExerciseBody
+ - option `blank/fill'
+ - bug fix in \xsim_start_collection:nn
+ - added further examples to package
+ - new option `file-extension'
+ v0.10a 2017/10/01 - bug fix: grading table options can now be set with
+ \xsimsetup (issue 15)
+ v0.11 2018/02/12 - change name requirement for style files in order to
+ prevent possible name clashes with module files
+ - fix bug in \SetExerciseProperty and
+ \SetExpandedExerciseProperty
+ - fix bug when xsimverb is used standalone (issue 21)
+ - add option `split-aux-lists' (issue 18)
+ - \IfExerciseTagSetTF and \IfExerciseTopicSetTF
+ - introduce a \xsim_if_<tagging>_value:nTF for each tag
+ kind
+ - \ProvideExerciseTagging
+ v0.12 2019/09/30 - add parameter versions for the plural forms of exercise
+ and solution names
+ - bug fixes (issues 37, 39, 43, 47)
+ v0.13 2019/10/06 - experimental package option `no-files'
+ v0.14 2019/10/13 - new exercise parameters `exercise-heading' and
+ `solution-heading'
+ - new options `exercise/heading' and `solution/heading' as
+ interface for setting the new parameters
+ - new command \GetExerciseHeadingF for using the new
+ parameters in environment templates
+ - change the environment template `default' to use the new
+ \GetExerciseHeadingF and output a \par at the end
+ - make argument of \xsimsetup long
+ - new template `minimal'
+ - new option `load-style'
+ - new example `texwelt-23968' (long and short solutions)
+ v0.14a 2019/10/19 - fix \xsim_if_exercise_exist:nnTF to obey the `no-files'
+ option
+ v0.15 2019/11/02 - use own auxiliary file per default and add option
+ `use-aux'
+ v0.16 2019/11/10 - fix issue due to usage of own auxiliary file
+ - \XSIMatbegindocument and \XSIMatenddocument
+ - \xprintexercise, \xprintsolution, \xsimprint, \xsimxprint
+ 2019/12/29 - bugfix in `xsimverb'
+ v0.16a 2020/01/16 - adapt to renaming of string case changing functions
+ v0.17 2020/02/21 - prefer lazy boolean evaluation if possible
+ - remove spurious \par at the beginning of typeset
+ exercises
+ - add `blank' option, implements issue #31
+ - add `solution' property, implements issue #33
+ - fix issue #27
+ - implement issue #2
+ - don't allow package options to be set with \xsimsetup
+ v0.18 2020/02/23 - fix issue #56
+ - change \printexercise and \printsolution to accept a
+ clist of either ids or IDs (or mixed)
+ - new templates in the `layouts' style
+ v0.19 2020/03/16 - improve performance
+ - only set \ExerciseID and \ExerciseType locally to ensure
+ correct values when exercises (of different types) are
+ nested
+ - new load-time option `debug' - only for development
+ v0.19a 2020/03/19 - fix missing-variant-bug introduced with the last update
+ v0.19b 2020/04/04 - fix bug in new attribute mechanism which was a problem
+ when `no-files` has been used
+ v0.20 2021/01/31 - switch to one sty file per package
+ - use LaTeX's new hooks
+ - declare undeclared variables
+ - new exercise setup mechanism which clearly determines the
+ difference between definition, usage, and printing of an
+ exercise; this also solves the problem with added goals
+ in the exercise body in a collection
+ - re-write collection mechanism:
+ * changes the behaviour of \collectexercises but doesn't
+ require external files any more and more importantly
+ doesn't require inputting files several times for
+ multiple collections
+ * drop \collectexercisestype
+ * new \(de)activatecollection
+ * new options `collect' and `<type>/collect'
+ - small improvements in performance
+ - new parameters `within' and `the-counter'
+ - make `no-files' the default
+ - new examples
+ - various small fixes
Modified: trunk/Master/texmf-dist/doc/latex/xsim/README
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/README 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/README 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,6 +1,6 @@
--------------------------------------------------------------------------
-XSIM 2020/04/04 v0.19b
-XSIMVERB 2019/12/29 v0.1a
+XSIM 2021/01/31 v0.20
+XSIMVERB 2021/01/31 v0.3
eXercise Sheets IMproved
@@ -9,15 +9,15 @@
Web: https://github.com/cgnieder/xsim
E-Mail: contact at mychemistry.eu
--------------------------------------------------------------------------
-Copyright 2017--2020 Clemens Niederberger
+Copyright 2017--2021 Clemens Niederberger
This work may be distributed and/or modified under the
-conditions of the LaTeX Project Public License, either version 1.3
+conditions of the LaTeX Project Public License, either version 1.3c
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.
+and version 1.3c or later is part of all distributions of LaTeX
+version 2008/05/04 or later.
This work has the LPPL maintenance status `maintained'.
@@ -26,30 +26,10 @@
The xsim package consists of the code files:
xsim.sty
xsimverb.sty
- xsim.auxfile.code.tex
- xsim.base.code.tex
- xsim.blanks.code.tex
- xsim.collections.code.tex
- xsim.definitions.code.tex
- xsim.environments.code.tex
- xsim.exercises.code.tex
- xsim.goals.code.tex
- xsim.grades.code.tex
- xsim.interface.code.tex
- xsim.modules.code.tex
- xsim.properties.code.tex
- xsim.random.code.tex
- xsim.solutions.code.tex
- xsim.style.layouts.code.tex
- xsim.tags.code.tex
- xsim.templates.code.tex
- xsim.translations.code.tex
- xsim.verbwrite.code.tex
--------------------------------------------------------------------------
The xsim package consists of the documentation files:
- README
- xsim.history, xsim.ideas
- xsim_manual.tex, xsim_manual.pdf
+ README HISTORY
+ xsim-manual.tex, xsim-manual.pdf
xsim-manual.cls
--------------------------------------------------------------------------
The xsim package consists of the example files:
@@ -84,12 +64,16 @@
xsim.texsx-370642.tex, xsim.texsx-370642.pdf
xsim.texsx-391530.tex, xsim.texsx-391530.pdf
xsim.texsx-395273.tex, xsim.texsx-395273.pdf
- xsim.texsx-498299.tex, xsim.texsx-498299.pdf,
+ xsim.texsx-466584.tex, xsim.texsx-466584.pdf
+ xsim.texsx-498299.tex, xsim.texsx-498299.pdf
+ xsim.texsx-576998.tex, xsim.texsx-576998.pdf
+ xsim.texsx-580636.tex, xsim.texsx-580636.pdf
xsim.texwelt-6698.tex, xsim.texwelt-6698.pdf
xsim.texwelt-15093.tex, xsim.texwelt-15093.pdf
xsim.texwelt-23968.tex, xsim.texwelt-23968.pdf
- xsim.golatex-16824.tex, xsim.golatex-16824.pdf
- xsim.golatex-18844.tex, xsim.golatex-18844.pdf
+ xsim.golatex-80640.tex, xsim.golatex-80640.pdf
+ xsim.golatex-91339.tex, xsim.golatex-91339.pdf
+ xsim.issues-49.tex, xsim.issues-49.pdf
--------------------------------------------------------------------------
If you have any ideas, questions, suggestions or bugs to report, please
feel free to contact me.
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.blanks.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.blanks.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.blanks.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.blanks.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,5 +1,4 @@
\documentclass{article}
-\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{xsim,lipsum,xcolor}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.boxed-headings.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.code-and-output.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.code-and-output.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.code-and-output.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.code-and-output.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -46,7 +46,7 @@
\bigskip
-\begin{code}[]
+\begin{code}
blubber \LaTeX
\end{code}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.collections.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.collections.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.collections.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.collections.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,12 +1,19 @@
\documentclass{article}
\usepackage{xsim}
+\usepackage{lipsum}
-\DeclareExerciseCollection{foo-easy}
-\DeclareExerciseCollection{foo-medium}
+\DeclareExerciseCollection[difficulty=easy]{easy}
+\DeclareExerciseCollection[difficulty=medium]{medium}
\DeclareExerciseTagging{difficulty}
-\usepackage{lipsum}
-\begin{filecontents*}{foo.tex}
+\xsimsetup{collect}
+
+\begin{document}
+
+\begin{exercise}[use,print]
+ outside before
+\end{exercise}
+
\begin{exercise}[difficulty=easy,points=1]
foo one \lipsum[4]
\end{exercise}
@@ -25,38 +32,13 @@
\begin{solution}
foo three \lipsum[4]
\end{solution}
-\end{filecontents*}
-\begin{document}
-
-\begin{exercise}
- outside before
-\end{exercise}
-
-\collectexercises{foo-easy}
-\xsimsetup{difficulty=easy}
-\input{foo.tex}
-\collectexercisesstop{foo-easy}
-% collection `foo-easy' now contains all exercises of file `foo.tex' tagged
-% with `difficulty=easy'
-
-\collectexercises{foo-medium}
-\xsimsetup{difficulty=medium}
-\input{foo.tex}
-\collectexercisesstop{foo-medium}
-% collection `foo-medium' now contains all exercises of file `foo.tex'
-% tagged with `difficulty=medium'
-
\section{Easy}
-\printcollection{foo-easy}
+\printcollection{easy}
\section{Medium}
-\printcollection{foo-medium}
+\printcollection{medium}
\printsolutions[difficulty=medium]
-\section{All Exercises and Their Solutions Again, in Order of Appearance}
-
-\printcollection[print=both]{all exercises}
-
\end{document}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.crossref.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.crossref.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.crossref.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.crossref.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -2,7 +2,7 @@
\usepackage{xsim,lipsum,hyperref}
\DeclareExerciseHeadingTemplate{custom}
- {\section{\XSIMtranslate{default-heading}}}
+ {\section{\XSIMexpandcode{\XSIMtranslate{default-heading}}}}
\DeclareExerciseEnvironmentTemplate{custom}
{%
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.description-list.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.different-point-types.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.difficulties.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.floating.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-80640.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-80640.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-80640.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-80640.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,6 +1,5 @@
% http://golatex.de/viewtopic,p,80640.html
\documentclass[fontsize=12pt,parskip=half]{scrartcl}
-\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-91339.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-91339.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-91339.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.golatex-91339.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,6 +1,5 @@
% http://golatex.de/viewtopic,p,91339.html
-\documentclass[18pt,a4paper]{article}
-\usepackage[utf8]{inputenc}
+\documentclass[a4paper]{article}
\usepackage[ngerman]{babel}
\usepackage{xsim,tcolorbox}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.grade-distribution.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.hints.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.hints.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.hints.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.hints.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -10,13 +10,8 @@
\newcommand\printhints{%
\begin{description}
\ForEachUsedExerciseByType{%
- \def\ExerciseType{##1}%
- \def\ExerciseID{##2}%
\GetExercisePropertyT{hint}
- {%
- \item[\XSIMmixedcase{\GetExerciseName}~##3]
- ####1%
- }%
+ {\item[\XSIMmixedcase{\GetExerciseName}~##3]####1}%
}%
\end{description}
}
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.pdf 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.pdf 2021-01-31 21:33:37 UTC (rev 57572)
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,122 @@
+\documentclass{article}
+\usepackage{xsim}
+
+\xsimsetup{
+ load-style = layouts ,
+ exercise/template = runin ,
+ solution/template = runin
+}
+
+\usepackage{tasks,fontawesome,fmtcount,multicol}
+\NewTasksEnvironment[label=\Alph*),label-width=12pt]{choices}[\choice]
+\newcommand*\correct{\thetask\expanded{\SetExerciseProperty{choice}{\thetask}}}
+
+\NewTasksEnvironment[label=\Roman*,label-width=12pt]{options}[\option]
+
+\DeclareExerciseProperty{choice}
+
+\newcommand*\pkg[1]{\texttt{#1}}
+\newcommand*\cls[1]{\texttt{#1}}
+
+\newcommand\EA[2]{\IfInsideSolutionTF{#2}{#1}}
+\newcommand\answer[1]{\IfInsideSolutionT{#1}}
+
+\begin{document}
+
+\section{List of exercises}
+Solve and answer the following exercises.
+
+\begin{exercise}
+ Factor $x^{2}-2x+1$
+\end{exercise}
+\begin{solution}
+ $\left(x-1\right)^{2}$
+\end{solution}
+\begin{exercise}
+ Factor $3x+3y+3z$
+\end{exercise}
+\begin{solution}
+ $3(x+y+z)$
+\end{solution}
+
+\begin{exercise}[solution]
+ \EA{True or false?}{}
+ \begin{tasks}(2)
+ \task \EA{$\alpha > \delta$}{False}
+ \task \EA{\LaTeX2e\ is cool?}{Very True!}
+ \end{tasks}
+\end{exercise}
+
+\begin{exercise}[subtitle=Talking Linux,solution]
+ \begin{tasks}(2)
+ \task \EA{You use linux?}{Yes}
+ \task \EA{Usually uses the package manager?}{Yes}
+ \end{tasks}
+\end{exercise}
+
+\begin{exercise}[solution]
+ \EA{Rate the following \LaTeX\ packages and classes.}{}
+ \begin{tasks}(\EA{3}{1})
+ \task \EA{\cls{xsim-exam}}{doesn't exist for now}
+ \task \EA{\pkg{xsim}}{very good}
+ \task \EA{\pkg{exsheets}}{obsolete}
+ \end{tasks}
+\end{exercise}
+
+\begin{exercise}
+ \begin{choices}(5)
+ \choice value
+ \choice value
+ \choice value
+ \choice[\correct] correct
+ \choice value
+ \end{choices}
+\end{exercise}
+\begin{solution}
+ \GetExerciseProperty{choice}
+\end{solution}
+
+\begin{exercise}
+ \begin{options}(3)
+ \option $2\alpha+2\delta=90^{\circ}$
+ \option $\alpha=\delta$
+ \option $\angle EDF=45^{\circ}$
+ \end{options}
+ \begin{choices}(4)
+ \choice I only
+ \choice[\correct] II only
+ \choice I and II only
+ \choice I and III only
+ \choice I, II, and III
+ \end{choices}
+\end{exercise}
+\begin{solution}
+ \GetExerciseProperty{choice}
+\end{solution}
+
+\begin{exercise}
+ \begin{tasks}[label=(\arabic*),label-width=13pt](2)
+ \task $2\alpha+2\delta=90^{\circ}$
+ \task $\angle EDF=45^{\circ}$
+ \end{tasks}
+ \begin{choices}(3)
+ \choice Alternative A
+ \choice Alternative B
+ \choice[\correct] Alternative C
+ \choice Alternative D
+ \choice Alternative E
+ \end{choices}
+\end{exercise}
+\begin{solution}
+ \GetExerciseProperty{choice}
+\end{solution}
+
+\clearpage
+
+\section{Solutions}
+\raggedcolumns
+\begin{multicols}{2}
+ \printsolutions[headings=false]
+\end{multicols}
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.issues-49.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listings.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listings.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listings.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listings.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -3,7 +3,7 @@
\usepackage{xcolor}
\usepackage{listings}
-\usepackage{xsim}
+\usepackage[use-files]{xsim}
\lstset{
frame=single,
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.listofexercises.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.multiplechoice.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.pointsums.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.randomexercises.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.randomexercises.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.randomexercises.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.randomexercises.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,10 +1,10 @@
\documentclass{article}
\usepackage{xsim}
-\DeclareExerciseCollection{foo}
+\xsimsetup{collect}
-\usepackage{filecontents}
-\begin{filecontents*}{random.tex}
+\begin{document}
+
\begin{exercise}[ID=A]
exercise A
\end{exercise}
@@ -41,18 +41,10 @@
\begin{solution}
solution F
\end{solution}
-\end{filecontents*}
-\begin{document}
-
-\collectexercises{foo}
-\input{random.tex}
-\collectexercisesstop{foo}
-
\section*{Exercises}
-\printrandomexercises[collection=foo,exclude=D]{3}
+\printrandomexercises[collection=all exercises,exclude=D]{3}
-\section*{Solutions}
-\printsolutions*
+\printsolutions
\end{document}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-13635.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-13635.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-13635.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-13635.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -27,6 +27,8 @@
\DeclareExerciseCollection{prime numbers}
\DeclareExerciseCollection{Zeta function}
+\xsimsetup{collect}
+
\begin{document}
\collectexercises{prime numbers}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-155630.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-155630.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-155630.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-155630.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -3,10 +3,10 @@
\usepackage{xsim}
\DeclareExerciseCollection{foo}
+\xsimsetup{collect}
\begin{document}
-\collectexercises{foo}
\begin{exercise}
foo
\end{exercise}
@@ -16,7 +16,6 @@
\begin{exercise}
baz
\end{exercise}
-\collectexercisesstop{foo}
% shuffle around for a different version:
\printexercise{exercise}{1}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-199360.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-299534.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-299534.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-299534.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-299534.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,7 +1,7 @@
% http://tex.stackexchange.com/q/299534/
\documentclass{article}
\usepackage{pythontex}
-\usepackage{xsim}
+\usepackage[use-files]{xsim}
\begin{document}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-305110.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-308883.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-338165.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-338165.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-338165.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-338165.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -10,26 +10,24 @@
\tcbuselibrary{breakable, skins}
\settasks{ label = \arabic*. }
-\DeclareExerciseEnvironmentTemplate{boxed}
- {%
- \tcolorbox[
- enhanced ,
- attach boxed title to top center = {yshift=-7.5pt} ,
- colback = white , colbacktitle = white ,
- coltitle = black , colframe = black ,
- boxed title style = { colframe = white } ,
- fonttitle=\bfseries,
- sharp corners=all,
- breakable,
- title=
- \XSIMmixedcase{\GetExerciseName}%
- \IfInsideSolutionF{%
- ~\GetExerciseProperty{counter}%
- \IfExercisePropertySetT{subtitle}{: \GetExerciseProperty{subtitle}}%
- }%
- ]
- }
- {\endtcolorbox}
+\DeclareExerciseEnvironmentTemplate{boxed}{%
+ \tcolorbox[
+ enhanced ,
+ attach boxed title to top center = {yshift=-7.5pt} ,
+ colback = white , colbacktitle = white ,
+ coltitle = black , colframe = black ,
+ boxed title style = { colframe = white } ,
+ fonttitle=\bfseries,
+ sharp corners=all,
+ breakable,
+ title=
+ \XSIMmixedcase{\GetExerciseName}%
+ \IfInsideSolutionF{%
+ ~\GetExerciseProperty{counter}%
+ \IfExercisePropertySetT{subtitle}{: \GetExerciseProperty{subtitle}}%
+ }%
+ ]
+}{\endtcolorbox}
\xsimsetup{
exercise/template = boxed ,
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-350028.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-350028.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-350028.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-350028.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -5,48 +5,44 @@
\usepackage[most]{tcolorbox}
\tcbuselibrary{skins,breakable}
-\DeclareExerciseEnvironmentTemplate{tcolorbox}
- {%
- \tcolorbox[
- enhanced,
- colframe=green!20!black,
- colback=yellow!10!white,
- coltitle=green!40!black,
- fonttitle=\bfseries,
- underlay={%
- \begin{tcbclipinterior}
- \shade[
- inner color=\IfInsideSolutionTF{red!50!yellow}{green!80!yellow},
- outer color=yellow!10!white]
- (interior.north west) circle (2cm);
- \draw[help lines,step=5mm,yellow!80!black,shift={(interior.north west)}]
- (interior.south west) grid (interior.north east);
- \end{tcbclipinterior}%
- },
- attach title to upper=\quad,
- title = \XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}
- \IfExercisePropertySetT{points}{%
- (\GetExerciseProperty{points}
- \IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}})%
- }]%
- \IfInsideSolutionT{\label{solution:\ExerciseID}}%
- }
- {%
- \endtcolorbox
- \vspace*{\baselineskip}
- \IfInsideSolutionTF
- {%
- \noindent Exercise~\GetExerciseProperty{counter} is on
- page~\GetExerciseProperty{page}.%
- }
- {%
- \noindent The solution of this exercise is on
- page~\pageref{solution:\ExerciseID}.%
- }%
- \vspace{\baselineskip}
- }
+\DeclareExerciseEnvironmentTemplate{tcolorbox}{%
+ \tcolorbox[
+ enhanced,
+ colframe=green!20!black,
+ colback=yellow!10!white,
+ coltitle=green!40!black,
+ fonttitle=\bfseries,
+ underlay={%
+ \begin{tcbclipinterior}
+ \shade[
+ inner color=\IfInsideSolutionTF{red!50!yellow}{green!80!yellow},
+ outer color=yellow!10!white]
+ (interior.north west) circle (2cm);
+ \draw[help lines,step=5mm,yellow!80!black,shift={(interior.north west)}]
+ (interior.south west) grid (interior.north east);
+ \end{tcbclipinterior}%
+ },
+ attach title to upper=\quad,
+ title = \XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}
+ \IfExercisePropertySetT{points}{%
+ (\GetExerciseProperty{points}
+ \IfExerciseGoalSingularTF{points}
+ {\XSIMtranslate{point}}
+ {\XSIMtranslate{points}})%
+ }]%
+ \IfInsideSolutionT{\label{solution:\ExerciseID}}%
+}{%
+ \endtcolorbox
+ \vspace*{\baselineskip}
+ \IfInsideSolutionTF{%
+ \noindent Exercise~\GetExerciseProperty{counter} is on
+ page~\GetExerciseProperty{page}.%
+ }{%
+ \noindent The solution of this exercise is on
+ page~\pageref{solution:\ExerciseID}.%
+ }%
+ \vspace{\baselineskip}
+}
\xsimsetup{
exercise/template = tcolorbox ,
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369065.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369065.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369065.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369065.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -11,29 +11,25 @@
solution/print=true
}
-\DeclareExerciseEnvironmentTemplate{cyan-box}
- {%
- \begin{tcolorbox}[arc=0mm,boxrule=1pt,colback=white,colframe=cyan,leftrule=3mm]
- \textsf{%
- \MakeUppercase{%
- \XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}%
- }%
+\DeclareExerciseEnvironmentTemplate{cyan-box}{%
+ \begin{tcolorbox}[arc=0mm,boxrule=1pt,colback=white,colframe=cyan,leftrule=3mm]
+ \textsf{%
+ \MakeUppercase{%
+ \XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}%
}%
- \GetExercisePropertyT{subtitle}{ \textit{#1}}%
- \quad
- }
- {\end{tcolorbox}}
-
-\DeclareExerciseEnvironmentTemplate{red}
- {%
- \par
- \Needspace*{2\baselineskip}
- \noindent
- \textsf{\textcolor{red}{\MakeUppercase{\XSIMmixedcase{\GetExerciseName}}}}%
+ }%
+ \GetExercisePropertyT{subtitle}{ \textit{#1}}%
\quad
- }
- {\par\bigskip}
+}{\end{tcolorbox}}
+\DeclareExerciseEnvironmentTemplate{red}{%
+ \par
+ \Needspace*{2\baselineskip}
+ \noindent
+ \textsf{\textcolor{red}{\MakeUppercase{\XSIMmixedcase{\GetExerciseName}}}}%
+ \quad
+}{\par\bigskip}
+
\begin{document}
\section{My first set of exercises}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369636.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369636.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369636.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369636.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -5,7 +5,6 @@
\usepackage[T1]{fontenc}
\usepackage{fourier}
\usepackage{tgpagella}
-\usepackage[utf8]{inputenc}
\usepackage{xsim,needspace,adjustbox,scrextend}
@@ -14,20 +13,18 @@
exercise/template = square
}
-\DeclareExerciseEnvironmentTemplate{square}
- {%
- \Needspace*{2\baselineskip}%
- \addmargin[0pt]{.15\textwidth}%
- \par\noindent
- \adjustbox{
- fbox = 1pt 0pt,
- lap = {\textwidth},
- valign = t,
- set vsize = {0pt}{0pt}
- }{\rule{0pt}{20pt}\hspace{20pt}}%
- \textbf{\GetExerciseProperty{counter}} %
- }
- {\endaddmargin\vspace{\baselineskip}}
+\DeclareExerciseEnvironmentTemplate{square}{%
+ \Needspace*{2\baselineskip}%
+ \addmargin[0pt]{.15\textwidth}%
+ \par\noindent
+ \adjustbox{
+ fbox = 1pt 0pt,
+ lap = {\textwidth},
+ valign = t,
+ set vsize = {0pt}{0pt}
+ }{\rule{0pt}{20pt}\hspace{20pt}}%
+ \textbf{\GetExerciseProperty{counter}} %
+}{\endaddmargin\vspace{\baselineskip}}
\usepackage{lipsum}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369803.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369803.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369803.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-369803.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,6 +1,5 @@
% https://tex.stackexchange.com/q/369803
\documentclass[a4paper,parskip=half]{scrartcl}
-\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{amsmath}
@@ -12,19 +11,16 @@
\usepackage{xsim,siunitx}
\DeclareExerciseTagging{difficulty}
-\DeclareExerciseEnvironmentTemplate{custom}
- {%
- \subsection*
- {%
- \XSIMmixedcase{\GetExerciseName}\nobreakspace
- \GetExerciseProperty{counter}%
- \IfInsideSolutionF
- {%
- \IfExercisePropertySetT{subtitle}
- { {\normalfont(\GetExerciseProperty{subtitle})}}%
- }%
- }%
- }{}
+\DeclareExerciseEnvironmentTemplate{custom}{%
+ \subsection*{%
+ \XSIMmixedcase{\GetExerciseName}\nobreakspace
+ \GetExerciseProperty{counter}%
+ \IfInsideSolutionF{%
+ \IfExercisePropertySetT{subtitle}
+ { {\normalfont(\GetExerciseProperty{subtitle})}}%
+ }%
+ }%
+}{}
\xsimsetup{
exercise/name = \XSIMtranslate{question} ,
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-370642.pdf
===================================================================
(Binary files differ)
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530-exercises.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530-exercises.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530-exercises.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,12 @@
+\begin{question}
+ Who is the Defence Minister?
+\end{question}
+\begin{question}
+ Who is the Home Minister?
+\end{question}
+\begin{question}
+ Who is the Finance Minister?
+\end{question}
+\begin{question}
+ Who is the External Affairs Minister?
+\end{question}
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530-exercises.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-391530.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -14,28 +14,23 @@
\DeclareExerciseProperty{title}
\makeatletter
-\DeclareExerciseEnvironmentTemplate{named}
- {%
- \subsection*{%
- \GetExercisePropertyTF{title}
- {#1}
- {??\@latex at warning{Please give an exercise title}}%
- }%
- }
- {}
+\DeclareExerciseEnvironmentTemplate{named}{%
+ \subsection*{%
+ \GetExercisePropertyTF{title}
+ {#1}
+ {??\@latex at warning{Please give an exercise title}}%
+ }%
+}{}
\makeatother
-\DeclareExerciseEnvironmentTemplate{item}
- {\item}
- {}
-
+\DeclareExerciseEnvironmentTemplate{item}{\item}{}
\DeclareExerciseCollection{exercise-pool}
-\xsimsetup{
- exercise/template = named
-}
+\xsimsetup{ exercise/template = named }
-\begin{filecontents*}{\jobname-exercises.tex}
+\begin{document}
+
+\collectexercises{exercise-pool}
\begin{question}
Who is the Defence Minister?
\end{question}
@@ -48,12 +43,6 @@
\begin{question}
Who is the External Affairs Minister?
\end{question}
-\end{filecontents*}
-
-\begin{document}
-
-\collectexercises{exercise-pool}
-\input{\jobname-exercises.tex}
\collectexercisesstop{exercise-pool}
\begin{exercise}[title=Answer the following in one sentence:]
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-395273.pdf
===================================================================
(Binary files differ)
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.pdf 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.pdf 2021-01-31 21:33:37 UTC (rev 57572)
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,56 @@
+% https://tex.stackexchange.com/q/466584
+\documentclass{article}
+\usepackage{xsim}
+\usepackage{needspace}
+\usepackage{tasks}
+
+\DeclareExerciseEnvironmentTemplate{exandsol}{%
+ \par\vspace{\baselineskip}
+ \Needspace*{2\baselineskip}
+ \noindent\sffamily
+ \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}%
+ \GetExercisePropertyT{subtitle}{\hspace{3em}{\small#1}}\par
+ \normalfont
+}{}
+
+\DeclareExerciseEnvironmentTemplate{flushright}{%
+ \begin{flushright}
+ \begin{minipage}{.4\linewidth}
+ \textsf{Solutions:}\par\normalfont
+}{%
+ \end{minipage}%
+ \end{flushright}%
+}
+
+\xsimsetup{
+ exercise/within = section ,
+ exercise/template = exandsol ,
+ solution/template = flushright ,
+ solution/print = true
+}
+
+\renewcommand*\theexercise{\thesection-\arabic{exercise}}
+\newcommand\QA[2]{\IfInsideSolutionTF{#2}{#1}}
+
+\newcommand*\answer[1]{%
+ \begingroup
+ \def\ExerciseType{exercise}%
+ \IfSolutionPrintT{\printsolution{exercise}{#1}}%
+ \endgroup
+}
+
+\begin{document}
+
+\setcounter{section}{1}
+\setcounter{exercise}{30}
+
+\begin{exercise}[ID=one,solution,subtitle=Factorize as much as possible the following expressions.]
+ \begin{tasks}
+ \task \QA{$(2x-3)^2 - (3x-2)^2 =$}{$-(x+5)(5x-1)$}
+ \task \QA{$(x^2-25) - 2(5-x)(x+6) =$}{$(x+5)(3x-17)$}
+ \task \QA{$2x(x+2) + (x+1)^2 + 2 =$}{$3(x+1)^2$}
+ \end{tasks}
+\end{exercise}
+\answer{one}
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-466584.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-498299.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-498299.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-498299.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-498299.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,3 +1,4 @@
+% https://tex.stackexchange.com/q/498299
\documentclass{article}
\usepackage[no-files]{xsim}
\usepackage{tasks}
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.pdf 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.pdf 2021-01-31 21:33:37 UTC (rev 57572)
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,135 @@
+% https://tex.stackexchange.com/q/576998
+\documentclass[twocolumn]{book}
+\usepackage{xsim}
+
+\DeclareExerciseEnvironmentTemplate{number-only}{%
+ \par\noindent
+ \textbf{\GetExerciseProperty{counter}}%
+ \GetExercisePropertyT{subtitle}{ \textit{#1}} %
+}{\par}
+
+\newcommand\printsectionexercises{%
+ \ForEachUsedExerciseByType{%
+ \ifnum\ExercisePropertyGet{##1}{##2}{chapter-value}=\value{chapter}
+ \ifnum\ExercisePropertyGet{##1}{##2}{section-value}=\value{section}
+ \XSIMprint{exercise}{##1}{##2}%
+ \fi
+ \fi
+ }%
+}
+
+\renewcommand\printsolutions{%
+ \def\currentchapter{}%
+ \def\currentsection{}%
+ \def\lastchapter{}%
+ \def\lastsection{}%
+ \ForEachUsedExerciseByType{%
+ \let\lastchapter\currentchapter
+ \let\lastsection\currentsection
+ \edef\currentchapter{\ExercisePropertyGet{##1}{##2}{chapter-value}}%
+ \edef\currentsection{\ExercisePropertyGet{##1}{##2}{section-value}}%
+ \ifx\lastchapter\currentchapter\else
+ \section*{Chapter \ExercisePropertyGet{##1}{##2}{chapter}}
+ \fi
+ \ifx\lastsection\currentsection\else
+ \subsection*{Exercises \ExercisePropertyGet{##1}{##2}{section}}
+ \fi
+ \XSIMprint{solution}{##1}{##2}%
+ }%
+}
+
+\xsimsetup{
+ exercise/template = number-only ,
+ solution/template = number-only ,
+ exercise/within = section ,
+ exercise/the-counter = \arabic{exercise}. ,
+ exercise/print = false
+}
+
+\begin{document}
+
+\setcounter{chapter}{13}
+\chapter{}
+\section{Cats as pets}
+Text text text\dots
+\begin{exercise}
+ Draw a cat.
+\end{exercise}
+\begin{solution}
+ Drawing a cat.
+\end{solution}
+
+Text text text\dots
+\begin{exercise}
+ Bathe a cat.
+\end{exercise}
+\begin{solution}
+ Bathing a cat.
+\end{solution}
+
+Text text text\dots
+\begin{exercise}
+ Trace the history of cats through time.
+\end{exercise}
+\begin{solution}
+ Tracing the history of cats through time.
+\end{solution}
+
+\subsection*{Exercises \thesection}
+\printsectionexercises
+
+\section{Frogs as pets}
+Text text text\dots
+\begin{exercise}
+ Lick a frog.
+\end{exercise}
+\begin{solution}
+ Licking a frog.
+\end{solution}
+
+Text text text\dots
+\begin{exercise}
+ Bathe a frog.
+\end{exercise}
+\begin{solution}
+ Bathing a frog.
+\end{solution}
+
+Text text text\dots
+\begin{exercise}
+ Feed a frog.
+\end{exercise}
+\begin{solution}
+ Feeding a frog.
+\end{solution}
+
+\subsection*{Exercises \thesection}
+\printsectionexercises
+
+\setcounter{chapter}{20}
+\chapter{}
+
+\section{The joys of fish}
+Text text text\dots
+\begin{exercise}
+ Catch a fish.
+\end{exercise}
+\begin{solution}
+ Catching a fish.
+\end{solution}
+
+Text text text\dots
+\begin{exercise}
+ Draw a fish.
+\end{exercise}
+\begin{solution}
+ Drawing a fish.
+\end{solution}
+
+\subsection*{Exercises \thesection}
+\printsectionexercises
+
+\chapter*{Solutions to the exercises}
+\printsolutions
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-576998.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.pdf 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.pdf 2021-01-31 21:33:37 UTC (rev 57572)
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,92 @@
+% https://tex.stackexchange.com/q/580636/
+\documentclass{article}
+\usepackage[use-files]{xsim}
+
+\usepackage[colorlinks,allcolors=blue]{hyperref}
+
+\DeclareExerciseProperty{hints}
+\newcounter{hint}
+\renewcommand\theHhint{\ExerciseID.\arabic{hint}}
+\newcounter{hints}
+\newcounter{step}
+
+\NewDocumentEnvironment{hint}{}{%
+ \stepcounter{hint}%
+ \XSIMsetfilebegin{%
+ \par
+ \refstepcounter{hint}\label{hint:\ExerciseID:\arabic{hint}}%
+ \noindent\textbf{Hint~\thehint\ to exercise \GetExerciseProperty{counter}}%
+ \hfill Back to exercise \ref{ex:\ExerciseID}\par
+ \noindent
+ }%
+ \XSIMsetfileend{\par\addvspace{\bigskipamount}}%
+ \XSIMfilewritestart{\jobname-hint-\ExerciseID-\arabic{hint}.tex}%
+}{%
+ \XSIMfilewritestop
+ \stepcounter{hints}%
+ \SetExpandedExerciseProperty{hints}{\arabic{hints}}%
+}
+
+\DeclareExerciseEnvironmentTemplate{hints}{%
+ \setcounter{hint}{0}%
+ \setcounter{hints}{0}%
+ \par\noindent
+ \textbf{\XSIMmixedcase{\GetExerciseName}\GetExerciseProperty{counter}:}\hfill
+ \IfExercisePropertySetT{hints}{%
+ \setcounter{step}{0}%
+ \def\hintcomma{\def\hintcomma{, }}%
+ Hint\ifnum\GetExerciseProperty{hints}=1\else s\fi:
+ \loop\unless\ifnum\value{step}=\GetExerciseProperty{hints}
+ \stepcounter{step}%
+ \hintcomma\ref{hint:\ExerciseID:\arabic{step}}%
+ \repeat
+ \par\noindent
+ }%
+}{\par\addvspace{\bigskipamount}}
+
+\xsimsetup{
+ exercise/within = section ,
+ exercise/begin-hook = \label{ex:\ExerciseID} ,
+ exercise/template = hints
+}
+
+\newcommand\printhints{%
+ \ForEachUsedExerciseByType{%
+ \setcounter{step}{0}%
+ \setcounter{hint}{0}%
+ \loop\unless\ifnum\value{step}=\GetExerciseProperty{hints}
+ \stepcounter{step}%
+ \input{\jobname-hint-\ExerciseID-\arabic{step}.tex}%
+ \repeat
+ }%
+}
+
+\begin{document}
+
+\section{Exercises}
+\begin{exercise}
+ Description of the exercise. Run the following command
+\begin{verbatim}
+print("Hello world")
+Verbatim &^%$&\content
+\end{verbatim}
+\begin{hint}
+ Run the example from the command line with the python command.
+\end{hint}
+\begin{hint}
+ The solution is 42.
+\end{hint}
+\end{exercise}
+
+\begin{exercise}
+ Another exercise
+\begin{hint}
+ The first ten million years were the worst. Some \verb+&$+.
+\end{hint}
+\end{exercise}
+
+
+\section{Hints}
+\printhints
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texsx-580636.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-15093.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-15093.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-15093.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-15093.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,6 +1,5 @@
% http://texwelt.de/wissen/fragen/15093/
\documentclass[paper=a4]{scrartcl}
-\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{xsim,needspace}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-23968.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-23968.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-23968.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-23968.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -18,13 +18,8 @@
\newcommand\printshortsolutions{%
\begin{description}
\ForEachUsedExerciseByType{%
- \def\ExerciseType{##1}%
- \def\ExerciseID{##2}%
\GetExercisePropertyT{shortsolution}
- {%
- \item[Short Solution ##3]
- ####1%
- }%
+ {\item[Short Solution ##3]####1}%
}%
\end{description}
}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-6698.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-6698.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-6698.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.texwelt-6698.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,6 +1,5 @@
% http://texwelt.de/wissen/fragen/6698/
\documentclass{article}
-\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{needspace}
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.various.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.various.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.various.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/examples/xsim.various.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,5 +1,6 @@
\documentclass{article}
-\usepackage{xsim,lipsum,tcolorbox}
+\usepackage[use-files]{xsim}
+\usepackage{lipsum,tcolorbox}
\DeclareExerciseType{question}{
exercise-env = question ,
Added: trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.pdf
===================================================================
(Binary files differ)
Index: trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.pdf 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.pdf 2021-01-31 21:33:37 UTC (rev 57572)
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.tex (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -0,0 +1,2439 @@
+% !arara: pdflatex: { interaction: nonstopmode }
+% !arara: biber
+% arara: pdflatex: { interaction: nonstopmode }
+% arara: pdflatex: { interaction: nonstopmode }
+% !arara: pdflatex: { interaction: nonstopmode }
+% ----------------------------------------------------------------------------
+% the XSIM package
+%
+% eXercise Sheets IMproved
+%
+% ----------------------------------------------------------------------------
+% Clemens Niederberger
+% Web: https://github.com/cgnieder/xsim
+% E-Mail: contact at mychemistry.eu
+% ----------------------------------------------------------------------------
+% Copyright 2017--2021 Clemens Niederberger
+%
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3c
+% 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.3c or later is part of all distributions of LaTeX
+% version 2008/05/04 or later.
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is Clemens Niederberger.
+% ----------------------------------------------------------------------------
+% If you have any ideas, questions, suggestions or bugs to report, please
+% feel free to contact me.
+% ----------------------------------------------------------------------------
+\documentclass{xsim-manual}
+
+\begin{filecontents*}[overwrite]{\jobname.bib}
+ at online{texsx:tagged/exsheets,
+ title = {Questions tagged `exsheets'} ,
+ author = {various} ,
+ url = {http://tex.stackexchange.com/questions/tagged/exsheets} ,
+ urldate = {2020-02-21}
+}
+\end{filecontents*}
+\addbibresource{\jobname.bib}
+
+\begin{document}
+
+\section{Licence, Requirements and \texorpdfstring{\textsc{readme}}{README}}
+\license
+
+\xsim\ loads the packages \pkg{expl3}~\cite{bnd:l3kernel},
+\pkg{xparse}~\cite{bnd:l3packages}, \pkg{array}~\cite{pkg:array}
+\pkg{booktabs}~\cite{pkg:booktabs} and
+\pkg{translations}~\cite{pkg:translations}. All of these packages are present
+on a modern and up to date \TeX\ distribution such as \TeX~Live or MiK\TeX\ so
+no further action should be needed. When you are using \xsim\ you should be
+using an up to date \TeX\ distribution, anyway.
+
+\begin{bewareofthedog}
+ Please be aware that \xsim\ is in an experimental state and actively
+ developed. Many aspects may change from one update to another until a
+ stable version~1 will be reached. However, I will try my best to keep the
+ interface stable.
+
+ Newer versions of \xsim\ may depend on newer versions of the support
+ packages. Remember: it is always dangerous to update single packages.
+ Always update your \TeX\ distribution if you want an up to date version of a
+ package. Be careful: if you're in the middle of an important project it
+ might be better to wait with the update until you've finished the project.
+ Every update might be breaking some things.
+\end{bewareofthedog}
+
+\section{Motivation, Background}
+
+It has been quite a while since I first published
+\pkg{exsheets}~\cite{pkg:exsheets} in June 2012. Since then it has gained a
+user base and a little bit of popularity as the number of questions on tex.sx
+shows (151~at the time of writing)~\cite{texsx:tagged/exsheets}. User
+questions, bug reports and feature requests improved it over the time. It
+still has a version number starting with a zero, though, which in my
+versioning system means I still consider it experimental.
+
+This is due to several facts. It lacks a few features which I consider
+essential for a full version~1. For one thing it is not possible to have
+several kinds of exercises numbered independently. Using verbatim material
+such as listings inside exercises and solutions is not possible and the
+current workaround isn't that ideal either. One request which dates back
+quite a while now was to have different types of points to exercises\ldots
+
+All of those aren't easy to add due to the way \pkg{exsheets} is implemented
+right now. As a consequence I wanted to re-implement \pkg{exsheets} for a long
+time. This is what lead to \xsim. Internally the package works completely
+different.
+
+\begin{bewareofthedog}
+ \xsim\ will be the official successor of \pkg{exsheets} which is now
+ considered obsolete but will stay alive and will still receive bugfix
+ releases. However, new features will not be added to \pkg{exsheets} any
+ more.
+\end{bewareofthedog}
+
+\section{How to Read the Manual}\label{sec:how-read-manual}
+
+\subsection{Nomenclature}
+
+Throughout this manual certain terms are used. This section explains their
+meaning in this manual.
+
+\acuseall
+\printacronyms[heading=none]
+
+\subsection{Package Options}\label{sec:package-options}
+\xsim\ has these package options:
+\begin{options}
+ \opt{verbose}
+ Writes extensive information about what \xsim\ is doing into the log
+ file.
+ \opt{final}
+ If used the exercise and solution environments will not rewrite the
+ environment body files.
+ \opt{clear-aux}
+ If used every time the total number of exercise changes \xsim\ will write
+ \emph{less} information to the auxiliary file on the next run and only if
+ the number of exercises stays stable between compilations the needed
+ information will be written to the auxiliary file. \emph{This needs more
+ compilations until everything stabilizes but should reduce the
+ probability of possibly faulty exercises after changes to the document.}
+ The \option{final} option automatically disables this option. See also
+ sections~\vref{sec:how-exerc-envir} and~\vref{sec:resolve-getting}.
+ \opt{no-files}\Default{true}
+ \sinceversion{0.13}This option prevents \xsim\ from writing the exercises
+ and solutions to external files. This will keep your working folder
+ ``clean'' but will also prevent using verbatim material in exercises and
+ solutions.
+ \opt{use-files}\Default{false}
+ \sinceversion{0.20}This is the opposite of the option \option{no-files}.
+ \opt{use-aux}
+ \sinceversion{0.15}With this option enabled \xsim\ will use the regular
+ auxiliary file \cs*{jobname}\code{.aux} instead of its own auxiliary file
+ \cs*{jobname}\code{.xsim}.
+ \opt{blank}
+ \sinceversion{0.17}With this option enabled \xsim\ will not define the
+ default environments \env{exercise} and \env{solution}.
+\end{options}
+
+Those options are load-time options and are used the usual way as package
+options:
+\begin{sourcecode}
+ \usepackage[use-files]{xsim}
+\end{sourcecode}
+\begin{bewareofthedog}
+ Although those options technically belong to the \module{package} module
+ (see also section~\vref{sec:setting-options}) it is \emph{not} possible to
+ set them via \cs{xsimsetup}.
+\end{bewareofthedog}
+
+\subsection{Setting Options}\label{sec:setting-options}
+Apart from the package options already described in
+section~\vref{sec:package-options} \xsim\ has further options. All those
+options are set using the following command:
+\begin{commands}
+ \command{xsimsetup}[\marg{options}]
+ Set up \xsim's package options and all other options described at
+ other places in the manual.
+\end{commands}
+Options can be \enquote{toplevel} options or options belonging to a module:
+\begin{options}
+ \keyval*{toplevel}{value}
+ A toplevel option.
+ \keyval*{sublevel}{value}\Module*{module}
+ A sublevel option belonging to the module \module*{module}
+\end{options}
+Both kinds of options are set with the setup command:
+\begin{sourcecode}
+ \xsimsetup{
+ toplevel = {value} ,
+ module/sublevel = {value}
+ }
+\end{sourcecode}
+
+\subsection{Command descriptions}
+
+Some commands do have a \expandablesymbol\ symbol printed next to their
+names. This indicates that the command is expandable, \ie, it is usable in an
+\cs*{edef} or \cs*{write} context and will expand according to its
+description. All other commands are engine protected, \ie, in the sense of
+\eTeX's \cs*{protected}.
+
+Some command name descriptions end with \code{\TF}.
+\begin{commands}
+ \command*{SomeCommand\TF}[\meta{arguments}\marg{true}\marg{false}]
+ A command with maybe some arguments and ending with the two arguments
+ \meta{true} and \meta{false}.
+\end{commands}
+This means two things: the command is a conditional which tests something and
+depending on the outcome of the test leaves either the \meta{true} argument
+(\code{T}) or the \meta{false} argument (\code{F}) in the input stream. It
+also means two additional commands exist:
+\begin{commands}
+ \command*{SomeCommandT}[\meta{arguments}\marg{true}]
+ The same as \cs*{SomeCommandTF} but only with the \meta{true} argument and
+ no \meta{false} argument.
+ \command*{SomeCommandF}[\meta{arguments}\marg{false}]
+ The same as \cs*{SomeCommandTF} but only with the \meta{false} argument and
+ no \meta{true} argument.
+\end{commands}
+
+\section{Exercises and Solutions}
+
+The two predefined environments for exercises and solutions are the following
+ones\footnote{When you load \xsim\ with the \option{blank} those environments
+ will \emph{not} be defined!}:
+\begin{environments}
+ \environment{exercise}[\oarg{\acsp*{prop}}]
+ Input and typeset an exercise. See section~\vref{sec:exercise-properties}
+ for details on exercise \acsp*{prop}.
+ \environment{solution}[\oarg{options}]
+ Input and typeset the solution to the exercise of the previous
+ \env{exercise} environment. See section~\vref{sec:printing-solutions} for
+ details on options of solutions.
+\end{environments}
+
+\begin{example}
+ \begin{exercise}
+ A first example for an exercise.
+ \end{exercise}
+ \begin{solution}
+ A first example for a solution.
+ \end{solution}
+\end{example}
+
+As can be seen in the example a solution is not printed with the default
+setup. This can be changed using the following option.
+\begin{options}
+ \keybool{print}\Module{solution}\Default{false}
+ Set if solutions are printed or not.
+\end{options}
+
+The option (belonging to the module \module*{solution}) can either be set
+locally as option to the \env{solution} environment
+\begin{sourcecode}
+ \begin{solution}[print=true]
+ A first example for a solution.
+ \end{solution}
+\end{sourcecode}
+or with the setup command for all following solutions:
+\begin{sourcecode}
+ \xsimsetup{
+ solution/print = true
+ }
+\end{sourcecode}
+
+There is an completely analoguous option for the \env{exercise} environment:
+\begin{options}
+ \keybool{print}\Module{exercise}\Default{true}
+ Set if exercises are printed or not.
+\end{options}
+More details on those two environments can be found in
+section~\vref{sec:using-printing}.
+
+\section{How the Exercise Environments Work}\label{sec:how-exerc-envir}
+\sinceversion{0.13}Depending on the options
+\option{no-files}/\option{use-files} the bodies of exercises and solutions is
+either just another property (see section~\vref{sec:exercise-properties}) --
+this is the default behavior -- or is written to an external file.
+
+If the option \keyis{no-files}{true} is set the exercise and solution bodies
+are saved as properties \property{exercise-body} and
+\property{solution-body}. This is the default behavior of \xsim\ since
+version~0.20 and should work fine in most cases. One obvious downsise is that
+verbatim material cannot be used in exercises and solutions.
+
+If the option \keyis{use-files}{true} is set both the exercise and the
+solution environments write the contents of their bodies verbatim to external
+files following a certain naming structure:
+\begin{itemize}
+ \item
+ \code{\meta{jobname}-\meta{type}-\meta{id}-exercise|solution-body.tex}
+\end{itemize}
+The name starts with the name of the job (which is the name of the document
+itself) followed by type and id of the corresponding exercise and then
+followed by the environment type. For example both environments from the first
+example have been written to files named
+\begin{itemize}
+ \item \verbcode+xsim-manual-exercise-1-exercise-body.tex+ and
+ \item \verbcode+xsim-manual-exercise-1-solution-body.tex+, respectively.
+\end{itemize}
+These external files are input when the respective exercise or solution is
+printed. An advantage of using external files is that \emph{verbatim material
+ is allowed} inside the environments. Details on the \meta{type} of an
+exercise will be given in section~\vref{sec:new-exercise-types}. \emph{The
+ \meta{id} of an exercise is a positive integer unique to each exercise
+ environment regardless if the exercise is being printed or used at all.}
+
+Each of those files contains some information about itself and where and why
+it was generated\footnote{In this example the sourcecode line number is
+ misleading as the example where the file was generated itself was an
+ external file where the \env{exercise} environment indeed \emph{was} on
+ line~1.}:
+
+\inputsourcecode{exercises/xsim-manual-exercise-1-exercise-body.tex}
+
+Arguably one downside of the approach using external files for each exercise
+and its solution is that your project folder will be cluttered with files. In
+order to deal with this somehow \xsim\ offers the following option:
+\begin{options}
+ \keyval{path}{path name}\Default
+ With this option a subfolder or path within the main project folder can be
+ given. Exercises will be written to and included from this path.
+ \emph{The path must exist on your system before you can use it!} This
+ document uses \keyis{path}{exercises}.
+ \keyval{file-extension}{string}\Default{\code{tex}}
+ \sinceversion{0.10}This option let's you choose the extension of the
+ external files.
+\end{options}
+
+\begin{bewareofthedog}
+ Another thing to keep in mind: the environment in many ways works the same
+ way as the \env{filecontents} environment. \emph{This also means that you
+ \emph{cannot} have comments or \cs*{label}s or anything else on the first
+ line of the environments!}
+\end{bewareofthedog}
+\begin{sourcecode}
+ \begin{exercise}[points=2] % this comment will cause trouble
+ Lorem ipsum
+ \end{exercise}
+\end{sourcecode}
+
+\begin{bewareofthedog}
+ \xsimauxfileinfo
+\end{bewareofthedog}
+
+\begin{bewareofthedog}
+ A lot of the lines \xsim\ writes to the auxiliary file and reads in a
+ subsequent run look like this:
+\begin{sourcecode}
+ \XSIM{points}{exercise-2=={4}||exercise-10=={2.5}||problem-11=={5}}
+\end{sourcecode}
+ As you can see different entries of the various properties of exercises are
+ separated with \code{||}. This means that you cannot use this symbol
+ combination inside properties. For this reason \xsim\ provides an option to
+ change the marker.
+\end{bewareofthedog}
+\begin{options}
+ \keyval{split-aux-lists}{string}\Default{\code{||}}
+ Set\sinceversion{0.11} the string that is used to separate the property
+ entries in the auxiliary file.
+\end{options}
+
+\section{New Exercise Types}\label{sec:new-exercise-types}
+
+It is easy to define new exercise environments together with a corresponding
+solution environment using the following command:
+\begin{commands}
+ \command{DeclareExerciseType}[\marg{type}\marg{parameters}]
+ Declare a new exercise type analoguous to the \env{exercise} and
+ \env{solution} environments.
+\end{commands}
+Declaring a new exercise type will also define a new command:
+\begin{commands}
+ \command{numberof\meta{exercise-env}s}
+ These commands hold the absolut number of used exercises of type
+ \meta{type}. The meaning of \meta{exercise-env} will become clear below
+ when the exercise parameters are explained. It is always the same as the
+ exercise environment name.
+\end{commands}
+\begin{example}
+ There are \numberofexercises~exercises and \numberofproblems~problem in this
+ manual.
+\end{example}
+\xsim's pre-defined environment pair\changedversion{0.14} has been defined as
+follows:
+\begin{sourcecode}
+ \DeclareExerciseType{exercise}{
+ exercise-env = exercise ,
+ solution-env = solution ,
+ exercise-name = \XSIMtranslate{exercise} ,
+ exercises-name = \XSIMtranslate{exercises} ,
+ solution-name = \XSIMtranslate{solution} ,
+ solutions-name = \XSIMtranslate{solutions} ,
+ exercise-template = default ,
+ solution-template = default ,
+ exercise-heading = \subsection* ,
+ solution-heading = \subsection*
+ }
+\end{sourcecode}
+
+The above already is an example for almost all parameters that can (and often
+must) be set. Here is the complete list:
+\begin{parameters}
+ \paraval{exercise-env}{exercise environment name}
+ The name for the environment used for the exercises of type \meta{type}.
+ \emph{This parameter is mandatory.} It can't be changed afterwards.
+ \paraval{solution-env}{solution environment name}
+ The name for the environment used for the solutions of type \meta{type}.
+ \emph{This parameter is mandatory.} It can't be changed afterwards.
+ \paraval{exercise-name}{exercise name}
+ The name of the exercises of type \meta{type} -- used for typesetting.
+ \emph{This parameter is mandatory.}
+ \paraval{exercises-name}{exercises name}
+ The\sinceversion{0.12} plural name of the exercises of type \meta{type} --
+ used for typesetting. If this is not set explicitly an \code{s} is
+ appended to the singular name.
+ \paraval{solution-name}{solution name}
+ The name of the solutions of type \meta{type} -- used for typesetting.
+ \emph{This parameter is mandatory.}
+ \paraval{solutions-name}{solutions name}
+ The\sinceversion{0.12} plural name of the solutions of type \meta{type} --
+ used for typesetting. If this is not set explicitly an \code{s} is
+ appended to the singular name.
+ \paraval{exercise-template}{exercise template}
+ The template used for typesetting the exercises of type \meta{type}.
+ \emph{This parameter is mandatory.} See
+ section~\vref{sec:styl-exerc-templ} for details on templates.
+ \paraval{solution-template}{solution template}
+ The template used for typesetting the exercises of type \meta{type}.
+ \emph{This parameter is mandatory.} See
+ section~\vref{sec:styl-exerc-templ} for details on templates.
+ \paraval{counter}{counter name}
+ The counter used for the exercises of type \meta{type}. If not explicitly
+ set the counter with the same name as \parameter{exercise-env} is used.
+ Otherwise the specified counter is used. This enables to have different
+ types of exercises sharing a common counter. \emph{This parameter can't
+ be changed afterwards.} If the explicit or implicit counter does not
+ exist, yet, it will be defined.
+ \paraval{within}{counter name}
+ \sinceversion{0.20}Adds \parameter{counter} to the reset list of
+ \meta{counter name} by applying \cs*{counterwithin}.
+ \paraval{the-counter}{code}
+ \sinceversion{0.20}Redefines the corresponding representation command
+ \cs*{the...} of \parameter{counter} to \meta{code}.
+ \paraval{solution-counter}{counter name}
+ The counter used for the solutions of type \meta{type}. If not explicitly
+ set the counter with the same name as \parameter{solution-env} is used.
+ Otherwise the specified counter is used. This enables to have different
+ types of solutions sharing a common counter although this doesn't actually
+ make much sense. But it can be useful to avoid using an already existing
+ counter. \emph{This parameter can't be changed afterwards.} If the
+ explicit or implicit counter does not exist, yet, it will be defined. The
+ sole purpose of this counter is to be able to label solutions so they can
+ be \cs*{pageref}ed.
+ \paraval{number}{integer}
+ An internal parameter that is used to keep track of the number of
+ exercises of a type. This parameter cannot be set or changed by the
+ user.
+ \paraval{exercise-heading}{exercise heading command}
+ The\sinceversion{0.14} command used for typesetting of the heading of
+ exercises of type \meta{type} -- used for typesetting with the command
+ \cs{GetExerciseHeadingF}.
+ \paraval{solution-heading}{solution heading command}
+ The\sinceversion{0.14} command used for typesetting of the heading of
+ solutions of type \meta{type} -- used for typesetting with the command
+ \cs{GetExerciseHeadingF}.
+\end{parameters}
+
+It is possible to change some of the parameters after an exercise type has
+been defined. Those include \parameter{exercise-name},
+\parameter{solution-name}, \parameter{exercise-template}, and
+\parameter{solution-template}. It is also possible to define new parameters.
+\begin{commands}
+ \command{DeclareExerciseParameter}[\sarg\marg{parameter}]
+ Declares the new parameter \meta{parameter}. The optional star declares a
+ fixed parameter which cannot be changed once it is set. \emph{You
+ probably will never need this command. Most tasks can be solved using
+ properties (see section~\vref{sec:exercise-properties}) instead.}
+ \command{SetExerciseParameter}[\marg{type}\marg{parameter}\marg{value}]
+ Usable to set a single parameter to a new value.
+ \command{SetExerciseParameters}[\marg{type}\marg{parameters}]
+ Set several parameters at once. \meta{parameters} is a csv list of
+ key/value pairs.
+\end{commands}
+If you try to set an already set but fixed parameter like
+\parameter{exercise-env} a warning will be written to the log file. For all
+parameters that can be changed also options exist wich can be set via
+\cs{xsimsetup}. They are explained in
+section~\vref{sec:environment-options-hooks}.
+
+\begin{bewareofthedog}
+ All exercises of a type use the parameters
+ (\eg, \parameter{exercise-template}) that are \emph{currently active}. If
+ you want exercises with a different look or different names in the same
+ document you should use different exercises types.
+\end{bewareofthedog}
+
+\section{Exercise Properties}\label{sec:exercise-properties}
+
+\subsection{Predefined Properties}
+
+Exercise like the \env{exercise} environment and possibly others defined with
+\cs{DeclareExerciseType} have a number of predefined \acsp*{prop}:
+\begin{properties}
+ \propval{id}{integer}
+ Holds the internal id of an exercise. \emph{Cannot be set by the user}.
+ \propval{ID}{text}
+ Holds the user id of an exercise if defined. Otherwise it is equal to
+ \property{id}.
+ \propval{counter}{text}
+ Holds the counter value representation of an exercise (\ie, what you
+ usually know as \cs*{the\meta{counter}}). \emph{Cannot be set by the
+ user}.
+ \propval{counter-value}{integer}
+ Holds the counter value of an exercise (\ie, what you usually know as
+ \cs*{the}\cs*{value}\marg{counter}). \emph{Cannot be set by the user}.
+ \propval{subtitle}{text}
+ Holds the subtitle of an exercise.
+ \propval{points}{number}
+ Holds the reachable points of an exercise.
+ \propval{bonus-points}{number}
+ Holds the reachable bonus-points of an exercise.
+ \propbool{print}
+ Holds the print boolean of an exercise.
+ \propbool{print\bang}
+ Holds a special print boolean of an exercise, see
+ page~\pageref{property:print!}.
+ \propbool{use}
+ Holds the usage boolean of an exercise.
+ \propbool{use\bang}
+ Holds a special usage boolean of an exercise, see
+ page~\pageref{property:print!}.
+ \propbool{used}
+ True if an exercise has been used at least once. For an existing exercise
+ this is only false for exercises that have been collected
+ (\cf~section~\vref{sec:collecting-exercises}).
+ \propbool{solution}
+ \sinceversion{0.17}Holds the solution boolean of an exercise. If this is
+ true then a solution has the same text\slash environment body as the
+ corresponding exercise. (This might be useful for multiple choice
+ questions for example.)
+ \propval{tags}{csv list of tags}
+ Holds the list of tags the exercise should be associated with.
+ \propval{topics}{csv list of topics}
+ Holds the list of topics the exercise should be associated with.
+ \propval{page}{text}
+ Holds the page counter value representation of an exercise \\
+ (\ie, what you usually know as \cs*{thepage}).
+ \propval{page-value}{integer}
+ Holds the page counter value of an exercise \\
+ (\ie, what you usually know as \cs*{the}\cs*{value}\Marg{page}).
+ \propval{section}{text}
+ Holds the section counter value representation of an exercise \\
+ (\ie, what you usually know as \cs*{thesection}).
+ \propval{section-value}{integer}
+ Holds the section counter value of an exercise \\
+ (\ie, what you usually know as \cs*{the}\cs*{value}\Marg{section}).
+ \propval{chapter}{text}
+ Holds the chapter counter value representation of an exercise \\
+ (\ie, what you usually know as \cs*{thechapter}). \\
+ \emph{Only if a command \cs*{chapter} \emph{and} a counter \code{chapter}
+ exist.}
+ \propval{chapter-value}{integer}
+ Holds the chapter counter value of an exercise \\
+ (\ie, what you usually know as \cs*{the}\cs*{value}\Marg{chapter}). \\
+ \emph{Only if a command \cs*{chapter} \emph{and} a counter \code{chapter}
+ exist.}
+ \propval{sectioning}{section numbers}
+ Holds five brace groups which in turn hold the section numbers (integers)
+ of the exercise in the order
+ \marg{chapter}\marg{section}\marg{subsection}\marg{subsubsection}\marg{paragraph}.
+ \propval{exercise-body}{\TeX code}
+ When\sinceversion{0.13} the package option \option{no-files} is set this
+ property is defined and holds the environment body of an exercise.
+ \propval{solution-body}{\TeX code}
+ When\sinceversion{0.13} the package option \option{no-files} is set this
+ property is defined and holds the environment body of the corresponding
+ solution.
+\end{properties}
+
+Some of these \acsp*{prop} are fixed and cannot be set by the user. Those
+include \property{id}, \property{counter}, and \property{counter-value}. The
+others can be set using the optional argument of the exercise environment.
+
+\begin{example}
+ \begin{exercise}[subtitle={This is a subtitle},points=4,bonus-points=1]
+ An exercise where some properties have been set.
+ \end{exercise}
+\end{example}
+
+\subsection{Declaring Own Properties}
+
+\xsim\ offers the possibility to declare additional exercise properties:
+\begin{commands}
+ \command{DeclareExerciseProperty}[\barg\sarg\narg\marg{property}]
+ Declares the property \meta{property}.
+
+ If used with the optional \barg\ a \textbf{unique property} is defined
+ which means that each exercise must have a property value distinct from
+ all other exercises (all means all -- \emph{independent from the exercise
+ type}).
+
+ If used with the optional \sarg\ a \textbf{boolean property} is defined
+ which means that it only should get the values \code{true} or \code{false}
+ and if used without value it gets the value \code{true} instead of an
+ empty value. If any other value is used the property is set to
+ \code{false}. A boolean property obviously cannot be unique. The
+ optional \sarg\ takes precedence over the optional \barg, \ie, if both are
+ present the property is boolean \emph{but not} unique.
+
+ If used with the optional \narg\ a property is defined which won't get
+ updated through subsequent compilation runs but is only set when the
+ exercise is used.
+ \command{DeclareExercisePropertyAlias}[\marg{property 1}\marg{property 2}]
+ Declares \meta{property 1} to be an alias of \meta{property 2}. This
+ means that each time \meta{property 2} is set \meta{property 1} will be
+ set to the same value \emph{unless} it has been set already. As an
+ example: property \property{ID} is an alias of property \property{id}.
+\end{commands}
+
+This is better demonstrated with an example:
+\begin{example}
+ \begin{exercise}
+ \verb+\GetExerciseProperty{id}+: \GetExerciseProperty{id} \par
+ \verb+\GetExerciseAliasProperty{ID}+: \GetExerciseAliasProperty{ID} \par
+ \verb+\GetExerciseProperty{ID}+: \GetExerciseProperty{ID}
+ \end{exercise}
+ \begin{exercise}[ID=foo-bar]
+ \verb+\GetExerciseProperty{id}+: \GetExerciseProperty{id} \par
+ \verb+\GetExerciseAliasProperty{ID}+: \GetExerciseAliasProperty{ID} \par
+ \verb+\GetExerciseProperty{ID}+: \GetExerciseProperty{ID}
+ \end{exercise}
+\end{example}
+
+The power of properties will get more clear when reading
+section~\vref{sec:styl-exerc-templ} about templates.
+
+\subsection[Exercise Goals]{A Special Kind of Property: Exercise Goals}\label{sec:goals}
+
+Exercise goals are a generic concept in \xsim\ for exercise properties like
+\property{points} or \property{bonus-points}. Those are properties which can
+(only) get a decimal number as value the sum of which is calculated and
+available (after a compilation) throughout the document.
+\begin{commands}
+ \command{DeclareExerciseGoal}[\marg{goal}]
+ Declare a new exercise goal named \meta{goal} and also a property called
+ \meta{goal}.
+ \command{TotalExerciseTypeGoal}[\marg{type}\marg{goal}\marg{singular}\marg{plural}]
+ Get the sum of goal \meta{goal} for all exercises of type \meta{type}.
+ \meta{singular} and \meta{plural} are placed after the sum in the input
+ stream depending on whether the sum equals~$1$ or not.
+ \command{TotalExerciseTypeGoals}[\marg{type}\marg{list of
+ goals}\marg{singular}\marg{plural}]
+ Get the sum of goal all goals in \meta{list of goals} for all exercises of
+ type \meta{type}. The goal names in \meta{list of goals} must be
+ separated with \code{+}. \meta{singular} and \meta{plural} are placed
+ after the sum in the input stream depending on whether the sum equals~$1$
+ or not.
+ \command{TotalExerciseGoal}[\marg{goal}\marg{singular}\marg{plural}]
+ Get the sum of goal \meta{goal} for all exercises. \meta{singular} and
+ \meta{plural} are placed after the sum in the input stream depending on
+ whether the sum equals~$1$ or not.
+ \command{TotalExerciseGoals}[\marg{list of
+ goals}\marg{singular}\marg{plural}]
+ Get the sum of goal all goals in \meta{list of goals} for all exercises.
+ The goal names in \meta{list of goals} must be separated with
+ \code{+}. \meta{singular} and \meta{plural} are placed after the sum in
+ the input stream depending on whether the sum equals~$1$ or not.
+ \command{AddtoExerciseTypeGoal}[\marg{type}\marg{goal}\marg{value}]
+ Adds \meta{value} to the goal \meta{goal} of exercise type \meta{type}.
+ \command{AddtoExerciseTypeGoalPrint}[\marg{type}\marg{goal}\marg{value}%
+ \marg{singular}\marg{plural}]
+ Adds \meta{value} to the goal \meta{goal} of exercise type \meta{type}.
+ The value and -- depending on wether the value equals $1$ or not --
+ \meta{singular} or \meta{plural} are left in the input stream.
+ \command{AddtoExerciseGoal}[\marg{goal}\marg{value}]
+ Adds \meta{value} to the goal \meta{goal} of the current exercise
+ type. (To be used within exercises.)
+ \command{AddtoExerciseTypeGoalPrint}[\marg{goal}\marg{value}%
+ \marg{singular}\marg{plural}]
+ Adds \meta{value} to the goal \meta{goal} of the current exercise type.
+ The value and -- depending on wether the value equals $1$ or not --
+ \meta{singular} or \meta{plural} are left in the input stream. (To be used
+ within exercises.)
+ \command{ExerciseGoalValuePrint}[\marg{value}\marg{singular}\marg{plural}]
+ Print \meta{value} and -- depending on wether the value equals $1$ or not --
+ \meta{singular} or \meta{plural}.
+ \command{printgoal}[\marg{value}]
+ Print \meta{value} according to option \option{goal-print}. Defined in
+ terms of \cs{ExerciseGoalValuePrint}.
+ \command{printpoints}[\marg{type}]
+ Print the sum of points for all exercises of type \meta{type} followed by
+ an appropriate translation of the words \enquote{point} or
+ \enquote{points}, respectively\footnote{See section~\vref{sec:exerc-transl}
+ for details on the definition and usage of language dependent words.}.
+ Defined in terms of \cs{TotalExerciseTypeGoal}.
+ \command{printtotalpoints}
+ Print the sum of points for all exercises followed by an appropriate
+ translation of the words \enquote{point} or \enquote{points},
+ respectively. Defined in terms of \cs{TotalExerciseGoal}.
+ \command{addpoints}[\sarg\marg{value}]
+ Adds \meta{value} to the points of the current exercise type. (To be used
+ within exercises.) Prints the value followed by an appropriate
+ translation of the words \enquote{point} or \enquote{points},
+ respectively. The starred version prints nothing. Defined in terms of
+ \cs{AddtoExerciseGoal} and \cs{AddtoExerciseGoalPrint}.
+ \command{points}[\marg{value}]
+ Print \meta{value} followed by an appropriate translation of the words
+ \enquote{point} or \enquote{points}, respectively. Defined in terms of
+ \cs{ExerciseGoalValuePrint}.
+ \command{printbonus}[\marg{type}]
+ Print the sum of bonus points for all exercises of type \meta{type}
+ followed by an appropriate translation of the words \enquote{point} or
+ \enquote{points}, respectively. Defined in terms of
+ \cs{TotalExerciseTypeGoal}.
+ \command{printtotalbonus}
+ Print the sum of bonus points for all exercises followed by an appropriate
+ translation of the words \enquote{point} or \enquote{points},
+ respectively. Defined in terms of \cs{TotalExerciseGoal}.
+ \command{addbonus}[\sarg\marg{value}]
+ Adds \meta{value} to the bonus points of the current exercise type. (To be
+ used within exercises.) Prints the value followed by an appropriate
+ translation of the words \enquote{point} or \enquote{points},
+ respectively. The starred version prints nothing. Defined in terms of
+ \cs{AddtoExerciseGoal} and \cs{AddtoExerciseGoalPrint}.
+\end{commands}
+
+The two existing goals are defined with
+\begin{sourcecode}
+ \DeclareExerciseGoal{points}
+ \DeclareExerciseGoal{bonus-points}
+\end{sourcecode}
+
+When goal values are printed the decimal number is fed to a function which can
+be changed using the following option:
+\begin{options}
+ \keyval{goal-print}{code}\Default{\#1}
+ How to format goal values. Use \code{\#1} to refer to the actual number.
+\end{options}
+
+At last some examples for a custom command: let's say you want a command which
+prints the complete sum for all exercises of all exercise types of both
+\property{points} \emph{and} \property{bonus-points} added up:
+\begin{sourcecode}
+ \NewDocumentCommand\printsumofpointsandbonus{}{%
+ \TotalExerciseGoals{points+bonus-points}
+ {\,\XSIMtranslate{point}}
+ {\,\XSIMtranslate{points}}%
+ }
+\end{sourcecode}
+Here is how you could mimick the command \cs*{totalpoints} from
+\pkg{exsheets}:
+\begin{sourcecode}
+ \NewDocumentCommand\pointsandbonus{}{%
+ \TotalExerciseGoal{points}{}{}%
+ \IfExerciseGoalsSumF{bonus-points}{=0}
+ {\,(+\,\TotalExerciseGoal{bonus-points}{}{})}%
+ \,\XSIMtranslate{points}%
+ }
+\end{sourcecode}
+
+
+\subsection[Exercise Tags]{A Special Kind of Property: Exercise Tags}\label{sec:tags}
+
+Exercise tags are a generic concept in \xsim\ for exercise properties like
+\property{tags} or \property{topics}. Those are properties which can (only)
+get a csv list of strings as value. Those strings can be used to selectively
+use exercises. See section~\vref{sec:using-printing} for details on
+\emph{usage} of exercises and the difference to \emph{printing} an exercise
+and how to use exercise tags for selection.
+\begin{commands}
+ \command{DeclareExerciseTagging}[\marg{tag}]
+ This defines an exercise tagging group named \meta{tag}. It also defines a
+ property named \meta{tag}. In addition two options are defined: an option
+ named \code{\meta{tag}} which can be used for selection and an boolean
+ option \code{\meta{tag}/ignore-untagged}.
+ \command{ProvideExerciseTagging}[\marg{tag}]
+ The\sinceversion{0.11} same as \cs{DeclareExerciseTagging} but does
+ nothing when \meta{tag} already exists.
+\end{commands}
+The two existing tagging groups have been defined and preset with the
+following code:
+\begin{sourcecode}
+ \DeclareExerciseTagging{tags}
+ \DeclareExerciseTagging{topics}
+ \xsimsetup{tags/ignore-untagged=false}
+\end{sourcecode}
+This means that these options are available:
+\begin{options}
+ \keyval{tags}{csv list of tags}
+ Choose the set of tags whose associated exercises should be printed.
+ \keyval{topics}{csv list of topics}
+ Choose the set of topics whose associated exercises should be printed.
+ \keybool{ignore-untagged}\Module{tags}\Default{false}
+ If set to true exercises with no tags will be printed even if tags have
+ been chosen with the option \option{tags}.
+ \keybool{ignore-untagged}\Module{topics}\Default{true}
+ If set to true exercises with no topics will be printed even if topics
+ have been chosen with the option \option{topics}.
+\end{options}
+
+It may happen that you choose certain tags for printing and want one or two
+exercises to be printed or used even if they don't match the tagging
+criteria. For this reason two additional properties exist which can be set to
+an exercise:\label{property:print!}
+\begin{properties}
+ \propbool{print\bang}
+ If set to true the exercise will be printed (and thus used) regardless of
+ other conditions.
+ \propbool{use\bang}
+ If set to true the exercise will be used regardless of other conditions.
+\end{properties}
+
+\section{Using and Printing an Exercise}\label{sec:using-printing}
+\subsection{What the Environments do}
+
+When an exercise is started with \environ{exercise} (or other environments
+defined through \cs{DeclareExerciseType}) then three things happen depending
+on the setup:
+\begin{enumerate}
+ \item where the environment is placed in the document the \textbf{base
+ setup} happens: this sets the \property{id} of the exercise and sets the
+ properties chosen in the optional argument.
+ \item in the default setting also the \textbf{usage setup} happens: this
+ increments the counter and sets the counter related properties like
+ \property{counter}. Also the properties related to section numbers and the
+ \property{page} are set.
+ \item in the default setting also the \textbf{print setup} happens: this
+ mostly does nothing. It initiates recording goals that are set inside of
+ the exercise body.
+\end{enumerate}
+
+Depending on wether the option \module{exercise}\code{/}\option{use} has been
+set to \code{false} or wether the property \property{use} has been set to
+\code{false} the \emph{usage setup} can be delayed. The usage the happens
+when the exercise is \emph{inserted} the first time elsewhere in the document,
+for example as part of a collection, see
+section~\vref{sec:collecting-exercises}.
+
+Depending on wether the option \module{exercise}\code{/}\option{print} has
+been set to \code{false} or if the property \property{print} has been set to
+\code{false} the \emph{print setup} can be suppressed. It happens each time
+an exercise is inserted.
+
+\begin{example}
+ \begin{exercise}[print=false,ID=invisible]
+ This exercise will not be printed but the exercise counter will be
+ incremented nonetheless. Its solution will be printed in the list of
+ solutions.
+ \end{exercise}
+ \begin{solution}
+ The solution of the exercise that has not been printed.
+ \end{solution}
+\end{example}
+
+The schematic structure of an exercise is shown in
+figure~\vref{fig:schematic-structure}.
+
+\begin{figure}
+ \centering
+ \begin{tikzpicture}
+ \node[draw,minimum width=.7\linewidth] at (0,0) {pre hook};
+ \node[draw,minimum width=.7\linewidth] at (0,-1) {begin template code};
+ \node[draw,minimum width=.7\linewidth] at (0,-2) {begin hook};
+ \node[draw,minimum width=.7\linewidth] at (0,-3) {environment body};
+ \node[draw,minimum width=.7\linewidth] at (0,-4) {end hook};
+ \node[draw,minimum width=.7\linewidth] at (0,-5) {end template code};
+ \node[draw,minimum width=.7\linewidth] at (0,-6) {post hook};
+ \end{tikzpicture}
+ \caption{Schematic structure of an exercise or solution.}\label{fig:schematic-structure}
+\end{figure}
+
+\subsection{Environment Options \& Hooks}\label{sec:environment-options-hooks}
+
+For each exercise type there are the following options for both environments,
+the environments' names are the module names for the options (here using the
+\enquote{exercise} type):
+\begin{options}
+ \keybool{print}\Module{exercise}\Default{true}
+ Determines if exercises of type \enquote{exercise} are printed.
+ \keybool{use}\Module{exercise}\Default{true}
+ Determines if exercises of type \enquote{exercise} are used.
+ \keybool{collect}\Module{exercise}\Default{false}
+ \sinceversion{0.20}Sets both \option{print} and \option{use} to
+ \code{false} when \keyis{collect}{true} is set and vice versa.
+ \keyval{within}{counter}\Module{exercise}\Default
+ \changedversion{0.20}Adds the exercise counter to the reset list of the
+ counter \meta{counter} using \cs*{counterwithin}. \emph{Beware that if
+ the counter is a shared counter this will affect \emph{all objects}
+ using this counter!}
+ \keyval{the-counter}{code}\Module{exercise}
+ An interface for redefining the counter representation command
+ \cs*{the\meta{counter}}.
+ \keyval{template}{template}\Module{exercise}
+ An interface for \cs{SetExerciseParameter}\Marg{exercise}%
+ \Marg{exercise-template}\marg{template}.
+ \keyval{template}{template}\Module{solution}
+ An interface for \cs{SetExerciseParameter}\Marg{exercise}%
+ \Marg{solution-template}\marg{template}.
+ \keyval{name}{name}\Module{exercise}
+ An interface for \cs{SetExerciseParameter}\Marg{exercise}%
+ \Marg{exercise-name}\marg{name}.
+ \keyval{name}{name}\Module{solution}
+ An interface for \cs{SetExerciseParameter}\Marg{exercise}%
+ \Marg{solution-name}\marg{name}.
+ \keyval{heading}{heading command}\Module{exercise}
+ An\sinceversion{0.14} interface for \cs{SetExerciseParameter}%
+ \Marg{exercise}\Marg{exercise-heading}\marg{heading command}.
+ \keyval{heading}{heading command}\Module{solution}
+ An\sinceversion{0.14} interface for \cs{SetExerciseParameter}%
+ \Marg{exercise}\Marg{solution-heading}\marg{heading command}.
+ \keyval{pre-hook}{code}\Module{exercise}\Default
+ The code for the \emph{pre exercise hook} for exercises of the type
+ \enquote{exercise}.
+ \keyval{begin-hook}{code}\Module{exercise}\Default
+ The code for the \emph{begin exercise hook} for exercises of the type
+ \enquote{exercise}.
+ \keyval{end-hook}{code}\Module{exercise}\Default
+ The code for the \emph{end exercise hook} for exercises of the type
+ \enquote{exercise}.
+ \keyval{post-hook}{code}\Module{exercise}\Default
+ The code for the \emph{post exercise hook} for exercises of the type
+ \enquote{exercise}.
+ \keybool{print}\Module{solution}\Default{false}
+ Determines if solutions of type \enquote{exercise} are printed.
+ \keyval{pre-hook}{code}\Module{solution}\Default
+ The code for the \emph{pre solution hook} for solutions of the type
+ \enquote{exercise}.
+ \keyval{begin-hook}{code}\Module{solution}\Default
+ The code for the \emph{begin solution hook} for solutions of the type
+ \enquote{exercise}.
+ \keyval{end-hook}{code}\Module{solution}\Default
+ The code for the \emph{end solution hook} for solutions of the type
+ \enquote{exercise}.
+ \keyval{post-hook}{code}\Module{solution}\Default
+ The code for the \emph{post solution hook} for solutions of the type
+ \enquote{exercise}.
+ % TODO
+\end{options}
+
+\subsection{(Re-) Inserting a Certain Exercise}
+If you know type and \property{id} of an exercise you can (re-)insert every
+existing exercise, \ie, every exercise whose external file exists.
+\begin{commands}
+ \command{printexercise}[\marg{type}\marg{csv of ids}]
+ \changedversion{0.17}Inserts the exercise or exercises of type
+ \meta{type} with the \property{id}s or \property{ID}s given in \meta{csv
+ of ids}.
+ \command{xprintexercise}[\marg{type}\marg{csv of ids}]
+ \sincechanged{0.16}{0.17}The same as \cs{printexercise} but expands
+ \meta{type} and the items of \meta{csv of ids} before it uses them.
+\end{commands}
+\begin{example}
+ \printexercise{exercise}{invisible}
+\end{example}
+
+\section{Collecting Exercises}\label{sec:collecting-exercises}
+
+\begin{bewareofthedog}
+ The whole collection mechanism has been changed completely with
+ version~0.20. Please check this section carefully and update and adapt your
+ collections.
+\end{bewareofthedog}
+
+\subsection{Background}
+\xsim\ knows the concept of \emph{exercise collections}. A collection of
+exercises can be used in two cases, basically:
+\begin{enumerate}
+ \item When you want to print a certain group of exercises several times. In
+ this case you add the exercise to a collection while also using it in the
+ running text. Somewhere later (or earlier actually) in the document you
+ can the reprint the collection\footnote{There is another way to do that,
+ but\dots}.
+ \item If you only want to print exercises which have certain tags. Maybe
+ you have some kind of exercise library in an external which you include
+ into you document and want to print only those exercises which fit
+ certain conditions.
+\end{enumerate}
+Each collection must have a unique name with which you can refer to the
+corresponding collection. A collection is realized by declaring the
+collection in the preamble and by activating the collection.
+
+\subsection{Usage}
+\subsubsection{Declaring collections}
+\emph{A collection must be declared in the preamble.} Using a pair of
+commands explained below exercises between those commands are added to the
+corresponding collection but not printed. After a collection is completed the
+collection can be printed as often as needed.
+\begin{commands}
+ \command{DeclareExerciseCollection}[\oarg{tag values}\marg{collection name}]
+ Define a new collection \meta{collection name} in the document preamble.
+ An example could look like this:
+ \cs{DeclareExerciseCollection}\Oarg{topics=algebra,level=1}\Marg{easy-algebra}.
+ Choosing tags automatically activates the collection which means that all
+ exercises which fit the tags are automatically added to the new
+ collection.
+\end{commands}
+
+\subsubsection{Activating collections}
+If a collection is not activated per default in can be activated (or
+deactivated in the opposite case) with these commands:
+\begin{commands}
+ \command{activatecollection}[\marg{collection name}]
+ \sinceversion{0.20}Activates the collection \meta{collection name} which
+ now collects all exercises until the collection is
+ deactivated. \meta{collection name} can be a csv list of collection
+ names.
+ \command{deactivatecollection}[\marg{collection name}]
+ \sinceversion{0.20}Deactivates the collection \meta{collection name}.
+ \meta{collection name} can be a csv list of collection names.
+\end{commands}
+These commands do not influence exercises in other ways other than adding them
+to collections.
+\begin{commands}
+ \command{collectexercises}[\marg{collection name}]
+ Activates the collection \meta{collection name} which now collects all
+ exercises until the collection is deactivated, starts a group with
+ \cs*{begingroup} and sets the option \option{collect}, see below.
+ \command{collectexercisesstop}[\marg{collection name}]
+ Deactivates the collection \meta{collection name} and ends a group with
+ \cs*{endgroup}.
+\end{commands}
+\begin{options}
+ \keybool{collect}\Default{false}
+ A shortcut option which sets the options
+ \module{\meta{type}}\code{/}\module{collect} for each exercise type.
+\end{options}
+
+\subsubsection{Printing collections}
+\begin{commands}
+ \command{printcollection}[\oarg{options}\marg{collection name}]
+ Prints the collection \meta{collection name}, \ie, all exercises collected
+ earlier. This command cannot be used before the corresponding collection
+ has been closed correctly.
+\end{commands}
+Valid options are the following:
+\begin{options}
+ \keybool{headings}\Module{print-collection}\Default{false}
+ If true a heading for each exercise type is inserted.
+ \keyval{headings-template}{template}\Module{print-collection}\Default{collection}
+ The heading template used when \keyis{headings}{true}.
+ \keychoice{print}{exercises,solutions,both}\Module{print-collection}\Default{exercises}
+ Determines wether \cs{printcollection} prints the exercises or the
+ solutions of the collection. When you choose \code{both} exercises and
+ solutions are printed alternately.
+\end{options}
+
+Those options can also be set via \cs{xsimsetup} using the module
+\module{print-collection}.
+
+\begin{bewareofthedog}
+ Please be aware that exercises are not used or printed while they are
+ collected. Nonetheless the property \property{use} is set to \code{true}
+ (so that solutions can be printed even if the exercises are not) and the
+ property \property{print} is set to \code{false}. Also their counters are
+ \emph{not stepped} during the process. This only happens when they are
+ printed the first time, \cf~the \property{used} property. At that time
+ also the properties \property{page}, \property{section} and
+ \property{chapter} are set and the property \property{print} is set to
+ \code{true}.
+\end{bewareofthedog}
+
+The usage should be clear:
+\begin{example}
+ \collectexercises{foo}
+ \begin{exercise}
+ This exercise is added to the collection `foo'.
+ \end{exercise}
+ \begin{exercise}
+ This exercise is also added to the collection `foo'.
+ \end{exercise}
+ \begin{exercise}
+ So is this.
+ \end{exercise}
+ \begin{exercise}
+ As well as this one.
+ \end{exercise}
+ \collectexercisesstop{foo}
+\end{example}
+Once the collection is closed it can be printed:
+\begin{example}
+ \printcollection{foo}
+\end{example}
+
+You can open several collections at the same time:
+\begin{sourcecode}
+ \collectexercises{foo}
+ ...
+ \activatecollection{bar}
+ ...
+ \deactivatecollection{foo}
+ ...
+ \collectexercisesstop{bar}
+\end{sourcecode}
+Exercises will be added to each open collection.
+
+There is one generic collection called \enquote{\code{all exercises}}. As the
+name already suggests it will hold all exercises. So if you say
+\begin{sourcecode}
+ \printcollection{all exercises}
+\end{sourcecode}
+all exercises will be printed.
+
+\begin{bewareofthedog}
+ If you use \cs*{label}s inside of exercises and you print exercises more
+ than once in your document (by reusing a collection for example) you will
+ get
+\begin{sourcecode}
+ LaTeX Warning: There were multiply-defined labels.
+\end{sourcecode}
+ Equally if you have environments like \environ{equation} which step a
+ counter inside an exercise or solution the counter will be stepped each time
+ the exercise is used.
+\end{bewareofthedog}
+
+At last now an example using external files, collections and tags:
+\begin{sourcecode}
+ % preamble:
+ % \DeclareExerciseCollection{foo-easy}
+ % \DeclareExerciseCollection{foo-medium}
+ % \DeclareExerciseTagging{difficulty}
+
+ % document:
+ \collectexercises{foo-easy}
+ \xsimsetup{difficulty=easy}
+ \input{foo.tex}
+ \collectexercisesstop{foo-easy}
+ % collection `foo-easy' now contains all exercises of file `foo.tex' tagged
+ % with `difficulty=easy'
+
+ \collectexercises{foo-medium}
+ \xsimsetup{difficulty=medium}
+ \input{foo.tex}
+ \collectexercisesstop{foo-medium}
+ % collection `foo-medium' now contains all exercises of file `foo.tex'
+ % tagged with `difficulty=medium'
+\end{sourcecode}
+
+\begin{bewareofthedog}
+ The recommended usage is similar to the last example. Actually a collection
+ can be printed \emph{before} it is opened, too. (This needs \emph{at least}
+ two compilations, though.) However, it is safer printing a collection only
+ once and only \emph{after it has been collected}. No guaranties are given
+ that properties are set correctly if you use the collection before. You
+ usually also will make sure that the exercises in a collection are unique,
+ \ie, that an exercise is not part of several collections -- at least not if
+ both collections are printed in the same document.
+\end{bewareofthedog}
+
+\section{Printing Random Exercises From a Collection}
+\xsim\ provides the possibility of selecting random exercises from a
+collection (\cf~section~\vref{sec:collecting-exercises}).
+\begin{bewareofthedog}
+ Please be aware that this feature is \emph{not} available in \XeLaTeX!
+\end{bewareofthedog}
+\begin{commands}
+ \command{printrandomexercises}[\oarg{options}\marg{number}]
+ This command prints \meta{number} random exercises from the collection
+ chosen with option \option{collection}, see below. When this command is
+ used it generates a random list of integers which is written to the
+ \code{aux} file. On the subsequent compilations the according exercises
+ are printed. \emph{If you want to regenerate the random list you have to
+ delete the \code{aux} file before compiling.}
+\end{commands}
+Valid options for this command are:
+\begin{options}
+ \keybool{sort}\Module{random}\Default{true}
+ Determines wether the random chosen exercises should be sorted according
+ to their order of definition in the collection or not.
+ \keyval{collection}{collection}\Module{random}\Default{all exercises}
+ The collection from which the exercises are to be chosen from.
+ \keyval{exclude}{csv list of ids}\Module{random}
+ A list of \property{id}s or \property{ID}s of exercises \emph{not} to be
+ chosen.
+ \keychoice{print}{exercises,solutions,both}\Module{random}\Default{exercises}
+ Determines wether \cs{printrandomexercises} prints the exercises or the
+ solutions. When you choose \code{both} exercises and solutions are
+ printed alternately.
+\end{options}
+
+\begin{example}
+ \printrandomexercises[collection=foo]{2}
+\end{example}
+
+The example above of course doesn't make much sense but if you have a
+collection which collects exercises from an external file and the exercises
+haven't been printed in the document before then you will get a list of
+subsequently numbered exercises.
+
+\section{Printing Solutions}\label{sec:printing-solutions}
+
+There are different commands for printing the solutions to exercises:
+\begin{commands}
+ \command{printsolutionstype}[\sarg\oarg{options}\marg{exercise type}]
+ Prints the solutions of all used exercises of type \meta{exercise type}.
+ The starred version only prints the solutions of all printed exercises of
+ type \meta{exercise type}.
+ \command{printsolutions}[\sarg\oarg{options}]
+ Prints the solutions of all used exercises of all types ordered by type.
+ The starred version only prints the solutions of all printed exercises of
+ all types.
+ \command{printallsolutions}[\sarg\oarg{options}]
+ Prints the solutions of all used exercises of all types ordered by
+ appearance in the document. The starred version only prints the solutions
+ of all printed exercises of all types.
+ \command{printsolution}[\oarg{options}\marg{type}\marg{id}]
+ Prints the solution of the exercise of type \meta{type} with the
+ \property{id} \meta{id}.
+ \command{xprintsolution}[\marg{type}\marg{id}]
+ \sinceversion{0.16}The same as \cs{printsolution} but expands \meta{type}
+ and \meta{id} before it uses them.
+\end{commands}
+
+\begin{example}
+ \printsolutionstype{exercise}
+\end{example}
+
+The options can be divided into two groups. The ones in the first group
+modify the layout.
+\begin{options}
+ \keybool{headings}\Module{print-solutions}\Default{true}
+ If true a heading for each exercise type is inserted.
+ \keyval{headings-template}{template}\Module{print-solutions}\Default{default}
+ The heading template used when \keyis{headings}{true}.
+\end{options}
+
+The ones in the second group set conditions selecting which solutions are
+printed. If you combine those conditions a solution is printed if it meets
+either of the conditions.
+\begin{options}
+ \keychoice{section}{\default{true},false,\meta{integer}}\Module{print-solutions}%
+ \Default{false}
+ If you set \keyis{section}{true} only solutions of exercises of the
+ current section are printed. If you set \keyis{section}{4} only solutions
+ of exercises in a section with number~$4$ are printed.
+ \keychoice{chapter}{\default{true},false,\meta{integer}}\Module{print-solutions}%
+ \Default{false}
+ If you set \keyis{chapter}{true} only solutions of exercises of the
+ current chapter are printed. If you set \keyis{chapter}{4} only solutions
+ of exercises in a chapter with number~$4$ are printed.
+ \keychoice{collection}{false,\meta{collection name}}\Module{print-solutions}%
+ \Default{false}
+ If used only solutions of exercises belonging to collection
+ \meta{collection name} are printed.
+\end{options}
+
+The conditions can be combined. The following call will only print solutions
+from exercises in section~3 of chapter~2:
+\begin{sourcecode}
+ \printsolutions[chapter=2,section=3]
+\end{sourcecode}
+
+\begin{bewareofthedog}
+ The selection per section or per chapter relies on the \emph{counter
+ numbers} of the sections or chapters, respectively. This means if section
+ numbers are reset (\eg\ by \cs*{chapter} or \cs*{appendix}) and you have
+ exercises from \emph{different} sections with \emph{the same section number}
+ the solutions of \emph{all those exercises} will be printed. This means you
+ only should use the \option{section} selection when section are the top
+ document level headings (apart from parts) and you have no exercises in the
+ appendix. Similar considerations are valid for the \option{chapter}
+ selection.
+\end{bewareofthedog}
+
+All options can also be set via \cs{xsimsetup} using the module
+\module{print-solutions}.
+
+\begin{example}
+ \printsolutions[section=4,headings-template=per-section]
+\end{example}
+
+\begin{example}
+ \printsolution{exercise}{5}
+\end{example}
+
+\section{Grading Tables}\label{sec:grading-tables}
+When you create exercises it may not only be desirable to be able to add
+points and bonus-points to a question (see section~\vref{sec:goals} about
+exercise goals) but also to be able to output a grading table. \xsim\ has
+built-in means for this.
+\begin{commands}
+ \command{gradingtable}[\oarg{options}]
+ Print a grading table.
+\end{commands}
+Valid options for this command are
+\begin{options}
+ \keyval{template}{template}\Default{default}
+ Choose the template used for the grading table.
+ \keyval{type}{exercise type}\Default
+ Choose the exercise type for which the table is printed.
+\end{options}
+Both option defaults can be changed with \cs{xsimsetup} setting the options
+using \module{grading-table}:
+\begin{sourcecode}
+ \xsimsetup{
+ grading-table/template = default*
+ }
+\end{sourcecode}
+
+An example:
+\begin{example}
+ \gradingtable[type=exercise]
+\end{example}
+
+Or using the \enquote{\code{default*}} template:
+\begin{example}
+ \gradingtable[template=default*,type=exercise]
+\end{example}
+
+Available templates and how to define new ones are explained in
+sections~\vref{sec:grad-table-templ} and~\vref{sec:template-examples}. \xsim\
+per default provides two templates \enquote{\code{default}} and
+\enquote{\code{default*}}, the first one has a vertical layout, the second a
+horizontal layout. Both templates can be used per type like in the examples
+above or for all types at once by leaving the specification \option{type}
+away:
+\begin{example}
+ \gradingtable
+\end{example}
+
+\section{Styling the Exercises -- Templates}\label{sec:styl-exerc-templ}
+
+\subsection{Background}
+Whenever \xsim\ outputs something to be typeset it uses so-called templates
+for the task. \xsim\ knows of three different kinds of templates:
+\begin{itemize}
+ \item environment templates (see section~\vref{sec:envir-templ}),
+ \item heading templates (see section~\vref{sec:heading-templates}) and
+ \item grading table templates (see section~\vref{sec:grad-table-templ})
+\end{itemize}
+
+The most important one for the styling of the exercises are the environment
+templates. Those templates give you complete control over the look and
+arrangement of an exercise. To be able to do this \xsim\ provides a large
+number of commands which can be used only inside template
+definitions\footnote{The last sentence is wrong: those commands can be used
+ anywhere but most of them only give useful results inside of templates.}.
+Those commands are explained in the next section. Their usage will hopefully
+become clear in the examples in section~\vref{sec:template-examples}. Having
+full control over the layout comes at a price: you need to be able to program
+yourself in order to achieve certain layouts\footnote{I plan to incorporate
+ the most common layouts -- and maybe some fancy ones, too -- in the examples
+ section~\vref{sec:template-examples} but at the time of writing this is still
+ up in the air.}.
+
+\subsection{Templates Provided by the Package}
+\xsim\ comes with a few predefined layouts:
+\begin{description}
+ \item[\code{default}] The template activated per default and the only one
+ available without further action.
+ \item[\code{runin}] A layout rather similar to the one by package
+ \pkg{exsheets}, see section~\vref{sec:runin-template}. Available through
+ the style file \code{layouts} (see section~\vref{sec:style-files} for more
+ information on style files\index{style file}).
+ \item[\code{margin}] A layout rather similar to the one by package
+ \pkg{exsheets}, see section~\ref{sec:margin-template}. Available through
+ the style file \code{layouts}.
+ \item[\code{minimal}] A\sinceversion{0.13} minimalistic layout, see
+ section~\ref{sec:minimal-template}. As the others inspired by an
+ \pkg{exsheets} layout. Available through the style file \code{layouts}.
+ \item[\code{inline}] A\sinceversion{0.18} minimalistic layout, the same as
+ \code{minimal} but doesn't add \cs*{par} at the beginning and end.
+ Available through the style file \code{layouts}.
+ \item[\code{centered}] A\sinceversion{0.18} layout with a centered heading.
+ Available through the style file \code{layouts}.
+\end{description}
+
+\collectexercises{layouts}
+\begin{exercise}[subtitle=The Subtitle,points=2.5,ID=showlayout]
+ Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
+ vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum
+ gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a,
+ magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique
+ senectus et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras
+ viverra metus rhoncus sem.
+\end{exercise}
+\collectexercisesstop{layouts}
+
+\listlayouts
+
+\subsection{Commands for Usage in Template Definitions}
+\subsubsection{Goals}
+\begin{commands}
+ \command{IfExerciseGoal\TF}[\marg{goal}\marg{relation and
+ value}\marg{true}\marg{false}]
+ Checks the sum of goal \meta{goal} against \meta{relation and value}.
+ \command{IfExerciseGoalSingular\TF}[\marg{goal}\marg{true}\marg{false}]
+ Checks if the value of the goal \meta{goal} of the current exercise
+ equals~$1$. This is the same as \\
+ \cs{IfExerciseGoalTF}\marg{goal}\Marg{=1}\marg{true}\marg{false}.
+ \command{IfExerciseTypeGoalsSum\TF}[\marg{type}\marg{list of
+ goals}\marg{relation and value}\marg{true}\marg{false}]
+ Ckecks the sum of all goals in \meta{list of goals} for the exercises of
+ type \meta{type} against \meta{relation and value}.
+ \command{IfExerciseGoalsSum\TF}[\marg{type}\marg{list of
+ goals}\marg{relation and value}\marg{true}\marg{false}]
+ Ckecks the sum of all goals in \meta{list of goals} for all exercises of
+ all types against \meta{relation and value}.
+ \command{TotalExerciseTypeGoal}[\marg{goal}\marg{type}\marg{singular}\marg{plural}]
+ Print the sum of goal \meta{goal} for the exercises of type \meta{type}
+ and append \meta{singular} or \meta{plural} depending on wether the sum
+ equals~$1$ or not.
+ \command{TotalExerciseGoal}[\marg{goal}\marg{singular}\marg{plural}]
+ Print the sum of goal \meta{goal} for all exercises of all types
+ and append \meta{singular} or \meta{plural} depending on wether the sum
+ equals~$1$ or not.
+\end{commands}
+
+\subsubsection{Properties}
+\begin{commands}
+ \expandable\command{IfExercisePropertyExist\TF}[\marg{property}\marg{true}%
+ \marg{false}]
+ Tests wether an exercise property with the name \meta{property} is defined.
+ \command{IfExercisePropertySet\TF}[\marg{property}\marg{true}\marg{false}]
+ Tests wether the exercise property \meta{property} has been set for the
+ current exercise.
+ \expandable\command{GetExerciseProperty}[\marg{property}]
+ Retrieves the value of the property \meta{property} for the current
+ exercise.
+ \command{GetExerciseProperty\TF}[\marg{property}\marg{true}\marg{false}]
+ Tests wether the exercise property \meta{property} has been set for the
+ current exercise. Inside the \meta{true} branch you can refer to the
+ retrieved value either with \code{\#1} or with \cs{PropertyValue}.
+ \emph{This command expands its contents inside a group.}
+ \command{GetExerciseBody}[\Marg{exercise\textnormal{|}solution}]
+ \sinceversion{0.10}Retrieves the environment body of either the
+ \code{exercise} or the corresponding \code{solution} of the current
+ exercise.
+ \expandable\command{GetExerciseIdForProperty}[\marg{property}\marg{value}]
+ Retrieves the property \property{id} of the exercise where the property
+ \meta{property} has the value \meta{value}. \emph{This only works for
+ \emph{unique} properties!}
+ \command{GetExerciseTypeForProperty}[\marg{property}\marg{value}]
+ Retrieves the property \property{type} of the exercise where the
+ property \meta{property} has the value \meta{value}. \emph{This only
+ works for \emph{unique} properties!}
+ \command{SetExerciseProperty}[\marg{property}\marg{value}]
+ \changedversion{0.9}Set the property \meta{property} of the current
+ exercise to \meta{value}.
+ \command{SetExpandedExerciseProperty}[\marg{property}\marg{value}]
+ \sinceversion{0.9}Expand \meta{value} \cs*{edef}-like and set the property
+ \meta{property} of the current exercise to the result of the expansion.
+ \command{ExerciseSetProperty}[\marg{type}\marg{id}\marg{property}\marg{value}]
+ \sinceversion{0.9}Set the property \meta{property} of the exercise of type
+ \meta{type} and id \meta{id} to \meta{value}.
+ \command{ExerciseSetExpandedProperty}[\marg{type}\marg{id}\marg{property}\marg{value}]
+ \sinceversion{0.9}Expand \meta{value} \cs*{edef}-like and set the property
+ \meta{property} of the exercise of type \meta{type} and id \meta{id} to
+ the result of the expansion.
+ \expandable\command{IfExerciseBooleanProperty\TF}[\marg{property}%
+ \marg{true}\marg{false}]
+ Checks wether the boolean property \meta{property} has value \code{true}
+ or \meta{false} and leaves the corresponding argument in the input
+ stream. Gives an error if \meta{property} is not a boolean property.
+ \expandable\command{GetExerciseAliasProperty}[\marg{property}]
+ Retrieves the value of the property of which \meta{property} is an alias
+ of for the current exercise.
+ \command{SaveExerciseProperty}[\marg{property}\meta{macro}]
+ Saves the value of the property \meta{property} for the current
+ exercise in macro \meta{macro}.
+ \command{GlobalSaveExerciseProperty}
+ Globally saves the value of the property \meta{property} for the current
+ exercise in macro \meta{macro}.
+ \command{ExercisePropertyIfSet\TF}[\marg{type}\marg{id}\marg{property}%
+ \marg{true}\marg{false}]
+ Test if the property \meta{property} has been set for the exercise of type
+ \meta{type} with id \meta{id}.
+ \expandable\command{ExercisePropertyGet}[\marg{type}\marg{id}\marg{property}]
+ Retrieves the value of the property \meta{property} for the exercise of type
+ \meta{type} with id \meta{id}.
+ \expandable\command{ExercisePropertyGetAlias}[\marg{type}\marg{id}\marg{property}]
+ Retrieves the value of the property of which \meta{property} is an alias
+ of for the exercise of type \meta{type} with id \meta{id}.
+ \command{ExercisePropertySave}[\marg{type}\marg{id}\marg{property}\meta{macro}]
+ Saves the value of the property \meta{property} for the exercise of type
+ \meta{type} with id \meta{id} in macro \meta{macro}.
+ \command{ExercisePropertyGlobalSave}[\marg{type}\marg{id}\marg{property}\meta{macro}]
+ Globally saves the value of the property \meta{property} for the exercise
+ of type \meta{type} with id \meta{id} in macro \meta{macro}.
+\end{commands}
+
+\subsubsection{Parameters}
+\begin{commands}
+ \expandable\command{GetExerciseParameter}[\marg{parameter}]
+ Retrieves the value of the parameter \meta{paramater} for the current
+ exercise type.
+ \command{GetExerciseParameter\TF}[\marg{parameter}\marg{true}\marg{false}]
+ \sinceversion{0.9}Retrieves the value of the parameter \meta{paramater}
+ for the current exercise type. Inside the \meta{true} branch you can refer
+ to the retrieved value either with \code{\#1} or with \cs{ParameterValue}.
+ \emph{This command expands its contents inside a group.}
+ \expandable\command{GetExerciseName}
+ Retrieves the value of the parameter \parameter{exercise-name} for the
+ current exercise or of the parameter \parameter{solution-name} for the
+ current solution.
+ \expandable\command{GetExerciseHeadingF}[\marg{false}]
+ \sinceversion{0.14}Retrieves the value of the parameter
+ \parameter{exercise-heading} for the current exercise or of the parameter
+ \parameter{solution-heading} for the current solution. Inserts
+ \meta{false} if the corresponding parameter has not been set.
+ \expandable\command{ExerciseParameterGet}[\marg{type}\marg{parameter}]
+ Retrieves the value of the parameter \meta{parameter} for the exercise of type
+ \meta{type} with id \meta{id}.
+ \expandable\command{IfExerciseParameterSet\TF}[\marg{parameter}%
+ \marg{true}\marg{false}]
+ \sinceversion{0.9}Test if the parameter \meta{parameter} has been set for
+ the current exercise type.
+ \expandable\command{ExerciseParameterIfSet\TF}[\marg{type}\marg{parameter}%
+ \marg{true}\marg{false}]
+ \sinceversion{0.9}Test if the parameter \meta{parameter} has been set for
+ the exercise type \meta{type}.
+\end{commands}
+
+\subsubsection{Tags}
+\begin{commands}
+ \command{ForEachExerciseTag}[\marg{type}\marg{code}]
+ Loops over all tags of tag type \meta{type} for the current exercise
+ applying \meta{code} each time. Inside \meta{code} you can refer to the
+ corresponding tag with \code{\#1}.
+ \command{ListExerciseTags}[\marg{type}\marg{between}]
+ Lists all tags of tag type \meta{type} for the current exercise using
+ \meta{between} as a separator.
+ \command{UseExerciseTags}[\marg{type}\marg{between
+ two}\marg{between}\marg{between last two}]
+ Lists all tags of tag type \meta{type} for the current exercise using
+ \meta{between} as a separator and \meta{between last two} as separator
+ between the last two tags of the list. If the list only consists of two
+ tags \meta{between two} is used as separator.
+ \command{IfExerciseTagSet\TF}[\marg{value}\marg{true}\marg{false}]
+ In\sinceversion{0.11} order to insert text (also \emph{outside} of
+ exercises) depending on the chosen tags this command lets you check if
+ value \meta{value} has been set for \property{tags}.
+ \command{IfExerciseTopicSet\TF}[\marg{value}\marg{true}\marg{false}]
+ In\sinceversion{0.11} order to insert text (also \emph{outside} of
+ exercises) depending on the chosen tags this command lets you check if
+ value \meta{value} has been set for \property{topics}.
+\end{commands}
+
+\subsubsection{Further Commands for Usage in Template Definitions}
+\begin{commands}
+ \command{UseExerciseTemplate}[\marg{type}\marg{name}]
+ Retrieve template \meta{name} of type \meta{type}. This can be useful if
+ you want to define a template which just adds some code to an existing
+ template (an automated \cs*{label}, say).
+ \expandable\command{ExerciseType}
+ Can be used to refer to the current exercise type.
+ \expandable\command{ExerciseID}
+ Can be used to refer to the current exercise id.
+ \expandable\command{ExerciseText}
+ Can be used inside solutions to retrieve the text of the corresponding
+ solution. This is propably seldom useful as in most use cases the
+ exercise property \property{solution} is the easier alternative.
+ \expandable\command{ExerciseCollection}
+ Can be used in certain templates to refer to the collection that is
+ currently inserted.
+ \expandable\command{numberofusedexercises}
+ Holds the total number of used exercises. Useful in table template
+ definitions.
+ \expandable\command{ExerciseTableType}[\marg{code}]
+ In table template definitions this macro either expands to the given
+ exercise type or -- if no type has been given -- to \meta{code}.
+ \expandable\command{IfInsideSolution\TF}[\marg{true}\marg{false}]
+ Tests if the template is used inside a solution environment or not.
+ \expandable\command{IfSolutionPrint\TF}[\marg{true}\marg{false}]
+ Tests if the option \option{print} for the solutions of the current
+ \cs{ExerciseType} is set to \code{true} or \code{false}.
+ \command{IfExistSolution\TF}[\marg{true}\marg{false}]
+ \sinceversion{0.9}Tests if a solution for the current exercise exists.
+ \command{ForEachPrintedExerciseByType}[\marg{code}]
+ Loops over each \emph{printed} exercise ordered by the exercise types and
+ within each type by id. Inside \meta{code} you can refer to several
+ properties of the corresponding exercise:
+ \begin{itemize}
+ \item \code{\#1}: the type of the exercise
+ \item \code{\#2}: the id of the exercise
+ \item \code{\#3}: the \property{counter} property of the exercise
+ \item \code{\#4}: the \property{subtitle} property of the exercise
+ \item \code{\#5}: the \property{points} property of the exercise
+ \item \code{\#6}: the \property{bonus-points} property of the exercise
+ \end{itemize}
+ \command{ForEachUsedExerciseByType}[\marg{code}]
+ Loops over each \emph{used} exercise ordered by the exercise types and
+ within each type by id. Inside \meta{code} you can refer to several
+ properties of the corresponding exercise:
+ \begin{itemize}
+ \item \code{\#1}: the type of the exercise
+ \item \code{\#2}: the id of the exercise
+ \item \code{\#3}: the \property{counter} property of the exercise
+ \item \code{\#4}: the \property{subtitle} property of the exercise
+ \item \code{\#5}: the \property{points} property of the exercise
+ \item \code{\#6}: the \property{bonus-points} property of the exercise
+ \end{itemize}
+ \command{ForEachPrintedExerciseByID}[\marg{code}]
+ Loops over each \emph{printed} exercise order by the exercise id. Inside
+ \meta{code} you can refer to several properties of the corresponding
+ exercise:
+ \begin{itemize}
+ \item \code{\#1}: the type of the exercise
+ \item \code{\#2}: the id of the exercise
+ \item \code{\#3}: the \property{counter} property of the exercise
+ \item \code{\#4}: the \property{subtitle} property of the exercise
+ \item \code{\#5}: the \property{points} property of the exercise
+ \item \code{\#6}: the \property{bonus-points} property of the exercise
+ \end{itemize}
+ \command{ForEachUsedExerciseByID}[\marg{code}]
+ Loops over each \emph{used} exercise order by the exercise id. Inside
+ \meta{code} you can refer to several properties of the corresponding
+ exercise:
+ \begin{itemize}
+ \item \code{\#1}: the type of the exercise
+ \item \code{\#2}: the id of the exercise
+ \item \code{\#3}: the \property{counter} property of the exercise
+ \item \code{\#4}: the \property{subtitle} property of the exercise
+ \item \code{\#5}: the \property{points} property of the exercise
+ \item \code{\#6}: the \property{bonus-points} property of the exercise
+ \end{itemize}
+ \command{XSIMprint}[\Marg{exercise|solution}\marg{type}\marg{id}]
+ \sincechanged{0.16}{0.17}Inserts the either the exercise or the solution
+ of type \meta{type} with the \property{id} or \property{ID} \meta{id}.
+ \command{XSIMxprint}[\Marg{exercise|solution}\marg{type}\marg{id}]
+ The same as \cs{XSIMprint} but expands \meta{type} and \meta{id} before it
+ uses them.\sincechanged{0.16}{0.17}
+ \expandable\command{XSIMtranslate}[\marg{keyword}]
+ Delivers the translation of \meta{keyword} according to the current
+ document language (in the meaning of a \pkg{babel}~\cite{pkg:babel} or
+ \pkg{polyglossia}~\cite{pkg:polyglossia} language). Existing keywords and
+ keyword translations (and how to add new ones) are explained in
+ section~\vref{sec:exerc-transl}.
+ \command{XSIMexpandcode}[\marg{code}]
+ Expands \meta{code} like \cs*{edef} does and leaves the result in the
+ input stream.
+ \expandable\command{XSIMifchapter\TF}[\marg{true}\marg{false}]
+ Returns \meta{true} if both a macro \cs*{chapter} and a counter
+ \code{chapter} are defined and \meta{false} otherwise.
+ \command{XSIMmixedcase}[\marg{code}]
+ Converts the full expansion of \meta{code} to mixed case: \\
+ \verbcode+\XSIMmixedcase{this is some text}+ \XSIMmixedcase{this is some
+ text} \\
+ \emph{This command expands \meta{code} before converting it}.
+ \command{XSIMputright}[\meta{macro}\marg{code}]
+ Extends the macro definition of \meta{macro} with \meta{code} putting it
+ to the right. This is more or less a local version of the LaTeX kernel
+ macro \cs*{g at addto@macro}.
+ \expandable\command{XSIMifeq\TF}[\marg{code 1}\marg{code
+ 2}\marg{true}\marg{false}]
+ Checks if the full expansion of \meta{code 1} and \meta{code 2} is the
+ same tokenlist.
+ \expandable\command{XSIMifblank\TF}[\marg{code}\marg{true}\marg{false}]
+ Checks if the full expansion of \meta{code} is blank (\ie, if it is empty
+ or only consists of spaces).
+ \command{XSIMatbegindocument}[\marg{code}]
+ \sinceversion{0.16}Adds \meta{code} to \xsim's begin document hook.
+ Should be used inside style files instead of \cs*{AtBeginDocument}.
+ \command{XSIMatenddocument}[\marg{code}]
+ \sinceversion{0.16}Adds \meta{code} to \xsim's end document hook.
+ Should be used inside style files instead of \cs*{AtEndDocument}.
+\end{commands}
+
+\subsection{Declaring Templates}
+\subsubsection{Environment Templates}\label{sec:envir-templ}
+\begin{commands}
+ \command{DeclareExerciseEnvironmentTemplate}[\marg{name}\marg{begin
+ code}\marg{end code}]
+ Declare the environment template \meta{name}.
+\end{commands}
+Environment templates are used by the exercise and solution environments.
+Those are the templates set with the parameters \parameter{exercise-template}
+and \parameter{solution-template}.
+
+The predefined template is called \enquote{\code{default}}, see
+section~\vref{sec:exercise-templ-default}.
+
+\subsubsection{Heading Templates}\label{sec:heading-templates}
+\begin{commands}
+ \command{DeclareExerciseHeadingTemplate}[\marg{name}\marg{code}]
+ Declare the heading template \meta{name}.
+\end{commands}
+Heading templates are used by \cs{printsolutions}, \cs{printsolutionstype} and
+\cs{printcollection}. Those are the templates set with the option
+\option{headings-template} of the modules \module{print-solutions} and
+\module{print-collection}.
+
+The predefined templates are \enquote{\code{default}},
+\enquote{\code{collection}}, \enquote{\code{per-section}} and
+\enquote{\code{per-chapter}} see section~\vref{sec:headings-templates}.
+
+\subsubsection{Grading Table Templates}\label{sec:grad-table-templ}
+\begin{commands}
+ \command{DeclareExerciseTableTemplate}[\marg{name}\marg{code}]
+ Declare the grading table template \meta{name}.
+\end{commands}
+Table templates are used by \cs{gradingtable}. Those are the templates set
+with the option \option{template} of module \module{grading-table}
+
+The predefined templates are \enquote{\code{default}} and
+\enquote{\code{default*}}, see sections~\vref{sec:table-templ-default}
+and~\vref{sec:table-templ-default*}.
+
+\subsection{Create and Use \xsim\ Style Files}\label{sec:style-files}
+\index{style file|(}
+
+\xsim\changedversion{0.11} offers you the possibility to create own
+\emph{style files}. Let's say you want to have a style called
+\code{math-exam}. Then you need to save all necessary definitions in a file
+called:
+\begin{center}
+ \code{xsim.style.math-exam.code.tex}
+\end{center}
+The first command in the file should be \cs{xsimstyle}\Marg{math-exam}. This
+file can now be loaded into your document using
+\cs{loadxsimstyle}\Marg{math-exam} or by using
+\cs{xsimsetup}\Marg{load-style=math-exam}:
+\begin{sourcecode}
+ \documentclass[DIV=18,parskip=half]{scrartcl}
+ \usepackage[T1]{fontenc}
+ \usepackage[utf8]{inputenc}
+
+ \usepackage[clear-aux]{xsim}
+ \loadxsimstyle{math-exam}
+
+ \title{Math Exam \#3}
+ \date{2017-03-28}
+\end{sourcecode}
+
+In this style file stuff like template and property definitions should
+happen. This is more or less a convenient way to
+\begin{itemize}
+ \item keep the preamble \enquote{clean} and
+ \item define re-usable styles without the need of copying the document
+ preamble to another document.
+\end{itemize}
+A style file is like a package or class file, \ie, \code{@} has category
+code~11 (letter).
+
+The formal description of the commands:
+\begin{commands}
+ \command{xsimstyle}[\sarg\marg{style name}]
+ The\changedversion{0.11} first command in a \xsim\ style file called
+ \code{xsim.style.\meta{style name}.code.tex} which defines the \xsim\
+ style \meta{style name}. The starred version activates expl3
+ syntax\footnote{Those users who want this will know what it means. If you
+ don't know what it means you will not need it.}.
+ \command{loadxsimstyle}[\marg{csv list of style names}]
+ Load one or more styles into the document.
+\end{commands}
+\begin{options}
+ \keyval{load-style}{csv list of style names}
+ Another\sinceversion{0.14} interface for \cs{loadxsimstyle}\marg{csv list
+ of style names}.
+\end{options}
+
+\begin{bewareofthedog}
+ At the moment this mechanism offers no advantages over creating a custom
+ package or simply \cs*{input}ing a file. Future versions might provide
+ additional features.
+\end{bewareofthedog}
+
+\index{style file|)}
+
+\subsection{Examples}\label{sec:template-examples}
+
+The repository of this package\footnote{GitHub:
+ \url{https://github.com/cgnieder/xsim/}, CTAN:
+ \url{http://www.ctan.org/pkg/xsim/}} currently includes
+\theexamplefiles~example documents demonstrating how different aspects of this
+package work or how different kinds of problems can be solved or how different
+kinds of layouts can be achieved as well as how solve concrete problems that
+have come up in different \LaTeX\ forums, see
+section~\vref{sec:example-files}.
+
+\subsubsection{The \code{default} Exercise Template}\label{sec:exercise-templ-default}
+
+Below the definition\changedversion{0.14} of the \code{default} exercise
+template provided by \xsim\ is shown:
+
+\begin{sourcecode}
+ \DeclareExerciseEnvironmentTemplate{default}{%
+ \GetExerciseHeadingF{\subsection*}%
+ {%
+ \XSIMmixedcase{\GetExerciseName}\nobreakspace
+ \GetExerciseProperty{counter}%
+ \IfInsideSolutionF
+ {%
+ \GetExercisePropertyT{subtitle}
+ { {\normalfont\itshape\PropertyValue}}%
+ }%
+ }
+ \GetExercisePropertyT{points}
+ {%
+ \marginpar
+ {%
+ \IfInsideSolutionF{\rule{1.2cm}{1pt}\slash}%
+ \printgoal{\PropertyValue}
+ \GetExercisePropertyT{bonus-points}{~(+\printgoal{\PropertyValue})}%
+ ~\XSIMtranslate {point-abbr}%
+ }%
+ }%
+ }
+ {\par}
+\end{sourcecode}
+
+\subsubsection{A New Exercise Type Using \pkg*{tcolorbox}}
+Let's say we want exercises to be put in a \env*{tcolorbox}. We want a bold
+title and. if given, an italic subtitle. Exercises should also have the
+points after the subtitle in parentheses if given. Let's also say we want
+those to be an additional exercise type in addition to the ones \xsim\ already
+provides. This is shown with the following code which is also how the
+problems in this manual have been defined:
+
+\begin{sourcecode}
+ \DeclareExerciseEnvironmentTemplate{tcolorbox}
+ {%
+ \tcolorbox[
+ colback = red!5!white ,
+ colframe = red!75!black ,
+ colbacktitle = yellow!50!red ,
+ coltitle = red!25!black ,
+ breakable ,
+ drop shadow ,
+ beforeafter skip = .5\baselineskip ,
+ title =
+ \textbf{\GetExerciseName~\GetExerciseProperty{counter}}%
+ \GetExercisePropertyT{subtitle}{ \textit{\PropertyValue}}%
+ \IfInsideSolutionF{%
+ \GetExercisePropertyT{points}{ % notice the space
+ (%
+ \printgoal{\PropertyValue}
+ \IfExerciseGoalSingularTF{points}
+ {\XSIMtranslate{point}}
+ {\XSIMtranslate{points}}%
+ )%
+ }%
+ }%
+ ]%
+ }
+ {\endtcolorbox}
+
+ \DeclareExerciseType{problem}{
+ exercise-env = problem ,
+ solution-env = answer ,
+ exercise-name = Problem ,
+ solution-name = Answer ,
+ exercise-template = tcolorbox ,
+ solution-template = tcolorbox
+ }
+\end{sourcecode}
+
+See it in action:
+\begin{example}
+ \begin{problem}[subtitle=My subtitle,points=5]
+ This is a problem using a subtitle and points.
+ \end{problem}
+ \begin{answer}
+ This is the answer to problem~\GetExerciseProperty{counter}.
+ \end{answer}
+\end{example}
+
+\subsubsection{Mimicking \pkg*{exsheets}' \code{runin} Template}
+\label{sec:runin-template}
+
+The following example shows how you could mimick \pkg*{exsheets}' \code{runin}
+template. The outcome isn't exactly the same since \pkg{exsheets} doesn't use
+\cs*{marginpar} but the result should look very similar. A safer definition
+would use a real sectioning command for the title.
+
+\begin{sourcecode}
+ \usepackage{needspace}
+ \DeclareExerciseEnvironmentTemplate{runin}
+ {%
+ \par\vspace{\baselineskip}
+ \Needspace*{2\baselineskip}
+ \noindent
+ \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}%
+ \GetExercisePropertyT{subtitle}{ \textit{#1}} % <<< notice the space
+ \IfInsideSolutionF{%
+ \GetExercisePropertyT{points}{%
+ \marginpar{%
+ \printgoal{\PropertyValue}%
+ \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
+ \,\IfExerciseGoalSingularTF{points}
+ {\XSIMtranslate{point}}
+ {\XSIMtranslate{points}}%
+ }%
+ }%
+ }%
+ }
+ {}
+\end{sourcecode}
+
+\subsubsection{Mimicking \pkg*{exsheets}' \code{margin} Template}
+\label{sec:margin-template}
+
+The following example shows how you could mimick \pkg*{exsheets}'
+\code{margin} template.
+
+\begin{sourcecode}
+ \DeclareExerciseEnvironmentTemplate{margin}
+ {%
+ \trivlist
+ \item[\llap{%
+ \smash{%
+ \tabular[t]{@{}r@{}}
+ \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}
+ \IfExercisePropertySetT{points}{%
+ \tabularnewline
+ (%
+ \printgoal{\GetExerciseProperty{points}}%
+ \GetExercisePropertyT{bonus-points}{+\printgoal{#1}}%
+ \,\XSIMtranslate{point-abbr}%
+ )%
+ }%
+ \endtabular
+ }%
+ }]\relax
+ }
+ {\endtrivlist}
+\end{sourcecode}
+
+\subsubsection{A \code{minimal} Template}
+\label{sec:minimal-template}
+
+This shows the implementation of the \code{minimal} template:
+\begin{sourcecode}
+ \DeclareExerciseEnvironmentTemplate{minimal}
+ {%
+ \par
+ \textbf{\GetExerciseProperty{counter}}%
+ \IfInsideSolutionF{%
+ \GetExercisePropertyT{points}{%
+ \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
+ \,\IfExerciseGoalSingularTF{points}
+ {\XSIMtranslate{point}}
+ {\XSIMtranslate{points}}%
+ }%
+ }%
+ }
+ {\par}
+\end{sourcecode}
+
+\subsubsection{The Headings Templates}\label{sec:headings-templates}
+\xsim\ defines four heading templates which only differ by which text they
+output:
+\begin{sourcecode}
+ \DeclareExerciseHeadingTemplate{default}
+ {\section*{\XSIMtranslate{default-heading}}}
+ \DeclareExerciseHeadingTemplate{collection}
+ {\section*{\XSIMtranslate{collection-heading}}}
+ \DeclareExerciseHeadingTemplate{per-section}
+ {\section*{\XSIMtranslate{per-section-heading}}}
+ \DeclareExerciseHeadingTemplate{per-chapter}
+ {\section*{\XSIMtranslate{per-chapter-heading}}}
+\end{sourcecode}
+Section~\vref{sec:exerc-transl} shows how the translations are defined.
+
+\subsubsection{The \code{default} Table Template}\label{sec:table-templ-default}
+This template is the one used for grading tables per default. It has a
+vertical layout.
+
+\begin{sourcecode}
+ \DeclareExerciseTableTemplate{default}{%
+ \XSIMputright\ExerciseTableCode{%
+ \toprule
+ \XSIMifblankF{\ExerciseType}
+ {\XSIMmixedcase{\GetExerciseParameter{exercise-name}}}
+ &
+ \XSIMmixedcase{\XSIMtranslate{points}} &
+ \XSIMtranslate{reached} \\
+ \midrule
+ }%
+ \ForEachUsedExerciseByType{%
+ \XSIMifeqT{#1}{\ExerciseTableType{#1}}
+ {%
+ \XSIMifblankT{\ExerciseTableType{}}
+ {%
+ \XSIMputright\ExerciseTableCode{%
+ \XSIMmixedcase{\ExerciseParameterGet{#1}{exercise-name} }%
+ }%
+ }%
+ \XSIMputright\ExerciseTableCode
+ {#3 & \XSIMifblankTF{#5}{\printgoal{0}}{\printgoal{#5}} & \\ }%
+ }%
+ }
+ \XSIMputright\ExerciseTableCode{%
+ \midrule
+ \XSIMtranslate{total} &
+ \XSIMifblankTF{\ExerciseType}
+ {\TotalExerciseGoal{points}{}{}}
+ {\TotalExerciseTypeGoal{\ExerciseType}{points}{}{}} &
+ \\ \bottomrule
+ }%
+ \XSIMexpandcode{%
+ \noexpand\begin{tabular}{\XSIMifblankTF{\ExerciseType}{l}{c}cc}
+ \noexpand\ExerciseTableCode
+ \noexpand\end{tabular}%
+ }%
+ }
+\end{sourcecode}
+
+The part
+\begin{sourcecode}
+ \XSIMifblankTF{\ExerciseType}{ ... }{ ... }
+\end{sourcecode}
+repeatedly checks if an exercise type has been given for the table. This
+makes it possible to design the table differently if it is for one exercise
+type only (the \code{true} case) or for all exercise types (the \code{false}
+case). \cs*{ExerciseTableType}\marg{code} either expands to the given
+exercise type or to \meta{code}.
+
+\subsubsection{The \code{default*} Table Template}\label{sec:table-templ-default*}
+The second of the predefined grading table templates. It has a horizontal
+layout.
+\begin{bewareofthedog}
+ If you have a lot of exercises the width of a table with this layout may
+ exceed the text width of the document!
+\end{bewareofthedog}
+
+\begin{sourcecode}
+ \DeclareExerciseTableTemplate{default*}{%
+ \XSIMputright\ExerciseTableCode{%
+ \toprule
+ \XSIMifblankF{\ExerciseType}
+ {\XSIMmixedcase{\GetExerciseParameter{exercise-name}}}
+ &%
+ }%
+ \ForEachUsedExerciseByType{%
+ \XSIMifeqT{#1}{\ExerciseTableType{#1}}
+ {
+ \XSIMifblankT{\ExerciseTableType{}}
+ {%
+ \XSIMputright\ExerciseTableCode{%
+ \XSIMmixedcase{\ExerciseParameterGet{#1}{exercise-name} }%
+ }%
+ }%
+ \XSIMputright\ExerciseTableCode{#3 &}
+ }%
+ }%
+ \XSIMputright\ExerciseTableCode{%
+ \XSIMtranslate{total} \\
+ \midrule
+ \XSIMmixedcase{\XSIMtranslate{points}} &
+ }%
+ \ForEachUsedExerciseByType{%
+ \XSIMifeqT{#1}{\ExerciseTableType{#1}}
+ {%
+ \XSIMputright\ExerciseTableCode{%
+ \XSIMifblankTF{#5}{\printgoal{0}}{\printgoal{#5}} &}%
+ }%
+ }%
+ \XSIMputright\ExerciseTableCode{%
+ \XSIMifblankTF{\ExerciseType}
+ {\TotalExerciseGoal{points}{}{}}
+ {\TotalExerciseTypeGoal{\ExerciseType}{points}{}{}}%
+ \\ \midrule
+ \XSIMtranslate{reached} &%
+ }%
+ \ForEachUsedExerciseByType{%
+ \XSIMifeqT{#1}{\ExerciseTableType{#1}}
+ {\XSIMputright\ExerciseTableCode{&}}%
+ }%
+ \XSIMputright\ExerciseTableCode{ \\ \bottomrule }%
+ \edef\numberofcolumns{%
+ \XSIMifblankTF{\ExerciseType}
+ {\numberofusedexercises}
+ {\csname numberof \ExerciseType s\endcsname}%
+ }%
+ \XSIMifeqF{\numberofcolumns}{0}
+ {%
+ \begin{tabular}{l*{\numberofcolumns}{c}c}
+ \ExerciseTableCode
+ \end {tabular}%
+ }%
+ }
+\end{sourcecode}
+
+The part
+\begin{sourcecode}
+ \XSIMifblankTF{\ExerciseType}{ ... }{ ... }
+\end{sourcecode}
+repeatedly checks if an exercise type has been given for the table. This
+makes it possible to design the table differently if it is for one exercise
+type only (the \code{true} case) or for all exercise types (the \code{false}
+case). \cs*{ExerciseTableType}\marg{code} either expands to the given
+exercise type or to \meta{code}.
+
+\section{Exercise Translations}\label{sec:exerc-transl}
+
+\begin{commands}
+ \command{DeclareExerciseTranslation}[\marg{language}\marg{keyword}\marg{translation}]
+ Declare the translation of \meta{keyword} for language \meta{language}.
+ \command{DeclareExerciseTranslations}[\marg{keyword}\marg{translations}]
+ Declare the translations of \meta{keyword} for several languages at once.
+ See an example of the usage below.
+ \expandable\command{XSIMtranslate}[\marg{keyword}]
+ Delivers the translation of \meta{keyword} according to the current
+ document language (in the meaning of a \pkg{babel}~\cite{pkg:babel} or
+ \pkg{polyglossia}~\cite{pkg:polyglossia} language).
+ \command{ForEachExerciseTranslation}[\marg{code}]
+ Loops over all translations of all keywords known to \xsim. Inside
+ \meta{code} you can refer to the keyword with \code{\#1}, to the language
+ with \code{\#2}, and to the translation with \code{\#3}.
+\end{commands}
+
+As an example how to use \cs{DeclareExerciseTranslations} here is how the
+translations for \code{exercise} have been defined:
+
+\begin{sourcecode}
+ \DeclareExerciseTranslations{exercise}{
+ Fallback = exercise ,
+ English = exercise ,
+ French = exercice ,
+ German = \"Ubung
+ }
+\end{sourcecode}
+
+Table~\vref{tab:translation-keys} shows all existing keywords with all
+predefined translations.
+
+\ForEachExerciseTranslation{
+ \appto\translationtable{\texttt{#1} & #2 & \texttt{\detokenize{#3}} \\}
+}
+
+\begin{longtable}{llp{.55\linewidth}}
+ \caption{Translation keywords predefined by \xsim.}
+ \label{tab:translation-keys} \\
+ \toprule
+ \bfseries keyword & \bfseries language & \bfseries translation \\
+ \midrule
+ \endfirsthead
+ \toprule
+ \bfseries keyword & \bfseries language & \bfseries translation \\
+ \midrule
+ \endhead
+ \bottomrule
+ \endlastfoot
+ \midrule
+ & & \hfill\emph{continues} \\
+ \endfoot
+ \translationtable
+\end{longtable}
+
+\section{Cloze Tests and Blank Lines}
+
+Similar to \pkg{exsheets} \xsim\ provides a command \cs{blank}:
+\begin{commands}
+ \command{blank}[\sarg\oarg{options}\marg{text to be filled in}]
+ Creates a blank in normal text or in an exercise but fills the text of its
+ argument if inside a solution. If used at the \emph{begin of a paragraph}
+ \cs{blank} will do two things: it will set the linespread according to an
+ option explained below and will insert \cs*{par} after the lines. The
+ starred version doesn't do these things.
+\end{commands}
+
+Those are the options for customization:
+\begin{options}
+ \keyval{blank-style}{code}\Module{blank}\Default{\cs*{underline}\Marg{\#1}}
+ Instructions for typesetting the blank cloze. Refer to the filled in
+ space with \code{\#1}.
+ \keyval{filled-style}{code}\Module{blank}\Default{\cs*{underline}\Marg{\#1}}
+ Instructions for typesetting the filled cloze. Refer to the filled in text
+ with \code{\#1}
+ \keyval{style}{code}
+ Shortcut for setting both \option{blank-style} and \option{filled-style}
+ at once.
+ \keyval{scale}{decimal number}\Module{blank}\Default{\code{1}}
+\textsc{} Scales the blank to \meta{decimal number} times its natural width.
+ \keyval{width}{dim}\Module{blank}\Default
+ Sets the blank to a width of \meta{dim}. This takes precendence over
+ \option{scale}.
+ \keyval{linespread}{decimal number}\Module{blank}\Default{\code{1}}
+ Set the linespread for the blank lines. This only has an effect if
+ \cs{blank} is used at the begin of a paragraph.
+ \keyval{line-increment}{dim}\Module{blank}\Default{\code{0.001\cs*{linewidth}}}
+ The blank line is built in multiples of this value. If the value is too
+ large you may end up with uneven lines. If the value is too small you may
+ end up with a non-ending compilation. Experiment with values to find the
+ suiting one for your use case.
+ \keyval{line-minimum-length}{dim}\Module{blank}\Default{\code{2em}}
+ The minimal length a line must have before it is built step by step.
+\end{options}
+
+\begin{example}
+ This is a \blank{blank} outside in normal text.
+ \begin{exercise}
+ Try to fill in \blank[width=4cm]{these} blanks. All of them
+ \blank{are created} by using the \cs{blank} \blank{command}.
+ \end{exercise}
+ \xsimsetup{blank/filled-style=\textcolor{red}{#1}}
+ \begin{solution}[print]
+ Try to fill in \blank[width=4cm]{these} blanks. All of them
+ \blank{are created} by using the \cs{blank} \blank{command}.
+ \end{solution}
+\end{example}
+A number of empty lines are easily created by setting the \option{width}
+option:
+\begin{example}
+ Write up the pros and cons of \xsim\ over \pkg{exsheets}:
+
+ \blank[width=4.8\linewidth,linespread=1.5]{}
+\end{example}
+
+\edef\lastsection{\arabic{section}}
+
+\appendix
+
+\section{Future Plans}
+
+\xsim\ is complete in so far as it is perfectly usable to create exams or
+exercise and solution sections in books with the most freedom in layout
+already. But still there are features which would be useful additions. Below
+I list all ideas that I currently plan to add to \xsim:
+\begin{itemize}
+ \item a document class \code{xsim-exam} for creating exams; this class
+ should itself feature the possibility of creating different versions of an
+ exam, maybe already provide multiple choice questions and so on; one could
+ also think about automatic creation of running headers and footers, \ie,
+ means for changing the layout of the exam; following the spirit of \xsim\
+ this should probably be done using templates as well.
+\end{itemize}
+I am very open to suggestions regarding features, both in general and
+specifically regarding the document class.
+
+\section{FAQ \& How to\dots}
+This section serves as a kind of gallery showing solutions to common
+problems. I expect this section to grow over the years. Some examples
+especially regarding other layouts are also shown in example files added to
+this package.
+
+\subsection{\dots Know if \xsim\ Needs Another Compilation?}
+If \xsim\ wants you to recompile your document it issues a warning and writes
+the following to the logfile:
+\begin{sourcecode}
+ Package xsim Warning: Exercise properties may have changed. Rerun to get them
+ (xsim) synchronized.
+\end{sourcecode}
+So just check the logfile regularly (which you should be doing anyway) and
+keep your eyes open.
+
+\subsection{\dots Resolve Getting Repeatedly Wrong Exercise Properties or
+ Wrong Exercise Lists?}\label{sec:resolve-getting}
+\xsimauxfileinfo
+
+\subsection{\dots Resolve Strange Errors After Updating?}
+\xsim\ writes a lot of stuff to the auxiliary file. An update may well change
+how this is done so deleting the auxiliary file and doing a few fresh
+compilations may resolve your problems.
+
+\subsection{\code{! TeX capacity exceeded, sorry [text input levels=15].}
+ Why?}
+Did you try to use an exercise or solution in a macro of some sort? This
+generally will fail if you also use the option \option{use-files}\footnote{The
+ reasons are similar to the ones given here:
+ \url{https://tex.stackexchange.com/a/295422/}.}. But there should never be
+the need to hide the environments inside of a macro, anyway.
+
+\subsection{\code{Runaway argument? !File ended while scanning use of \^{}\^{}M.} Why?}
+Did you try to use an exercise or solution in a macro of some sort? This
+generally will fail if you also use the option \option{use-files}. But there
+should never be the need to hide the environments inside of a macro, anyway.
+
+\subsection{\dots Put a Star (or Another Symbol) in Headings of Exercises That
+ Are Special?}
+
+The code below shows one possible modification of an exercise template which
+allows to easily create bonus exercises:
+\begin{sourcecode}
+ % preamble:
+ \usepackage{amsymb}
+ % declare boolean property:
+ \DeclareExerciseProperty*{bonus}
+ \DeclareExerciseEnvironmentTemplate{bonus}
+ {%
+ \subsection*
+ {%
+ % test for boolean property and insert star symbol if true:
+ \IfExerciseBooleanPropertyT{bonus}{\llap{$\bigstar$ }Bonus }%
+ \XSIMmixedcase{\GetExerciseName}\nobreakspace
+ \GetExerciseProperty{counter}%
+ \IfInsideSolutionF
+ {%
+ \IfExercisePropertySetT{subtitle}
+ { {\normalfont\itshape\GetExerciseProperty{subtitle}}}%
+ }%
+ }
+ \GetExercisePropertyT{points}
+ {%
+ \marginpar
+ {%
+ \IfInsideSolutionF{\rule{1.2cm}{1pt}\slash}%
+ \PropertyValue
+ \GetExercisePropertyT{bonus-points}
+ {\nobreakspace(+\PropertyValue)}%
+ \nobreakspace\XSIMtranslate{point-abbr}%
+ }%
+ }%
+ }
+ {}
+\end{sourcecode}
+
+The usage is now as follows:
+\begin{example}
+ \xsimsetup{exercise/template = bonus}
+ % set the boolean property to true
+ \begin{exercise}[bonus]
+ A bonus question.
+ \end{exercise}
+\end{example}
+
+\subsection{\dots Print All Solutions Grouped by Section?}
+Here is an idea how to get a list of all solutions grouped by the section the
+corresponding exercises are appearing in.
+\begin{sourcecode}
+ % preamble:
+ % \usepackage{etoolbox}
+ % \newcounter{sections}
+
+ % document:
+ \setcounter{sections}{1}
+ \whileboolexpr
+ { test {\ifnumless{\value{sections}}{\value{section}+1}} }
+ {
+ \printsolutions[section=\value{sections},headings-template=per-section]
+ \stepcounter{sections}
+ }
+\end{sourcecode}
+For this manual we then get the following list\footnote{Taking care of the
+ fact that we're in the appendix now which means we can't use
+ \cs*{value}\Marg{section}. Therefore this manual does
+ \cs*{edef}\cs*{lastsection}\Marg{\cs*{arabic}\Marg{section}} right before
+ \cs*{appendix}}.
+
+\newcounter{sections}
+\setcounter{sections}{1}
+\whileboolexpr
+ { test {\ifnumless{\value{sections}}{\lastsection+1}} }
+ {
+ \printsolutions[section=\value{sections},headings-template=per-section]
+ \stepcounter{sections}
+ }
+
+\section{The \pkg*{xsimverb} package}\label{sec:xsimverb-package}
+\xsim\ comes bundled with another package called
+\pkg{xsimverb}\xsimverbversion. This package loads a very small subset of
+\xsim\ which allows to create environments that write their contents verbatim
+to external files. It provides the following commands (which of course are
+also available in \xsim, too):
+
+\begin{commands}
+ \command{XSIMfilewritestart}[\sarg\marg{file name}]
+ Start writing to the file named \meta{file name}. This should be the
+ \emph{last} command in the \emph{begin} definition of an environment. If
+ is is used in an environment with arguments where the \emph{last} argument
+ is optional you should check if the optional argument is given and use
+ the starred version if the test is negative. This is demonstrated in an
+ example below using \pkg{xparse}'s \cs{NewDocumentEnvironment}. \emph{If
+ you want an environment with only an optional argument you \emph{should}
+ use \pkg{xparse}'s commands to define it. Due to the way how
+ \cs*{newenvironment} scans for optional arguments you'll otherwise may
+ end up with leading spaces gobbled from the first line in your
+ environment.}
+ \command{XSIMfilewritestop}
+ Stop writing to the file. This should be the \emph{first} command in the
+ \emph{end} definition of an environment.
+ \command{XSIMsetfilebegin}[\marg{code}]
+ This command can be used to write something to the external file
+ \emph{before} the environment contents. Must be set before
+ \cs{XSIMfilewritestart} in the \emph{begin} definition.
+ \command{XSIMsetfileend}[\marg{code}]
+ This command can be used to write something to the external file
+ \emph{after} the environment contents. Must be set before
+ \cs{XSIMfilewritestart} in the \emph{begin} definition.
+ \command{XSIMgobblechars}[\marg{integer}]
+ Determines how many characters are cut off of the beginning of each line
+ of the environment body before it is written to the file. The default
+ value is~$0$.
+\end{commands}
+
+The following code shows an example of how to use those commands:
+\begin{sourcecode}
+ \documentclass{article}
+ \usepackage{xsimverb,listings}
+
+ \makeatletter
+ \NewDocumentEnvironment{example}{o}
+ {%
+ \XSIMsetfilebegin{\@percentchar\space file `\jobname.tmp'}%
+ \XSIMsetfileend{\@percentchar\space bye bye}%
+ \IfNoValueTF{#1}
+ {\XSIMfilewritestart*{\jobname.tmp}}
+ {\XSIMfilewritestart{\jobname.tmp}}%
+ }
+ {%
+ \XSIMfilewritestop
+ \lstinputlisting[language={[LaTeX]TeX}]{\jobname.tmp}%
+ \input{\jobname.tmp}
+ }
+ \makeatother
+
+ \begin{document}
+
+ \begin{example}
+ bla bla \LaTeX
+ \end{example}
+
+ \end{document}
+\end{sourcecode}
+
+The \code{tmp} file produced by the above example will contain the following
+three lines (if the file itself was called \code{test.tex}):
+\begin{sourcecode}
+ % file `test.tmp'
+ bla bla \LaTeX
+ % bye bye
+\end{sourcecode}
+
+\section{All Exercise Examples}
+
+\begin{bewareofthedog}
+ You will notice that some exercises from
+ section~\vref{sec:template-examples} look differently in this section. That
+ is because all exercises of a type use the template that's \emph{currently
+ active}. If you want exercises with a different look you should use
+ different exercises types.
+\end{bewareofthedog}
+
+The following list is created with this code:
+\begin{sourcecode}
+ \xsimsetup{exercise/template = bonus}
+ \printcollection[headings]{all exercises}
+\end{sourcecode}
+
+\xsimsetup{exercise/template = bonus}
+\printcollection[headings]{all exercises}
+
+\section{All Solution Examples}
+\printsolutions
+
+\section{Example Documents Coming With This Package}\label{sec:example-files}
+The repository of this package\footnote{GitHub:
+ \url{https://github.com/cgnieder/xsim/}, CTAN:
+ \url{http://www.ctan.org/pkg/xsim/}} currently includes
+\theexamplefiles~example documents demonstrating how different aspects of this
+package work or how different kinds of problems can be solved or how different
+kinds of layouts can be achieved as well as how to solve concrete problems
+that have come up in different \LaTeX\ forums.
+
+Besides showing excerpts of the code and the resulting pdf the examples below
+also link to both the \code{tex} source the resulting pdf.
+
+\listexamplefiles
+
+\printbibliography
+
+\end{document}
Property changes on: trunk/Master/texmf-dist/doc/latex/xsim/xsim-manual.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Deleted: trunk/Master/texmf-dist/doc/latex/xsim/xsim.history
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/xsim.history 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/xsim.history 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,158 +0,0 @@
---------------------------------------------------------------------------
-
-XSIM -- eXercise Sheets IMproved
-
---------------------------------------------------------------------------
-Clemens Niederberger
-Web: https://github.com/cgnieder/xsim
-E-Mail: contact at mychemistry.eu
---------------------------------------------------------------------------
-Copyright 2017--2020 Clemens Niederberger
-
-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 Clemens Niederberger.
---------------------------------------------------------------------------
-
-HISTORY:
-
- v0.0 2017/02/09 - start with coding the first ideas
- v0.1 2017/03/19 - first draft which actually seems to do everything as
- planned
- v0.2 2017/03/21 - bugfix in the verbwrite module
- - add `use!' and `print!' properties
- - add the concepts of `noupdate' and `boolean' properties
- v0.4 2017/03/24 - \IfExerciseBooleanPropertyTF
- - \GetExercisePropertyTF, \PropertyValue
- - \printallsolutions
- - \UseExerciseTemplate
- - bug fix in solution environments: now get printed again
- when option `print=true' is used
- - bug fix to the translations of the solution list headings:
- exercise name instead of exercise type is now printed
- - \AddtoExerciseTypeGoal, \AddtoExerciseGoal
- \AddtoExerciseTypeGoalPrint, \AddtoExerciseGoalPrint,
- \ExerciseGoalValuePrint
- - \addpoints, \addbonus, \points, \printgoal
- v0.5 2017/03/30 - add style file mechanism
- - make solution print conditions `section' and `chapter'
- combinable
- v0.5a 2017/04/15 - fix wrong translation of the `default-heading'
- v0.5b 2017/04/16 - add \SetExerciseProperty
- v0.6 2017/04/27 - official interface for grade distributions
- - refine hook management (environment module)
- v0.6a 2017/04/28 - refine \blank command, add documentation for said command
- v0.7 2017/05/09 - \xsim_list_length:n
- - new boolean property `used'
- - when an exercise is collected the counter isn't stepped
- but only when the exercise is inserted for the first
- time; when this happens the new property `used' is set to
- `true'
- - make setting boolean properties case insensitive
- - add missing pieces to manual (eg `page' property...)
- - \TotalExerciseGoals and \TotalExerciseTypeGoals
- - \XSIMifchapterTF
- - \xsim_if_goal_sum:nnnTF and friends,
- \IfExerciseTypeGoalsSumTF and \IfExerciseGoalsSumTF
- - some more hints in the manual regarding collections
- v0.8 2017/05/18 - bug fix in \xsim_set_property:nnnn
- - random exercise lists from collections
- - \xsim_collection_count:n
- - \GetExerciseIdForProperty and \GetExerciseTypeForProperty
- for unique properties
- - set property `print=false' during collection and only to
- true when the corresponding exercises actually are
- printed
- - do not insert \par at the beginning and end of exercises
- and solutions; this should be left to the templates!
- - new option `print-collection/print' which allows to
- choose between exercises, solutions, and both to be
- printed
- - new parameter `solution-counter' in order to avoid
- possible conflicts with existing counters
- v0.8a 2017/05/19 - \IfPrintSolutionTF
- v0.8b 2017/05/23 - use \printgoal in default environment template
- - \xsim_print_goal:nnn now expands input to a number
- v0.9 2017/06/20 - \xsimstyle's behaviour now matches the description in
- the manual
- - add style file `layouts' which at the moment provides the
- two exercise templates `runin' and `margin'
- - \printforexercises , \xsim_print_type_code:nnnnn
- - \IfExerciseParameterSetTF
- - \GetExerciseParameterTF
- - change syntax of \SetExerciseProperty
- - \SetExpandedExerciseProperty
- - \ExerciseSetProperty, \ExerciseSetExpandedProperty
- - property `sectioning'
- - \IfExistSolutionTF
- v0.10 2017/09/19 - \xsim_input:nnn
- - \GetExerciseBody
- - option `blank/fill'
- - bug fix in \xsim_start_collection:nn
- - added further examples to package
- - new option `file-extension'
- v0.10a 2017/10/01 - bug fix: grading table options can now be set with
- \xsimsetup (issue 15)
- v0.11 2018/02/12 - change name requirement for style files in order to
- prevent possible name clashes with module files
- - fix bug in \SetExerciseProperty and
- \SetExpandedExerciseProperty
- - fix bug when xsimverb is used standalone (issue 21)
- - add option `split-aux-lists' (issue 18)
- - \IfExerciseTagSetTF and \IfExerciseTopicSetTF
- - introduce a \xsim_if_<tagging>_value:nTF for each tag
- kind
- - \ProvideExerciseTagging
- v0.12 2019/09/30 - add parameter versions for the plural forms of exercise
- and solution names
- - bug fixes (issues 37, 39, 43, 47)
- v0.13 2019/10/06 - experimental package option `no-files'
- v0.14 2019/10/13 - new exercise parameters `exercise-heading' and
- `solution-heading'
- - new options `exercise/heading' and `solution/heading' as
- interface for setting the new parameters
- - new command \GetExerciseHeadingF for using the new
- parameters in environment templates
- - change the environment template `default' to use the new
- \GetExerciseHeadingF and output a \par at the end
- - make argument of \xsimsetup long
- - new template `minimal'
- - new option `load-style'
- - new example `texwelt-23968' (long and short solutions)
- v0.14a 2019/10/19 - fix \xsim_if_exercise_exist:nnTF to obey the `no-files'
- option
- v0.15 2019/11/02 - use own auxiliary file per default and add option
- `use-aux'
- v0.16 2019/11/10 - fix issue due to usage of own auxiliary file
- - \XSIMatbegindocument and \XSIMatenddocument
- - \xprintexercise, \xprintsolution, \xsimprint, \xsimxprint
- 2019/12/29 - bugfix in `xsimverb'
- v0.16a 2020/01/16 - adapt to renaming of string case changing functions
- v0.17 2020/02/21 - prefer lazy boolean evaluation if possible
- - remove spurious \par at the beginning of typeset
- exercises
- - add `blank' option, implements issue #31
- - add `solution' property, implements issue #33
- - fix issue #27
- - implement issue #2
- - don't allow package options to be set with \xsimsetup
- v0.18 2020/02/23 - fix issue #56
- - change \printexercise and \printsolution to accept a
- clist of either ids or IDs (or mixed)
- - new templates in the `layouts' style
- v0.19 2020/03/16 - improve performance
- - only set \ExerciseID and \ExerciseType locally to ensure
- correct values when exercises (of different types) are
- nested
- - new load-time option `debug' - only for development
- v0.19a 2020/03/19 - fix missing-variant-bug introduced with the last update
- v0.19b 2020/04/04 - fix bug in new attribute mechanism which was a problem
- when `no-files` has been used
Deleted: trunk/Master/texmf-dist/doc/latex/xsim/xsim.ideas
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/xsim.ideas 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/xsim.ideas 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,29 +0,0 @@
---------------------------------------------------------------------------
-
-XSIM -- eXercise Sheets IMproved
-
---------------------------------------------------------------------------
-Clemens Niederberger
-Web: https://github.com/cgnieder/xsim
-E-Mail: contact at mychemistry.eu
---------------------------------------------------------------------------
-Copyright 2017--2020 Clemens Niederberger
-
-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 Clemens Niederberger.
---------------------------------------------------------------------------
-
-IDEAS:
-
-- a document class `xsim-exam' for creating exams
-- a mechanism for providing variants of an exam
-
Deleted: trunk/Master/texmf-dist/doc/latex/xsim/xsim_manual.pdf
===================================================================
(Binary files differ)
Deleted: trunk/Master/texmf-dist/doc/latex/xsim/xsim_manual.tex
===================================================================
--- trunk/Master/texmf-dist/doc/latex/xsim/xsim_manual.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/doc/latex/xsim/xsim_manual.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,2421 +0,0 @@
-% !arara: pdflatex: { interaction: nonstopmode }
-% !arara: biber
-% arara: pdflatex: { interaction: nonstopmode }
-% arara: pdflatex: { interaction: nonstopmode }
-% arara: pdflatex: { interaction: nonstopmode }
-% ----------------------------------------------------------------------------
-% the XSIM package
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\documentclass{xsim-manual}
-
-\begin{filecontents*}[overwrite]{\jobname.bib}
- at online{texsx:romannumeral,
- author = {Bruno Le Floch} ,
- title = {Cunning (La)TeX tricks} ,
- urldate = {2017-03-02} ,
- url = {http://tex.stackexchange.com/a/19769/}
-}
- at online{texsx:tagged/exsheets,
- title = {Questions tagged `exsheets'} ,
- author = {various} ,
- url = {http://tex.stackexchange.com/questions/tagged/exsheets} ,
- urldate = {2020-02-21}
-}
-\end{filecontents*}
-\addbibresource{\jobname.bib}
-
-\begin{document}
-
-\section{Licence, Requirements and \texorpdfstring{\textsc{readme}}{README}}
-\license
-
-\xsim\ loads the packages \pkg{expl3}~\cite{bnd:l3kernel},
-\pkg{xparse}~\cite{bnd:l3packages}, \pkg{etoolbox}~\cite{pkg:etoolbox},
-\pkg{array}~\cite{pkg:array} \pkg{booktabs}~\cite{pkg:booktabs} and
-\pkg{translations}~\cite{pkg:translations}. All of these packages are present
-on a modern and up to date \TeX\ distribution such as \TeX~Live or MiK\TeX\ so
-no further action should be needed. When you are using \xsim\ you should be
-using an up to date \TeX\ distribution, anyway.
-
-\begin{bewareofthedog}
- Newer versions of \xsim\ may depend on newer versions of the support
- packages. Remember: it is always dangerous to update single packages.
- Always update your \TeX\ distribution if you want an up to date version of a
- package. Be careful: if you're in the middle of an important project it
- might be better to wait with the update until you've finished the project.
- Every update might be breaking some things.
-
- Please also be aware that \xsim\ is actively developed and many things may
- still change. However, I will try my best to keep the interface stable.
-\end{bewareofthedog}
-
-I'm currently thinking to make the option \option{no-files} the default
-behavior of \xsim. There is a poll and discussion regarding this question on
-\xsim's github page if you like to give your opinion on this.
-
-\begin{bewareofthedog}
- The whole collection mechanism is likely to change completely in the
- not-so-far future (let's say sometime in the six months from April~2020 or
- so).
-\end{bewareofthedog}
-
-\section{Motivation, Background}
-
-It has been quite a while since I first published
-\pkg{exsheets}~\cite{pkg:exsheets} in June 2012. Since then it has gained a
-user base and a little bit of popularity as the number of questions on tex.sx
-shows (143~at the time of writing)~\cite{texsx:tagged/exsheets}. User
-questions, bug reports and feature requests improved it over the time. It
-still has a version number starting with a zero, though, which in my
-versioning system means I still consider it experimental.
-
-This is due to several facts. It lacks a few features which I consider
-essential for a full version~1. For one thing it is not possible to have
-several kinds of exercises numbered independently. Using verbatim material
-such as listings inside exercises and solutions is not possible and the
-current workaround isn't that ideal either. One request which dates back
-quite a while now was to have different types of points to exercises\ldots
-
-All of those aren't easy to add due to the way \pkg{exsheets} is implemented
-right now. As a consequence I wanted to re-implement \pkg{exsheets} for a long
-time. This is what lead to \xsim. Internally the package works completely
-different.
-
-\begin{bewareofthedog}
- \xsim\ will be the official successor of \pkg{exsheets} which is now
- considered obsolete but will stay alive and will still receive bugfix
- releases. However, new features will not be added to \pkg{exsheets} any
- more.
-\end{bewareofthedog}
-
-\section{How to Read the Manual}\label{sec:how-read-manual}
-
-\subsection{Nomenclature}
-
-Throughout this manual certain terms are used. This section explains their
-meaning in this manual.
-
-\acuseall
-\printacronyms[heading=none]
-
-\subsection{Package Options}\label{sec:package-options}
-\xsim\ has these package options:
-\begin{options}
- \opt{verbose}
- Writes extensive information about what \xsim\ is doing into the log
- file.
- \opt{final}
- If used the exercise and solution environments will not rewrite the
- environment body files.
- \opt{clear-aux}
- If used every time the total number of exercise changes \xsim\ will write
- \emph{less} information to the auxiliary file on the next run and only if
- the number of exercises stays stable between compilations the needed
- information will be written to the auxiliary file. \emph{This needs more
- compilations until everything stabilizes but should reduce the
- probability of possibly faulty exercises after changes to the document.}
- The \option{final} option automatically disables this option. See also
- sections~\vref{sec:how-exerc-envir} and~\vref{sec:resolve-getting}.
- \opt{no-files}
- \sinceversion{0.13}This option prevents \xsim\ from writing the exercises
- and solutions to external files. This will keep your working folder
- ``clean'' but will also prevent using verbatim material in exercises and
- solutions and will possibly slow processing further down. \emph{This
- option is considered experimental. Feedback is very welcome.}
- \opt{use-aux}
- \sinceversion{0.15}With this option enabled \xsim\ will use the regular
- auxiliary file \cs*{jobname}\code{.aux} instead of its own auxiliary file
- \cs*{jobname}\code{.xsim}.
- \opt{blank}
- \sinceversion{0.17}With this option enabled \xsim\ will not define the
- default environments \env{exercise} and \env{solution}.
-\end{options}
-
-Those options are load-time options and are used the usual way as package
-options:
-\begin{sourcecode}
- \usepackage[verbose]{xsim}
-\end{sourcecode}
-\begin{bewareofthedog}
- Although those options technically belong to the \module{package} module
- (see also section~\vref{sec:setting-options}) it is \emph{not} possible to
- set them via \cs{xsimsetup}.
-\end{bewareofthedog}
-
-\subsection{Setting Options}\label{sec:setting-options}
-Apart from the package options already described in
-section~\vref{sec:package-options} \xsim\ has further options. All those
-options are set using the following command:
-\begin{commands}
- \command{xsimsetup}[\marg{options}]
- Set up \xsim's package options and all other options described at
- other places in the manual.
-\end{commands}
-Options can be \enquote{toplevel} options or options belonging to a module:
-\begin{options}
- \keyval*{toplevel}{value}
- A toplevel option.
- \keyval*{sublevel}{value}\Module*{module}
- A sublevel option belonging to the module \module*{module}
-\end{options}
-Both kinds of options are set with the setup command:
-\begin{sourcecode}
- \xsimsetup{
- toplevel = {value} ,
- module/sublevel = {value}
- }
-\end{sourcecode}
-
-\subsection{Command descriptions}
-
-Some commands do have a \expandablesymbol\ symbol printed next to their
-names. This indicates that the command is expandable, \ie, it is usable in an
-\cs*{edef} or \cs*{write} context and will expand according to its
-description. All other commands are engine protected, \ie, in the sense of
-\eTeX's \cs*{protected}.
-
-Some command name descriptions end with \code{\TF}.
-\begin{commands}
- \command*{SomeCommand\TF}[\meta{arguments}\marg{true}\marg{false}]
- A command with maybe some arguments and ending with the two arguments
- \meta{true} and \meta{false}.
-\end{commands}
-This means two things: the command is a conditional which tests something and
-depending on the outcome of the test leaves either the \meta{true} argument
-(\code{T}) or the \meta{false} argument (\code{F}) in the input stream. It
-also means two additional commands exist:
-\begin{commands}
- \command*{SomeCommandT}[\meta{arguments}\marg{true}]
- The same as \cs*{SomeCommandTF} but only with the \meta{true} argument and
- no \meta{false} argument.
- \command*{SomeCommandF}[\meta{arguments}\marg{false}]
- The same as \cs*{SomeCommandTF} but only with the \meta{false} argument and
- no \meta{true} argument.
-\end{commands}
-
-\section{Exercises and Solutions}
-
-The two predefined environments for exercises and solutions are the following
-ones\footnote{When you load \xsim\ with the \option{blank} those environments
- will \emph{not} be defined!}:
-\begin{environments}
- \environment{exercise}[\oarg{\acsp*{prop}}]
- Input and typeset an exercise. See section~\vref{sec:exercise-properties}
- for details on exercise \acsp*{prop}.
- \environment{solution}[\oarg{options}]
- Input and typeset the solution to the exercise of the previous
- \env{exercise} environment. See section~\vref{sec:printing-solutions} for
- details on options of solutions.
-\end{environments}
-
-\begin{example}
- \begin{exercise}
- A first example for an exercise.
- \end{exercise}
- \begin{solution}
- A first example for a solution.
- \end{solution}
-\end{example}
-
-As can be seen in the example a solution is not printed with the default
-setup. This can be changed using the following option.
-\begin{options}
- \keybool{print}\Module{solution}\Default{false}
- Set if solutions are printed or not.
-\end{options}
-
-The option (belonging to the module \module*{solution}) can either be set
-locally as option to the \env{solution} environment
-\begin{sourcecode}
- \begin{solution}[print=true]
- A first example for a solution.
- \end{solution}
-\end{sourcecode}
-or with the setup command for all following solutions:
-\begin{sourcecode}
- \xsimsetup{
- solution/print = true
- }
-\end{sourcecode}
-
-There is an completely analoguous option for the \env{exercise} environment:
-\begin{options}
- \keybool{print}\Module{exercise}\Default{true}
- Set if exercises are printed or not.
-\end{options}
-More details on those two environments can be found in
-section~\vref{sec:using-printing}.
-
-\section{How the Exercise Environments Work}\label{sec:how-exerc-envir}
-Both the exercise and the solution environments write the contents of their
-bodies verbatim to external files following a certain naming structure:
-\begin{itemize}
- \item
- \code{\meta{jobname}-\meta{type}-\meta{id}-exercise|solution-body.tex}
-\end{itemize}
-The name starts with the name of the job (which is the name of the document
-itself) followed by type and id of the corresponding exercise and then
-followed by the environment type. For example both environments from the first
-example have been written to files named
-\begin{itemize}
- \item \verbcode+xsim_manual-exercise-1-exercise-body.tex+ and
- \item \verbcode+xsim_manual-exercise-1-solution-body.tex+, respectively.
-\end{itemize}
-These external files are input when the respective exercise or solution is
-printed. An advantage of using external files is that \emph{verbatim material
- is allowed} inside the environments. Details on the \meta{type} of an
-exercise will be given in section~\vref{sec:new-exercise-types}. \emph{The
- \meta{id} of an exercise is a positive integer unique to each exercise
- environment regardless if the exercise is being printed or used at all.}
-
-Each of those files contains some information about itself and where and why
-it was generated\footnote{In this example the sourcecode line number is
- misleading as the example where the file was generated itself was an
- external file where the \env{exercise} environment indeed \emph{was} on
- line~1.}:
-
-\inputsourcecode{exercises/xsim_manual-exercise-1-exercise-body.tex}
-
-Arguably one downside of the approach using external files for each exercise
-and its solution is that your project folder will be cluttered with files. In
-order to deal with this somehow \xsim\ offers the following option:
-\begin{options}
- \keyval{path}{path name}\Default
- With this option a subfolder or path within the main project folder can be
- given. Exercises will be written to and included from this path.
- \emph{The path must exist on your system before you can use it!} This
- document uses \keyis{path}{exercises}.
- \keyval{file-extension}{string}\Default{\code{tex}}
- \sinceversion{0.10}This option let's you choose the extension of the
- external files.
-\end{options}
-
-\begin{bewareofthedog}
- Another thing to keep in mind: the environment in many ways works the same
- way as the \env{filecontents} environment. \emph{This also means that you
- \emph{cannot} have comments or \cs*{label}s or anything else on the first
- line of the environments!}
-\end{bewareofthedog}
-\begin{sourcecode}
- \begin{exercise}[points=2] % this comment will cause trouble
- Lorem ipsum
- \end{exercise}
-\end{sourcecode}
-
-If\sinceversion{0.13} you don't like all the external files and the problems
-which come with them \emph{and} if you don't need any verbatim or similar
-material inside the exercises and solutions then you can use the following
-package option:
-\begin{options}
- \opt{no-files}
- This package option prevents \xsim\ from writing the exercises and
- solutions to external files. This will keep your working folder ``clean''
- but will also prevent using verbatim material in exercises and solutions
- and will possibly slow processing further down. \emph{This option is
- considered experimental. Feedback is very welcome.}
-\end{options}
-
-\begin{bewareofthedog}
- \xsimauxfileinfo
-\end{bewareofthedog}
-
-\begin{bewareofthedog}
- A lot of the lines \xsim\ writes to the auxiliary file and reads in a
- subsequent run look like this:
-\begin{sourcecode}
- \XSIM{points}{exercise-2=={4}||exercise-10=={2.5}||problem-11=={5}}
-\end{sourcecode}
- As you can see different entries of the various properties of exercises are
- separated with \code{||}. This means that you cannot use this symbol
- combination inside properties. For this reason \xsim\ provides an option to
- change the marker.
-\end{bewareofthedog}
-\begin{options}
- \keyval{split-aux-lists}{string}\Default{\code{||}}
- Set\sinceversion{0.11} the string that is used to separate the property
- entries in the auxiliary file.
-\end{options}
-
-\section{New Exercise Types}\label{sec:new-exercise-types}
-
-It is easy to define new exercise environments together with a corresponding
-solution environment using the following command:
-\begin{commands}
- \command{DeclareExerciseType}[\marg{type}\marg{parameters}]
- Declare a new exercise type analoguous to the \env{exercise} and
- \env{solution} environments.
-\end{commands}
-Declaring a new exercise type will also define a new command:
-\begin{commands}
- \command{numberof\meta{exercise-env}s}
- These commands hold the absolut number of used exercises of type
- \meta{type}. The meaning of \meta{exercise-env} will become clear below
- when the exercise parameters are explained. It is always the same as the
- exercise environment name.
-\end{commands}
-\begin{example}
- There are \numberofexercises~exercises and \numberofproblems~problem in this
- manual.
-\end{example}
-\xsim's pre-defined environment pair\changedversion{0.14} has been defined as
-follows:
-\begin{sourcecode}
- \DeclareExerciseType{exercise}{
- exercise-env = exercise ,
- solution-env = solution ,
- exercise-name = \XSIMtranslate{exercise} ,
- exercises-name = \XSIMtranslate{exercises} ,
- solution-name = \XSIMtranslate{solution} ,
- solutions-name = \XSIMtranslate{solutions} ,
- exercise-template = default ,
- solution-template = default ,
- exercise-heading = \subsection* ,
- solution-heading = \subsection*
- }
-\end{sourcecode}
-
-The above already is an example for almost all parameters that can (and often
-must) be set. Here is the complete list:
-\begin{parameters}
- \paraval{exercise-env}{exercise environment name}
- The name for the environment used for the exercises of type \meta{type}.
- \emph{This parameter is mandatory.} It can't be changed afterwards.
- \paraval{solution-env}{solution environment name}
- The name for the environment used for the solutions of type \meta{type}.
- \emph{This parameter is mandatory.} It can't be changed afterwards.
- \paraval{exercise-name}{exercise name}
- The name of the exercises of type \meta{type} -- used for typesetting.
- \emph{This parameter is mandatory.}
- \paraval{exercises-name}{exercises name}
- The\sinceversion{0.12} plural name of the exercises of type \meta{type} --
- used for typesetting. If this is not set explicitly an \code{s} is
- appended to the singular name.
- \paraval{solution-name}{solution name}
- The name of the solutions of type \meta{type} -- used for typesetting.
- \emph{This parameter is mandatory.}
- \paraval{solutions-name}{solutions name}
- The\sinceversion{0.12} plural name of the solutions of type \meta{type} --
- used for typesetting. If this is not set explicitly an \code{s} is
- appended to the singular name.
- \paraval{exercise-template}{exercise template}
- The template used for typesetting the exercises of type \meta{type}.
- \emph{This parameter is mandatory.} See
- section~\vref{sec:styl-exerc-templ} for details on templates.
- \paraval{solution-template}{solution template}
- The template used for typesetting the exercises of type \meta{type}.
- \emph{This parameter is mandatory.} See
- section~\vref{sec:styl-exerc-templ} for details on templates.
- \paraval{counter}{counter name}
- The counter used for the exercises of type \meta{type}. If not explicitly
- set the counter with the same name as \parameter{exercise-env} is used.
- Otherwise the specified counter is used. This enables to have different
- types of exercises sharing a common counter. \emph{This parameter can't
- be changed afterwards.} If the explicit or implicit counter does not
- exist, yet, it will be defined.
- \paraval{solution-counter}{counter name}
- The counter used for the solutions of type \meta{type}. If not explicitly
- set the counter with the same name as \parameter{solution-env} is used.
- Otherwise the specified counter is used. This enables to have different
- types of solutions sharing a common counter although this doesn't actually
- make much sense. But it can be useful to avoid using an already existing
- counter. \emph{This parameter can't be changed afterwards.} If the
- explicit or implicit counter does not exist, yet, it will be defined. The
- sole purpose of this counter is to be able to label solutions so they can
- be \cs*{pageref}ed.
- \paraval{number}{integer}
- An internal parameter that is used to keep track of the number of
- exercises of a type. This parameter cannot be set or changed by the
- user.
- \paraval{exercise-heading}{exercise heading command}
- The\sinceversion{0.14} command used for typesetting of the heading of
- exercises of type \meta{type} -- used for typesetting with the command
- \cs{GetExerciseHeadingF}.
- \paraval{solution-heading}{solution heading command}
- The\sinceversion{0.14} command used for typesetting of the heading of
- solutions of type \meta{type} -- used for typesetting with the command
- \cs{GetExerciseHeadingF}.
-\end{parameters}
-
-It is possible to change some of the parameters after an exercise type has
-been defined. Those include \parameter{exercise-name},
-\parameter{solution-name}, \parameter{exercise-template}, and
-\parameter{solution-template}. It is also possible to define new parameters.
-\begin{commands}
- \command{DeclareExerciseParameter}[\sarg\marg{parameter}]
- Declares the new parameter \meta{parameter}. The optional star declares a
- fixed parameter which cannot be changed once it is set. \emph{You
- probably will never need this command. Most tasks can be solved using
- properties (see section~\vref{sec:exercise-properties}) instead.}
- \command{SetExerciseParameter}[\marg{type}\marg{parameter}\marg{value}]
- Usable to set a single parameter to a new value.
- \command{SetExerciseParameters}[\marg{type}\marg{parameters}]
- Set several parameters at once. \meta{parameters} is a csv list of
- key/value pairs.
-\end{commands}
-If you try to set an already set but fixed parameter like
-\parameter{exercise-env} a warning will be written to the log file. For all
-parameters that can be changed also options exist wich can be set via
-\cs{xsimsetup}. They are explained in
-section~\vref{sec:environment-options-hooks}.
-
-\begin{bewareofthedog}
- All exercises of a type use the parameters
- (\eg, \parameter{exercise-template}) that are \emph{currently active}. If
- you want exercises with a different look or different names in the same
- document you should use different exercises types.
-\end{bewareofthedog}
-
-\section{Exercise Properties}\label{sec:exercise-properties}
-
-\subsection{Predefined Properties}
-
-Exercise like the \env{exercise} environment and possibly others defined with
-\cs{DeclareExerciseType} have a number of predefined \acsp*{prop}:
-\begin{properties}
- \propval{id}{integer}
- Holds the internal id of an exercise. \emph{Cannot be set by the user}.
- \propval{ID}{text}
- Holds the user id of an exercise if defined. Otherwise it is equal to
- \property{id}.
- \propval{counter}{text}
- Holds the counter value representation of an exercise (\ie, what you
- usually know as \cs*{the\meta{counter}}). \emph{Cannot be set by the
- user}.
- \propval{counter-value}{integer}
- Holds the counter value of an exercise (\ie, what you usually know as
- \cs*{the}\cs*{value}\marg{counter}). \emph{Cannot be set by the user}.
- \propval{subtitle}{text}
- Holds the subtitle of an exercise.
- \propval{points}{number}
- Holds the reachable points of an exercise.
- \propval{bonus-points}{number}
- Holds the reachable bonus-points of an exercise.
- \propbool{print}
- Holds the print boolean of an exercise.
- \propbool{print\bang}
- Holds a special print boolean of an exercise, see
- page~\pageref{property:print!}.
- \propbool{use}
- Holds the usage boolean of an exercise.
- \propbool{use\bang}
- Holds a special usage boolean of an exercise, see
- page~\pageref{property:print!}.
- \propbool{used}
- True if an exercise has been used at least once. For an existing exercise
- this is only false for exercises that have been collected
- (\cf~section~\vref{sec:collecting-exercises}).
- \propbool{solution}
- \sinceversion{0.17}Holds the solution boolean of an exercise. If this is
- true then a solution has the same text\slash environment body as the
- corresponding exercise. (This might be useful for multiple choice
- questions for example.)
- \propval{tags}{csv list of tags}
- Holds the list of tags the exercise should be associated with.
- \propval{topics}{csv list of topics}
- Holds the list of topics the exercise should be associated with.
- \propval{page}{text}
- Holds the page counter value representation of an exercise \\
- (\ie, what you usually know as \cs*{thepage}).
- \propval{page-value}{integer}
- Holds the page counter value of an exercise \\
- (\ie, what you usually know as \cs*{the}\cs*{value}\Marg{page}).
- \propval{section}{text}
- Holds the section counter value representation of an exercise \\
- (\ie, what you usually know as \cs*{thesection}).
- \propval{section-value}{integer}
- Holds the section counter value of an exercise \\
- (\ie, what you usually know as \cs*{the}\cs*{value}\Marg{section}).
- \propval{chapter}{text}
- Holds the chapter counter value representation of an exercise \\
- (\ie, what you usually know as \cs*{thechapter}). \\
- \emph{Only if a command \cs*{chapter} \emph{and} a counter \code{chapter}
- exist.}
- \propval{chapter-value}{integer}
- Holds the chapter counter value of an exercise \\
- (\ie, what you usually know as \cs*{the}\cs*{value}\Marg{chapter}). \\
- \emph{Only if a command \cs*{chapter} \emph{and} a counter \code{chapter}
- exist.}
- \propval{sectioning}{section numbers}
- Holds five brace groups which in turn hold the section numbers (integers)
- of the exercise in the order
- \marg{chapter}\marg{section}\marg{subsection}\marg{subsubsection}\marg{paragraph}.
- \propval{exercise-body}{\TeX code}
- When\sinceversion{0.13} the package option \option{no-files} is set this
- property is defined and holds the environment body of an exercise.
- \propval{solution-body}{\TeX code}
- When\sinceversion{0.13} the package option \option{no-files} is set this
- property is defined and holds the environment body of the corresponding
- solution.
-\end{properties}
-
-Some of these \acsp*{prop} are fixed and cannot be set by the user. Those
-include \property{id}, \property{counter}, and \property{counter-value}. The
-others can be set using the optional argument of the exercise environment.
-
-\begin{example}
- \begin{exercise}[subtitle={This is a subtitle},points=4,bonus-points=1]
- An exercise where some properties have been set.
- \end{exercise}
-\end{example}
-
-\subsection{Declaring Own Properties}
-
-\xsim\ offers the possibility to declare additional exercise properties:
-\begin{commands}
- \command{DeclareExerciseProperty}[\barg\sarg\narg\marg{property}]
- Declares the property \meta{property}.
-
- If used with the optional \barg\ a \textbf{unique property} is defined
- which means that each exercise must have a property value distinct from
- all other exercises (all means all -- \emph{independent from the exercise
- type}).
-
- If used with the optional \sarg\ a \textbf{boolean property} is defined
- which means that it only should get the values \code{true} or \code{false}
- and if used without value it gets the value \code{true} instead of an
- empty value. If any other value is used the property is set to
- \code{false}. A boolean property obviously cannot be unique. The
- optional \sarg\ takes precedence over the optional \barg, \ie, if both are
- present the property is boolean \emph{but not} unique.
-
- If used with the optional \narg\ a property is defined which won't get
- updated through subsequent compilation runs but is only set when the
- exercise is used.
- \command{DeclareExercisePropertyAlias}[\marg{property 1}\marg{property 2}]
- Declares \meta{property 1} to be an alias of \meta{property 2}. This
- means that each time \meta{property 2} is set \meta{property 1} will be
- set to the same value \emph{unless} it has been set already. As an
- example: property \property{ID} is an alias of property \property{id}.
-\end{commands}
-
-This is better demonstrated with an example:
-\begin{example}
- \begin{exercise}
- \verb+\GetExerciseProperty{id}+: \GetExerciseProperty{id} \par
- \verb+\GetExerciseAliasProperty{ID}+: \GetExerciseAliasProperty{ID} \par
- \verb+\GetExerciseProperty{ID}+: \GetExerciseProperty{ID}
- \end{exercise}
- \begin{exercise}[ID=foo-bar]
- \verb+\GetExerciseProperty{id}+: \GetExerciseProperty{id} \par
- \verb+\GetExerciseAliasProperty{ID}+: \GetExerciseAliasProperty{ID} \par
- \verb+\GetExerciseProperty{ID}+: \GetExerciseProperty{ID}
- \end{exercise}
-\end{example}
-
-The power of properties will get more clear when reading
-section~\vref{sec:styl-exerc-templ} about templates.
-
-\subsection[Exercise Goals]{A Special Kind of Property: Exercise Goals}\label{sec:goals}
-
-Exercise goals are a generic concept in \xsim\ for exercise properties like
-\property{points} or \property{bonus-points}. Those are properties which can
-(only) get a decimal number as value the sum of which is calculated and
-available (after a compilation) throughout the document.
-\begin{commands}
- \command{DeclareExerciseGoal}[\marg{goal}]
- Declare a new exercise goal named \meta{goal} and also a property called
- \meta{goal}.
- \command{TotalExerciseTypeGoal}[\marg{type}\marg{goal}\marg{singular}\marg{plural}]
- Get the sum of goal \meta{goal} for all exercises of type \meta{type}.
- \meta{singular} and \meta{plural} are placed after the sum in the input
- stream depending on whether the sum equals~$1$ or not.
- \command{TotalExerciseTypeGoals}[\marg{type}\marg{list of
- goals}\marg{singular}\marg{plural}]
- Get the sum of goal all goals in \meta{list of goals} for all exercises of
- type \meta{type}. The goal names in \meta{list of goals} must be
- separated with \code{+}. \meta{singular} and \meta{plural} are placed
- after the sum in the input stream depending on whether the sum equals~$1$
- or not.
- \command{TotalExerciseGoal}[\marg{goal}\marg{singular}\marg{plural}]
- Get the sum of goal \meta{goal} for all exercises. \meta{singular} and
- \meta{plural} are placed after the sum in the input stream depending on
- whether the sum equals~$1$ or not.
- \command{TotalExerciseGoals}[\marg{list of
- goals}\marg{singular}\marg{plural}]
- Get the sum of goal all goals in \meta{list of goals} for all exercises.
- The goal names in \meta{list of goals} must be separated with
- \code{+}. \meta{singular} and \meta{plural} are placed after the sum in
- the input stream depending on whether the sum equals~$1$ or not.
- \command{AddtoExerciseTypeGoal}[\marg{type}\marg{goal}\marg{value}]
- Adds \meta{value} to the goal \meta{goal} of exercise type \meta{type}.
- \command{AddtoExerciseTypeGoalPrint}[\marg{type}\marg{goal}\marg{value}%
- \marg{singular}\marg{plural}]
- Adds \meta{value} to the goal \meta{goal} of exercise type \meta{type}.
- The value and -- depending on wether the value equals $1$ or not --
- \meta{singular} or \meta{plural} are left in the input stream.
- \command{AddtoExerciseGoal}[\marg{goal}\marg{value}]
- Adds \meta{value} to the goal \meta{goal} of the current exercise
- type. (To be used within exercises.)
- \command{AddtoExerciseTypeGoalPrint}[\marg{goal}\marg{value}%
- \marg{singular}\marg{plural}]
- Adds \meta{value} to the goal \meta{goal} of the current exercise type.
- The value and -- depending on wether the value equals $1$ or not --
- \meta{singular} or \meta{plural} are left in the input stream. (To be used
- within exercises.)
- \command{ExerciseGoalValuePrint}[\marg{value}\marg{singular}\marg{plural}]
- Print \meta{value} and -- depending on wether the value equals $1$ or not --
- \meta{singular} or \meta{plural}.
- \command{printgoal}[\marg{value}]
- Print \meta{value} according to option \option{goal-print}. Defined in
- terms of \cs{ExerciseGoalValuePrint}.
- \command{printpoints}[\marg{type}]
- Print the sum of points for all exercises of type \meta{type} followed by
- an appropriate translation of the words \enquote{point} or
- \enquote{points}, respectively\footnote{See section~\vref{sec:exerc-transl}
- for details on the definition and usage of language dependent words.}.
- Defined in terms of \cs{TotalExerciseTypeGoal}.
- \command{printtotalpoints}
- Print the sum of points for all exercises followed by an appropriate
- translation of the words \enquote{point} or \enquote{points},
- respectively. Defined in terms of \cs{TotalExerciseGoal}.
- \command{addpoints}[\sarg\marg{value}]
- Adds \meta{value} to the points of the current exercise type. (To be used
- within exercises.) Prints the value followed by an appropriate
- translation of the words \enquote{point} or \enquote{points},
- respectively. The starred version prints nothing. Defined in terms of
- \cs{AddtoExerciseGoal} and \cs{AddtoExerciseGoalPrint}.
- \command{points}[\marg{value}]
- Print \meta{value} followed by an appropriate translation of the words
- \enquote{point} or \enquote{points}, respectively. Defined in terms of
- \cs{ExerciseGoalValuePrint}.
- \command{printbonus}[\marg{type}]
- Print the sum of bonus points for all exercises of type \meta{type}
- followed by an appropriate translation of the words \enquote{point} or
- \enquote{points}, respectively. Defined in terms of
- \cs{TotalExerciseTypeGoal}.
- \command{printtotalbonus}
- Print the sum of bonus points for all exercises followed by an appropriate
- translation of the words \enquote{point} or \enquote{points},
- respectively. Defined in terms of \cs{TotalExerciseGoal}.
- \command{addbonus}[\sarg\marg{value}]
- Adds \meta{value} to the bonus points of the current exercise type. (To be
- used within exercises.) Prints the value followed by an appropriate
- translation of the words \enquote{point} or \enquote{points},
- respectively. The starred version prints nothing. Defined in terms of
- \cs{AddtoExerciseGoal} and \cs{AddtoExerciseGoalPrint}.
-\end{commands}
-
-The two existing goals are defined with
-\begin{sourcecode}
- \DeclareExerciseGoal{points}
- \DeclareExerciseGoal{bonus-points}
-\end{sourcecode}
-
-When goal values are printed the decimal number is fed to a function which can
-be changed using the following option:
-\begin{options}
- \keyval{goal-print}{code}\Default{\#1}
- How to format goal values. Use \code{\#1} to refer to the actual number.
-\end{options}
-
-At last some examples for a custom command: let's say you want a command which
-prints the complete sum for all exercises of all exercise types of both
-\property{points} \emph{and} \property{bonus-points} added up:
-\begin{sourcecode}
- \NewDocumentCommand\printsumofpointsandbonus{}{%
- \TotalExerciseGoals{points+bonus-points}
- {\,\XSIMtranslate{point}}
- {\,\XSIMtranslate{points}}%
- }
-\end{sourcecode}
-Here is how you could mimick the command \cs*{totalpoints} from
-\pkg{exsheets}:
-\begin{sourcecode}
- \NewDocumentCommand\pointsandbonus{}{%
- \TotalExerciseGoal{points}{}{}%
- \IfExerciseGoalsSumF{bonus-points}{=0}
- {\,(+\,\TotalExerciseGoal{bonus-points}{}{})}%
- \,\XSIMtranslate{points}%
- }
-\end{sourcecode}
-
-
-\subsection[Exercise Tags]{A Special Kind of Property: Exercise Tags}\label{sec:tags}
-
-Exercise tags are a generic concept in \xsim\ for exercise properties like
-\property{tags} or \property{topics}. Those are properties which can (only)
-get a csv list of strings as value. Those strings can be used to selectively
-use exercises. See section~\vref{sec:using-printing} for details on
-\emph{usage} of exercises and the difference to \emph{printing} an exercise
-and how to use exercise tags for selection.
-\begin{commands}
- \command{DeclareExerciseTagging}[\marg{tag}]
- This defines an exercise tagging group named \meta{tag}. It also defines a
- property named \meta{tag}. In addition two options are defined: an option
- named \code{\meta{tag}} which can be used for selection and an boolean
- option \code{\meta{tag}/ignore-untagged}.
- \command{ProvideExerciseTagging}[\marg{tag}]
- The\sinceversion{0.11} same as \cs{DeclareExerciseTagging} but does
- nothing when \meta{tag} already exists.
-\end{commands}
-The two existing tagging groups have been defined and preset with the
-following code:
-\begin{sourcecode}
- \DeclareExerciseTagging{tags}
- \DeclareExerciseTagging{topics}
- \xsimsetup{tags/ignore-untagged=false}
-\end{sourcecode}
-This means that these options are available:
-\begin{options}
- \keyval{tags}{csv list of tags}
- Choose the set of tags whose associated exercises should be printed.
- \keyval{topics}{csv list of topics}
- Choose the set of topics whose associated exercises should be printed.
- \keybool{ignore-untagged}\Module{tags}\Default{false}
- If set to true exercises with no tags will be printed even if tags have
- been chosen with the option \option{tags}.
- \keybool{ignore-untagged}\Module{topics}\Default{true}
- If set to true exercises with no topics will be printed even if topics
- have been chosen with the option \option{topics}.
-\end{options}
-
-It may happen that you choose certain tags for printing and want one or two
-exercises to be printed or used even if they don't match the tagging
-criteria. For this reason two additional properties exist which can be set to
-an exercise:\label{property:print!}
-\begin{properties}
- \propbool{print\bang}
- If set to true the exercise will be printed (and thus used) regardless of
- other conditions.
- \propbool{use\bang}
- If set to true the exercise will be used regardless of other conditions.
-\end{properties}
-
-\section{Using and Printing an Exercise}\label{sec:using-printing}
-\subsection{What the Environments do}
-
-When an exercise is started with \environ{exercise} (or other environments
-defined through \cs{DeclareExerciseType}) then different things happen
-depending on different settings:
-\begin{itemize}
- \item If the \emph{insert mode} is active nothing happens, see
- section~\vref{sec:collecting-exercises} for details on this.
- \item Else the id integer is incremented.
- \item If the exercise is \emph{used} the corresponding counter is stepped
- and the exercise is added to the \enquote{use list}. The properties
- \property{counter} and \property{use} are updated accordingly.
- \item If an exercise is \emph{printed} then it is also \emph{used}. An
- exercise that isn't used cannot be printed. Being printed means two
- things: being added to the \enquote{print list} and being typeset at the
- position where the exercise is placed in the source file. If an exercise
- is \emph{not printed but used} it means that the counter will be stepped.
- This can be useful for creating an exercise sheet only containing the
- solutions for some exercises.
- \item If an exercise is printed certain hooks and template code is inserted
- around the environment body.
-\end{itemize}
-
-\begin{example}
- \begin{exercise}[print=false,ID=invisible]
- This exercise will not be printed but the exercise counter will be
- incremented nonetheless. Its solution will be printed in the list of
- solutions.
- \end{exercise}
- \begin{solution}
- The solution of the exercise that has not been printed.
- \end{solution}
-\end{example}
-
-The schematic structure of an exercise is shown in
-figure~\vref{fig:schematic-structure}.
-
-\begin{figure}
- \centering
- \begin{tikzpicture}
- \node[draw,minimum width=.7\linewidth] at (0,0) {pre hook};
- \node[draw,minimum width=.7\linewidth] at (0,-1) {begin template code};
- \node[draw,minimum width=.7\linewidth] at (0,-2) {begin hook};
- \node[draw,minimum width=.7\linewidth] at (0,-3) {environment body};
- \node[draw,minimum width=.7\linewidth] at (0,-4) {end hook};
- \node[draw,minimum width=.7\linewidth] at (0,-5) {end template code};
- \node[draw,minimum width=.7\linewidth] at (0,-6) {post hook};
- \end{tikzpicture}
- \caption{Schematic structure of an exercise or solution.}\label{fig:schematic-structure}
-\end{figure}
-
-\subsection{Environment Options \& Hooks}\label{sec:environment-options-hooks}
-
-For each exercise type there are the following options for both environments,
-the environments' names are the module names for the options (here using the
-\enquote{exercise} type):
-\begin{options}
- \keybool{print}\Module{exercise}\Default{true}
- Determines if exercises of type \enquote{exercise} are printed.
- \keybool{use}\Module{exercise}\Default{true}
- Determines if exercises of type \enquote{exercise} are used.
- \keyval{within}{counter}\Module{exercise}\Default
- Adds the exercise counter to the reset list of the counter
- \meta{counter}. \emph{Beware that if the counter is a shared counter
- this will affect \emph{all objects} using this counter!}
- \keyval{the-counter}{code}\Module{exercise}
- An interface for redefining the counter representation command
- \cs*{the\meta{counter}}.
- \keyval{template}{template}\Module{exercise}
- An interface for \cs{SetExerciseParameter}\Marg{exercise}%
- \Marg{exercise-template}\marg{template}.
- \keyval{template}{template}\Module{solution}
- An interface for \cs{SetExerciseParameter}\Marg{exercise}%
- \Marg{solution-template}\marg{template}.
- \keyval{name}{name}\Module{exercise}
- An interface for \cs{SetExerciseParameter}\Marg{exercise}%
- \Marg{exercise-name}\marg{name}.
- \keyval{name}{name}\Module{solution}
- An interface for \cs{SetExerciseParameter}\Marg{exercise}%
- \Marg{solution-name}\marg{name}.
- \keyval{heading}{heading command}\Module{exercise}
- An\sinceversion{0.14} interface for \cs{SetExerciseParameter}%
- \Marg{exercise}\Marg{exercise-heading}\marg{heading command}.
- \keyval{heading}{heading command}\Module{solution}
- An\sinceversion{0.14} interface for \cs{SetExerciseParameter}%
- \Marg{exercise}\Marg{solution-heading}\marg{heading command}.
- \keyval{pre-hook}{code}\Module{exercise}\Default
- The code for the \emph{pre exercise hook} for exercises of the type
- \enquote{exercise}.
- \keyval{begin-hook}{code}\Module{exercise}\Default
- The code for the \emph{begin exercise hook} for exercises of the type
- \enquote{exercise}.
- \keyval{end-hook}{code}\Module{exercise}\Default
- The code for the \emph{end exercise hook} for exercises of the type
- \enquote{exercise}.
- \keyval{post-hook}{code}\Module{exercise}\Default
- The code for the \emph{post exercise hook} for exercises of the type
- \enquote{exercise}.
- \keybool{print}\Module{solution}\Default{false}
- Determines if solutions of type \enquote{exercise} are printed.
- \keyval{pre-hook}{code}\Module{solution}\Default
- The code for the \emph{pre solution hook} for solutions of the type
- \enquote{exercise}.
- \keyval{begin-hook}{code}\Module{solution}\Default
- The code for the \emph{begin solution hook} for solutions of the type
- \enquote{exercise}.
- \keyval{end-hook}{code}\Module{solution}\Default
- The code for the \emph{end solution hook} for solutions of the type
- \enquote{exercise}.
- \keyval{post-hook}{code}\Module{solution}\Default
- The code for the \emph{post solution hook} for solutions of the type
- \enquote{exercise}.
- % TODO
-\end{options}
-
-\subsection{(Re-) Inserting a Certain Exercise}
-If you know type and \property{id} of an exercise you can (re-)insert every
-existing exercise, \ie, every exercise whose external file exists.
-\begin{commands}
- \command{printexercise}[\marg{type}\marg{csv of ids}]
- \changedversion{0.17}Inserts the exercise or exercises of type
- \meta{type} with the \property{id}s or \property{ID}s given in \meta{csv
- of ids}.
- \command{xprintexercise}[\marg{type}\marg{csv of ids}]
- \sincechanged{0.16}{0.17}The same as \cs{printexercise} but expands
- \meta{type} and the items of \meta{csv of ids} before it uses them.
-\end{commands}
-\begin{example}
- \printexercise{exercise}{invisible}
-\end{example}
-
-\section{Collecting Exercises}\label{sec:collecting-exercises}
-
-\begin{bewareofthedog}
- The whole collection mechanism is likely to change completely in the
- not-so-far future (let's say sometime in the six months from April~2020 or
- so).
-\end{bewareofthedog}
-
-\subsection{Background}
-\xsim\ knows the concept of \enquote{exercise collections}. A collection of
-exercises can be useful when you want to print a certain group of exercises
-several times. Each collection must have a unique name with which you can
-refer to the corresponding collection. A collection is realized by declaring
-the collection and by surrounding the exercises belonging to the collection
-with a certain pair of commands (this is explained in the next section).
-
-Let's say you have several files of math exercises where one only contains
-geometry exercises and another only calculus exercises and so on. Surrounding
-the \cs*{input} of each file with said pair of commands for a certain
-collection all exercises of the corresponding file now are a collection which
-then can be printed at once whereever you want the collection of exercises to
-be printed. By choosing certain tags (see section~\vref{sec:tags}) inside
-each collection you could even cherry-pick exercises from the external file.
-
-\subsection{Usage}
-\emph{A collection must be declared in the preamble.} Using a pair of
-commands explained below exercises between those commands are added to the
-corresponding collection but not printed. After a collection is completed the
-collection can be printed as often as needed.
-\begin{commands}
- \command{DeclareExerciseCollection}[\marg{collection name}]
- Define a new collection \meta{collection name} in the document preamble.
- \command{collectexercisestype}[\marg{collection name}\marg{exercise type}]
- Opens the collection \meta{collection name} which now collects all
- exercises of type \meta{exercise type} until the collection is closed with
- \cs{collectexercisesstop}. Collections of other types are not
- collected\footnote{This command starts a group with
- \cs*{begingroup}!}.
- \command{collectexercises}[\marg{collection name}]
- Opens the collection \meta{collection name} which now collects all
- exercises until the collection is closed with
- \cs{collectexercisesstop}\footnote{This command starts a group with
- \cs*{begingroup}!}.
- \command{collectexercisesstop}[\marg{collection name}]
- Closes the collection \meta{collection name}\footnote{This command ends
- a group with \cs*{endgroup}!}.
- \command{printcollection}[\oarg{options}\marg{collection name}]
- Prints the collection \meta{collection name}, \ie, all exercises collected
- earlier. This command cannot be used before the corresponding collection
- has been closed correctly.
-\end{commands}
-
-Valid options are the following:
-\begin{options}
- \keybool{headings}\Module{print-collection}\Default{false}
- If true a heading for each exercise type is inserted.
- \keyval{headings-template}{template}\Module{print-collection}\Default{collection}
- The heading template used when \keyis{headings}{true}.
- \keychoice{print}{exercises,solutions,both}\Module{print-collection}\Default{exercises}
- Determines wether \cs{printcollection} prints the exercises or the
- solutions of the collection. When you choose \code{both} exercises and
- solutions are printed alternately.
-\end{options}
-
-Those options can also be set via \cs{xsimsetup} using the module
-\module{print-collection}.
-
-\begin{bewareofthedog}
- Please be aware that exercises are not used or printed while they are
- collected. Nonetheless the property \property{use} is set to \code{true}
- (so that solutions can be printed even if the exercises are not) and the
- property \property{print} is set to \code{false}. Also their counters are
- \emph{not stepped} during the process. This only happens when they are
- printed the first time, \cf~the \property{used} property. At that time
- also the properties \property{page}, \property{section} and
- \property{chapter} are set and the property \property{print} is set to
- \code{true}.
-\end{bewareofthedog}
-
-The usage should be clear:
-\begin{example}
- \collectexercises{foo}
- \begin{exercise}
- This exercise is added to the collection `foo'.
- \end{exercise}
- \begin{exercise}
- This exercise is also added to the collection `foo'.
- \end{exercise}
- \begin{exercise}
- So is this.
- \end{exercise}
- \begin{exercise}
- As well as this one.
- \end{exercise}
- \collectexercisesstop{foo}
-\end{example}
-Once the collection is closed it can be printed:
-\begin{example}
- \printcollection{foo}
-\end{example}
-
-You can open several collections at the same time:
-\begin{sourcecode}
- \collectexercises{foo}
- ...
- \collectexercisestype{bar}{exercises}
- ...
- \collectexercisesstop{bar}
- ...
- \collectexercisesstop{foo}
-\end{sourcecode}
-Exercises will be added to each open collection.
-
-There is one generic collection called \enquote{\code{all exercises}}. As the
-name already suggests it will hold all exercises. So if you say
-\begin{sourcecode}
- \printcollection{all exercises}
-\end{sourcecode}
-all exercises will be printed.
-
-\begin{bewareofthedog}
- If you use \cs*{label}s inside of exercises and you print exercises more
- than once in your document (by reusing a collection for example) you will
- get
-\begin{sourcecode}
- LaTeX Warning: There were multiply-defined labels.
-\end{sourcecode}
- Equally if you have environments like \environ{equation} which step a
- counter inside an exercise or solution the counter will be stepped each time
- the exercise is used.
-\end{bewareofthedog}
-
-At last now an example using external files, collections and tags:
-\begin{sourcecode}
- % preamble:
- % \DeclareExerciseCollection{foo-easy}
- % \DeclareExerciseCollection{foo-medium}
- % \DeclareExerciseTagging{difficulty}
-
- % document:
- \collectexercises{foo-easy}
- \xsimsetup{difficulty=easy}
- \input{foo.tex}
- \collectexercisesstop{foo-easy}
- % collection `foo-easy' now contains all exercises of file `foo.tex' tagged
- % with `difficulty=easy'
-
- \collectexercises{foo-medium}
- \xsimsetup{difficulty=medium}
- \input{foo.tex}
- \collectexercisesstop{foo-medium}
- % collection `foo-medium' now contains all exercises of file `foo.tex'
- % tagged with `difficulty=medium'
-\end{sourcecode}
-
-\begin{bewareofthedog}
- The recommended usage is similar to the last example. Actually a collection
- can be printed \emph{before} it is opened, too. (This needs \emph{at least}
- two compilations, though.) However, it is safer printing a collection only
- once and only \emph{after it has been collected}. No guaranties are given
- that properties are set correctly if you use the collection before. You
- usually also will make sure that the exercises in a collection are unique,
- \ie, that an exercise is not part of several collections -- at least not if
- both collections are printed in the same document.
-\end{bewareofthedog}
-
-\section{Printing Random Exercises From a Collection}
-\xsim\ provides the possibility of selecting random exercises from a
-collection (\cf~section~\vref{sec:collecting-exercises}).
-\begin{bewareofthedog}
- Please be aware that this feature is \emph{not} available in \XeLaTeX!
-\end{bewareofthedog}
-\begin{commands}
- \command{printrandomexercises}[\oarg{options}\marg{number}]
- This command prints \meta{number} random exercises from the collection
- chosen with option \option{collection}, see below. When this command is
- used it generates a random list of integers which is written to the
- \code{aux} file. On the subsequent compilations the according exercises
- are printed. \emph{If you want to regenerate the random list you have to
- delete the \code{aux} file before compiling.}
-\end{commands}
-Valid options for this command are:
-\begin{options}
- \keybool{sort}\Module{random}\Default{true}
- Determines wether the random chosen exercises should be sorted according
- to their order of definition in the collection or not.
- \keyval{collection}{collection}\Module{random}\Default{all exercises}
- The collection from which the exercises are to be chosen from.
- \keyval{exclude}{csv list of ids}\Module{random}
- A list of \property{id}s or \property{ID}s of exercises \emph{not} to be
- chosen.
- \keychoice{print}{exercises,solutions,both}\Module{random}\Default{exercises}
- Determines wether \cs{printrandomexercises} prints the exercises or the
- solutions. When you choose \code{both} exercises and solutions are
- printed alternately.
-\end{options}
-
-\begin{example}
- \printrandomexercises[collection=foo]{2}
-\end{example}
-
-The example above of course doesn't make much sense but if you have a
-collection which collects exercises from an external file and the exercises
-haven't been printed in the document before then you will get a list of
-subsequently numbered exercises.
-
-\section{Printing Solutions}\label{sec:printing-solutions}
-
-There are different commands for printing the solutions to exercises:
-\begin{commands}
- \command{printsolutionstype}[\sarg\oarg{options}\marg{exercise type}]
- Prints the solutions of all used exercises of type \meta{exercise type}.
- The starred version only prints the solutions of all printed exercises of
- type \meta{exercise type}.
- \command{printsolutions}[\sarg\oarg{options}]
- Prints the solutions of all used exercises of all types ordered by type.
- The starred version only prints the solutions of all printed exercises of
- all types.
- \command{printallsolutions}[\sarg\oarg{options}]
- Prints the solutions of all used exercises of all types ordered by
- appearance in the document. The starred version only prints the solutions
- of all printed exercises of all types.
- \command{printsolution}[\oarg{options}\marg{type}\marg{id}]
- Prints the solution of the exercise of type \meta{type} with the
- \property{id} \meta{id}.
- \command{xprintsolution}[\marg{type}\marg{id}]
- \sinceversion{0.16}The same as \cs{printsolution} but expands \meta{type}
- and \meta{id} before it uses them.
-\end{commands}
-
-\begin{example}
- \printsolutionstype{exercise}
-\end{example}
-
-The options can be divided into two groups. The ones in the first group
-modify the layout.
-\begin{options}
- \keybool{headings}\Module{print-solutions}\Default{true}
- If true a heading for each exercise type is inserted.
- \keyval{headings-template}{template}\Module{print-solutions}\Default{default}
- The heading template used when \keyis{headings}{true}.
-\end{options}
-
-The ones in the second group set conditions selecting which solutions are
-printed. If you combine those conditions a solution is printed if it meets
-either of the conditions.
-\begin{options}
- \keychoice{section}{\default{true},false,\meta{integer}}\Module{print-solutions}%
- \Default{false}
- If you set \keyis{section}{true} only solutions of exercises of the
- current section are printed. If you set \keyis{section}{4} only solutions
- of exercises in a section with number~$4$ are printed.
- \keychoice{chapter}{\default{true},false,\meta{integer}}\Module{print-solutions}%
- \Default{false}
- If you set \keyis{chapter}{true} only solutions of exercises of the
- current chapter are printed. If you set \keyis{chapter}{4} only solutions
- of exercises in a chapter with number~$4$ are printed.
- \keychoice{collection}{false,\meta{collection name}}\Module{print-solutions}%
- \Default{false}
- If used only solutions of exercises belonging to collection
- \meta{collection name} are printed.
-\end{options}
-
-The conditions can be combined. The following call will only print solutions
-from exercises in section~3 of chapter~2:
-\begin{sourcecode}
- \printsolutions[chapter=2,section=3]
-\end{sourcecode}
-
-\begin{bewareofthedog}
- The selection per section or per chapter relies on the \emph{counter
- numbers} of the sections or chapters, respectively. This means if section
- numbers are reset (\eg\ by \cs*{chapter} or \cs*{appendix}) and you have
- exercises from \emph{different} sections with \emph{the same section number}
- the solutions of \emph{all those exercises} will be printed. This means you
- only should use the \option{section} selection when section are the top
- document level headings (apart from parts) and you have no exercises in the
- appendix. Similar considerations are valid for the \option{chapter}
- selection.
-\end{bewareofthedog}
-
-All options can also be set via \cs{xsimsetup} using the module
-\module{print-solutions}.
-
-\begin{example}
- \printsolutions[section=4,headings-template=per-section]
-\end{example}
-
-\begin{example}
- \printsolution{exercise}{5}
-\end{example}
-
-\section{Grading Tables}\label{sec:grading-tables}
-When you create exercises it may not only be desirable to be able to add
-points and bonus-points to a question (see section~\vref{sec:goals} about
-exercise goals) but also to be able to output a grading table. \xsim\ has
-built-in means for this.
-\begin{commands}
- \command{gradingtable}[\oarg{options}]
- Print a grading table.
-\end{commands}
-Valid options for this command are
-\begin{options}
- \keyval{template}{template}\Default{default}
- Choose the template used for the grading table.
- \keyval{type}{exercise type}\Default
- Choose the exercise type for which the table is printed.
-\end{options}
-Both option defaults can be changed with \cs{xsimsetup} setting the options
-using \module{grading-table}:
-\begin{sourcecode}
- \xsimsetup{
- grading-table/template = default*
- }
-\end{sourcecode}
-
-An example:
-\begin{example}
- \gradingtable[type=exercise]
-\end{example}
-
-Or using the \enquote{\code{default*}} template:
-\begin{example}
- \gradingtable[template=default*,type=exercise]
-\end{example}
-
-Available templates and how to define new ones are explained in
-sections~\vref{sec:grad-table-templ} and~\vref{sec:template-examples}. \xsim\
-per default provides two templates \enquote{\code{default}} and
-\enquote{\code{default*}}, the first one has a vertical layout, the second a
-horizontal layout. Both templates can be used per type like in the examples
-above or for all types at once by leaving the specification \option{type}
-away:
-\begin{example}
- \gradingtable
-\end{example}
-
-\section{Styling the Exercises -- Templates}\label{sec:styl-exerc-templ}
-
-\subsection{Background}
-Whenever \xsim\ outputs something to be typeset it uses so-called templates
-for the task. \xsim\ knows of three different kinds of templates:
-\begin{itemize}
- \item environment templates (see section~\vref{sec:envir-templ}),
- \item heading templates (see section~\vref{sec:heading-templates}) and
- \item grading table templates (see section~\vref{sec:grad-table-templ})
-\end{itemize}
-
-The most important one for the styling of the exercises are the environment
-templates. Those templates give you complete control over the look and
-arrangement of an exercise. To be able to do this \xsim\ provides a large
-number of commands which can be used only inside template
-definitions\footnote{The last sentence is wrong: those commands can be used
- anywhere but most of them only give useful results inside of templates.}.
-Those commands are explained in the next section. Their usage will hopefully
-become clear in the examples in section~\vref{sec:template-examples}. Having
-full control over the layout comes at a price: you need to be able to program
-yourself in order to achieve certain layouts\footnote{I plan to incorporate
- the most common layouts -- and maybe some fancy ones, too -- in the examples
- section~\vref{sec:template-examples} but at the time of writing this is still
- up in the air.}.
-
-\subsection{Templates Provided by the Package}
-\xsim\ comes with a few predefined layouts:
-\begin{description}
- \item[\code{default}] The template activated per default and the only one
- available without further action.
- \item[\code{runin}] A layout rather similar to the one by package
- \pkg{exsheets}, see section~\vref{sec:runin-template}. Available through
- the style file \code{layouts} (see section~\vref{sec:style-files} for more
- information on style files\index{style file}).
- \item[\code{margin}] A layout rather similar to the one by package
- \pkg{exsheets}, see section~\ref{sec:margin-template}. Available through
- the style file \code{layouts}.
- \item[\code{minimal}] A\sinceversion{0.13} minimalistic layout, see
- section~\ref{sec:minimal-template}. As the others inspired by an
- \pkg{exsheets} layout. Available through the style file \code{layouts}.
- \item[\code{inline}] A\sinceversion{0.18} minimalistic layout, the same as
- \code{minimal} but doesn't add \cs*{par} at the beginning and end.
- Available through the style file \code{layouts}.
- \item[\code{centered}] A\sinceversion{0.18} layout with a centered heading.
- Available through the style file \code{layouts}.
-\end{description}
-
-\collectexercises{layouts}
-\begin{exercise}[subtitle=The Subtitle,points=2.5,ID=showlayout]
- Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut purus elit,
- vestibulum ut, placerat ac, adipiscing vitae, felis. Curabitur dictum
- gravida mauris. Nam arcu libero, nonummy eget, consectetuer id, vulputate a,
- magna. Donec vehicula augue eu neque. Pellentesque habitant morbi tristique
- senectus et netus et malesuada fames ac turpis egestas. Mauris ut leo. Cras
- viverra metus rhoncus sem.
-\end{exercise}
-\collectexercisesstop{layouts}
-
-\listlayouts
-
-\subsection{Commands for Usage in Template Definitions}
-\subsubsection{Goals}
-\begin{commands}
- \command{IfExerciseGoal\TF}[\marg{goal}\marg{relation and
- value}\marg{true}\marg{false}]
- Checks the sum of goal \meta{goal} against \meta{relation and value}.
- \command{IfExerciseGoalSingular\TF}[\marg{goal}\marg{true}\marg{false}]
- Checks if the value of the goal \meta{goal} of the current exercise
- equals~$1$. This is the same as \\
- \cs{IfExerciseGoalTF}\marg{goal}\Marg{=1}\marg{true}\marg{false}.
- \command{IfExerciseTypeGoalsSum\TF}[\marg{type}\marg{list of
- goals}\marg{relation and value}\marg{true}\marg{false}]
- Ckecks the sum of all goals in \meta{list of goals} for the exercises of
- type \meta{type} against \meta{relation and value}.
- \command{IfExerciseGoalsSum\TF}[\marg{type}\marg{list of
- goals}\marg{relation and value}\marg{true}\marg{false}]
- Ckecks the sum of all goals in \meta{list of goals} for all exercises of
- all types against \meta{relation and value}.
- \command{TotalExerciseTypeGoal}[\marg{goal}\marg{type}\marg{singular}\marg{plural}]
- Print the sum of goal \meta{goal} for the exercises of type \meta{type}
- and append \meta{singular} or \meta{plural} depending on wether the sum
- equals~$1$ or not.
- \command{TotalExerciseGoal}[\marg{goal}\marg{singular}\marg{plural}]
- Print the sum of goal \meta{goal} for all exercises of all types
- and append \meta{singular} or \meta{plural} depending on wether the sum
- equals~$1$ or not.
-\end{commands}
-
-\subsubsection{Properties}
-\begin{commands}
- \expandable\command{IfExercisePropertyExist\TF}[\marg{property}\marg{true}%
- \marg{false}]
- Tests wether an exercise property with the name \meta{property} is defined.
- \command{IfExercisePropertySet\TF}[\marg{property}\marg{true}\marg{false}]
- Tests wether the exercise property \meta{property} has been set for the
- current exercise.
- \expandable\command{GetExerciseProperty}[\marg{property}]
- Retrieves the value of the property \meta{property} for the current
- exercise.
- \command{GetExerciseProperty\TF}[\marg{property}\marg{true}\marg{false}]
- Tests wether the exercise property \meta{property} has been set for the
- current exercise. Inside the \meta{true} branch you can refer to the
- retrieved value either with \code{\#1} or with \cs{PropertyValue}.
- \emph{This command expands its contents inside a group.}
- \command{GetExerciseBody}[\Marg{exercise\textnormal{|}solution}]
- \sinceversion{0.10}Retrieves the environment body of either the
- \code{exercise} or the corresponding \code{solution} of the current
- exercise.
- \expandable\command{GetExerciseIdForProperty}[\marg{property}\marg{value}]
- Retrieves the property \property{id} of the exercise where the property
- \meta{property} has the value \meta{value}. \emph{This only works for
- \emph{unique} properties!}
- \command{GetExerciseTypeForProperty}[\marg{property}\marg{value}]
- Retrieves the property \property{type} of the exercise where the
- property \meta{property} has the value \meta{value}. \emph{This only
- works for \emph{unique} properties!}
- \command{SetExerciseProperty}[\marg{property}\marg{value}]
- \changedversion{0.9}Set the property \meta{property} of the current
- exercise to \meta{value}.
- \command{SetExpandedExerciseProperty}[\marg{property}\marg{value}]
- \sinceversion{0.9}Expand \meta{value} \cs*{edef}-like and set the property
- \meta{property} of the current exercise to the result of the expansion.
- \command{ExerciseSetProperty}[\marg{type}\marg{id}\marg{property}\marg{value}]
- \sinceversion{0.9}Set the property \meta{property} of the exercise of type
- \meta{type} and id \meta{id} to \meta{value}.
- \command{ExerciseSetExpandedProperty}[\marg{type}\marg{id}\marg{property}\marg{value}]
- \sinceversion{0.9}Expand \meta{value} \cs*{edef}-like and set the property
- \meta{property} of the exercise of type \meta{type} and id \meta{id} to
- the result of the expansion.
- \expandable\command{IfExerciseBooleanProperty\TF}[\marg{property}%
- \marg{true}\marg{false}]
- Checks wether the boolean property \meta{property} has value \code{true}
- or \meta{false} and leaves the corresponding argument in the input
- stream. Gives an error if \meta{property} is not a boolean property.
- \expandable\command{GetExerciseAliasProperty}[\marg{property}]
- Retrieves the value of the property of which \meta{property} is an alias
- of for the current exercise.
- \command{SaveExerciseProperty}[\marg{property}\meta{macro}]
- Saves the value of the property \meta{property} for the current
- exercise in macro \meta{macro}.
- \command{GlobalSaveExerciseProperty}
- Globally saves the value of the property \meta{property} for the current
- exercise in macro \meta{macro}.
- \command{ExercisePropertyIfSet\TF}[\marg{type}\marg{id}\marg{property}%
- \marg{true}\marg{false}]
- Test if the property \meta{property} has been set for the exercise of type
- \meta{type} with id \meta{id}.
- \expandable\command{ExercisePropertyGet}[\marg{type}\marg{id}\marg{property}]
- Retrieves the value of the property \meta{property} for the exercise of type
- \meta{type} with id \meta{id}.
- \expandable\command{ExercisePropertyGetAlias}[\marg{type}\marg{id}\marg{property}]
- Retrieves the value of the property of which \meta{property} is an alias
- of for the exercise of type \meta{type} with id \meta{id}.
- \command{ExercisePropertySave}[\marg{type}\marg{id}\marg{property}\meta{macro}]
- Saves the value of the property \meta{property} for the exercise of type
- \meta{type} with id \meta{id} in macro \meta{macro}.
- \command{ExercisePropertyGlobalSave}[\marg{type}\marg{id}\marg{property}\meta{macro}]
- Globally saves the value of the property \meta{property} for the exercise
- of type \meta{type} with id \meta{id} in macro \meta{macro}.
-\end{commands}
-
-\subsubsection{Parameters}
-\begin{commands}
- \expandable\command{GetExerciseParameter}[\marg{parameter}]
- Retrieves the value of the parameter \meta{paramater} for the current
- exercise type.
- \command{GetExerciseParameter\TF}[\marg{parameter}\marg{true}\marg{false}]
- \sinceversion{0.9}Retrieves the value of the parameter \meta{paramater}
- for the current exercise type. Inside the \meta{true} branch you can refer
- to the retrieved value either with \code{\#1} or with \cs{ParameterValue}.
- \emph{This command expands its contents inside a group.}
- \expandable\command{GetExerciseName}
- Retrieves the value of the parameter \parameter{exercise-name} for the
- current exercise or of the parameter \parameter{solution-name} for the
- current solution.
- \expandable\command{GetExerciseHeadingF}[\marg{false}]
- \sinceversion{0.14}Retrieves the value of the parameter
- \parameter{exercise-heading} for the current exercise or of the parameter
- \parameter{solution-heading} for the current solution. Inserts
- \meta{false} if the corresponding parameter has not been set.
- \expandable\command{ExerciseParameterGet}[\marg{type}\marg{parameter}]
- Retrieves the value of the parameter \meta{parameter} for the exercise of type
- \meta{type} with id \meta{id}.
- \expandable\command{IfExerciseParameterSet\TF}[\marg{parameter}%
- \marg{true}\marg{false}]
- \sinceversion{0.9}Test if the parameter \meta{parameter} has been set for
- the current exercise type.
- \expandable\command{ExerciseParameterIfSet\TF}[\marg{type}\marg{parameter}%
- \marg{true}\marg{false}]
- \sinceversion{0.9}Test if the parameter \meta{parameter} has been set for
- the exercise type \meta{type}.
-\end{commands}
-
-\subsubsection{Tags}
-\begin{commands}
- \command{ForEachExerciseTag}[\marg{type}\marg{code}]
- Loops over all tags of tag type \meta{type} for the current exercise
- applying \meta{code} each time. Inside \meta{code} you can refer to the
- corresponding tag with \code{\#1}.
- \command{ListExerciseTags}[\marg{type}\marg{between}]
- Lists all tags of tag type \meta{type} for the current exercise using
- \meta{between} as a separator.
- \command{UseExerciseTags}[\marg{type}\marg{between
- two}\marg{between}\marg{between last two}]
- Lists all tags of tag type \meta{type} for the current exercise using
- \meta{between} as a separator and \meta{between last two} as separator
- between the last two tags of the list. If the list only consists of two
- tags \meta{between two} is used as separator.
- \command{IfExerciseTagSet\TF}[\marg{value}\marg{true}\marg{false}]
- In\sinceversion{0.11} order to insert text (also \emph{outside} of
- exercises) depending on the chosen tags this command lets you check if
- value \meta{value} has been set for \property{tags}.
- \command{IfExerciseTopicSet\TF}[\marg{value}\marg{true}\marg{false}]
- In\sinceversion{0.11} order to insert text (also \emph{outside} of
- exercises) depending on the chosen tags this command lets you check if
- value \meta{value} has been set for \property{topics}.
-\end{commands}
-
-\subsubsection{Further Commands for Usage in Template Definitions}
-\begin{commands}
- \command{UseExerciseTemplate}[\marg{type}\marg{name}]
- Retrieve template \meta{name} of type \meta{type}. This can be useful if
- you want to define a template which just adds some code to an existing
- template (an automated \cs*{label}, say).
- \expandable\command{ExerciseType}
- Can be used to refer to the current exercise type.
- \expandable\command{ExerciseID}
- Can be used to refer to the current exercise id.
- \expandable\command{ExerciseText}
- Can be used inside solutions to retrieve the text of the corresponding
- solution. This is propably seldom useful as in most use cases the
- exercise property \property{solution} is the easier alternative.
- \expandable\command{ExerciseCollection}
- Can be used in certain templates to refer to the collection that is
- currently inserted.
- \expandable\command{numberofusedexercises}
- Holds the total number of used exercises. Useful in table template
- definitions.
- \expandable\command{ExerciseTableType}[\marg{code}]
- In table template definitions this macro either expands to the given
- exercise type or -- if no type has been given -- to \meta{code}.
- \expandable\command{IfInsideSolution\TF}[\marg{true}\marg{false}]
- Tests if the template is used inside a solution environment or not.
- \expandable\command{IfSolutionPrint\TF}[\marg{true}\marg{false}]
- Tests if the option \option{print} for the solutions of the current
- \cs{ExerciseType} is set to \code{true} or \code{false}.
- \command{IfExistSolution\TF}[\marg{true}\marg{false}]
- \sinceversion{0.9}Tests if a solution for the current exercise exists.
- \command{ForEachPrintedExerciseByType}[\marg{code}]
- Loops over each \emph{printed} exercise ordered by the exercise types and
- within each type by id. Inside \meta{code} you can refer to several
- properties of the corresponding exercise:
- \begin{itemize}
- \item \code{\#1}: the type of the exercise
- \item \code{\#2}: the id of the exercise
- \item \code{\#3}: the \property{counter} property of the exercise
- \item \code{\#4}: the \property{subtitle} property of the exercise
- \item \code{\#5}: the \property{points} property of the exercise
- \item \code{\#6}: the \property{bonus-points} property of the exercise
- \end{itemize}
- \command{ForEachUsedExerciseByType}[\marg{code}]
- Loops over each \emph{used} exercise ordered by the exercise types and
- within each type by id. Inside \meta{code} you can refer to several
- properties of the corresponding exercise:
- \begin{itemize}
- \item \code{\#1}: the type of the exercise
- \item \code{\#2}: the id of the exercise
- \item \code{\#3}: the \property{counter} property of the exercise
- \item \code{\#4}: the \property{subtitle} property of the exercise
- \item \code{\#5}: the \property{points} property of the exercise
- \item \code{\#6}: the \property{bonus-points} property of the exercise
- \end{itemize}
- \command{ForEachPrintedExerciseByID}[\marg{code}]
- Loops over each \emph{printed} exercise order by the exercise id. Inside
- \meta{code} you can refer to several properties of the corresponding
- exercise:
- \begin{itemize}
- \item \code{\#1}: the type of the exercise
- \item \code{\#2}: the id of the exercise
- \item \code{\#3}: the \property{counter} property of the exercise
- \item \code{\#4}: the \property{subtitle} property of the exercise
- \item \code{\#5}: the \property{points} property of the exercise
- \item \code{\#6}: the \property{bonus-points} property of the exercise
- \end{itemize}
- \command{ForEachUsedExerciseByID}[\marg{code}]
- Loops over each \emph{used} exercise order by the exercise id. Inside
- \meta{code} you can refer to several properties of the corresponding
- exercise:
- \begin{itemize}
- \item \code{\#1}: the type of the exercise
- \item \code{\#2}: the id of the exercise
- \item \code{\#3}: the \property{counter} property of the exercise
- \item \code{\#4}: the \property{subtitle} property of the exercise
- \item \code{\#5}: the \property{points} property of the exercise
- \item \code{\#6}: the \property{bonus-points} property of the exercise
- \end{itemize}
- \command{XSIMprint}[\Marg{exercise|solution}\marg{type}\marg{id}]
- \sincechanged{0.16}{0.17}Inserts the either the exercise or the solution
- of type \meta{type} with the \property{id} or \property{ID} \meta{id}.
- \command{XSIMxprint}[\Marg{exercise|solution}\marg{type}\marg{id}]
- The same as \cs{XSIMprint} but expands \meta{type} and \meta{id} before it
- uses them.\sincechanged{0.16}{0.17}
- \expandable\command{XSIMtranslate}[\marg{keyword}]
- Delivers the translation of \meta{keyword} according to the current
- document language (in the meaning of a \pkg{babel}~\cite{pkg:babel} or
- \pkg{polyglossia}~\cite{pkg:polyglossia} language). Existing keywords and
- keyword translations (and how to add new ones) are explained in
- section~\vref{sec:exerc-transl}.
- \command{XSIMexpandcode}[\marg{code}]
- Expands \meta{code} like \cs*{edef} does and leaves the result in the
- input stream.
- \expandable\command{XSIMifchapter\TF}[\marg{true}\marg{false}]
- Returns \meta{true} if both a macro \cs*{chapter} and a counter
- \code{chapter} are defined and \meta{false} otherwise.
- \command{XSIMmixedcase}[\marg{code}]
- Converts the full expansion\footnote{This is a \cs*{romannumeral}
- expansion~\cite{texsx:romannumeral}.\label{fn:romannumeral}} of
- \meta{code} to mixed case: \\
- \verbcode+\XSIMmixedcase{this is some text}+ \XSIMmixedcase{this is some
- text} \\
- \emph{This command expands \meta{code} before converting it}.
- \command{XSIMputright}[\meta{macro}\marg{code}]
- Extends the macro definition of \meta{macro} with \meta{code} putting it
- to the right. This is more or less a local version of the LaTeX kernel
- macro \cs*{g at addto@macro}.
- \expandable\command{XSIMifeq\TF}[\marg{code 1}\marg{code
- 2}\marg{true}\marg{false}]
- Checks if the full expansion\footref{fn:romannumeral} of \meta{code 1} and
- \meta{code 2} is the same tokenlist.
- \expandable\command{XSIMifblank\TF}[\marg{code}\marg{true}\marg{false}]
- Checks if the full expansion\footref{fn:romannumeral} of \meta{code} is
- blank (\ie, if it is empty or only consists of spaces).
- \command{XSIMatbegindocument}[\marg{code}]
- \sinceversion{0.15a}Adds \meta{code} to \xsim's begin document hook.
- Should be used inside style files instead of \cs*{AtBeginDocument}.
- \command{XSIMatenddocument}[\marg{code}]
- \sinceversion{0.15a}Adds \meta{code} to \xsim's end document hook.
- Should be used inside style files instead of \cs*{AtEndDocument}.
-\end{commands}
-
-\subsection{Declaring Templates}
-\subsubsection{Environment Templates}\label{sec:envir-templ}
-\begin{commands}
- \command{DeclareExerciseEnvironmentTemplate}[\marg{name}\marg{begin
- code}\marg{end code}]
- Declare the environment template \meta{name}.
-\end{commands}
-Environment templates are used by the exercise and solution environments.
-Those are the templates set with the parameters \parameter{exercise-template}
-and \parameter{solution-template}.
-
-The predefined template is called \enquote{\code{default}}, see
-section~\vref{sec:exercise-templ-default}.
-
-\subsubsection{Heading Templates}\label{sec:heading-templates}
-\begin{commands}
- \command{DeclareExerciseHeadingTemplate}[\marg{name}\marg{code}]
- Declare the heading template \meta{name}.
-\end{commands}
-Heading templates are used by \cs{printsolutions}, \cs{printsolutionstype} and
-\cs{printcollection}. Those are the templates set with the option
-\option{headings-template} of the modules \module{print-solutions} and
-\module{print-collection}.
-
-The predefined templates are \enquote{\code{default}},
-\enquote{\code{collection}}, \enquote{\code{per-section}} and
-\enquote{\code{per-chapter}} see section~\vref{sec:headings-templates}.
-
-\subsubsection{Grading Table Templates}\label{sec:grad-table-templ}
-\begin{commands}
- \command{DeclareExerciseTableTemplate}[\marg{name}\marg{code}]
- Declare the grading table template \meta{name}.
-\end{commands}
-Table templates are used by \cs{gradingtable}. Those are the templates set
-with the option \option{template} of module \module{grading-table}
-
-The predefined templates are \enquote{\code{default}} and
-\enquote{\code{default*}}, see sections~\vref{sec:table-templ-default}
-and~\vref{sec:table-templ-default*}.
-
-\subsection{Create and Use \xsim\ Style Files}\label{sec:style-files}
-\index{style file|(}
-
-\xsim\changedversion{0.11} offers you the possibility to create own
-\emph{style files}. Let's say you want to have a style called
-\code{math-exam}. Then you need to save all necessary definitions in a file
-called:
-\begin{center}
- \code{xsim.style.math-exam.code.tex}
-\end{center}
-The first command in the file should be \cs{xsimstyle}\Marg{math-exam}. This
-file can now be loaded into your document using
-\cs{loadxsimstyle}\Marg{math-exam} or by using
-\cs{xsimsetup}\Marg{load-style=math-exam}:
-\begin{sourcecode}
- \documentclass[DIV=18,parskip=half]{scrartcl}
- \usepackage[T1]{fontenc}
- \usepackage[utf8]{inputenc}
-
- \usepackage[clear-aux]{xsim}
- \loadxsimstyle{math-exam}
-
- \title{Math Exam \#3}
- \date{2017-03-28}
-\end{sourcecode}
-
-In this style file stuff like template and property definitions should
-happen. This is more or less a convenient way to
-\begin{itemize}
- \item keep the preamble \enquote{clean} and
- \item define re-usable styles without the need of copying the document
- preamble to another document.
-\end{itemize}
-A style file is like a package or class file, \ie, \code{@} has category
-code~11 (letter).
-
-The formal description of the commands:
-\begin{commands}
- \command{xsimstyle}[\sarg\marg{style name}]
- The\changedversion{0.11} first command in a \xsim\ style file called
- \code{xsim.style.\meta{style name}.code.tex} which defines the \xsim\
- style \meta{style name}. The starred version activates expl3
- syntax\footnote{Those users who want this will know what it means. If you
- don't know what it means you will not need it.}.
- \command{loadxsimstyle}[\marg{csv list of style names}]
- Load one or more styles into the document.
-\end{commands}
-\begin{options}
- \keyval{load-style}{csv list of style names}
- Another\sinceversion{0.14} interface for \cs{loadxsimstyle}\marg{csv list
- of style names}.
-\end{options}
-
-\begin{bewareofthedog}
- At the moment this mechanism offers no advantages over creating a custom
- package or simply \cs*{input}ing a file. Future versions might provide
- additional features.
-\end{bewareofthedog}
-
-\index{style file|)}
-
-\subsection{Examples}\label{sec:template-examples}
-
-The repository of this package\footnote{GitHub:
- \url{https://github.com/cgnieder/xsim/}, CTAN:
- \url{http://www.ctan.org/pkg/xsim/}} currently includes
-\theexamplefiles~example documents demonstrating how different aspects of this
-package work or how different kinds of problems can be solved or how different
-kinds of layouts can be achieved as well as how solve concrete problems that
-have come up in different \LaTeX\ forums, see
-section~\vref{sec:example-files}.
-
-\subsubsection{The \code{default} Exercise Template}\label{sec:exercise-templ-default}
-
-Below the definition\changedversion{0.14} of the \code{default} exercise
-template provided by \xsim\ is shown:
-
-\begin{sourcecode}
- \DeclareExerciseEnvironmentTemplate{default}{%
- \GetExerciseHeadingF{\subsection*}%
- {%
- \XSIMmixedcase{\GetExerciseName}\nobreakspace
- \GetExerciseProperty{counter}%
- \IfInsideSolutionF
- {%
- \GetExercisePropertyT{subtitle}
- { {\normalfont\itshape\PropertyValue}}%
- }%
- }
- \GetExercisePropertyT{points}
- {%
- \marginpar
- {%
- \IfInsideSolutionF{\rule{1.2cm}{1pt}\slash}%
- \printgoal{\PropertyValue}
- \GetExercisePropertyT{bonus-points}{~(+\printgoal{\PropertyValue})}%
- ~\XSIMtranslate {point-abbr}%
- }%
- }%
- }
- {\par}
-\end{sourcecode}
-
-\subsubsection{A New Exercise Type Using \pkg*{tcolorbox}}
-Let's say we want exercises to be put in a \env*{tcolorbox}. We want a bold
-title and. if given, an italic subtitle. Exercises should also have the
-points after the subtitle in parentheses if given. Let's also say we want
-those to be an additional exercise type in addition to the ones \xsim\ already
-provides. This is shown with the following code which is also how the
-problems in this manual have been defined:
-
-\begin{sourcecode}
- \DeclareExerciseEnvironmentTemplate{tcolorbox}
- {%
- \tcolorbox[
- colback = red!5!white ,
- colframe = red!75!black ,
- colbacktitle = yellow!50!red ,
- coltitle = red!25!black ,
- breakable ,
- drop shadow ,
- beforeafter skip = .5\baselineskip ,
- title =
- \textbf{\GetExerciseName~\GetExerciseProperty{counter}}%
- \GetExercisePropertyT{subtitle}{ \textit{\PropertyValue}}%
- \IfInsideSolutionF{%
- \GetExercisePropertyT{points}{ % notice the space
- (%
- \printgoal{\PropertyValue}
- \IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}}%
- )%
- }%
- }%
- ]%
- }
- {\endtcolorbox}
-
- \DeclareExerciseType{problem}{
- exercise-env = problem ,
- solution-env = answer ,
- exercise-name = Problem ,
- solution-name = Answer ,
- exercise-template = tcolorbox ,
- solution-template = tcolorbox
- }
-\end{sourcecode}
-
-See it in action:
-\begin{example}
- \begin{problem}[subtitle=My subtitle,points=5]
- This is a problem using a subtitle and points.
- \end{problem}
- \begin{answer}
- This is the answer to problem~\GetExerciseProperty{counter}.
- \end{answer}
-\end{example}
-
-\subsubsection{Mimicking \pkg*{exsheets}' \code{runin} Template}
-\label{sec:runin-template}
-
-The following example shows how you could mimick \pkg*{exsheets}' \code{runin}
-template. The outcome isn't exactly the same since \pkg{exsheets} doesn't use
-\cs*{marginpar} but the result should look very similar. A safer definition
-would use a real sectioning command for the title.
-
-\begin{sourcecode}
- \usepackage{needspace}
- \DeclareExerciseEnvironmentTemplate{runin}
- {%
- \par\vspace{\baselineskip}
- \Needspace*{2\baselineskip}
- \noindent
- \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}%
- \GetExercisePropertyT{subtitle}{ \textit{#1}} % <<< notice the space
- \IfInsideSolutionF{%
- \GetExercisePropertyT{points}{%
- \marginpar{%
- \printgoal{\PropertyValue}%
- \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
- \,\IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}}%
- }%
- }%
- }%
- }
- {}
-\end{sourcecode}
-
-\subsubsection{Mimicking \pkg*{exsheets}' \code{margin} Template}
-\label{sec:margin-template}
-
-The following example shows how you could mimick \pkg*{exsheets}'
-\code{margin} template.
-
-\begin{sourcecode}
- \DeclareExerciseEnvironmentTemplate{margin}
- {%
- \trivlist
- \item[\llap{%
- \smash{%
- \tabular[t]{@{}r@{}}
- \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}
- \IfExercisePropertySetT{points}{%
- \tabularnewline
- (%
- \printgoal{\GetExerciseProperty{points}}%
- \GetExercisePropertyT{bonus-points}{+\printgoal{#1}}%
- \,\XSIMtranslate{point-abbr}%
- )%
- }%
- \endtabular
- }%
- }]\relax
- }
- {\endtrivlist}
-\end{sourcecode}
-
-\subsubsection{A \code{minimal} Template}
-\label{sec:minimal-template}
-
-This shows the implementation of the \code{minimal} template:
-\begin{sourcecode}
- \DeclareExerciseEnvironmentTemplate{minimal}
- {%
- \par
- \textbf{\GetExerciseProperty{counter}}%
- \IfInsideSolutionF{%
- \GetExercisePropertyT{points}{%
- \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
- \,\IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}}%
- }%
- }%
- }
- {\par}
-\end{sourcecode}
-
-\subsubsection{The Headings Templates}\label{sec:headings-templates}
-\xsim\ defines four heading templates which only differ by which text they
-output:
-\begin{sourcecode}
- \DeclareExerciseHeadingTemplate{default}
- {\section*{\XSIMtranslate{default-heading}}}
- \DeclareExerciseHeadingTemplate{collection}
- {\section*{\XSIMtranslate{collection-heading}}}
- \DeclareExerciseHeadingTemplate{per-section}
- {\section*{\XSIMtranslate{per-section-heading}}}
- \DeclareExerciseHeadingTemplate{per-chapter}
- {\section*{\XSIMtranslate{per-chapter-heading}}}
-\end{sourcecode}
-Section~\vref{sec:exerc-transl} shows how the translations are defined.
-
-\subsubsection{The \code{default} Table Template}\label{sec:table-templ-default}
-This template is the one used for grading tables per default. It has a
-vertical layout.
-
-\begin{sourcecode}
- \DeclareExerciseTableTemplate{default}{%
- \XSIMputright\ExerciseTableCode{%
- \toprule
- \XSIMifblankTF{\ExerciseType}
- {}
- {\XSIMmixedcase{\GetExerciseParameter{exercise-name}}}
- &
- \XSIMmixedcase{\XSIMtranslate{points}} &
- \XSIMtranslate{reached} \\
- \midrule
- }%
- \ForEachUsedExerciseByType{%
- \XSIMifeqTF{#1}{\ExerciseTableType{#1}}
- {%
- \XSIMifblankTF{\ExerciseType}
- {%
- \XSIMputright\ExerciseTableCode{%
- \XSIMmixedcase{\ExerciseParameterGet{#1}{exercise-name} }%
- }%
- }
- {}%
- \XSIMputright\ExerciseTableCode
- {#3 & \XSIMifblankTF{#5}{\printgoal{0}}{\printgoal{#5}} & \\ }%
- }
- {}%
- }
- \XSIMputright\ExerciseTableCode{%
- \midrule
- \XSIMtranslate{total} &
- \XSIMifblankTF{\ExerciseType}
- {\TotalExerciseGoal{points}{}{}}
- {\TotalExerciseTypeGoal{\ExerciseType}{points}{}{}} &
- \\ \bottomrule
- }%
- \XSIMexpandcode{%
- \noexpand\begin{tabular}{\XSIMifblankTF{\ExerciseType}{l}{c}cc}
- \noexpand\ExerciseTableCode
- \noexpand\end{tabular}%
- }%
- }
-\end{sourcecode}
-
-The part
-\begin{sourcecode}
- \XSIMifblankTF{\ExerciseType}{ ... }{ ... }
-\end{sourcecode}
-repeatedly checks if an exercise type has been given for the table. This
-makes it possible to design the table differently if it is for one exercise
-type only (the \code{true} case) or for all exercise types (the \code{false}
-case). \cs*{ExerciseTableType}\marg{code} either expands to the given
-exercise type or to \meta{code}.
-
-\subsubsection{The \code{default*} Table Template}\label{sec:table-templ-default*}
-The second of the predefined grading table templates. It has a horizontal
-layout.
-\begin{bewareofthedog}
- If you have a lot of exercises the width of a table with this layout may
- exceed the text width of the document!
-\end{bewareofthedog}
-
-\begin{sourcecode}
- \DeclareExerciseTableTemplate{default*}{%
- \XSIMputright\ExerciseTableCode{%
- \toprule
- \XSIMifblankTF{\ExerciseType}
- {}
- {\XSIMmixedcase{\GetExerciseParameter{exercise-name}}}
- &%
- }%
- \ForEachUsedExerciseByType{%
- \XSIMifeqTF {#1} { \ExerciseTableType {#1} }
- {
- \XSIMifblankTF{\ExerciseType}
- {%
- \XSIMputright\ExerciseTableCode{%
- \XSIMmixedcase{\ExerciseParameterGet{#1}{exercise-name} }%
- }%
- }
- {}%
- \XSIMputright\ExerciseTableCode{#3 &}
- }
- {}%
- }%
- \XSIMputright\ExerciseTableCode{%
- \XSIMtranslate{total} \\
- \midrule
- \XSIMmixedcase{\XSIMtranslate{points}} &
- }%
- \ForEachUsedExerciseByType{%
- \XSIMifeqTF{#1}{\ExerciseTableType{#1}}
- {%
- \XSIMputright\ExerciseTableCode{%
- \XSIMifblankTF{#5}{\printgoal{0}}{\printgoal{#5}} &}%
- }
- {}%
- }%
- \XSIMputright\ExerciseTableCode{%
- \XSIMifblankTF{\ExerciseType}
- {\TotalExerciseGoal{points}{}{}}
- {\TotalExerciseTypeGoal{\ExerciseType}{points}{}{}}%
- \\ \midrule
- \XSIMtranslate{reached} &%
- }%
- \ForEachUsedExerciseByType{%
- \XSIMifeqTF{#1}{\ExerciseTableType{#1}}
- {\XSIMputright\ExerciseTableCode{&}}
- {}%
- }%
- \XSIMputright\ExerciseTableCode{ \\ \bottomrule }%
- \def\numberofcolumns{%
- \XSIMifblankTF{\ExerciseType}
- {\numberofusedexercises}
- {\csname numberof \ExerciseType s\endcsname}%
- }%
- \XSIMifeqF{\numberofcolumns}{0}
- {%
- \begin{tabular}{l*{\numberofcolumns}{c}c}
- \ExerciseTableCode
- \end {tabular}%
- }%
- }
-\end{sourcecode}
-
-The part
-\begin{sourcecode}
- \XSIMifblankTF{\ExerciseType}{ ... }{ ... }
-\end{sourcecode}
-repeatedly checks if an exercise type has been given for the table. This
-makes it possible to design the table differently if it is for one exercise
-type only (the \code{true} case) or for all exercise types (the \code{false}
-case). \cs*{ExerciseTableType}\marg{code} either expands to the given
-exercise type or to \meta{code}.
-
-\section{Exercise Translations}\label{sec:exerc-transl}
-
-\begin{commands}
- \command{DeclareExerciseTranslation}[\marg{language}\marg{keyword}\marg{translation}]
- Declare the translation of \meta{keyword} for language \meta{language}.
- \command{DeclareExerciseTranslations}[\marg{keyword}\marg{translations}]
- Declare the translations of \meta{keyword} for several languages at once.
- See an example of the usage below.
- \expandable\command{XSIMtranslate}[\marg{keyword}]
- Delivers the translation of \meta{keyword} according to the current
- document language (in the meaning of a \pkg{babel}~\cite{pkg:babel} or
- \pkg{polyglossia}~\cite{pkg:polyglossia} language).
- \command{ForEachExerciseTranslation}[\marg{code}]
- Loops over all translations of all keywords known to \xsim. Inside
- \meta{code} you can refer to the keyword with \code{\#1}, to the language
- with \code{\#2}, and to the translation with \code{\#3}.
-\end{commands}
-
-As an example how to use \cs{DeclareExerciseTranslations} here is how the
-translations for \code{exercise} have been defined:
-
-\begin{sourcecode}
- \DeclareExerciseTranslations{exercise}{
- Fallback = exercise ,
- English = exercise ,
- French = exercice ,
- German = \"Ubung
- }
-\end{sourcecode}
-
-Table~\vref{tab:translation-keys} shows all existing keywords with all
-predefined translations.
-
-\ForEachExerciseTranslation{
- \appto\translationtable{\texttt{#1} & #2 & \texttt{\detokenize{#3}} \\}
-}
-
-\begin{longtable}{llp{.55\linewidth}}
- \caption{Translation keywords predefined by \xsim.}
- \label{tab:translation-keys} \\
- \toprule
- \bfseries keyword & \bfseries language & \bfseries translation \\
- \midrule
- \endfirsthead
- \toprule
- \bfseries keyword & \bfseries language & \bfseries translation \\
- \midrule
- \endhead
- \bottomrule
- \endlastfoot
- \midrule
- & & \hfill\emph{continues} \\
- \endfoot
- \translationtable
-\end{longtable}
-
-\section{Cloze Tests and Blank Lines}
-
-Similar to \pkg{exsheets} \xsim\ provides a command \cs{blank}:
-\begin{commands}
- \command{blank}[\sarg\oarg{options}\marg{text to be filled in}]
- Creates a blank in normal text or in an exercise but fills the text of its
- argument if inside a solution. If used at the \emph{begin of a paragraph}
- \cs{blank} will do two things: it will set the linespread according to an
- option explained below and will insert \cs*{par} after the lines. The
- starred version doesn't do these things.
-\end{commands}
-
-Those are the options for customization:
-\begin{options}
- \keyval{blank-style}{code}\Module{blank}\Default{\cs*{underline}\Marg{\#1}}
- Instructions for typesetting the blank cloze. Refer to the filled in
- space with \code{\#1}.
- \keyval{filled-style}{code}\Module{blank}\Default{\cs*{underline}\Marg{\#1}}
- Instructions for typesetting the filled cloze. Refer to the filled in text
- with \code{\#1}
- \keyval{style}{code}
- Shortcut for setting both \option{blank-style} and \option{filled-style}
- at once.
- \keyval{scale}{decimal number}\Module{blank}\Default{\code{1}}
-\textsc{} Scales the blank to \meta{decimal number} times its natural width.
- \keyval{width}{dim}\Module{blank}\Default
- Sets the blank to a width of \meta{dim}. This takes precendence over
- \option{scale}.
- \keyval{linespread}{decimal number}\Module{blank}\Default{\code{1}}
- Set the linespread for the blank lines. This only has an effect if
- \cs{blank} is used at the begin of a paragraph.
- \keyval{line-increment}{dim}\Module{blank}\Default{\code{0.001\cs*{linewidth}}}
- The blank line is built in multiples of this value. If the value is too
- large you may end up with uneven lines. If the value is too small you may
- end up with a non-ending compilation. Experiment with values to find the
- suiting one for your use case.
- \keyval{line-minimum-length}{dim}\Module{blank}\Default{\code{2em}}
- The minimal length a line must have before it is built step by step.
-\end{options}
-
-\begin{example}
- This is a \blank{blank} outside in normal text.
- \begin{exercise}
- Try to fill in \blank[width=4cm]{these} blanks. All of them
- \blank{are created} by using the \cs{blank} \blank{command}.
- \end{exercise}
- \xsimsetup{blank/filled-style=\textcolor{red}{#1}}
- \begin{solution}[print]
- Try to fill in \blank[width=4cm]{these} blanks. All of them
- \blank{are created} by using the \cs{blank} \blank{command}.
- \end{solution}
-\end{example}
-A number of empty lines are easily created by setting the \option{width}
-option:
-\begin{example}
- Write up the pros and cons of \xsim\ over \pkg{exsheets}:
-
- \blank[width=4.8\linewidth,linespread=1.5]{}
-\end{example}
-
-\edef\lastsection{\arabic{section}}
-
-\appendix
-
-\section{Future Plans}
-
-\xsim\ is complete in so far as it is perfectly usable to create exams or
-exercise and solution sections in books with the most freedom in layout
-already. But still there are features which would be useful additions. Below
-I list all ideas that I currently plan to add to \xsim:
-\begin{itemize}
- \item a document class \code{xsim-exam} for creating exams; this class
- should itself feature the possibility of creating different versions of an
- exam, maybe already provide multiple choice questions and so on; one could
- also think about automatic creation of running headers and footers, \ie,
- means for changing the layout of the exam; following the spirit of \xsim\
- this should probably be done using templates as well.
-\end{itemize}
-I am very open to suggestions regarding features, both in general and
-specifically regarding the document class.
-
-\section{FAQ \& How to\dots}
-This section serves as a kind of gallery showing solutions to common
-problems. I expect this section to grow over the years. Some examples
-especially regarding other layouts are also shown in example files added to
-this package.
-
-\subsection{\dots Know if \xsim\ Needs Another Compilation?}
-If \xsim\ wants you to recompile your document it writes the following to the
-logfile:
-\begin{sourcecode}
- *************************************************
- * xsim warning: "rerun"
- *
- * Exercise properties may have changed. Rerun to get them synchronized.
- *************************************************
-\end{sourcecode}
-So just check the logfile regularly (which you should be doing anyway) and
-keep your eyes open.
-
-\subsection{\dots Resolve Getting Repeatedly Wrong Exercise Properties or
- Wrong Exercise Lists?}\label{sec:resolve-getting}
-\xsimauxfileinfo
-
-\subsection{\dots Resolve Strange Errors After Updating?}
-\xsim\ writes a lot of stuff to the auxiliary file. An update may well change
-how this is done so deleting the auxiliary file and doing a few fresh
-compilations may resolve your problems.
-
-\subsection{\code{! TeX capacity exceeded, sorry [text input levels=15].}
- Why?}
-Did you try to use an exercise or solution in a macro of some sort? This
-generally will fail\footnote{The reasons are similar to the ones given here:
- \url{https://tex.stackexchange.com/a/295422/}.}. But there should never be
-the need to hide the environments inside of a macro, anyway.
-
-\subsection{\code{Runaway argument? !File ended while scanning use of \^{}\^{}M.} Why?}
-Did you try to use an exercise or solution in a macro of some sort? This
-generally will fail. But there should never be the need to hide the
-environments inside of a macro, anyway.
-
-\subsection{\dots Put a Star (or Another Symbol) in Headings of Exercises That
- Are Special?}
-
-The code below shows one possible modification of an exercise template which
-allows to easily create bonus exercises:
-\begin{sourcecode}
- % preamble:
- \usepackage{amsymb}
- % declare boolean property:
- \DeclareExerciseProperty*{bonus}
- \DeclareExerciseEnvironmentTemplate{bonus}
- {%
- \subsection*
- {%
- % test for boolean property and insert star symbol if true:
- \IfExerciseBooleanPropertyT{bonus}{\llap{$\bigstar$ }Bonus }%
- \XSIMmixedcase{\GetExerciseName}\nobreakspace
- \GetExerciseProperty{counter}%
- \IfInsideSolutionF
- {%
- \IfExercisePropertySetT{subtitle}
- { {\normalfont\itshape\GetExerciseProperty{subtitle}}}%
- }%
- }
- \GetExercisePropertyT{points}
- {%
- \marginpar
- {%
- \IfInsideSolutionF{\rule{1.2cm}{1pt}\slash}%
- \PropertyValue
- \GetExercisePropertyT{bonus-points}
- {\nobreakspace(+\PropertyValue)}%
- \nobreakspace\XSIMtranslate{point-abbr}%
- }%
- }%
- }
- {}
-\end{sourcecode}
-
-The usage is now as follows:
-\begin{example}
- \xsimsetup{exercise/template = bonus}
- % set the boolean property to true
- \begin{exercise}[bonus]
- A bonus question.
- \end{exercise}
-\end{example}
-
-\subsection{\dots Print All Solutions Grouped by Section?}
-Here is an idea how to get a list of all solutions grouped by the section the
-corresponding exercises are appearing in.
-\begin{sourcecode}
- % preamble:
- % \usepackage{etoolbox}
- % \newcounter{sections}
-
- % document:
- \setcounter{sections}{1}
- \whileboolexpr
- { test {\ifnumless{\value{sections}}{\value{section}+1}} }
- {
- \printsolutions[section=\value{sections},headings-template=per-section]
- \stepcounter{sections}
- }
-\end{sourcecode}
-For this manual we then get the following list\footnote{Taking care of the
- fact that we're in the appendix now which means we can't use
- \cs*{value}\Marg{section}. Therefore this manual does
- \cs*{edef}\cs*{lastsection}\Marg{\cs*{arabic}\Marg{section}} right before
- \cs*{appendix}}.
-
-\newcounter{sections}
-\setcounter{sections}{1}
-\whileboolexpr
- { test {\ifnumless{\value{sections}}{\lastsection+1}} }
- {
- \printsolutions[section=\value{sections},headings-template=per-section]
- \stepcounter{sections}
- }
-
-\section{The \pkg*{xsimverb} package}\label{sec:xsimverb-package}
-\xsim\ comes bundled with another package called
-\pkg{xsimverb}\xsimverbversion. This package loads a very small subset of
-\xsim\ which allows to create environments that write their contents verbatim
-to external files. It provides the following commands (which of course are
-also available in \xsim, too):
-
-\begin{commands}
- \command{XSIMfilewritestart}[\sarg\marg{file name}]
- Start writing to the file named \meta{file name}. This should be the
- \emph{last} command in the \emph{begin} definition of an environment. If
- is is used in an environment with arguments where the \emph{last} argument
- is optional you should check if the optional argument is given and use
- the starred version if the test is negative. This is demonstrated in an
- example below using \pkg{xparse}'s \cs{NewDocumentEnvironment}. \emph{If
- you want an environment with only an optional argument you \emph{should}
- use \pkg{xparse}'s commands to define it. Due to the way how
- \cs*{newenvironment} scans for optional arguments you'll otherwise may
- end up with leading spaces gobbled from the first line in your
- environment.}
- \command{XSIMfilewritestop}
- Stop writing to the file. This should be the \emph{first} command in the
- \emph{end} definition of an environment.
- \command{XSIMsetfilebegin}[\marg{code}]
- This command can be used to write something to the external file
- \emph{before} the environment contents. Must be set before
- \cs{XSIMfilewritestart} in the \emph{begin} definition.
- \command{XSIMsetfileend}[\marg{code}]
- This command can be used to write something to the external file
- \emph{after} the environment contents. Must be set before
- \cs{XSIMfilewritestart} in the \emph{begin} definition.
- \command{XSIMgobblechars}[\marg{integer}]
- Determines how many characters are cut off of the beginning of each line
- of the environment body before it is written to the file. The default
- value is~$0$.
-\end{commands}
-
-The following code shows an example of how to use those commands:
-\begin{sourcecode}
- \documentclass{article}
- \usepackage{xsimverb,listings}
-
- \makeatletter
- \NewDocumentEnvironment{example}{o}
- {%
- \XSIMsetfilebegin{\@percentchar\space file `\jobname.tmp'}%
- \XSIMsetfileend{\@percentchar\space bye bye}%
- \IfNoValueTF{#1}
- {\XSIMfilewritestart*{\jobname.tmp}}
- {\XSIMfilewritestart{\jobname.tmp}}%
- }
- {%
- \XSIMfilewritestop
- \lstinputlisting[language={[LaTeX]TeX}]{\jobname.tmp}%
- \input{\jobname.tmp}
- }
- \makeatother
-
- \begin{document}
-
- \begin{example}
- bla bla \LaTeX
- \end{example}
-
- \end{document}
-\end{sourcecode}
-
-The \code{tmp} file produced by the above example will contain the following
-three lines (if the file itself was called \code{test.tex}):
-\begin{sourcecode}
- % file `test.tmp'
- bla bla \LaTeX
- % bye bye
-\end{sourcecode}
-
-\section{All Exercise Examples}
-
-\begin{bewareofthedog}
- You will notice that some exercises from
- section~\vref{sec:template-examples} look differently in this section. That
- is because all exercises of a type use the template that's \emph{currently
- active}. If you want exercises with a different look you should use
- different exercises types.
-\end{bewareofthedog}
-
-The following list is created with this code:
-\begin{sourcecode}
- \xsimsetup{exercise/template = bonus}
- \printcollection[headings]{all exercises}
-\end{sourcecode}
-
-\xsimsetup{exercise/template = bonus}
-\printcollection[headings]{all exercises}
-
-\section{All Solution Examples}
-\printsolutions
-
-\section{Example Documents Coming With This Package}\label{sec:example-files}
-The repository of this package\footnote{GitHub:
- \url{https://github.com/cgnieder/xsim/}, CTAN:
- \url{http://www.ctan.org/pkg/xsim/}} currently includes
-\theexamplefiles~example documents demonstrating how different aspects of this
-package work or how different kinds of problems can be solved or how different
-kinds of layouts can be achieved as well as how to solve concrete problems
-that have come up in different \LaTeX\ forums.
-
-Besides showing excerpts of the code and the resulting pdf the examples below
-also link to both the \code{tex} source the resulting pdf.
-
-\listexamplefiles
-
-\printbibliography
-
-\end{document}
Modified: trunk/Master/texmf-dist/tex/latex/xsim/xsim-manual.cls
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim-manual.cls 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim-manual.cls 2021-01-31 21:33:37 UTC (rev 57572)
@@ -8,15 +8,15 @@
% Web: https://github.com/cgnieder/xsim
% E-Mail: contact at mychemistry.eu
% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
+% Copyright 2017--2021 Clemens Niederberger
%
% This work may be distributed and/or modified under the
-% conditions of the LaTeX Project Public License, either version 1.3
+% conditions of the LaTeX Project Public License, either version 1.3c
% 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.
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008/05/04 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
@@ -29,19 +29,18 @@
% please ignore the contents of this file -- it is not a good example for
% coding...
%
-\ProvidesClass{xsim-manual}[2020/04/04]
+\ProvidesClass{xsim-manual}[2021/01/31]
\LoadClass[load-preamble,add-index]{cnltx-doc}
\RequirePackage{imakeidx}
-\RequirePackage[utf8]{inputenc}
-\RequirePackage{xsim,xsimverb}
+\RequirePackage[use-files]{xsim}
\RequirePackage{geometry}
\geometry{
- left = 3.5cm ,
- right = 3cm ,
- marginparwidth = 3cm ,
- marginparsep = 2mm
+ left = 4cm ,
+ right = 2.5cm ,
+ marginparwidth = 3.3cm ,
+ marginparsep = 5mm
}
\setcnltx{
@@ -56,6 +55,7 @@
quote-format = \small\biolinumLF ,
add-cmds = {
blank ,
+ activatecollection ,
addbonus ,
addpoints ,
AddtoExerciseGoal ,
@@ -66,6 +66,7 @@
collectexercises ,
collectexercisestype ,
collectexercisesstop ,
+ deactivatecollection ,
DeclareExerciseCollection ,
DeclareExerciseEnvironmentTemplate ,
DeclareExerciseGoal ,
@@ -204,11 +205,14 @@
@percentchar ,
bottomrule ,
breite ,
+ captionsetup ,
choice ,
+ correct ,
cs ,
DeclareFloatingEnvironment ,
enddescription ,
endtcolorbox ,
+ ex ,
hint ,
hoehe ,
iflist ,
@@ -221,9 +225,11 @@
Needspace ,
NewDocumentCommand ,
NewDocumentEnvironment ,
+ NewTasksEnvironment ,
newlist ,
numberofcolumns ,
numberofproblems ,
+ option ,
pkg ,
pointsandbonus ,
printA, printC, printE ,
@@ -236,6 +242,7 @@
tcolorbox ,
thechapter ,
thesection ,
+ thetask ,
toprule ,
whileboolexpr ,
xsim
@@ -691,14 +698,13 @@
\RequirePackage{varioref}
\RequirePackage{bookmark}
+\DeclareExerciseCollection{foo}
+\DeclareExerciseCollection{layouts}
\xsimsetup{
% clear-aux ,
path = exercises
}
-\DeclareExerciseCollection{foo}
-\DeclareExerciseCollection{layouts}
-
\newrobustcmd*\TF{%
\colorlet{outside}{.}%
\textcolor{red}{\underline{\textcolor{outside}{TF}}}%
@@ -934,7 +940,10 @@
\xsim at add@example{texsx-370642}{Minimalistic layout}
\xsim at add@example{texsx-391530}{Exercises and sub-exercises}
\xsim at add@example{texsx-395273}{Different aspects of exercises, highlighted solutions}
+\xsim at add@example{texsx-466584}{Flushright Solutions}
\xsim at add@example{texsx-498299}{Multiple choice questions with automated solutions}
+\xsim at add@example{texsx-576998}{Exercises at the end of section and sectionwise solutions}
+\xsim at add@example{texsx-580636}{Multiple hints per exercise with backlinks}
\xsim at add@example{texwelt-6698}{Custom list of exercises}
\xsim at add@example{texwelt-15093}{Indicate difficulty level}
\xsim at add@example{texwelt-23968}{Long and short solutions}
@@ -985,12 +994,13 @@
\xsim at add@version{0.19} {2020-03-16}
\xsim at add@version{0.19a} {2020-03-19}
\xsim at add@version{0.19b} {2020-04-04}
+\xsim at add@version{0.20} {2021-01-31}
% ----------------------------------------------------------------------------
\newrobustcmd*\xsimauxfileinfo{%
\xsim\ writes a lot of stuff to an auxiliary file called
- \cs*{jobname}\code{.xsim} (or the common \cs*{jobname}\code{.aux} if you use
- option \option{use-aux}) for re-using information on subsequent
+ \meta{file name}\code{.xsim} (or the common \meta{file name}\code{.aux} if
+ you use option \option{use-aux}) for re-using information on subsequent
compilations. If you add exercises, change properties \etc\ it might happen
that wrong information is staying in the auxiliary file and is wrongly used
by \xsim. In such cases deleting the auxiliary file and doing a few fresh
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.auxfile.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.auxfile.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.auxfile.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,221 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - auxfile module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{auxfile}{writing stuff to an auxiliary file}
-
-\prg_new_conditional:Npnn \xsim_if_use_aux: {p,T,F,TF}
- {
- \bool_if:NTF \g_xsim_use_aux_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\cs_new_protected:Npn \xsim_write_to_aux:n #1
- {
- \legacy_if:nT {@filesw}
- {
- \xsim_if_use_aux:TF
- { \iow_now:Nn \@auxout {#1} }
- { \iow_now:Nn \l__xsim_aux_file_iow {#1} }
- }
- }
-\cs_generate_variant:Nn \xsim_write_to_aux:n {x}
-
-% --------------------------------------------------------------------------
-
-\cs_new_protected:Npn \XSIM #1 { \use:c {XSIMaux#1} }
-
-\cs_new_protected:Npn \xsim_new_aux_property:cpn #1
- { \cs_new_protected:cpn {XSIMaux#1} }
-
-\cs_new_protected:Npn \xsim_add_property_to_aux:nn #1#2
- {
- \xsim_verbose:n { Writing~ command~ \XSIM {#1}~ to~ aux~ file }
- \xsim_write_to_aux:x { \token_to_str:N \XSIM {#1} #2 }
- }
-
-\xsim_at_begin_document:n
- {
- \iow_now:Nx \@auxout
- { \token_to_str:N \providecommand \token_to_str:N \XSIM [1] {} }
- }
-
-% ----------------------------------------------------------------------------
-
-\xsim_if_use_aux:F
- {
- \iow_new:N \l__xsim_aux_file_iow
- \xsim_at_begin_document:n
- { \iow_open:Nn \l__xsim_aux_file_iow { \c_sys_jobname_str .xsim } }
- }
-
-\cs_new_protected:Npn \xsim_close_aux:
- {
- \xsim_if_use_aux:F
- {
- \iow_close:N \l__xsim_aux_file_iow
- \legacy_if:nT {@filesw}
- { \iow_now:Nx \@auxout { \token_to_str:N \XSIM {readaux} } }
- }
- }
-
-\xsim_new_aux_property:cpn {readaux}
- {
- \file_if_exist:nT { \c_sys_jobname_str .xsim }
- { \file_input:n { \c_sys_jobname_str .xsim } }
- }
-
-% ----------------------------------------------------------------------------
-% list for recording values that need to be written to the aux file and
-% updated at begin document
-
-\str_new:N \l__xsim_split_aux_lists_str
-\keys_define:nn {xsim}
- {
- split-aux-lists .code:n = \str_set:Nn \l__xsim_split_aux_lists_str {#1} ,
- split-aux-lists .initial:n = ||
- }
-
-% define list:
-% #1: name
-\cs_new_protected:Npn \xsim_new_list:n #1
- {
- \xsim_verbose:n { Defining~ new~ auxfile~ list~ `#1'. }
- \seq_new:c {g__xsim_list_#1_seq}
- \seq_new:c {g__xsim_list_recorded_#1_seq}
- \xsim_new_aux_property:cpn {#1} ##1
- {
- \tl_if_blank:nF {##1}
- {
- \seq_gset_split:cVx {g__xsim_list_#1_seq}
- \l__xsim_split_aux_lists_str
- { \tl_to_str:n {##1} }
- \seq_map_inline:cn {g__xsim_list_#1_seq}
- { \xsim_attribute_set:nnn {#1} {####1} {} }
- }
- }
- \xsim_at_begin_document:n
- {
- \seq_gclear:c {g__xsim_list_recorded_#1_seq}
- \seq_set_eq:Nc \l__xsim_tmpa_seq {g__xsim_list_#1_seq}
- \seq_map_inline:Nn \l__xsim_tmpa_seq
- {
- \str_set:Nn \l__xsim_tmpa_str {##1}
- \seq_gput_right:cV {g__xsim_list_recorded_#1_seq} \l__xsim_tmpa_str
- }
- \seq_gremove_duplicates:c {g__xsim_list_recorded_#1_seq}
- }
- }
-
-% add to or remove from list:
-% #1: name
-% #2: entry
-\cs_new_protected:Npn \xsim_add_to_list:nn #1#2
- {
- \xsim_verbose:n { Adding~ `#2'~ to~ list~ `#1'. }
- \str_set:Nn \l__xsim_tmpa_str {#2}
- \xsim_attribute_set:nnn {#1} {#2} {}
- \seq_if_in:cVT {g__xsim_list_#1_seq} \l__xsim_tmpa_str
- { \seq_gremove_all:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str }
- \seq_gput_right:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str
- }
-\cs_generate_variant:Nn \xsim_add_to_list:nn {nx}
-
-% #1: name
-% #2: entry
-\cs_new_protected:Npn \xsim_remove_from_list:nn #1#2
- {
- \xsim_verbose:n { Removing~ `#2'~ to~ list~ `#1'. }
- \str_set:Nn \l__xsim_tmpa_str {#2}
- \xsim_attribute_if_set:nnT {#1} {#2}
- { \xsim_attribute_unset:nn {#1} {#2} }
- \seq_if_in:cVT {g__xsim_list_#1_seq} \l__xsim_tmpa_str
- { \seq_gremove_all:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str }
- \seq_if_in:cVT {g__xsim_list_recorded#1_seq} \l__xsim_tmpa_str
- { \seq_gremove_all:cV {g__xsim_list_recorded_#1_seq} \l__xsim_tmpa_str }
- }
-\cs_generate_variant:Nn \xsim_remove_from_list:nn {nx}
-
-% check if in list:
-% #1: name
-% #2: entry
-\prg_new_conditional:Npnn \xsim_if_in_list:nn #1#2 {p,T,F,TF}
- {
- \xsim_attribute_if_set:nnTF {#1} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_in_list:nnTF {nx}
-\cs_generate_variant:Nn \xsim_if_in_list:nnT {nx}
-
-\bool_new:N \l__xsim_empty_lists_bool
-\cs_new_protected:Npn \xsim_empty_lists:
- { \bool_set_true:N \l__xsim_empty_lists_bool }
-
-% update list (should be used inside \xsim_at_end_document:n):
-% #1: name
-\cs_new_protected:Npn \xsim_update_list:n #1
- {
- \xsim_verbose:n { Updating~ list~ `#1'. }
- \seq_remove_duplicates:c {g__xsim_list_#1_seq}
- \seq_remove_duplicates:c {g__xsim_list_recorded_#1_seq}
- \str_set:Nx \l__xsim_tmpa_str
- { \seq_use:cn {g__xsim_list_#1_seq} {} }
- \str_set:Nx \l__xsim_tmpb_str
- { \seq_use:cn {g__xsim_list_recorded_#1_seq} {} }
- \str_if_eq:NNF \l__xsim_tmpa_str \l__xsim_tmpb_str
- { \xsim_rerun: }
- \bool_if:NF \l__xsim_empty_lists_bool
- {
- \xsim_add_property_to_aux:nn {#1}
- { { \seq_use:cV {g__xsim_list_#1_seq} \l__xsim_split_aux_lists_str } }
- }
- }
-
-% loop over list:
-% #1: name
-% #2: code
-\cs_new_protected:Npn \xsim_foreach_list_entry:nn #1#2
- { \seq_map_inline:cn {g__xsim_list_recorded_#1_seq} {#2} }
-
-\cs_new_protected:Npn \xsim_foreach_new_list_entry:nn #1#2
- { \seq_map_inline:cn {g__xsim_list_#1_seq} {#2} }
-
-% length of a list:
-% #1: name
-\cs_new:Npn \xsim_list_count:n #1
- { \seq_count:c {g__xsim_list_recorded_#1_seq} }
-
-% item of a list:
-% #1: name
-% #2: integer
-\cs_new:Npn \xsim_list_item:nn #1#2
- { \seq_item:cn {g__xsim_list_recorded_#1_seq} {#2} }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-2020/03/16 - performance optimizations
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.base.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.base.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.base.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,287 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - base module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{base}{basic functionality of the package}
-
-\tl_new:N \g_xsim_end_document_hook_tl
-\tl_new:N \g_xsim_begin_document_hook_tl
-
-\AtBeginDocument { \tl_use:N \g_xsim_begin_document_hook_tl }
-\AtEndDocument { \tl_use:N \g_xsim_end_document_hook_tl }
-
-\cs_new_protected:Npn \xsim_at_begin_document:n #1
- { \tl_gput_right:Nn \g_xsim_begin_document_hook_tl {#1} }
-
-\cs_new_protected:Npn \xsim_at_end_document:n #1
- { \tl_gput_right:Nn \g_xsim_end_document_hook_tl {#1} }
-
-% ----------------------------------------------------------------------------
-
-\xsim_load_modules:n {auxfile}
-
-% ----------------------------------------------------------------------------
-% variants of kernel functions:
-\cs_generate_variant:Nn \seq_set_split:Nnn {Nnx,NV}
-\cs_generate_variant:Nn \seq_gset_split:Nnn {c,cVx,cnx}
-\cs_generate_variant:Nn \seq_use:Nn {cV}
-\cs_generate_variant:Nn \seq_count:N {c}
-\cs_generate_variant:Nn \seq_if_empty:NT {c}
-\cs_generate_variant:Nn \seq_if_in:NnT {cV}
-\cs_generate_variant:Nn \seq_gremove_all:Nn {cV}
-\cs_generate_variant:Nn \seq_gput_right:Nn {cV}
-\cs_generate_variant:Nn \prop_put:Nnn {Nnx,cxx}
-\cs_generate_variant:Nn \prop_gput:Nnn {Nx,Nnx,cxx}
-\cs_generate_variant:Nn \prop_item:Nn {c}
-\cs_generate_variant:Nn \prop_if_in:NnTF {Nx}
-\cs_generate_variant:Nn \use:nn {nx}
-\cs_generate_variant:Nn \file_input:n {V,x}
-\cs_generate_variant:Nn \file_if_exist:nT {V,x}
-\cs_generate_variant:Nn \file_if_exist:nTF {V}
-\cs_generate_variant:Nn \msg_error:nnnnn {nnnxx}
-\cs_generate_variant:Nn \keys_define:nn {nx}
-\cs_generate_variant:Nn \keys_set:nn {xn}
-\cs_generate_variant:Nn \tl_mixed_case:n {x,f}
-\cs_generate_variant:Nn \tl_if_eq:nnTF {ff,V}
-\cs_generate_variant:Nn \tl_if_eq:nnT {x}
-\cs_generate_variant:Nn \tl_if_blank:nTF {f}
-\cs_generate_variant:Nn \tl_set_rescan:Nnn {Nnx}
-\cs_generate_variant:Nn \iow_now:Nn {NV}
-\cs_generate_variant:Nn \str_if_eq:nnT {x}
-\cs_generate_variant:Nn \str_if_eq:nnF {xx}
-\cs_generate_variant:Nn \str_if_eq_p:nn {e}
-\cs_generate_variant:Nn \prg_new_protected_conditional:Npnn {c}
-
-% ----------------------------------------------------------------------------
-% temporary variables:
-\tl_new:N \l__xsim_tmpa_tl
-\tl_new:N \l__xsim_tmpb_tl
-\tl_new:N \l__xsim_tmpc_tl
-\tl_new:N \l__xsim_tmpd_tl
-
-\str_new:N \l__xsim_tmpa_str
-\str_new:N \l__xsim_tmpb_str
-\str_new:N \l__xsim_tmpc_str
-
-\bool_new:N \l__xsim_tmpa_bool
-\bool_new:N \l__xsim_tmpb_bool
-\bool_new:N \l__xsim_tmpc_bool
-
-\dim_new:N \l__xsim_tmpa_dim
-\dim_new:N \l__xsim_tmpb_dim
-\dim_new:N \l__xsim_tmpc_dim
-
-\seq_new:N \l__xsim_tmpa_seq
-\seq_new:N \l__xsim_tmpb_seq
-\seq_new:N \l__xsim_tmpc_seq
-
-\int_new:N \l__xsim_tmpa_int
-\int_new:N \l__xsim_tmpb_int
-\int_new:N \l__xsim_tmpc_int
-
-\box_new:N \l__xsim_tmpa_box
-\box_new:N \l__xsim_tmpb_box
-\box_new:N \l__xsim_tmpc_box
-
-\clist_new:N \l__xsim_tmpa_clist
-\clist_new:N \l__xsim_tmpb_clist
-\clist_new:N \l__xsim_tmpc_clist
-
-% ----------------------------------------------------------------------------
-
-\prg_new_conditional:Npnn \xsim_if_komascript: {T,F,TF}
- {
- \cs_if_exist:cTF {KOMAClassName}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% ----------------------------------------------------------------------------
-
-\prg_new_conditional:Npnn \xsim_if_final: {p,T,F,TF}
- {
- \bool_if:NTF \g__xsim_final_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_verbose: {p,T,F,TF}
- {
- \bool_if:NTF \g__xsim_verbose_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_debug: {p,T,F,TF}
- {
- \bool_if:NTF \g__xsim_debug_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_package_blank: {p,T,F,TF}
- {
- \bool_if:NTF \g__xsim_blank_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_rerun: {p,T,F,TF}
- {
- \bool_if:NTF \g__xsim_rerun_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_write_to_files: {p,T,F,TF}
- {
- \bool_if:NTF \g__xsim_write_to_file_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_clear_aux: {p,T,F,TF}
- {
- \xsim_if_final:TF
- { \prg_return_false: }
- {
- \bool_if:NTF \g_xsim_clear_aux_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
- }
-
-\cs_new_protected:Npn \xsim_verbose:n #1
- { \xsim_if_verbose:T { \msg_info:nnn {xsim} {verbose} {#1} } }
-\cs_generate_variant:Nn \xsim_verbose:n {x}
-
-\cs_new_protected:Npn \xsim_rerun:
- { \bool_gset_true:N \g__xsim_rerun_bool }
-
-\prg_new_conditional:Npnn \xsim_if_chapter: {p,T,F,TF}
- {
- \bool_lazy_and:nnTF
- { \cs_if_exist_p:N \chapter }
- { \cs_if_exist_p:N \c at chapter }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% ----------------------------------------------------------------------------
-
-% #1: macro name
-% #2: 0 to 9 times `n' (= number of arguments of internal item)
-% #3: code; may contain a suiting \__xsim_loop_item:<nnn>
-\cs_new_protected:Npn \xsim_define_loop_macro:Nnn #1#2#3
- {
- \xsim_verbose:n { Defining~ loop~ macro~ #1 }
- \cs_new_protected:Npn #1 ##1##2
- { \cs_set:cn {__xsim_loop_item:#2} {##2} #3 }
- }
-
-% ----------------------------------------------------------------------------
-
-\msg_new:nnn {xsim} {attribute-not-set}
- { The~ attribute~ `#1'~ is~ not~ set~ \msg_line_context: }
-
-% #1: attribute
-% #2: item
-\cs_new_protected:Npn \xsim_attribute_new:nn #1#2
- { \cs_new:cpn {____xsim_attribute_ \tl_to_str:n {#1::#2} :} {} }
-
-% #1: attribute
-% #2: item
-% #3: value
-\cs_new_protected:Npn \xsim_attribute_set:nnn #1#2#3
- {
- \cs_gset:cpx
- {____xsim_attribute_ \tl_to_str:n {#1::#2} :}
- { \exp_not:n { \exp_not:n {#3} } }
- }
-\cs_generate_variant:Nn \xsim_attribute_set:nnn {nnx}
-
-% #1: attribute
-% #2: item
-\cs_new_protected:Npn \xsim_attribute_unset:nn #1#2
- { \cs_undefine:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} }
-
-% #1: attribute
-% #2: item
-\cs_new:Npn \xsim_attribute_get:nn #1#2
- {
- \cs_if_exist:cTF {____xsim_attribute_ \tl_to_str:n {#1::#2} :}
- { \use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} }
- {
- \xsim_if_debug:T
- { \msg_expandable_error:nnn {xsim} {attribute-not-set} {#1::#2} }
- }
- }
-
-% #1: attribute
-% #2: item
-\prg_new_conditional:Npnn \xsim_attribute_if_set:nn #1#2 {p,T,F,TF}
- {
- \cs_if_exist:cTF {____xsim_attribute_ \tl_to_str:n {#1::#2} :}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: attribute
-% #2: item
-\prg_new_conditional:Npnn \__xsim_if_attribute_eq:nnn #1#2#3 {p,T,F,TF}
- {
- \tl_if_eq:enTF
- { \use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} }
- {#3}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: attribute
-% #2: item
-\cs_new_protected:Npn \xsim_attribute_show:nn #1#2
- {
- \iow_term:n {}
- \iow_term:x
- {
- \c_space_tl \c_space_tl
- \tl_to_str:n {#1::#2}
- \c_space_tl \c_space_tl == \c_space_tl \c_space_tl
- {\use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :}}
- }
- \iow_term:n {}
- }
-
-% ----------------------------------------------------------------------------
-
-\cs_new_protected:Npn \xsim_setup:n #1
- { \keys_set:nn {xsim} {#1} }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-2020/03/15 - alternative to property lists for performance optimizations
-2020/03/22 - fix bug in new attribute mechanism which was a problem when
- `no-files` has been used
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.blanks.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.blanks.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.blanks.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,162 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - blanks module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{blanks}{add blanks, cloze}
-
-\bool_new:N \l__xsim_blank_width_bool
-\bool_new:N \l__xsim_blank_linespread_bool
-\bool_new:N \l__xsim_fill_blank_bool
-\tl_new:N \l__xsim_blank_linespread_tl
-\tl_new:N \l__xsim_blank_scale_tl
-\dim_new:N \l__xsim_blank_dim
-\dim_new:N \l__xsim_blank_line_increment_dim
-\dim_new:N \l__xsim_blank_line_minimum_length_dim
-\box_new:N \l__xsim_blank_box
-
-\cs_new_protected:Npn \xsim_write_cloze_blank:n #1 {#1}
-\cs_new_protected:Npn \xsim_write_cloze_filled:n #1 {#1}
-
-\keys_define:nn {xsim/blank}
- {
- blank-style .code:n =
- \cs_set_protected:Npn \xsim_write_cloze_blank:n ##1 {#1} ,
- blank-style .initial:n = \underline {#1} ,
- filled-style .code:n =
- \cs_set_protected:Npn \xsim_write_cloze_filled:n ##1 {#1} ,
- filled-style .initial:n = \underline {#1} ,
- style .meta:n =
- {
- blank-style = #1 ,
- filled-style = #1
- } ,
- fill .bool_set:N = \l__xsim_fill_blank_bool ,
- fill .initial:n = false ,
- scale .tl_set:N = \l__xsim_blank_scale_tl ,
- scale .initial:n = 1 ,
- width .code:n =
- {
- \bool_set_true:N \l__xsim_blank_width_bool
- \dim_set:Nn \l__xsim_blank_dim {#1}
- } ,
- linespread .code:n =
- \bool_set_true:N \l__xsim_blank_linespread_bool
- \tl_set:Nn \l__xsim_blank_linespread_tl {#1} ,
- linespread .initial:n = 1 ,
- line-increment .dim_set:N = \l__xsim_blank_line_increment_dim ,
- line-increment .initial:n = 0.001\linewidth ,
- line-minimum-length .dim_set:N = \l__xsim_blank_line_minimum_length_dim ,
- line-minimum-length .initial:n = 2em
- }
-
-\cs_new_protected:Npn \xsim_blank:n #1
- {
- \box_clear:N \l__xsim_blank_box
- \mode_if_math:TF
- { \hbox_set:Nn \l__xsim_blank_box { $ \m at th \mathpalette{}{#1} $ } }
- { \hbox_set:Nn \l__xsim_blank_box {#1} }
- \bool_lazy_or:nnTF
- { \xsim_if_inside_solution_p: }
- { \l__xsim_fill_blank_bool }
- { \xsim_write_cloze_filled:n {#1} }
- {
- \bool_if:NTF \l__xsim_blank_width_bool
- { \__xsim_blank_skip:V \l__xsim_blank_dim }
- { \__xsim_blank_skip:n { \box_wd:N \l__xsim_blank_box } }
- }
- }
-
-\cs_new_protected:Npn \__xsim_blank_skip:n #1
- {
- \bool_if:NTF \l__xsim_blank_width_bool
- { \dim_set:Nn \l__xsim_tmpa_dim {#1} }
- {
- \fp_set:Nn \l__xsim_tmpa_fp
- { \dim_to_fp:n {#1} * \l__xsim_blank_scale_tl }
- \dim_set:Nn \l__xsim_tmpa_dim { \fp_to_dim:N \l__xsim_tmpa_fp }
- }
- \dim_compare:nTF
- { \l__xsim_tmpa_dim > \l__xsim_blank_line_minimum_length_dim }
- {
- \mode_if_math:TF
- { \xsim_write_cloze_blank:n { \skip_horizontal:N \l__xsim_tmpa_dim } }
- {
- \dim_do_while:nn { \l__xsim_tmpa_dim > \c_zero_dim }
- {
- % I wonder what the correct l3 way would be -- if there is
- % one, yet:
- % \tex_hfil:D
- \tex_penalty:D \hyphenpenalty
- % \tex_hfilneg:D
- \dim_compare:nTF
- { \l__xsim_tmpa_dim < \l__xsim_blank_line_increment_dim }
- { \xsim_write_cloze_blank:n { \skip_horizontal:N \l__xsim_tmpa_dim } }
- {
- \xsim_write_cloze_blank:n
- { \skip_horizontal:N \l__xsim_blank_line_increment_dim }
- }
- \dim_sub:Nn \l__xsim_tmpa_dim { \l__xsim_blank_line_increment_dim }
- }
- }
- }
- {
- \xsim_write_cloze_blank:n
- { \skip_horizontal:N \l__xsim_blank_line_minimum_length_dim }
- }
- }
-\cs_generate_variant:Nn \__xsim_blank_skip:n {V}
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-
-the following code from Heiko Oberdieck in d.c.t.t served as inspiration
-and basis for the \blank command:
-https://groups.google.com/d/msg/de.comp.text.tex/fZLwraH04jE/o1RSdFXjGuIJ
-
-\makeatletter
-\newcommand*{\luecke}{%
- \begingroup
- \setlength{\dimen@}{6cm}%
- \ifdim\dimen@>2em %
- \underline{\hspace{1em}}%
- \advance\dimen@ by -2em\relax
- \@whiledim\dimen@>0pt\do{%
- \penalty\hyphenpenalty
- \ifdim\dimen@<1pt %
- \underline{\hspace{\dimen@}}%
- \else
- \underline{\hspace{1pt}}%
- \fi
- \advance\dimen@ by -1pt %
- }%
- \underline{\hspace{1em}}%
- \else
- \underline{\hspace{\dimen@}}%
- \fi
- \endgroup
- \xspace
-}
-\makeatother
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.collections.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.collections.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.collections.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,397 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - collections module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{collections}{collect exercises and print collected exercises}
-
-\xsim_load_modules:n {base}
-
-\seq_new:N \g__xsim_collections_seq
-\bool_new:N \l____xsim_active_bool
-
-\msg_new:nnn {xsim} {collection-exists}
- {
- The~ collection~ `#1'~ you're~ trying~ to~ define~ \msg_line_context:
- \c_space_tl already~ exists.
- }
-
-\msg_new:nnn {xsim} {collection-active}
- {
- You~ can't~ print~ collection~ `#1'~ while~ it~ is~ still~ active~
- \msg_line_context:
- }
-
-\msg_new:nnn {xsim} {unknown-collection}
- {
- You're~ trying~ to~ use~ the~ collection~ `#1'~ \msg_line_context:
- \c_space_tl but~ no~ collection~ with~ that~ name~ exists.~ You~ need~ to~
- define~ it~ first!
- }
-
-\msg_new:nnn {xsim} {print-collection-choice}
- {
- The~ choice~ `#1'~ for~ the~ option~ `print-collection/print'~ does~ not~
- exist.~ I'm~ using~ `exercises'~ instead~ \msg_line_context:
- }
-
-% ----------------------------------------------------------------------------
-
-% #1: collection name
-\cs_new_protected:Npn \xsim_new_collection:n #1
- {
- \xsim_if_collection_exist:nTF {#1}
- { \msg_error:nnn {xsim} {collection-exists} {#1} }
- {
- \xsim_verbose:n { Declaring~ new~ collection~ `#1'. }
- \xsim_attribute_set:nnn {collection} {#1} { \c_false_bool }
- \seq_gput_right:Nn \g__xsim_collections_seq {#1}
- \xsim_new_list:n {collection:#1}
- \seq_new:c {g__xsim_collection_#1_seq}
- }
- }
-
-% #1: collection name
-\prg_new_conditional:Npnn \xsim_if_collection_exist:n #1 {T,F,TF}
- {
- \seq_if_in:NnTF \g__xsim_collections_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\xsim_new_collection:n {all~ exercises}
-
-\cs_new_protected:Npn \xsim_foreach_collection:n #1
- { \seq_map_inline:Nn \g__xsim_collections_seq {#1} }
-
-\cs_new:Npn \xsim_collection_map_break: { \seq_map_break: }
-
-% ----------------------------------------------------------------------------
-
-% #1: collection name
-% #2: type
-\cs_new_protected:Npn \xsim_activate_collection:nn #1#2
- {
- \xsim_if_collection_active:nTF {#1}
- { % TODO: error
- }
- {
- \xsim_verbose:n { Activating~ collection~ `#1'. }
- \xsim_attribute_set:nnn {collection} {#1} { \c_true_bool }
- \tl_if_blank:nF {#2}
- { \seq_gput_right:cn {g__xsim_collection_#1_seq} {#2} }
- }
- }
-
-\cs_new_protected:Npn \xsim_activate_collection:n #1
- { \xsim_activate_collection:nn {#1} {} }
-
-% #1: collection name
-\cs_new_protected:Npn \xsim_deactivate_collection:n #1
- {
- \xsim_if_collection_active:nTF {#1}
- {
- \xsim_verbose:n { Deactivating~ collection~ `#1'. }
- \xsim_attribute_set:nnn {collection} {#1} { \c_false_bool }
- % \seq_gclear:c {g__xsim_collection_#1_seq}
- }
- { % TODO: warning
- }
- }
-
-% start collection for an exercise type:
-% #1: collection name
-% #2: type
-\cs_new_protected:Npn \xsim_start_collection:nn #1#2
- {
- \group_begin:
- \xsim_if_collection_exist:nF {#1}
- { \msg_error:nnn {xsim} {unknown-collection} {#1} }
- \xsim_activate_collection:nn {#1} {#2}
- \xsim_setup:x { \xsim_get_parameter:nn {#2} {exercise-env} /print = false }
- }
-\cs_generate_variant:Nn \xsim_setup:n {x}
-
-% start collection for all exercise types:
-% #1: collection name
-\cs_new_protected:Npn \xsim_start_collection:n #1
- {
- \group_begin:
- \xsim_if_collection_exist:nF {#1}
- { \msg_error:nnn {xsim} {unknown-collection} {#1} }
- \xsim_activate_collection:n {#1}
- \xsim_foreach_exercise_type:n
- { \xsim_setup:x { \xsim_get_parameter:nn {##1} {exercise-env} /print = false } }
- }
-
-% stop collection:
-% #1: collection name
-\cs_new_protected:Npn \xsim_stop_collection:n #1
- {
- \xsim_deactivate_collection:n {#1}
- \group_end:
- }
-
-% ----------------------------------------------------------------------------
-
-% #1: collection name
-% #2: type
-% #3: id
-\cs_new_protected:Npn \xsim_add_to_collection:nnn #1#2#3
- {
- \seq_if_empty:cTF {g__xsim_collection_#1_seq}
- { \__xsim_add_to_collection:nnn {#1} {#2} {#3} }
- {
- \seq_if_in:cnF {g__xsim_collection_#1_seq} {#2}
- { \__xsim_add_to_collection:nnn {#1} {#2} {#3} }
- }
- }
-
-% #1: collection name
-% #2: type
-% #3: id
-\cs_new_protected:Npn \__xsim_add_to_collection:nnn #1#2#3
- {
- \xsim_verbose:n
- { Adding~ exercise~ type~ `#2'~ id~ `#3'~ to~ collection~ `#1'. }
- \xsim_add_to_list:nn {collection:#1} {#2-#3}
- }
-
-\cs_new:Npn \xsim_collection_count:n #1
- { \xsim_list_count:n {collection:#1} }
-
-% #1: type
-% #2: id
-\cs_new_protected:Npn \xsim_update_collections:nn #1#2
- {
- \xsim_if_insert_mode:F
- {
- \xsim_exercise_if_use:nnT {#1} {#2}
- { \xsim_add_to_collection:nnn {all~ exercises} {#1} {#2} }
- \xsim_foreach_collection:n
- {
- \xsim_exercise_if_use:nnTF {#1} {#2}
- {
- \xsim_if_collection_active:nT {##1}
- { \xsim_add_to_collection:nnn {##1} {#1} {#2} }
- }
- { \xsim_remove_from_list:nn {collection:##1} {#1-#2} }
- }
- }
- }
-\cs_generate_variant:Nn \xsim_update_collections:nn {nV}
-
-% #1: collection name
-\cs_new_protected:Npn \xsim_get_collections:
- {
- \xsim_foreach_collection:n
- {
- \xsim_foreach_list_entry:nn {collection:##1}
- { \__xsim_list_to_collection:nww {##1} ####1 \q_stop }
- }
- }
-
-\cs_new_protected:Npn \__xsim_list_to_collection:nww #1#2-#3 \q_stop
- { \xsim_add_to_collection:nnn {#1} {#2} {#3} }
-
-% ----------------------------------------------------------------------------
-
-% #1: collection name
-% #2: type
-% #3: id
-\prg_new_conditional:Npnn \xsim_if_in_collection:nnn #1#2#3 {T,F,TF}
- {
- \xsim_if_in_list:nnTF {collection:#1} {#2-#3}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_in_collection:nnnTF {V}
-\cs_generate_variant:Nn \xsim_if_in_collection:nnnT {x,nV}
-
-% ----------------------------------------------------------------------------
-
-\bool_new:N \l__xsim_printcollection_headings_bool
-\tl_new:N \l__xsim_printcollection_headings_template_tl
-\tl_new:N \l__xsim_print_collection_choice_tl
-
-\keys_define:nn {xsim/print-collection}
- {
- headings .bool_set:N = \l__xsim_printcollection_headings_bool ,
- headings .initial:n = false ,
- headings-template .tl_set:N = \l__xsim_printcollection_headings_template_tl ,
- headings-template .initial:n = collection ,
- print .choice: ,
- print/exercises .code:n =
- \tl_set:Nn \l__xsim_print_collection_choice_tl {exercise} ,
- print/solutions .code:n =
- \tl_set:Nn \l__xsim_print_collection_choice_tl {solution} ,
- print/both .code:n =
- \tl_set:Nn \l__xsim_print_collection_choice_tl {both} ,
- print/unknown .code:n =
- \msg_warning:nnn {xsim} {print-collection-choice} {#1}
- \tl_set:Nn \l__xsim_print_collection_choice_tl {exercise} ,
- print .initial:n = exercises
- }
-
-% #1: options
-% #2: collection name
-\cs_new_protected:Npn \xsim_print_collection:nn #1#2
- {
- \xsim_if_collection_active:nTF {#2}
- { \msg_error:nnn {xsim} {collection-active} {#2} }
- {
- \xsim_verbose:x
- {
- Printing~
- \l__xsim_print_collection_choice_tl \c_space_tl
- \str_if_eq:onT { \l__xsim_print_collection_choice_tl } {both}
- { exercises~ and~ solutions~ }
- of~ collection~ `#2'
- }
- \group_begin:
- \keys_set:nn {xsim/print-collection} {#1}
- \tl_set:Nn \ExerciseCollection {#2}
- \xsim_foreach_exercise_type:n
- {
- \tl_set:Nn \ExerciseType {##1}
- \bool_if:NT \l__xsim_printcollection_headings_bool
- {
- \bool_set_false:N \l__xsim_tmpa_bool
- \xsim_foreach_exercise_id:n
- {
- \xsim_if_in_collection:nnnT {#2} {##1} {####1}
- {
- \tl_if_eq:VnTF
- \l__xsim_print_collection_choice_tl
- {both}
- {
- \xsim_if_exercise_exist:nnT {##1} {####1}
- { \bool_set_true:N \l__xsim_tmpa_bool }
- }
- {
- \use:c
- {
- xsim_if_
- \l__xsim_print_collection_choice_tl
- _exist:nnT
- }
- {##1}
- {####1}
- { \bool_set_true:N \l__xsim_tmpa_bool }
- }
- }
- }
- \bool_if:NT \l__xsim_tmpa_bool
- {
- \xsim_use_template:nV
- {heading}
- \l__xsim_printcollection_headings_template_tl
- }
- }
- \xsim_foreach_exercise_id:n
- {
- \xsim_if_in_collection:nnnT {#2} {##1} {####1}
- {
- \tl_if_eq:VnTF
- \l__xsim_print_collection_choice_tl
- {both}
- {
- \xsim_if_exercise_exist:nnT {##1} {####1}
- { \xsim_insert:nnnn {##1} {####1} {} {exercise} }
- \xsim_if_solution_exist:nnT {##1} {####1}
- { \xsim_insert:nnnn {##1} {####1} {} {solution} }
- }
- {
- \use:c
- {
- xsim_if_
- \l__xsim_print_collection_choice_tl
- _exist:nnT
- }
- {##1}
- {####1}
- {
- \xsim_insert:nnnV
- {##1}
- {####1}
- {}
- \l__xsim_print_collection_choice_tl
- }
- }
- }
- }
- }
- \group_end:
- }
- }
-
-% ----------------------------------------------------------------------------
-
-% #1: collection name
-\prg_new_conditional:Npnn \xsim_if_collection_active:n #1 {T,F,TF}
- {
- \xsim_attribute_if_set:nnTF {collection} {#1}
- {
- \bool_lazy_and:nnTF
- { !\str_if_eq_p:en {#1} {all~ exercises} }
- { \xsim_attribute_get:nn {collection} {#1} }
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
-
-\prg_new_protected_conditional:Npnn \xsim_if_collections_active: {T,F,TF}
- {
- \bool_set_false:N \l____xsim_active_bool
- \xsim_foreach_collection:n
- {
- \xsim_if_collection_active:nT {##1}
- {
- \bool_set_true:N \l____xsim_active_bool
- \xsim_collection_map_break:
- }
- }
- \bool_if:NTF \l____xsim_active_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% ----------------------------------------------------------------------------
-
-\xsim_at_begin_document:n
- {
- \xsim_get_collections:
- \xsim_activate_collection:n {all~ exercises}
- }
-
-\xsim_at_end_document:n
- {
- \xsim_deactivate_collection:n {all~ exercises}
- \xsim_foreach_collection:n { \xsim_update_list:n {collection:#1} }
- }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.definitions.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.definitions.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.definitions.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,482 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - definitions module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{definitions}{definition of user commands}
-
-\xsim_load_modules:n {base,exercises,blanks,translations,interface,grades,random}
-
-% not exactly a user choice: the `exercises' environments rely on them:
-\DeclareExerciseParameter*!{exercise-env}
-\DeclareExerciseParameter*!{solution-env}
-\DeclareExerciseParameter !{exercise-name}
-\DeclareExerciseParameter !{solution-name}
-\DeclareExerciseParameter {exercises-name}
-\DeclareExerciseParameter {solutions-name}
-\DeclareExerciseParameter !{exercise-template}
-\DeclareExerciseParameter !{solution-template}
-\DeclareExerciseParameter* {counter}
-\DeclareExerciseParameter* {solution-counter}
-\DeclareExerciseParameter* {number}
-
-% these are additional - but are used in the `default' environment
-% template:
-\DeclareExerciseParameter {exercise-heading}
-\DeclareExerciseParameter {solution-heading}
-
-% ----------------------------------------------------------------------------
-
-% not exactly a user choice, must be present at various places:
-\DeclareExerciseProperty! {id}
-\DeclareExerciseProperty! {ID}
-\DeclareExerciseProperty {counter}
-\DeclareExerciseProperty {counter-value}
-\DeclareExerciseProperty * {print}
-\DeclareExerciseProperty *-{print!}
-\DeclareExerciseProperty * {use}
-\DeclareExerciseProperty * {used}
-\DeclareExerciseProperty *-{use!}
-\DeclareExerciseProperty * {solution}
-\XSIMifchapterT{
- \DeclareExerciseProperty {chapter-value}
- \DeclareExerciseProperty {chapter}
-}
-\DeclareExerciseProperty {section-value}
-\DeclareExerciseProperty {section}
-\DeclareExerciseProperty {sectioning}
-
-% those are additional and wouldn't *need* to be present except for
-% pre-defined templates which make use of them (the page and page-value
-% property actually needs to be defined for xsim to be able to save the
-% corresponding values):
-\DeclareExerciseProperty {subtitle}
-\DeclareExerciseProperty {points}
-\DeclareExerciseProperty {bonus-points}
-\DeclareExerciseProperty {page-value}
-\DeclareExerciseProperty {page}
-
-\DeclareExercisePropertyAlias {ID} {id}
-
-% ----------------------------------------------------------------------------
-
-\DeclareExerciseTagging {tags}
-\DeclareExerciseTagging {topics}
-
-\xsimsetup{tags/ignore-untagged=false}
-
-% ----------------------------------------------------------------------------
-
-\DeclareExerciseGoal {points}
-\DeclareExerciseGoal {bonus-points}
-
-\NewDocumentCommand \printgoal {m}
- { \ExerciseGoalValuePrint {#1} {} {} }
-
-\NewDocumentCommand \points {m}
- {
- \ExerciseGoalValuePrint {#1}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-\NewDocumentCommand \addpoints {sm}
- {
- \AddtoExerciseGoal {points} {#2}
- \IfBooleanF {#1} { \points {#2} }
- }
-
-\NewDocumentCommand \printpoints {m}
- {
- \TotalExerciseTypeGoal {#1} {points}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-\NewDocumentCommand \printtotalpoints {}
- {
- \TotalExerciseGoal {points}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-\NewDocumentCommand \addbonus {sm}
- {
- \AddtoExerciseGoal {bonus-points} {#2}
- \IfBooleanF {#1} { \points {#2} }
- }
-
-\NewDocumentCommand \printbonus {m}
- {
- \TotalExerciseTypeGoal {#1} {bonus-points}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-\NewDocumentCommand \printtotalbonus {}
- {
- \TotalExerciseGoal {bonus-points}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-% ----------------------------------------------------------------------------
-\NewDocumentCommand \pointsforgrade {m}
- {
- \GetGradeRequirementForGoal {#1} {points}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-\NewDocumentCommand \goalsforgrade {mm}
- {
- \GetGradeRequirementForGoals {#2} {#1}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-\NewDocumentCommand \totalgoalforgrade {m}
- {
- \GetGradeRequirement {#1}
- { \, \XSIMtranslate {point} }
- { \, \XSIMtranslate {points} }
- }
-
-% ----------------------------------------------------------------------------
-
-\xsim_if_package_blank:F
- {
- \DeclareExerciseType {exercise} {
- exercise-env = exercise ,
- solution-env = solution ,
- exercise-name = \XSIMtranslate {exercise} ,
- exercises-name = \XSIMtranslate {exercises} ,
- solution-name = \XSIMtranslate {solution} ,
- solutions-name = \XSIMtranslate {solutions} ,
- exercise-template = default ,
- solution-template = default ,
- exercise-heading = \subsection* ,
- solution-heading = \subsection*
- }
- }
-
-% ----------------------------------------------------------------------------
-
-\DeclareExerciseEnvironmentTemplate {default}
- {
- \GetExerciseHeadingF { \subsection* }
- {
- \XSIMmixedcase { \GetExerciseName } \nobreakspace
- \GetExerciseProperty {counter}
- \IfInsideSolutionF
- {
- \IfExercisePropertySetT {subtitle}
- { ~ { \normalfont \itshape \GetExerciseProperty {subtitle} } }
- }
- }
- \GetExercisePropertyT {points}
- {
- \marginpar
- {
- \IfInsideSolutionF { \rule {1.2cm} {1pt} \slash }
- \printgoal {\PropertyValue}
- \GetExercisePropertyT {bonus-points}
- { \nobreakspace ( + \printgoal {\PropertyValue} ) }
- \nobreakspace\XSIMtranslate {point-abbr}
- }
- }
- }
- { \par }
-
-% ----------------------------------------------------------------------------
-
-\DeclareExerciseHeadingTemplate {none} {}
-
-\DeclareExerciseHeadingTemplate {default}
- { \section* { \XSIMtranslate {default-heading} } }
-
-\DeclareExerciseHeadingTemplate {collection}
- { \section* { \XSIMtranslate {collection-heading} } }
-
-\DeclareExerciseHeadingTemplate {per-section}
- { \section* { \XSIMtranslate {per-section-heading} } }
-
-\DeclareExerciseHeadingTemplate {per-chapter}
- { \section* { \XSIMtranslate {per-chapter-heading} } }
-
-% ----------------------------------------------------------------------------
-
-\RequirePackage{array,booktabs}
-
-\DeclareExerciseTableTemplate {default*}
- {
- \XSIMputright \ExerciseTableCode
- {
- \toprule
- \XSIMifblankTF {\ExerciseType}
- {}
- { \XSIMmixedcase { \GetExerciseParameter {exercise-name} } }
- &
- }
- \ForEachUsedExerciseByType
- {
- \XSIMifeqTF {#1} { \ExerciseTableType {#1} }
- {
- \XSIMifblankTF { \ExerciseType }
- {
- \XSIMputright \ExerciseTableCode
- {
- \XSIMmixedcase
- { \ExerciseParameterGet {#1} {exercise-name} ~ }
- }
- }
- {}
- \XSIMputright \ExerciseTableCode { #3 & }
- }
- {}
- }
- \XSIMputright \ExerciseTableCode
- {
- \XSIMtranslate {total} \\
- \midrule \XSIMmixedcase { \XSIMtranslate {points} } &
- }
- \ForEachUsedExerciseByType
- {
- \XSIMifeqTF {#1} { \ExerciseTableType {#1} }
- {
- \XSIMputright \ExerciseTableCode
- { \XSIMifblankTF {#5} {\printgoal{0}} {\printgoal{#5}} & }
- }
- {}
- }
- \XSIMputright \ExerciseTableCode
- {
- \XSIMifblankTF {\ExerciseType}
- { \TotalExerciseGoal {points} {} {} }
- { \TotalExerciseTypeGoal {\ExerciseType} {points} {} {} }
- \\ \midrule
- \XSIMtranslate {reached} &
- }
- \ForEachUsedExerciseByType
- {
- \XSIMifeqTF {#1} { \ExerciseTableType {#1} }
- { \XSIMputright \ExerciseTableCode {&} }
- {}
- }
- \XSIMputright \ExerciseTableCode { \\ \bottomrule }
- \def\numberofcolumns{
- \XSIMifblankTF {\ExerciseType}
- {\numberofusedexercises}
- {\csname numberof \ExerciseType s\endcsname}
- }
- \XSIMifeqF{\numberofcolumns}{0}
- {
- \begin {tabular} {l*{\numberofcolumns}{c}c}
- \ExerciseTableCode
- \end {tabular}
- }
- }
-
-\DeclareExerciseTableTemplate {default}
- {
- \XSIMputright \ExerciseTableCode
- {
- \toprule
- \XSIMifblankTF {\ExerciseType}
- {}
- { \XSIMmixedcase { \GetExerciseParameter {exercise-name} } }
- &
- \XSIMmixedcase { \XSIMtranslate {points} } &
- \XSIMtranslate {reached} \\
- \midrule
- }
- \ForEachUsedExerciseByType
- {
- \XSIMifeqTF {#1} { \ExerciseTableType {#1} }
- {
- \XSIMifblankTF { \ExerciseType }
- {
- \XSIMputright \ExerciseTableCode
- {
- \XSIMmixedcase
- { \ExerciseParameterGet {#1} {exercise-name} ~ }
- }
- }
- {}
- \XSIMputright \ExerciseTableCode
- { #3 & \XSIMifblankTF {#5} {\printgoal{0}} {\printgoal{#5}} & \\ }
- }
- {}
- }
- \XSIMputright \ExerciseTableCode
- {
- \midrule
- \XSIMtranslate {total} &
- \XSIMifblankTF {\ExerciseType}
- { \TotalExerciseGoal {points} {} {} }
- { \TotalExerciseTypeGoal {\ExerciseType} {points} {} {} } &
- \\ \bottomrule
- }
- \XSIMexpandcode
- {
- \noexpand \begin {tabular} {\XSIMifblankTF{\ExerciseType}{l}{c}cc}
- \noexpand \ExerciseTableCode
- \noexpand \end {tabular}
- }
- }
-
-% ----------------------------------------------------------------------------
-
-\DeclareExerciseTranslations {exercise} {
- Fallback = exercise ,
- English = exercise ,
- French = exercice ,
- German = \"Ubung
-}
-
-\DeclareExerciseTranslations {exercises} {
- Fallback = exercises ,
- English = exercises ,
- French = exercices ,
- German = \"Ubungen
-}
-
-\DeclareExerciseTranslations {question} {
- Fallback = question ,
- English = question ,
- French = question ,
- German = Aufgabe
-}
-
-\DeclareExerciseTranslations {questions} {
- Fallback = questions ,
- English = questions ,
- French = questions ,
- German = Aufgaben
-}
-
-\DeclareExerciseTranslations {solution} {
- Fallback = solution ,
- English = solution ,
- French = solution ,
- German = L\"osung
-}
-
-\DeclareExerciseTranslations {solutions} {
- Fallback = solutions ,
- English = solutions ,
- French = solutions ,
- German = L\"osungen
-}
-
-\DeclareExerciseTranslations {point-abbr} {
- Fallback = p. ,
- English = p. ,
- French = p. ,
- German = P.
-}
-
-\DeclareExerciseTranslations {point} {
- Fallback = point ,
- English = point ,
- French = point ,
- German = Punkt
-}
-
-\DeclareExerciseTranslations {points} {
- Fallback = points ,
- English = points ,
- French = points ,
- German = Punkte
-}
-
-\DeclareExerciseTranslations {reached} {
- Fallback = reached ,
- English = reached ,
- French = obtenus ,
- German = erreicht
-}
-
-\DeclareExerciseTranslations {total} {
- Fallback = total ,
- English = total ,
- French = total ,
- German = insgesamt
-}
-
-\DeclareExerciseTranslations {default-heading} {
- Fallback = \XSIMmixedcase { \GetExerciseParameter {solutions-name} }~
- to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
- English = \XSIMmixedcase { \GetExerciseParameter {solutions-name} }~
- to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
- French = \XSIMmixedcase { \GetExerciseParameter {solutions-name} ~
- des~ \GetExerciseParameter {exercises-name} } ,
- German = \XSIMmixedcase { \GetExerciseParameter {solutions-name} }~
- zu~ den~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} }
-}
-
-\DeclareExerciseTranslations {collection-heading} {
- Fallback = \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
- English = \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
- French = \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
- German = \XSIMmixedcase { \GetExerciseParameter {exercises-name} }
-}
-
-\DeclareExerciseTranslations {per-section-heading} {
- Fallback = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
- to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
- of~ Section \nobreakspace \ExerciseSection ,
- English = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
- to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
- of~ Section \nobreakspace \ExerciseSection ,
- French = \XSIMmixedcase { \GetExerciseParameter {solutions-name} ~
- des~ \GetExerciseParameter {exercises-name} ~ de~ la~
- section \nobreakspace \ExerciseSection } ,
- German = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
- zu~ den~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} }~
- in~ Abschnitt \nobreakspace \ExerciseSection
-}
-
-\DeclareExerciseTranslations {per-chapter-heading} {
- Fallback = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
- to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
- of~ Chapter \nobreakspace \ExerciseChapter ,
- English = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
- to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
- of~ Chapter \nobreakspace \ExerciseChapter ,
- French = \XSIMmixedcase { \GetExerciseParameter {solutions-name} ~
- des~ \GetExerciseParameter {exercises-name} ~
- du~ chapitre \nobreakspace \ExerciseChapter } ,
- German = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
- zu~ den~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
- in~ Kapitel \nobreakspace \ExerciseChapter
-}
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-
-2019/02/17 - fix issue #39 (error in German translations)
-2020/02/19 - implement issue #33 (solution property)
-2020/02/20 - implement issue #31 (blank package option)
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.environments.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.environments.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.environments.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,529 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - environments module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{environments}{generic code for exercise and solution environments}
-
-\xsim_load_modules:n {templates,verbwrite}
-
-\xsim_if_write_to_files:F
- {
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_false_bool }
- { \c_false_bool }
- {solution-body}
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_false_bool }
- { \c_false_bool }
- {exercise-body}
- }
-
-\tl_new:N \l__xsim_file_name_signature_tl
-\tl_new:N \l__xsim_file_path_tl
-\tl_new:N \l__xsim_file_path_and_name_tl
-\tl_new:N \l__xsim_file_name_tl
-\tl_new:N \l__xsim_file_extension_tl
-\tl_new:N \l__xsim_solution_tl
-\bool_new:N \l__xsim_options_given_bool
-\bool_new:N \l__xsim_insert_mode_bool
-
-\tl_new:N \ExerciseText
-\tl_set:Nn \ExerciseText { \msg_error:nn {xsim} {only-in-solution} }
-
-% ----------------------------------------------------------------------------
-
-\msg_new:nnn {xsim} {only-in-solution}
- {
- You~ can't~ use~ \token_to_str:N \ExerciseText \c_space_tl inside~ an~
- exercise.~ It~ is~ only~ allowed~ inside~ solution~ environments!
- }
-
-% ----------------------------------------------------------------------------
-
-\keys_define:nn {xsim}
- {
- path .tl_set:N = \l__xsim_file_path_tl ,
- file-extension .tl_set:N = \l__xsim_file_extension_tl ,
- file-extension .initial:n = tex
- }
-
-% ----------------------------------------------------------------------------
-
-\tl_const:Nn \c__xsim_comment_line_tl { \c__xsim_percent_char_tl }
-\tl_const:Nn \c__xsim_comment_line_fill_tl { \prg_replicate:nn {72} {-} }
-\tl_const:Nn \c__xsim_comment_line_indent_tl { \c_space_tl \c_space_tl }
-
-\cs_new:Npn \__xsim_comment_line_and_feed:n #1
- { \__xsim_comment_line:n {#1} ^^J }
-
-\cs_new:Npn \__xsim_comment_line:n #1
- {
- \c__xsim_comment_line_tl
- \tl_if_blank:nF {#1} { \c_space_tl }
- #1
- }
-
-\cs_new:Npn \__xsim_two_digits:n #1
- { \int_compare:nT { #1 < 10 } {0} \int_eval:n {#1} }
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\cs_new_protected:Npn \__xsim_set_file_signature:nnn #1#2#3
- { \tl_set:Nn \l__xsim_file_name_signature_tl {#1-#2-#3} }
-\cs_generate_variant:Nn \__xsim_set_file_signature:nnn {nx,nV}
-
-\tl_set:Nn \l__xsim_file_name_tl
- { \c_sys_jobname_str - \l__xsim_file_name_signature_tl -body . \l__xsim_file_extension_tl }
-
-\tl_set:Nn \l__xsim_file_path_and_name_tl
- {
- \tl_if_blank:VF \l__xsim_file_path_tl
- { \l__xsim_file_path_tl / }
- \l__xsim_file_name_tl
- }
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-% #4: file name
-% #5: path
-\cs_new_protected:Npn \__xsim_file_info:nnnnn #1#2#3#4#5
- {
- \tl_set:Nn \l_xsim_file_begin_tl
- {
- \__xsim_comment_line_and_feed:n { \c__xsim_comment_line_fill_tl }
- \__xsim_comment_line_and_feed:n {file~ `#4'}
- \tl_if_blank:nF {#5}
- {
- \__xsim_comment_line_and_feed:n
- { \c__xsim_comment_line_indent_tl in~ folder~ `#5/'}
- }
- \__xsim_comment_line_and_feed:n {}
- \__xsim_comment_line_and_feed:n
- {
- \c__xsim_comment_line_indent_tl
- \c__xsim_comment_line_indent_tl
- #3~ of~ type~ `#1'~ with~ id~ `#2'
- }
- \__xsim_comment_line_and_feed:n {}
- \__xsim_comment_line_and_feed:n
- {generated~ by~ the~ `\@currenvir'~ environment~ of~ the}
- \__xsim_comment_line_and_feed:n
- {
- \c__xsim_comment_line_indent_tl
- `xsim'~ package~ v \c_xsim_version_tl
- \c_space_tl (\c_xsim_date_tl)
- }
- \__xsim_comment_line_and_feed:n
- {
- from~ source~ `\c_sys_jobname_str'~ on~
- \int_use:N \c_sys_year_int /
- \__xsim_two_digits:n { \c_sys_month_int } /
- \__xsim_two_digits:n { \c_sys_day_int } ~
- \msg_line_context:
- }
- \__xsim_comment_line:n { \c__xsim_comment_line_fill_tl }
- }
- }
-\cs_generate_variant:Nn \__xsim_file_info:nnnnn {nnnVV}
-
-% ----------------------------------------------------------------------------
-% #1: type
-% #2: id
-% #3: exercise|solution
-% #4: potential environment body
-\cs_new_protected:Npn \xsim_save_environment_body:nnnn #1#2#3#4
- {
- \xsim_if_write_to_files:TF
- { \__xsim_write_environment_body:nnn {#1} {#2} {#3} }
- { \__xsim_save_environment_body:nnnn {#1} {#2} {#3} {#4} }
- }
-
-\cs_new_protected:Npn \xsim_save_environment_body_end:
- {
- \xsim_if_write_to_files:TF
- { \__xsim_write_environment_body_end: }
- { \__xsim_save_environment_body_end: }
- }
-
-% writing to files:
-% #1: type
-% #2: id
-% #3: exercise|solution
-\cs_new_protected:Npn \__xsim_write_environment_body:nnn #1#2#3
- {
- \xsim_verbose:n
- { Starting~ to~ write~ #3~ environment~ type~ `#1'~ id~ `#2' }
- \__xsim_set_file_signature:nnn {#1} {#2} {#3}
- \__xsim_file_info:nnnVV {#1} {#2} {#3}
- \l__xsim_file_name_tl
- \l__xsim_file_path_tl
- \int_zero:N \l_xsim_line_gobble_int
- \xsim_file_write_start:nV
- { \l__xsim_options_given_bool }
- \l__xsim_file_path_and_name_tl
- }
-
-\cs_new_protected:Npn \__xsim_write_environment_body_end:
- { \xsim_file_write_stop: }
-
-% saving to property lists:
-% #1: type
-% #2: id
-% #3: exercise|solution
-% #4: environment body
-\cs_new_protected:Npn \__xsim_save_environment_body:nnnn #1#2#3#4
- {
- \xsim_verbose:n { Saving~ #3~ environment~ type~ `#1'~ id~ `#2' }
- \xsim_set_property:nnnn {#1} {#2} {#3-body} {#4}
- }
-
-\cs_new:Npn \__xsim_save_environment_body_end: { }
-
-% ----------------------------------------------------------------------------
-% #1: type
-% #2: exercise|solution
-% #3: hook
-\cs_new_protected:Npn \xsim_new_hook:nnn #1#2#3
- {
- \xsim_verbose:n { Defining~ new~ #1~ (#2)~ hook~ `#3' }
- \tl_new:c {l__xsim_#1_#2_#3_hook_tl}
- \keys_define:nx {xsim}
- {
- \xsim_get_parameter:nn {#1} {#2-env}/#3-hook .tl_set:N =
- \exp_not:c {l__xsim_#1_#2_#3_hook_tl}
- }
- }
-
-% #1: type
-% #2: exercise|solution
-% #3: hook
-\cs_new:Npn \xsim_use_hook:nnn #1#2#3
- { \exp_not:v {l__xsim_#1_#2_#3_hook_tl} }
-
-% #1: type
-% #2: exercise|solution
-% #3: hook
-% #4: code
-\cs_new_protected:Npn \xsim_set_hook:nnnn #1#2#3#4
- {
- \xsim_verbose:n { Setting~ #1~ (#2)~ hook~ `#3' }
- \tl_set:cn {l__xsim_#1_#2_#3_hook_tl} {#4}
- }
-
-% #1: type
-% #2: exercise|solution
-% #3: hook
-% #4: code
-\cs_new_protected:Npn \xsim_addto_hook:nnnn #1#2#3#4
- {
- \xsim_verbose:n { Adding~ to~ #1~ (#2)~ hook~ `#3' }
- \tl_put_right:cn {l__xsim_#1_#2_#3_hook_tl} {#4}
- }
-
-% ----------------------------------------------------------------------------
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-% #4: potential enironment body
-\cs_new_protected:Npn \xsim_start_environment:nnnn #1#2#3#4
- { \xsim_save_environment_body:nnnn {#1} {#2} {#3} {#4} }
-\cs_generate_variant:Nn \xsim_start_environment:nnnn {nV}
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\cs_new_protected:Npn \xsim_stop_environment:nnn #1#2#3
- {
- \xsim_save_environment_body_end:
- \xsim_if_print:nnnTF {#1} {#2} {#3}
- { \xsim_typeset_environment:nnn {#1} {#2} {#3} }
- { \xsim_use_hook:nnn {#1} {#3} {print-false} }
- }
-\cs_generate_variant:Nn \xsim_stop_environment:nnn {nV}
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\cs_new_protected:Npn \xsim_typeset_environment:nnn #1#2#3
- {
- \tl_set:Nn \ExerciseType {#1}
- \tl_set:Nn \ExerciseID {#2}
- \xsim_if_exchange:nnnT {#1} {#2} {#3}
- { \__xsim_set_file_signature:nnn {#1} {#2} {exercise} }
- \xsim_verbose:n
- { Typesetting~ #3~ environment~ type~ `#1'~ id~ `#2' }
- \xsim_use_hook:nnn {#1} {#3} {pre}
- \xsim_use_template:nx
- {begin}
- { \xsim_get_parameter:nn {#1} {#3-template} }
- \xsim_use_hook:nnn {#1} {#3} {begin}
- \xsim_if_write_to_files:TF
- {
- \file_if_exist:nTF { \exp_not:V \l__xsim_file_path_and_name_tl }
- { \file_input:n { \exp_not:V \l__xsim_file_path_and_name_tl } }
- {
- \xsim_verbose:n
- { File~ `\l__xsim_file_path_and_name_tl'~ doesn't~ exist. }
- }
- }
- {
- \xsim_if_exchange:nnnTF {#1} {#2} {#3}
- { \xsim_get_property:nnn {#1} {#2} {exercise-body} }
- { \xsim_get_property:nnn {#1} {#2} {#3-body} }
- }
- \xsim_synchronize_goals:nn {#1} {#2}
- \str_if_eq:nnT {#3} {exercise}
- { \xsim_update_goals:nn {#1} {#2} }
- \xsim_use_hook:nnn {#1} {#3} {end}
- \xsim_use_template:nx
- {end}
- { \xsim_get_parameter:nn {#1} {#3-template} }
- \xsim_use_hook:nnn {#1} {#3} {post}
- }
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\prg_new_conditional:Npnn \xsim_if_exchange:nnn #1#2#3 {T,F,TF}
- {
- \str_if_eq:nnTF {#3} {solution}
- {
- \xsim_if_boolean_property:nnnTF {#1} {#2} {solution}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\prg_new_protected_conditional:Npnn \xsim_if_exist:nnn #1#2#3 {T,F,TF}
- {
- \xsim_if_write_to_files:TF
- {
- \__xsim_set_file_signature:nnn {#1} {#2} {#3}
- \file_if_exist:VTF \l__xsim_file_path_and_name_tl
- { \prg_return_true: }
- { \prg_return_false: }
- }
- {
- \xsim_if_property_exist:nTF {#3-body}
- {
- \xsim_if_property_set:nnnTF {#1} {#2} {#3-body}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
- }
-
-% #1: type
-% #2: id
-% #3: options
-% #4: exercise|solution
-\cs_new_protected:Npn \xsim_insert:nnnn #1#2#3#4
- {
- \xsim_if_exchange:nnnTF {#1} {#2} {#4}
- { \xsim_if_exist:nnnTF {#1} {#2} {exercise} }
- { \xsim_if_exist:nnnTF {#1} {#2} {#4} }
- {
- \xsim_verbose:n
- { Inserting~ #4~ type~ `#1'~ id~ `#2'. }
- \group_begin:
- \xsim_insert_mode:
- \use:c {xsim_start_#4:nn} {#1} {#3}
- \tl_set:Nn \ExerciseType {#1}
- \tl_set:Nn \ExerciseID {#2}
- \str_if_eq:nnT {#4} {exercise}
- {
- \xsim_if_boolean_property:nnnF {#1} {#2} {used}
- {
- \xsim_step_exercise_counter:nn {#1} {#2}
- \xsim_set_properties:nnx {#1} {#2}
- {
- page-value = \the\value{page} ,
- page = \thepage ,
- section-value = \the\value{section} ,
- section = \thesection
- }
- \xsim_synchronize_goals:nn {#1} {#2}
- \xsim_update_goals:nn {#1} {#2}
- }
- \xsim_if_property_exist:nT {chapter}
- {
- \xsim_set_properties:nnx {#1} {#2}
- {
- chapter-value = \the\value{chapter} ,
- chapter = \thechapter
- }
- }
- \xsim_set_properties:nnn {#1} {#2}
- { print=true , used=true }
- }
- \str_if_eq:nnT {#4} {solution}
- {
- \xsim_if_write_to_files:TF
- {
- \__xsim_set_file_signature:nnn {#1} {#2} {exercise}
- \file_get:nnN {\l__xsim_file_path_and_name_tl} {} \ExerciseText
- \tl_trim_spaces:N \ExerciseText
- }
- {
- \tl_set:Nx \ExerciseText
- { \xsim_get_property:nnn {#1} {#2} {exercise-body} }
- }
- }
- \use:x
- {
- \xsim_use_hook:nnn {#1} {#4} {pre}
- \xsim_use_template:nn
- {begin}
- { \xsim_get_parameter:nn {#1} {#4-template} }
- \xsim_use_hook:nnn {#1} {#4} {begin}
- \xsim_input:nnn {#1} {#2} {#4}
- \xsim_use_hook:nnn {#1} {#4} {end}
- \xsim_use_template:nn
- {end}
- { \xsim_get_parameter:nn {#1} {#4-template} }
- \xsim_use_hook:nnn {#1} {#4} {post}
- }
- \group_end:
- }
- {
- \xsim_if_write_to_files:T
- {
- \xsim_verbose:x
- { File~ `\l__xsim_file_path_and_name_tl'~ doesn't~ exist. }
- }
- }
- }
-\cs_generate_variant:Nn \xsim_insert:nnnn {nV,VV,nnnV,xx,ne}
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\cs_new_protected:Npn \xsim_input:nnn #1#2#3
- {
- \group_begin:
- \xsim_if_write_to_files:TF
- {
- \xsim_if_exchange:nnnTF {#1} {#2} {#3}
- { \__xsim_set_file_signature:nnn {#1} {#2} {exercise} }
- { \__xsim_set_file_signature:nnn {#1} {#2} {#3} }
- \file_input:n { \l__xsim_file_path_and_name_tl }
- }
- {
- \xsim_if_exchange:nnnTF {#1} {#2} {#3}
- { \xsim_get_property:nnn {#1} {#2} {exercise-body} }
- { \xsim_get_property:nnn {#1} {#2} {#3-body} }
- }
- \group_end:
- }
-\cs_generate_variant:Nn \xsim_input:nnn {oo}
-
-\prg_new_conditional:Npnn \xsim_if_insert_mode: {T,F,TF}
- {
- \bool_if:NTF \l__xsim_insert_mode_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\cs_new_protected:Npn \xsim_insert_mode:
- { \bool_set_true:N \l__xsim_insert_mode_bool }
-
-% ----------------------------------------------------------------------------
-
-% #1: type
-% #2: exercise|solution
-\cs_new_protected:Npn \xsim_new_environment:nn #1#2
- {
- \xsim_verbose:n { Defining~ #2~ environment~ type~ `#1'. }
- \xsim_new_hook:nnn {#1} {#2} {pre}
- \xsim_new_hook:nnn {#1} {#2} {begin}
- \xsim_new_hook:nnn {#1} {#2} {end}
- \xsim_new_hook:nnn {#1} {#2} {post}
- \xsim_new_hook:nnn {#1} {#2} {print-false}
- \xsim_if_write_to_files:TF
- {
- \NewDocumentEnvironment
- { \xsim_get_parameter:nn {#1} {#2-env} } {!o}
- {
- \IfNoValueTF {##1}
- {
- \bool_set_false:N \l__xsim_options_given_bool
- \use:c {xsim_start_#2:nn} {#1} {}
- }
- {
- \bool_set_true:N \l__xsim_options_given_bool
- \use:c {xsim_start_#2:nn} {#1} {##1}
- }
- \xsim_start_environment:nVnn {#1} \g_xsim_exercise_id_tl {#2} { }
- }
- {
- \xsim_stop_environment:nVn {#1} \g_xsim_exercise_id_tl {#2}
- \use:c {xsim_stop_#2:n} {#1}
- }
- }
- {
- \NewDocumentEnvironment
- { \xsim_get_parameter:nn {#1} {#2-env} } {o+b}
- {
- \IfNoValueTF {##1}
- {
- \bool_set_false:N \l__xsim_options_given_bool
- \use:c {xsim_start_#2:nn} {#1} {}
- }
- {
- \bool_set_true:N \l__xsim_options_given_bool
- \use:c {xsim_start_#2:nn} {#1} {##1}
- }
- \xsim_start_environment:nVnn {#1} \g_xsim_exercise_id_tl {#2} {##2}
- }
- {
- \xsim_stop_environment:nVn {#1} \g_xsim_exercise_id_tl {#2}
- \use:c {xsim_stop_#2:n} {#1}
- }
- }
- }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-
-2019/02/17 - fix issue #43
-2019/10/03 - add possibility to save environment bodies to property list
-2020/02/15 - remove spurious \par at the beginning and end of typeset
- exercises and solutions
-2020/02/19 - implement issue #33 (solution property)
-2020/02/20 - fix issue #27
- - implement issue #2
-2020/03/08 - correctly re-set \ExerciseType and \ExerciseID for typesetting
- (they're no longer local)
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,637 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - exercises module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{exercises}{main exercises definitions}
-
-\xsim_load_modules:n
- {
- base, properties, environments, templates, solutions, tags, goals,
- collections
- }
-
-\seq_new:N \l__xsim_exercise_types_seq
-\seq_new:N \l__xsim_parameters_seq
-\seq_new:N \l__xsim_fixed_parameters_seq
-\seq_new:N \l__xsim_mandatory_parameters_seq
-\int_gzero_new:N \g_xsim_id_int
-\int_gzero_new:N \g_xsim_max_id_int
-\tl_new:N \l_xsim_current_id_tl
-\tl_new:N \g_xsim_exercise_id_tl
-\tl_new:N \g_xsim_exercise_type_tl
-\tl_new:N \ExerciseID
-\tl_new:N \ExerciseType
-\bool_new:N \l____xsim_print_bool
-
-% ----------------------------------------------------------------------------
-
-\msg_new:nnn {xsim} {parameter-fixed}
- {
- You~ tried~ to~ set~ parameter~ `#2'~ for~ type~ `#1'~ \msg_line_context:
- . ~ However,~ parameter~ `#2'~ is~ a~ fixed~ parameter~ that~ already~
- has~ been~ set~ for~ type~ `#1'.~ Its~ value~ can't~ be~ changed!
- }
-
-\msg_new:nnn {xsim} {type-exists}
- {
- You~ try~ to~ define~ exercise~ type~ `#1'~ \msg_line_context: .~
- However,~ the~ exercise~ type~ `#1'~ already~ exists.
- }
-
-\msg_new:nnn {xsim} {mandatory-parameter}
- {
- You~ forget~ to~ set~ the~ mandatory~ parameter~ `#1'~ when~ defining~
- exercise~ type~ `#2'.
- }
-
-\msg_new:nnn {xsim} {unknown-parameter}
- {
- You~ tried~ to~ retrieve~ the~ parameter~ `#1'~ \msg_line_context: . \\
- This~ parameter~ does~ not~ exist.~ Check~ for~ a~ typo~ or~ \\
- define~ the~ parameter~ yourself.
- }
-
-% ----------------------------------------------------------------------------
-% #1: type
-% #2: parameter
-% #3: value
-\cs_new_protected:Npn \__xsim_set_parameter_type:nnn #1#2#3
- { \xsim_attribute_set:nnn {#1} {#2} {#3} }
-
-% #1: type
-% #2: parameter
-\cs_new:Npn \xsim_get_parameter:nn #1#2
- { \xsim_attribute_get:nn {#1} {#2} }
-\cs_generate_variant:Nn \xsim_get_parameter:nn {o}
-
-% #1: type
-% #2: parameter
-\prg_new_conditional:Npnn \xsim_if_parameter_set:nn #1#2 {p,T,F,TF}
- {
- \xsim_attribute_if_set:nnTF {#1} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% ----------------------------------------------------------------------------
-
-\xsim_new_list:n {types}
-
-% #1: true|false (fixed parameter)
-% #2: true|false (mandatory parameter)
-% #3: parameter name
-\cs_new_protected:Npn \xsim_declare_parameter:nnn #1#2#3
- {
- \xsim_verbose:n { Declaring~ parameter~ `#3'. }
- \xsim_if_parameter_exist:nF {#3}
- {
- \seq_put_right:Nn \l__xsim_parameters_seq {#3}
- \bool_if:cT {c_#1_bool}
- { \seq_put_right:Nn \l__xsim_fixed_parameters_seq {#3} }
- \bool_if:cT {c_#2_bool}
- { \seq_put_right:Nn \l__xsim_mandatory_parameters_seq {#3} }
- }
- }
-
-\cs_new_protected:Npn \xsim_remove_parameter:n #1
- {
- \xsim_verbose:n { Removing~ parameter~ `#1'. }
- \xsim_if_parameter_exist:nT {#1}
- { \seq_remove_all:Nn \l__xsim_parameters_seq {#1} }
- }
-
-\prg_new_conditional:Npnn \xsim_if_parameter_exist:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_parameters_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_parameter_exist:nT {x}
-
-\prg_new_conditional:Npnn \xsim_if_parameter_fixed:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_fixed_parameters_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: type
-% #2: csv list of parameters
-\cs_new_protected:Npn \xsim_set_parameters:nn #1#2
- {
- \clist_map_inline:nn {#2}
- {
- \seq_set_split:Nnx \l__xsim_tmpa_seq {=} { \tl_trim_spaces:n {##1} }
- \xsim_set_parameter:nxx {#1}
- { \seq_item:Nn \l__xsim_tmpa_seq {1} }
- { \seq_item:Nn \l__xsim_tmpa_seq {2} }
- }
- }
-\cs_generate_variant:Nn \xsim_set_parameters:nn {nx}
-
-% #1: type
-\cs_new_protected:Npn \xsim_check_mandatory_parameters:n #1
- {
- \seq_map_inline:Nn \l__xsim_mandatory_parameters_seq
- {
- \xsim_if_parameter_set:nnF {#1} {##1}
- { \msg_error:nnnn {xsim} {mandatory-parameter} {##1} {#1} }
- }
- }
-
-% #1: type
-\prg_new_conditional:Npnn \xsim_if_type:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_exercise_types_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: type
-% #2: parameter
-% #3: value
-\cs_new_protected:Npn \xsim_set_parameter:nnn #1#2#3
- {
- \xsim_if_parameter_exist:nT {#2}
- {
- \xsim_if_parameter_fixed:nTF {#1}
- {
- \xsim_if_parameter_set:nnTF {#1} {#2}
- {
- \msg_warning:nnnn {xsim} {parameter-fixed} {#1} {#2}
- \xsim_verbose:n
- {
- Not~ setting~ already~ set~ and~ fixed~ parameter~ `#2'~
- for~ type~ `#1'.
- }
- }
- {
- \xsim_verbose:n
- { Setting~ parameter~ `#2'~ for~ type~ `#1'~ to~ `#3'. }
- \__xsim_set_parameter_type:nnn {#1} {#2} {#3}
- }
- }
- {
- \xsim_verbose:n
- { Setting~ parameter~ `#2'~ for~ type~ `#1'~ to~ `#3'. }
- \__xsim_set_parameter_type:nnn {#1} {#2} {#3}
- }
- }
- }
-\cs_generate_variant:Nn \xsim_set_parameter:nnn {nnx,nxx}
-
-\cs_new:Npn \__xsim_get_parameter_tmp:n #1 {}
-\cs_generate_variant:Nn \__xsim_get_parameter_tmp:n {V}
-
-% #1: type
-% #2: parameter
-\cs_new_protected:Npn \xsim_get_parameter_if_set:nnTF #1#2#3#4
- {
- \group_begin:
- \xsim_if_parameter_exist:nTF {#2}
- {
- \xsim_if_parameter_set:nnTF {#1} {#2}
- {
- \tl_set:Nx \ParameterValue
- { \xsim_get_parameter:nn {#1} {#2} }
- \cs_set:Npn \__xsim_get_parameter_tmp:n ##1 {#3}
- \__xsim_get_parameter_tmp:V \ParameterValue
- }
- {#4}
- }
- { \msg_error:nnn {xsim} {unknown-parameter} {#2} }
- \group_end:
- }
-\cs_new_protected:Npn \xsim_get_parameter_if_set:nnT #1#2#3
- { \xsim_get_parameter_if_set:nnTF {#1} {#2} {#3} {} }
-\cs_new_protected:Npn \xsim_get_parameter_if_set:nnF #1#2#3
- { \xsim_get_parameter_if_set:nnTF {#1} {#2} {} {#3} }
-\cs_generate_variant:Nn \xsim_get_parameter_if_set:nnTF {o}
-
-% ----------------------------------------------------------------------------
-% inside the argument `#1' refers to the type
-\cs_new_protected:Npn \xsim_foreach_exercise_type:n #1
- { \xsim_foreach_new_list_entry:nn {types} {#1} }
-
-\cs_new_protected:Npn \xsim_foreach_exercise_id:n #1
- { \int_step_inline:nnnn {1} {1} { \g_xsim_max_id_int } {#1} }
-
-\cs_new:Npn \__xsim_loop_item:nnnnnn #1#2#3#4#5#6 {}
-\cs_generate_variant:Nn \__xsim_loop_item:nnnnnn {VVxxxx}
-
-% #1: type
-% #2: id
-% #3: boolean property
-\cs_new:Npn \__xsim_deliver_exercise_details:nnn #1#2#3
- {
- \xsim_if_in_list:nnT {#3} {#1-#2=={true}}
- {
- \tl_set_rescan:Nnx \l__xsim_tmpa_tl {} {#1}
- \tl_set_rescan:Nnx \l__xsim_tmpb_tl {} {#2}
- \__xsim_loop_item:VVxxxx
- \l__xsim_tmpa_tl % #1
- \l__xsim_tmpb_tl % #2
- { \xsim_get_property:nnn {#1} {#2} {counter} } % #3
- { \xsim_get_property:nnn {#1} {#2} {subtitle} } % #4
- { \xsim_get_property:nnn {#1} {#2} {points} } % #5
- { \xsim_get_property:nnn {#1} {#2} {bonus-points} } % #6
- }
- }
-
-% #1: boolean property
-% #2: loop code
-\xsim_define_loop_macro:Nnn \xsim_foreach_exercise_type_id:nn
- {nnnnnn}
- {
- \xsim_foreach_exercise_type:n
- {
- \xsim_foreach_exercise_id:n
- { \__xsim_deliver_exercise_details:nnn {##1} {####1} {#1} }
- }
- }
-
-\xsim_define_loop_macro:Nnn \xsim_foreach_exercise_id_type:nn
- {nnnnnn}
- {
- \xsim_foreach_exercise_id:n
- {
- \xsim_foreach_exercise_type:n
- { \__xsim_deliver_exercise_details:nnn {####1} {##1} {#1} }
- }
- }
-
-\cs_new_protected:Npn \xsim_define_exercise_type_variables:n #1
- {
- \seq_put_right:Nn \l__xsim_exercise_types_seq {#1}
- \bool_new:c {l__xsim_#1_solution_print_bool}
- \bool_new:c {l__xsim_#1_exercise_print_bool}
- \bool_new:c {l__xsim_#1_exercise_use_bool}
- }
-
-\cs_new_protected:Npn \xsim_define_counters:n #1
- {
- \xsim_verbose:n { Defining~ counters~ for~ new~ exercise~ type~ `#1' }
- \cs_if_exist:cF { c@ \xsim_get_parameter:nn {#1} {counter} }
- { \newcounter { \xsim_get_parameter:nn {#1} {counter} } }
- \cs_if_exist:cF { c@ \xsim_get_parameter:nn {#1} {solution-counter} }
- { \newcounter { \xsim_get_parameter:nn {#1} {solution-counter} } }
- \cs_if_exist:cF { c@ number of \xsim_get_parameter:nn {#1} {exercise-env} s }
- { \newcounter { number of \xsim_get_parameter:nn {#1} {exercise-env} s } }
- }
-
-% #1: type
-% #2: id
-\cs_new_protected:Npn \xsim_step_exercise_counter:nn #1#2
- {
- \refstepcounter { \xsim_get_parameter:nn {#1} {counter} }
- \xsim_set_properties:nnx {#1} {#2}
- {
- counter = \use:c { the \xsim_get_parameter:nn {#1} {counter} } ,
- counter-value = \arabic { \xsim_get_parameter:nn {#1} {counter} }
- }
- }
-\cs_generate_variant:Nn \xsim_step_exercise_counter:nn {nV}
-
-% #1: type
-\cs_new_protected:Npn \xsim_declare_exercise_type:nn #1#2
- {
- \xsim_if_type:nTF {#1}
- { \msg_error:nnn {xsim} {type-exists} {#1} }
- {
- \xsim_verbose:n { Declaring~ new~ exercise~ type~ `#1'. }
- \xsim_define_exercise_type_variables:n {#1}
- \xsim_add_to_list:nn {types} {#1}
- \xsim_set_parameters:nn {#1} {#2}
- \xsim_set_parameter:nnx {#1} {number}
- { number of \xsim_get_parameter:nn {#1} {exercise-env} s }
- \xsim_check_mandatory_parameters:n {#1}
- \xsim_if_parameter_set:nnF {#1} {exercises-name}
- {
- \xsim_set_parameters:nn {#1}
- { exercises-name = \xsim_get_parameter:nn {#1} {exercise-name} s }
- }
- \xsim_if_parameter_set:nnF {#1} {solutions-name}
- {
- \xsim_set_parameters:nn {#1}
- { solutions-name = \xsim_get_parameter:nn {#1} {solution-name} s }
- }
- \xsim_if_parameter_set:nnF {#1} {counter}
- {
- \xsim_set_parameters:nx {#1}
- { counter = \xsim_get_parameter:nn {#1} {exercise-env} }
- }
- \xsim_if_parameter_set:nnF {#1} {solution-counter}
- {
- \xsim_set_parameters:nx {#1}
- { solution-counter = \xsim_get_parameter:nn {#1} {solution-env} }
- }
- \xsim_define_counters:n {#1}
- \xsim_verbose:n { Defining~ options~ for~ new~ exercise~ type~ `#1' }
- \keys_define:nx {xsim}
- {
- \xsim_get_parameter:nn {#1} {solution-env} / print
- .bool_set:N = \exp_not:c {l__xsim_#1_solution_print_bool} ,
- \xsim_get_parameter:nn {#1} {solution-env} / print
- .initial:n = false ,
- \xsim_get_parameter:nn {#1} {exercise-env} / print
- .bool_set:N = \exp_not:c {l__xsim_#1_exercise_print_bool} ,
- \xsim_get_parameter:nn {#1} {exercise-env} / print
- .initial:n = true ,
- \xsim_get_parameter:nn {#1} {exercise-env} / use
- .bool_set:N = \exp_not:c {l__xsim_#1_exercise_use_bool} ,
- \xsim_get_parameter:nn {#1} {exercise-env} / use
- .initial:n = true ,
- \xsim_get_parameter:nn {#1} {exercise-env} / within .code:n =
- \exp_not:N \@addtoreset { \xsim_get_parameter:nn {#1} {counter} } {####1},
- \xsim_get_parameter:nn {#1} {exercise-env} / the-counter .code:n =
- \cs_set:cpn {the \xsim_get_parameter:nn {#1} {counter} } {####1} ,
- \xsim_get_parameter:nn {#1} {exercise-env} / template
- .code:n = \xsim_set_parameter:nnn {#1} {exercise-template} {####1} ,
- \xsim_get_parameter:nn {#1} {solution-env} / template
- .code:n = \xsim_set_parameter:nnn {#1} {solution-template} {####1} ,
- \xsim_get_parameter:nn {#1} {exercise-env} / name
- .code:n = \xsim_set_parameter:nnn {#1} {exercise-name} {####1} ,
- \xsim_get_parameter:nn {#1} {exercise-env} s / name
- .code:n = \xsim_set_parameter:nnn {#1} {exercises-name} {####1} ,
- \xsim_get_parameter:nn {#1} {solution-env} / name
- .code:n = \xsim_set_parameter:nnn {#1} {solution-name} {####1} ,
- \xsim_get_parameter:nn {#1} {solution-env} s / name
- .code:n = \xsim_set_parameter:nnn {#1} {solutions-name} {####1} ,
- \xsim_get_parameter:nn {#1} {exercise-env} / heading
- .code:n = \xsim_set_parameter:nnn {#1} {exercise-heading} {####1} ,
- \xsim_get_parameter:nn {#1} {solution-env} / heading
- .code:n = \xsim_set_parameter:nnn {#1} {solution-heading} {####1}
- }
- \xsim_new_environment:nn {#1} {exercise}
- \xsim_new_environment:nn {#1} {solution}
- }
- }
-
-% #1: type
-% #2: id
-\prg_new_conditional:Npnn \xsim_if_exercise_exist:nn #1#2 {T,F,TF}
- {
- \xsim_if_exist:nnnTF {#1} {#2} {exercise}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_exercise_exist:nnT {VV}
-
-% #1: type
-% #2: options
-\cs_new_protected:Npn \xsim_start_exercise:nn #1#2
- {
- \xsim_if_insert_mode:F
- {
- \int_gincr:N \g_xsim_id_int
- \int_compare:nF { \g_xsim_max_id_int > \g_xsim_id_int }
- { \int_gset_eq:NN \g_xsim_max_id_int \g_xsim_id_int }
- \tl_gset:Nx \g_xsim_exercise_id_tl { \int_use:N \g_xsim_id_int }
- \tl_gset:Nn \g_xsim_exercise_type_tl {#1}
- % save the goal values from the auxiliary files:
- \xsim_foreach_goal:n
- {
- \xsim_temporary_goal_new:nVn {#1} \g_xsim_exercise_id_tl {##1}
- \xsim_if_property_set:nVnT {#1} \g_xsim_exercise_id_tl {##1}
- {
- \xsim_temporary_goal_set:nVnn
- {#1}
- \g_xsim_exercise_id_tl
- {##1}
- { \xsim_get_property:nVn {#1} \g_xsim_exercise_id_tl {##1} }
- }
- }
- \xsim_set_properties:nVx {#1} \g_xsim_exercise_id_tl
- {
- % preset options so the user doesn't has to:
- print = true ,
- use = true ,
- % options set by the user:
- \exp_not:n {#2} ,
- % options which need to have certain values:
- id = \g_xsim_exercise_id_tl ,
- section-value = \arabic{section} ,
- section = \thesection ,
- page-value = \arabic{page} ,
- sectioning =
- { \cs_if_exist:NTF \thechapter { \arabic {chapter} } {0} }
- { \arabic {section} }
- { \arabic {subsection} }
- { \arabic {subsubsection} }
- { \arabic {paragraph} } ,
- page = \thepage ,
- % this cannot yet be set (see below):
- used = false
- }
- % temporary goal now: either 0 or equal the complete property
- % property: equal to the given value
- \xsim_foreach_goal:n
- {
- \fp_set:Nn \l__xsim_tmpa_fp
- { \xsim_temporary_goal_get:nVn {#1} \g_xsim_exercise_id_tl {##1} }
- % set temporary goal to given property:
- \xsim_if_property_given:nTF {##1}
- {
- \xsim_temporary_goal_set:nVnn
- {#1}
- \g_xsim_exercise_id_tl
- {##1}
- { \xsim_get_property:nVn {#1} \g_xsim_exercise_id_tl {##1} }
- }
- {
- \xsim_temporary_goal_set:nVnn
- {#1}
- \g_xsim_exercise_id_tl
- {##1}
- {0}
- }
- % update to property to complete value:
- \xsim_if_property_set:nVnT {#1} \g_xsim_exercise_id_tl {##1}
- {
- \xsim_set_property:nVnx {#1} \g_xsim_exercise_id_tl {##1}
- { \fp_to_decimal:N \l__xsim_tmpa_fp }
- }
- }
- \xsim_if_property_exist:nT {chapter}
- {
- \xsim_set_properties:nVx {#1} \g_xsim_exercise_id_tl
- {
- chapter-value = \arabic{chapter} ,
- chapter = \thechapter
- }
- }
- \tl_set_eq:NN \ExerciseID \g_xsim_exercise_id_tl
- \tl_set:Nn \ExerciseType {#1}
- \xsim_verbose:x
- {
- Starting~ exercise~ type~ `#1' with~ id~
- ` \g_xsim_exercise_id_tl '.
- }
- \xsim_exercise_if_use:nVTF {#1} \g_xsim_exercise_id_tl
- {
- \stepcounter { \xsim_get_parameter:nn {#1} {number} }
- % don't step if in active collection:
- \xsim_if_collections_active:TF
- {
- \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl
- {print}
- {false}
- }
- {
- \xsim_step_exercise_counter:nV {#1} \g_xsim_exercise_id_tl
- \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl
- {used}
- {true}
- }
- \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl
- {use}
- {true}
- }
- {
- \xsim_set_properties:nVn {#1} \g_xsim_exercise_id_tl
- { use = false , print = false }
- }
- \xsim_update_collections:nV {#1} \g_xsim_exercise_id_tl
- }
- }
-
-\cs_new_protected:Npn \xsim_stop_exercise:n #1
- {
- \xsim_if_insert_mode:F
- { \tl_gset_eq:NN \g_xsim_exercise_id_tl \ExerciseID }
- }
-
-% ----------------------------------------------------------------------------
-% #1: type
-% #2: id
-\prg_new_protected_conditional:Npnn \xsim_exercise_if_print:nn #1#2 {T,F,TF}
- {
- \xsim_if_boolean_property:nnnTF {#1} {#2} {print!}
- { \prg_return_true: }
- {
- \bool_set_true:N \l____xsim_print_bool
- \bool_if:cF {l__xsim_#1_exercise_print_bool}
- { \bool_set_false:N \l____xsim_print_bool }
- \xsim_if_tagged:nnF {#1} {#2}
- { \bool_set_false:N \l____xsim_print_bool }
- \xsim_if_boolean_property:nnnF {#1} {#2} {print}
- { \bool_set_false:N \l____xsim_print_bool }
- \bool_if:NTF \l____xsim_print_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
- }
-\cs_generate_variant:Nn \xsim_exercise_if_print:nnT {nV}
-\cs_generate_variant:Nn \xsim_exercise_if_print:nnTF {nV}
-
-% #1: type
-% #2: id
-\prg_new_protected_conditional:Npnn \xsim_exercise_if_use:nn #1#2 {T,F,TF}
- {
- \xsim_if_boolean_property:nnnTF {#1} {#2} {use!}
- { \prg_return_true: }
- {
- \xsim_exercise_if_print:nnTF {#1} {#2}
- { \prg_return_true: }
- {
- \bool_if:cTF {l__xsim_#1_exercise_use_bool}
- {
- \xsim_if_boolean_property:nnnTF {#1} {#2} {use}
- {
- \xsim_if_tagged:nnTF {#1} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
-
- }
- }
-\cs_generate_variant:Nn \xsim_exercise_if_use:nnT {nV}
-\cs_generate_variant:Nn \xsim_exercise_if_use:nnTF {nV}
-
-% #1: type
-% #2: id
-% #3: exercise|solution
-\prg_new_protected_conditional:Npnn \xsim_if_print:nnn #1#2#3 {T,F,TF}
- {
- \use:c {xsim_#3_if_print:nnTF} {#1} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% ----------------------------------------------------------------------------
-
-\xsim_new_aux_property:cpn {total-number} #1
- { \int_gset:Nn \g_xsim_max_id_int {#1} }
-
-\RequirePackage {etoolbox}
-
-\AtEndPreamble
- {
- \xsim_foreach_exercise_type:n
- {
- \tl_new:c { number of #1 s }
- \tl_set:cn { number of #1 s } {0}
- \xsim_new_aux_property:cpn {#1} ##1
- { \tl_gset:cn { number of #1 s } {##1} }
- }
- }
-
-\xsim_at_begin_document:n
- {
- \xsim_foreach_exercise_type:n
- {
- \xsim_write_to_aux:x
- { \token_to_str:N \providecommand \token_to_str:N \numberof #1 s {} }
- }
- }
-
-\xsim_at_end_document:n
- {
- \xsim_if_clear_aux:T
- {
- \int_compare:nNnF { \g_xsim_max_id_int } = { \g_xsim_id_int }
- { \xsim_empty_lists: }
- }
- \xsim_add_property_to_aux:nn {total-number} { { \int_use:N \g_xsim_id_int } }
- \xsim_foreach_exercise_type:n
- {
- \xsim_add_property_to_aux:nn {#1}
- { { \arabic { \xsim_get_parameter:nn {#1} {number} } } }
- }
- \xsim_update_list:n {types}
- }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-
-2020/02/21 - implement issue #2
-2020/03/01 - add options `<ex-env>s/name` and `<sol-env>/name`
-2020/03/07 - set \ExerciseID and \ExerciseType only locally
-2020/03/14 - performance optimizations
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.goals.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.goals.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.goals.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,385 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - goals module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{goals}{counting of points and bonus points}
-
-\xsim_load_modules:n {properties,exercises}
-
-\msg_new:nnn {xsim} {goal-unknown}
- { The~ goal~ `#1'~ has~ never~ been~ declared~ \msg_line_context: }
-
-\seq_new:N \l__xsim_goals_seq
-\tl_new:N \l_xism_grading_table_template_tl
-\tl_new:N \l_xism_grading_table_exercise_type_tl
-
-% #1: name
-\cs_new_protected:Npn \xsim_declare_exercise_goal:n #1
- {
- \xsim_if_goal_exist:nF {#1}
- {
- \xsim_verbose:n { Declaring~ new~ goal~ `#1'. }
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_false_bool }
- { \c_false_bool }
- {#1}
- \seq_put_right:Nn \l__xsim_goals_seq {#1}
- \fp_gzero_new:c {g__xsim_goal_#1_fp}
- \bool_new:c {l__xsim_goal_#1_given_bool}
- \fp_gzero_new:c {l__xsim_current_goal_#1_fp}
- \fp_if_exist:cF {g__xsim_total_goal_#1_fp}
- { \fp_new:c {g__xsim_total_goal_#1_fp} }
- \fp_if_exist:cF {g__xsim_total_goal_recorded_#1_fp}
- { \fp_new:c {g__xsim_total_goal_recorded_#1_fp} }
- \xsim_at_begin_document:n
- {
- \xsim_foreach_exercise_type:n
- {
- \fp_gzero_new:c {g__xsim_##1_goal_#1_fp}
- \fp_if_exist:cF {g__xsim_total_##1_goal_#1_fp}
- { \fp_new:c {g__xsim_total_##1_goal_#1_fp} }
- }
- }
- }
- }
-
-\prg_new_conditional:Npnn \xsim_if_goal_exist:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_goals_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_goal_given:n #1 {p,T,F,TF}
- {
- \bool_if:cTF {l__xsim_goal_#1_given_bool}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\cs_new_protected:Npn \xsim_goal_given:n #1
- { \bool_set_true:c {l__xsim_goal_#1_given_bool} }
-
-% #1: exercise type
-% #2: id
-% #3: goal
-\cs_new_protected:Npn \xsim_update_goal:nnn #1#2#3
- {
- \xsim_if_goal_exist:nT {#3}
- {
- \fp_gadd:cn {g__xsim_goal_#3_fp}
- { \xsim_get_property:nnn {#1} {#2} {#3} + 0 }
- \fp_gadd:cn {g__xsim_#1_goal_#3_fp}
- { \xsim_get_property:nnn {#1} {#2} {#3} + 0 }
- }
- }
-
-% #1: exercise type
-% #2: id
-\cs_new_protected:Npn \xsim_update_goals:nn #1#2
- {
- \xsim_foreach_goal:n
- { \xsim_update_goal:nnn {#1} {#2} {##1} }
- }
-\cs_generate_variant:Nn \xsim_update_goals:nn {nV}
-
-\cs_new_protected:Npn \xsim_foreach_goal:n #1
- { \seq_map_inline:Nn \l__xsim_goals_seq {#1} }
-
-% #1: type
-% #2: id
-\cs_new_protected:Npn \xsim_synchronize_goals:nn #1#2
- {
- \xsim_foreach_goal:n
- {
- \xsim_if_property_set:nnnTF {#1} {#2} {##1}
- {
- \xsim_set_property:nnnx {#1} {#2} {##1}
- { \xsim_temporary_goal_get:nnn {#1} {#2} {##1} }
- }
- {
- \fp_compare:nNnT
- { \xsim_temporary_goal_get:nnn {#1} {#2} {##1} } > {0}
- {
- \xsim_set_property:nnnx {#1} {#2} {##1}
- { \xsim_temporary_goal_get:nnn {#1} {#2} {##1} }
- }
- }
- }
- }
-
-% #1: exercise type
-% #2: id
-% #3: goal
-% #4: value
-\cs_new_protected:Npn \xsim_addto_goal:nnnn #1#2#3#4
- {
- \xsim_if_goal_exist:nT {#3}
- {
- \xsim_verbose:n { Adding~ `#4'~ to~ `#3'~ goal~ of~ #1~ #2 }
- % \fp_gadd:cn {g__xsim_goal_#3_fp} {#4}
- % \fp_gadd:cn {g__xsim_#1_goal_#3_fp} {#4}
- % \fp_add:cn {l__xsim_current_goal_#3_fp} {#4}
- \xsim_temporary_goal_add:nnnn {#1} {#2} {#3} {#4}
- }
- }
-\cs_generate_variant:Nn \xsim_addto_goal:nnnn {xx,nVnx}
-
-% #1: exercise type
-% #2: id
-% #3: goal
-% #4: relation and value
-\prg_new_conditional:Npnn \xsim_if_goal_value:nnnn #1#2#3#4 {p,T,F,TF}
- {
- \fp_compare:nTF
- { (0 + \xsim_get_property:nnn {#1} {#2} {#3}) #4 }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_goal_value:nnnnTF {xx}
-
-% ----------------------------------------------------------------------------
-% we need some kind of temporary variable to be able to set goals both as
-% option to exercises and within the exercise body
-
-% #1: type
-% #2: id
-% #3: goal
-\cs_new_protected:Npn \xsim_temporary_goal_new:nnn #1#2#3
- { \fp_new:c {g__xsim_goal_#3_#1_#2_fp} }
-\cs_generate_variant:Nn \xsim_temporary_goal_new:nnn {nV}
-
-% #1: type
-% #2: id
-% #3: goal
-% #4: value
-\cs_new_protected:Npn \xsim_temporary_goal_set:nnnn #1#2#3#4
- { \fp_gset:cn {g__xsim_goal_#3_#1_#2_fp} {#4} }
-\cs_generate_variant:Nn \xsim_temporary_goal_set:nnnn {nV}
-
-% #1: type
-% #2: id
-% #3: goal
-% #4: value
-\cs_new_protected:Npn \xsim_temporary_goal_add:nnnn #1#2#3#4
- { \fp_gadd:cn {g__xsim_goal_#3_#1_#2_fp} {#4} }
-\cs_generate_variant:Nn \xsim_temporary_goal_add:nnnn {nV}
-
-% #1: type
-% #2: id
-% #3: goal
-\cs_new:Npn \xsim_temporary_goal_get:nnn #1#2#3
- { \fp_to_decimal:c {g__xsim_goal_#3_#1_#2_fp} }
-\cs_generate_variant:Nn \xsim_temporary_goal_get:nnn {nV}
-
-% #1: type
-% #2: id
-% #3: goal
-\cs_new_protected:Npn \__xsim_temporary_goal_show:nnn #1#2#3
- { \fp_show:c {g__xsim_goal_#3_#1_#2_fp} }
-
-% ----------------------------------------------------------------------------
-% a function which can be used to modify how the numbers of a goal are
-% printed:
-\cs_new_protected:Npn \__xsim_print_goal:n #1 {#1}
-\cs_generate_variant:Nn \__xsim_print_goal:n {x}
-
-% #1: value
-% #2: value == 1
-% #3: value != 1
-\cs_new_protected:Npn \xsim_print_goal:nnn #1#2#3
- {
- \__xsim_print_goal:x { \fp_to_decimal:n {#1} }
- \fp_compare:nTF { (#1) = 1 } {#2} {#3}
- }
-
-% #1: exercise type
-% #2: goal
-% #3: sum == 1
-% #4: sum != 1
-\cs_new_protected:Npn \xsim_print_goal_sum:nnnn #1#2#3#4
- { \xsim_print_goal:nnn { \use:c {g__xsim_total_#1_goal_#2_fp} } {#3} {#4} }
-
-% #1: goal
-% #2: sum == 1
-% #3: sum != 1
-\cs_new_protected:Npn \xsim_print_total_goal_sum:nnn #1#2#3
- { \xsim_print_goal:nnn { \use:c {g__xsim_total_goal_#1_fp} } {#2} {#3} }
-
-% ----------------------------------------------------------------------------
-% the same as the last to functions but for a list of goals:
-
-% #1: fp variable to be set
-% #2: list of goals (separated with +)
-% #3: function to be applied to goal names
-\cs_new_protected:Npn \__xsim_exercise_goals_sum_aux:Nnn #1#2#3
- {
- \seq_set_split:Nnn \l__xsim_tmpa_seq {+} {#2}
- \seq_set_map:NNn \l__xsim_tmpb_seq \l__xsim_tmpa_seq {#3}
- \fp_set:Nn #1 { \seq_use:Nn \l__xsim_tmpb_seq {+} }
- }
-
-% #1: fp variable
-% #2: exercise type
-% #3: list of goals (separated with +)
-\cs_new_protected:Npn \__xsim_exercise_goals_sum:Nnn #1#2#3
- {
- \__xsim_exercise_goals_sum_aux:Nnn #1 {#3}
- { \exp_not:c {g__xsim_total_#2_goal_ \tl_trim_spaces:n {##1} _fp} }
- }
-
-% #1: fp variable
-% #2: list of goals (separated with +)
-\cs_new_protected:Npn \__xsim_exercise_goals_sum:Nn #1#2
- {
- \__xsim_exercise_goals_sum_aux:Nnn #1 {#2}
- { \exp_not:c {g__xsim_total_goal_ \tl_trim_spaces:n {##1} _fp} }
- }
-
-% #1: exercise type
-% #2: list of goals (separated with +)
-% #3: sum == 1
-% #4: sum != 1
-\cs_new_protected:Npn \xsim_print_goals_sum:nnnn #1#2#3#4
- {
- \__xsim_exercise_goals_sum:Nnn \l__xsim_tmpa_fp {#1} {#2}
- \xsim_print_goal:nnn { \l__xsim_tmpa_fp } {#3} {#4}
- }
-
-% #1: list of goals (separated with +)
-% #2: sum == 1
-% #3: sum != 1
-\cs_new_protected:Npn \xsim_print_total_goals_sum:nnn #1#2#3
- {
- \__xsim_exercise_goals_sum:Nn \l__xsim_tmpa_fp {#1}
- \xsim_print_goal:nnn { \l__xsim_tmpa_fp } {#2} {#3}
- }
-
-% ----------------------------------------------------------------------------
-% #1: exercise type
-% #2: goal
-% #3: relation and value
-\prg_new_conditional:Npnn \xsim_if_goal_sum:nnn #1#2#3 {p,T,F,TF}
- {
- \fp_compare:nTF
- { ( \use:c {g__xsim_total_#1_goal_#2_fp} ) #3 }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: exercise type
-% #2: list of goals (separated with +)
-% #3: relation and value
-\prg_new_protected_conditional:Npnn \xsim_if_goals_sum:nnn #1#2#3 {T,F,TF}
- {
- \__xsim_exercise_goals_sum:Nnn \l__xsim_tmpa_fp {#1} {#2}
- \fp_compare:nTF
- { ( \l__xsim_tmpa_fp ) #3 }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: goal
-% #2: relation and value
-\prg_new_conditional:Npnn \xsim_if_total_goal_sum:nn #1#2 {p,T,F,TF}
- {
- \fp_compare:nTF
- { ( \use:c {g__xsim_total_goal_#1_fp} ) #2 }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: list of goals (separated with +)
-% #2: relation and value
-\prg_new_protected_conditional:Npnn \xsim_if_total_goals_sum:nn #1#2 {T,F,TF}
- {
- \__xsim_exercise_goals_sum:Nn \l__xsim_tmpa_fp {#1}
- \fp_compare:nTF
- { ( \l__xsim_tmpa_fp ) #2 }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% ----------------------------------------------------------------------------
-% #1: exercise type
-% #2: goal
-% #3: value
-\xsim_new_aux_property:cpn {goal} #1#2#3
- { \fp_gset:cn {g__xsim_total_#1_goal_#2_fp} {#3} }
-
-% #1: goal
-% #2: value
-\xsim_new_aux_property:cpn {totalgoal} #1#2
- { \fp_gset:cn {g__xsim_total_goal_#1_fp} {#2} }
-
-\xsim_at_begin_document:n
- {
- \seq_map_inline:Nn \l__xsim_goals_seq
- {
- \fp_gset_eq:cc
- {g__xsim_total_goal_recorded_#1_fp}
- {g__xsim_total_goal_#1_fp}
- }
- }
-
-\xsim_at_end_document:n
- {
- \seq_map_inline:Nn \l__xsim_goals_seq
- {
- \xsim_foreach_exercise_type:n
- {
- \xsim_add_property_to_aux:nn {goal}
- { {##1} {#1} { \fp_to_decimal:c {g__xsim_##1_goal_#1_fp} } }
- }
- \tl_set:Nx \l__xsim_tmpa_tl
- { \fp_to_decimal:c {g__xsim_total_goal_#1_fp} }
- \tl_set:Nx \l__xsim_tmpb_tl
- { \fp_to_decimal:c {g__xsim_total_goal_recorded_#1_fp} }
- \tl_if_eq:NNF \l__xsim_tmpa_tl \l__xsim_tmpb_tl { \xsim_rerun: }
- \xsim_add_property_to_aux:nn {totalgoal}
- { {#1} { \fp_to_decimal:c {g__xsim_goal_#1_fp} } }
- }
- }
-
-% ----------------------------------------------------------------------------
-
-\keys_define:nn {xsim}
- {
- goal-print .code:n =
- \cs_set_protected:Npn \__xsim_print_goal:n ##1 {#1} ,
- grading-table/template .tl_set:N = \l_xism_grading_table_template_tl ,
- grading-table/template .initial:n = default ,
- grading-table/type .tl_set:N = \l_xism_grading_table_exercise_type_tl ,
- grading-table/type .initial:n =
- }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-
-2019/01/30 - bug fix (cf. https://texwelt.de/wissen/fragen/24101/)
-2020/02/20 - add temporary variables for the whole subpoint thing
- (cf. issue #2)
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.grades.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.grades.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.grades.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,153 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - grades module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{grades}{distribute goal sums to grades}
-
-\xsim_load_modules:n {goals}
-
-\msg_new:nnn {xsim} {grade-unknown}
- { The~ grade~ `#1'~ has~ never~ been~ declared~ \msg_line_context: }
-
-\bool_new:N \l__xsim_grades_half_bool
-\fp_new:N \l__xsim_grade_round_fp
-\fp_zero:N \l__xsim_grade_round_fp
-\prop_new:N \l__xsim_relative_grades_prop
-\tl_new:N \l__xsim_grade_split_tl
-
-\cs_new:Npn \__xsim_fp_round_to_half:n #1
- { round( 2*(#1),0)/2 }
-
-\cs_new:Npn \__xsim_grades_round:n #1
- { round ( #1 , \l__xsim_grade_round_fp ) }
-
-% #1: factor
-% #2: goal sum
-\cs_new:Npn \__xsim_grade_rounded:nn #1#2
- {
- \bool_if:NTF \l__xsim_grades_half_bool
- { \__xsim_fp_round_to_half:n }
- { \__xsim_grades_round:n }
- { (#1) * (#2) }
- }
-
-\cs_new_protected:Npn \xsim_declare_relative_grades:n #1
- {
- \seq_set_split:NVn \l__xsim_tmpa_seq \l__xsim_grade_split_tl {#1}
- \seq_map_inline:Nn \l__xsim_tmpa_seq
- { \__xsim_declare_relative_grade:w ##1 \q_stop }
- \xsim_verbose:n {Declaring~ relative~ grade~ distribution}
- }
-
-\cs_new_protected:Npn \__xsim_declare_relative_grade:w #1 = #2 \q_stop
- {
- \tl_set:Nx \l__xsim_tmpa_tl { \tl_trim_spaces:n {#1} }
- \tl_set:Nx \l__xsim_tmpb_tl { \tl_trim_spaces:n {#2} }
- \prop_put:NVV \l__xsim_relative_grades_prop
- \l__xsim_tmpa_tl
- \l__xsim_tmpb_tl
- }
-
-% #1: grade
-% #2: sum of points
-% #3: code after grade requirement if == 1
-% #4: code after grade requirement if != 1
-\cs_new_protected:Npn \xsim_get_grade:nnnn #1#2#3#4
- {
- \prop_get:NnNTF \l__xsim_relative_grades_prop {#1} \l__xsim_tmpa_tl
- {
- \xsim_print_goal:nnn
- {
- min(
- \__xsim_grade_rounded:nn
- { \l__xsim_tmpa_tl }
- {#2} ,
- #2
- )
- }
- {#3}
- {#4}
- }
- { \msg_error:nnn {xsim} {grade-unknown} {#1} }
- }
-
-% #1: grade
-% #2: goal
-% #3: code after grade requirement if == 1
-% #4: code after grade requirement if != 1
-\cs_new_protected:Npn \xsim_get_grade_goal:nnnn #1#2#3#4
- {
- \xsim_if_goal_exist:nTF {#2}
- {
- \xsim_get_grade:nnnn
- {#1}
- { \use:c {g__xsim_total_goal_#2_fp} }
- {#3}
- {#4}
- }
- { \msg_error:nnn {xsim} {goal-unknown} {#2} }
- }
-
-% #1: grade
-% #2: goal list (separated with +)
-% #3: code after grade requirement if == 1
-% #4: code after grade requirement if != 1
-\cs_new_protected:Npn \xsim_get_grade_requirement:nnnn #1#2#3#4
- {
- \seq_set_split:Nnn \l__xsim_tmpa_seq {+} {#2}
- \fp_zero:N \l__xsim_tmpa_fp
- \seq_map_inline:Nn \l__xsim_tmpa_seq
- {
- \fp_add:Nn \l__xsim_tmpa_fp
- { \use:c {g__xsim_total_goal_\tl_trim_spaces:n {##1} _fp} }
- }
- \xsim_get_grade:nnnn {#1} { \l__xsim_tmpa_fp } {#3} {#4}
- }
-
-% #1: grade
-% #2: code after grade requirement if == 1
-% #3: code after grade requirement if != 1
-\cs_new_protected:Npn \xsim_get_absolute_grade_requirement:nnn #1#2#3
- {
- \fp_zero:N \l__xsim_tmpa_fp
- \xsim_foreach_goal:n
- {
- \fp_add:Nn \l__xsim_tmpa_fp
- { \use:c {g__xsim_total_goal_##1_fp} }
- }
- \xsim_get_grade:nnnn {#1} { \l__xsim_tmpa_fp } {#2} {#3}
- }
-
-\keys_define:nn {xsim/grades}
- {
- round .fp_set:N = \l__xsim_grade_round_fp ,
- half .bool_set:N = \l__xsim_grades_half_bool ,
- split .tl_set:N = \l__xsim_grade_split_tl ,
- split .initial:n = {,}
- }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.interface.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.interface.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.interface.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,696 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - interface module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{interface}{user interface}
-
-\NewDocumentCommand \DeclareExerciseEnvironmentTemplate {m+m+m}
- { \xsim_declare_environment_template:nnn {#1} {#2} {#3} }
-\@onlypreamble \DeclareExerciseEnvironmentTemplate
-
-\NewDocumentCommand \DeclareExerciseHeadingTemplate {m+m}
- { \xsim_declare_heading_template:nn {#1} {#2} }
-\@onlypreamble \DeclareExerciseHeadingTemplate
-
-\NewDocumentCommand \DeclareExerciseTableTemplate {m+m}
- { \xsim_declare_table_template:nn {#1} {#2} }
-\@onlypreamble \DeclareExerciseTableTemplate
-
-\NewDocumentCommand \UseExerciseTemplate {mm}
- { \xsim_use_template:nn {#1} {#2} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseType {mm}
- { \xsim_declare_exercise_type:nn {#1} {#2} }
-\@onlypreamble \DeclareExerciseType
-
-\NewExpandableDocumentCommand \numberofusedexercises {}
- { \int_use:N \g_xsim_max_id_int }
-
-% ----------------------------------------------------------------------------
-
-\ProvideDocumentCommand \IfExistSolutionTF {+m+m}
- { \xsim_if_solution_exist:ooTF {\ExerciseType} {\ExerciseID} {#1} {#2} }
-
-\NewDocumentCommand \IfExistSolutionT {+m}
- { \IfExistSolutionTF {#1} {} }
-
-\NewDocumentCommand \IfExistSolutionF {+m}
- { \IfExistSolutionTF {} {#1} }
-
-\NewExpandableDocumentCommand \IfInsideSolutionTF {+m+m}
- { \xsim_if_inside_solution:TF {#1} {#2} }
-
-\NewExpandableDocumentCommand \IfInsideSolutionT {+m}
- { \IfInsideSolutionTF {#1} {} }
-
-\NewExpandableDocumentCommand \IfInsideSolutionF {+m}
- { \IfInsideSolutionTF {} {#1} }
-
-\NewExpandableDocumentCommand \IfSolutionPrintTF {+m+m}
- { \xsim_if_solution_print:nTF {\ExerciseType} {#1} {#2} }
-
-\NewExpandableDocumentCommand \IfSolutionPrintT {+m}
- { \IfSolutionPrintTF {#1} {} }
-
-\NewExpandableDocumentCommand \IfSolutionPrintF {+m}
- { \IfSolutionPrintTF {} {#1} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseProperty {t!st-m}
- {
- \IfBooleanTF {#2}
- {
- \IfBooleanTF {#3}
- {
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_true_bool }
- { \c_true_bool }
- {#4}
- }
- {
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_true_bool }
- { \c_false_bool }
- {#4}
- }
- }
- {
- \IfBooleanTF {#1}
- {
- \IfBooleanTF {#3}
- {
- \xsim_declare_property:nnnn
- { \c_true_bool }
- { \c_false_bool }
- { \c_true_bool }
- {#4}
- }
- {
- \xsim_declare_property:nnnn
- { \c_true_bool }
- { \c_false_bool }
- { \c_false_bool }
- {#4}
- }
- }
- {
- \IfBooleanTF {#3}
- {
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_false_bool }
- { \c_true_bool }
- {#4}
- }
- {
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_false_bool }
- { \c_false_bool }
- {#4}
- }
- }
- }
- }
-\@onlypreamble \DeclareExerciseProperty
-
-\NewDocumentCommand \DeclareExercisePropertyAlias {mm}
- { \xsim_make_property_alias:nn {#1} {#2} }
-\@onlypreamble \DeclareExercisePropertyAlias
-
-\NewDocumentCommand \SetExerciseProperty {m+m}
- { \xsim_set_property:xxnn {\ExerciseType} {\ExerciseID} {#1} {#2} }
-
-\NewDocumentCommand \SetExpandedExerciseProperty {m+m}
- { \xsim_set_property:xxnx {\ExerciseType} {\ExerciseID} {#1} {#2} }
-
-\NewDocumentCommand \ExerciseSetProperty {mmm+m}
- { \xsim_set_property:nnnn {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \ExerciseSetExpandedProperty {mmm+m}
- { \xsim_set_property:nnnx {#1} {#2} {#3} {#4} }
-
-\NewExpandableDocumentCommand \IfExercisePropertyExistTF {+m+m+m}
- { \xsim_if_property_exist:nTF {#1} {#2} {#3} }
-
-\NewExpandableDocumentCommand \IfExercisePropertyExistT {+m+m}
- { \IfExercisePropertyExistTF {#1} {#2} {} }
-
-\NewExpandableDocumentCommand \IfExercisePropertyExistF {+m+m}
- { \IfExercisePropertyExistTF {#1} {} {#2} }
-
-\NewDocumentCommand \IfExercisePropertySetTF {m+m+m}
- { \xsim_if_property_set:xxnTF {\ExerciseType} {\ExerciseID} {#1} {#2} {#3} }
-
-\NewDocumentCommand \IfExercisePropertySetT {m+m}
- { \IfExercisePropertySetTF {#1} {#2} {} }
-
-\NewDocumentCommand \IfExercisePropertySetF {m+m}
- { \IfExercisePropertySetTF {#1} {} {#2} }
-
-\NewExpandableDocumentCommand \GetExerciseProperty {m}
- { \xsim_get_property:oon {\ExerciseType} {\ExerciseID} {#1} }
-
-\NewExpandableDocumentCommand \GetExerciseAliasProperty {m}
- {
- \xsim_get_property:oof
- {\ExerciseType}
- {\ExerciseID}
- { \xsim_property_alias:n {#1} }
- }
-
-\NewDocumentCommand \GetExercisePropertyTF {m+m+m}
- {
- \xsim_get_property_if_set:oonTF {\ExerciseType} {\ExerciseID} {#1}
- {#2}
- {#3}
- }
-
-\NewDocumentCommand \GetExercisePropertyT {m+m}
- { \GetExercisePropertyTF {#1} {#2} {} }
-\NewDocumentCommand \GetExercisePropertyF {m+m+m}
- { \GetExercisePropertyTF {#1} {} {#2} }
-
-\NewExpandableDocumentCommand \GetExerciseIdForProperty {mm}
- { \xsim_get_id_for_property:nn {#1} {#2} }
-
-\NewExpandableDocumentCommand \GetExerciseTypeForProperty {mm}
- { \xsim_get_type_for_property:nn {#1} {#2} }
-
-\NewExpandableDocumentCommand \IfExerciseBooleanPropertyTF {+m+m+m}
- {
- \xsim_if_boolean_property:oonTF {\ExerciseType} {\ExerciseID} {#1}
- {#2}
- {#3}
- }
-
-\NewExpandableDocumentCommand \IfExerciseBooleanPropertyT {+m+m}
- { \IfExerciseBooleanPropertyTF {#1} {#2} {} }
-\NewExpandableDocumentCommand \IfExerciseBooleanPropertyF {+m+m}
- { \IfExerciseBooleanPropertyTF {#1} {} {#2} }
-
-\NewDocumentCommand \SaveExerciseProperty {mm}
- { \xsim_save_property:xxnN {\ExerciseType} {\ExerciseID} {#1} #2 }
-
-\NewDocumentCommand \GlobalSaveExerciseProperty {mm}
- { \xsim_gsave_property:xxnN {\ExerciseType} {\ExerciseID} {#1} #2 }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseParameter {st!m}
- {
- \IfBooleanTF {#1} % fixed
- {
- \IfBooleanTF {#2} % mandatory
- { \xsim_declare_parameter:nnn {true} {true} {#3} }
- { \xsim_declare_parameter:nnn {true} {false} {#3} }
- }
- {
- \IfBooleanTF {#2} % mandatory
- { \xsim_declare_parameter:nnn {false} {true} {#3} }
- { \xsim_declare_parameter:nnn {false} {false} {#3} }
- }
- }
-
-\NewExpandableDocumentCommand \GetExerciseParameter {m}
- { \xsim_get_parameter:on {\ExerciseType} {#1} }
-
-\NewDocumentCommand \SetExerciseParameter {mmm}
- { \xsim_set_parameter:nnn {#1} {#2} {#3} }
-
-\NewDocumentCommand \SetExerciseParameters {mm}
- { \xsim_set_parameters:nn {#1} {#2} }
-
-\NewExpandableDocumentCommand \GetExerciseName {}
- {
- \IfInsideSolutionTF
- { \GetExerciseParameter {solution-name} }
- { \GetExerciseParameter {exercise-name} }
- }
-
-\NewExpandableDocumentCommand \GetExerciseHeadingF {m}
- {
- \IfInsideSolutionTF
- {
- \IfExerciseParameterSetTF {solution-heading}
- { \GetExerciseParameter {solution-heading} }
- {#1}
- }
- {
- \IfExerciseParameterSetTF {exercise-heading}
- { \GetExerciseParameter {exercise-heading} }
- {#1}
- }
- }
-
-\NewDocumentCommand \GetExerciseBody {m}
- { \xsim_input:oon { \ExerciseType } { \ExerciseID } {#1} }
-
-\NewExpandableDocumentCommand \IfExerciseParameterSetTF {+m+m+m}
- { \xsim_if_parameter_set:nnTF {\ExerciseType} {#1} {#2} {#3} }
-
-\NewExpandableDocumentCommand \IfExerciseParameterSetT {+m+m}
- { \IfExerciseParameterSetTF {#1} {#2} {} }
-
-\NewExpandableDocumentCommand \IfExerciseParameterSetF {+m+m}
- { \IfExerciseParameterSetTF {#1} {} {#2} }
-
-\NewExpandableDocumentCommand \ExerciseParameterIfSetTF {+m+m+m+m}
- { \xsim_if_parameter_set:nnTF {#1} {#2} {#3} {#4} }
-
-\NewExpandableDocumentCommand \ExerciseParameterIfSetT {+m+m+m}
- { \ExerciseParameterIfSetTF {#1} {#2} {#3} {} }
-
-\NewExpandableDocumentCommand \ExerciseParameterIfSetF {+m+m+m}
- { \ExerciseParameterIfSetTF {#1} {#2} {} {#3} }
-
-\NewDocumentCommand \GetExerciseParameterTF {m+m+m}
- { \xsim_get_parameter_if_set:onTF {\ExerciseType} {#1} {#2} {#3} }
-
-\NewDocumentCommand \GetExerciseParameterT {m+m}
- { \GetExerciseParameterTF {#1} {#2} {} }
-
-\NewDocumentCommand \GetExerciseParameterF {m+m+m}
- { \GetExerciseParameterTF {#1} {} {#2} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \ExercisePropertyIfSetTF {mmm+m+m}
- { \xsim_if_property_set:nnnTF {#1} {#2} {#3} {#4} {#5} }
-
-\NewDocumentCommand \ExercisePropertyIfSetT {mmm+m}
- { \ExercisePropertyIfSetTF {#1} {#2} {#3} {#4} {} }
-
-\NewDocumentCommand \ExercisePropertyIfSetF {mmm+m}
- { \ExercisePropertyIfSetTF {#1} {#2} {#3} {} {#4} }
-
-\NewExpandableDocumentCommand \ExercisePropertyGet {mmm}
- { \xsim_get_property:nnn {#1} {#2} {#3} }
-
-\NewExpandableDocumentCommand \ExercisePropertyGetAlias {mm}
- { \xsim_get_property:nnf {#1} {#2} { \xsim_property_alias:n {#1} } }
-
-\NewDocumentCommand \ExercisePropertySave {mmmm}
- { \xsim_save_property:nnnN {#1} {#2} {#3} #4 }
-
-\NewDocumentCommand \ExercisePropertyGlobalSave {mmmm}
- { \xsim_gsave_property:nnnN {#1} {#2} {#3} #4 }
-
-\NewExpandableDocumentCommand \ExerciseParameterGet {mm}
- { \xsim_get_parameter:nn {#1} {#2} }
-
-% ----------------------------------------------------------------------------
-
-\NewExpandableDocumentCommand \XSIMtranslate {m}
- { \xsim_translate:n {#1} }
-
-\NewExpandableDocumentCommand \XSIMexpandcode {+m}
- { \use:e {#1} }
-
-\NewExpandableDocumentCommand \XSIMmixedcase {m}
- { \tl_mixed_case:f {#1} }
-
-\NewDocumentCommand \XSIMputright {mm}
- { \tl_put_right:Nn #1 {#2} }
-
-\NewExpandableDocumentCommand \XSIMifeqTF {+m+m+m+m}
- { \tl_if_eq:ffTF {#1} {#2} {#3} {#4} }
-
-\NewExpandableDocumentCommand \XSIMifeqT {+m+m+m}
- { \XSIMifeqTF {#1} {#2} {#3} {} }
-
-\NewExpandableDocumentCommand \XSIMifeqF {+m+m+m}
- { \XSIMifeqTF {#1} {#2} {} {#3} }
-
-\NewExpandableDocumentCommand \XSIMifblankTF {+m+m+m}
- { \tl_if_blank:fTF {#1} {#2} {#3} }
-
-\NewExpandableDocumentCommand \XSIMifblankT {+m+m}
- { \XSIMifblankTF {#1} {#2} {} }
-
-\NewExpandableDocumentCommand \XSIMifblankF {+m+m}
- { \XSIMifblankTF {#1} {} {#2} {} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseGoal {m}
- { \xsim_declare_exercise_goal:n {#1} }
-\@onlypreamble \DeclareExerciseGoal
-
-\NewDocumentCommand \IfExerciseGoalTF {mm+m+m}
- {
- \xsim_if_goal_value:xxnnTF
- {\ExerciseType} {\ExerciseID} {#1}
- {#2}
- {#3} {#4}
- }
-
-\NewDocumentCommand \IfExerciseGoalT {mm+m}
- { \IfExerciseGoalTF {#1} {#2} {#3} {} }
-
-\NewDocumentCommand \IfExerciseGoalF {mm+m}
- { \IfExerciseGoalTF {#1} {#2} {} {#3} }
-
-\NewDocumentCommand \IfExerciseGoalSingularTF {mmm}
- { \IfExerciseGoalTF {#1} {=1} {#2} {#3} }
-
-\NewDocumentCommand \IfExerciseGoalSingularT {mm}
- { \IfExerciseGoalT {#1} {=1} {#2} }
-
-\NewDocumentCommand \IfExerciseGoalSingularF {mm}
- { \IfExerciseGoalF {#1} {=1} {#2} }
-
-\NewDocumentCommand \IfExerciseTypeGoalsSumTF {mmm+m+m}
- { \xsim_if_goals_sum:nnnTF {#1} {#2} {#3} {#4} {#5} }
-
-\NewDocumentCommand \IfExerciseTypeGoalsSumT {mmm+m}
- { \IfExerciseTypeGoalsSumTF {#1} {#2} {#3} {#4} {} }
-
-\NewDocumentCommand \IfExerciseTypeGoalsSumF {mmm+m}
- { \IfExerciseTypeGoalsSumTF {#1} {#2} {#3} {} {#4} }
-
-\NewDocumentCommand \IfExerciseGoalsSumTF {mm+m+m}
- { \xsim_if_total_goals_sum:nnTF {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \IfExerciseGoalsSumT {mm+m}
- { \IfExerciseGoalsSumTF {#1} {#2} {#3} {} }
-
-\NewDocumentCommand \IfExerciseGoalsSumF {mm+m}
- { \IfExerciseGoalsSumTF {#1} {#2} {} {#3} }
-
-\NewDocumentCommand \TotalExerciseTypeGoal {mmmm}
- { \xsim_print_goal_sum:nnnn {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \TotalExerciseTypeGoals {mmmm}
- { \xsim_print_goals_sum:nnnn {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \TotalExerciseGoal {mmm}
- { \xsim_print_total_goal_sum:nnn {#1} {#2} {#3} }
-
-\NewDocumentCommand \TotalExerciseGoals {mmm}
- { \xsim_print_total_goals_sum:nnn {#1} {#2} {#3} }
-
-\NewDocumentCommand \AddtoExerciseTypeGoal {mmmm}
- { \xsim_addto_goal:nnnn {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \AddtoExerciseGoal {mm}
- { \xsim_addto_goal:xxnn {\ExerciseType} {\ExerciseID} {#1} {#2} }
-
-\NewDocumentCommand \ExerciseGoalValuePrint {mmm}
- { \xsim_print_goal:nnn {#1} {#2} {#3} }
-
-\NewDocumentCommand \AddtoExerciseTypeGoalPrint {mmmmmm}
- {
- \xsim_addto_goal:nnnn {#1} {#2} {#3} {#4}
- \xsim_print_goal:nnn {#4} {#5} {#6}
- }
-
-\NewDocumentCommand \AddtoExerciseGoalPrint {mmmm}
- {
- \xsim_addto_goal:xxnn {\ExerciseType} {\ExerciseID} {#1} {#2}
- \xsim_print_goal:nnn {#2} {#3} {#4}
- }
-
-% ----------------------------------------------------------------------------
-\NewDocumentCommand \DeclareGradeDistribution {m}
- { \xsim_declare_relative_grades:n {#1} }
-
-\NewDocumentCommand \GetGradeRequirementForGoal {mmmm}
- { \xsim_get_grade_goal:nnnn {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \GetGradeRequirementForGoals {mmmm}
- { \xsim_get_grade_requirement:nnnn {#1} {#2} {#3} {#4} }
-
-\NewDocumentCommand \GetGradeRequirement {mmm}
- { \xsim_get_absolute_grade_requirement:nnn {#1} {#2} {#3} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseTagging {m}
- { \xsim_new_tag_type:n {#1} }
-\@onlypreamble \DeclareExerciseTagging
-
-\NewDocumentCommand \ProvideExerciseTagging {m}
- {
- \xsim_if_tag_type_exist:nTF {#1}
- { \msg_warning:nnn {xsim} {tag-exists} {#1} }
- { \xsim_new_tag_type:n {#1} }
- }
-
-\NewDocumentCommand \ForEachExerciseTag {m+m}
- { \xsim_foreach_exercise_tag:oonn {\ExerciseType} {\ExerciseID} {#1} {#2} }
-
-\NewDocumentCommand \ListExerciseTags {mm}
- { \xsim_exercise_tags_use:oonn {\ExerciseType} {\ExerciseID} {#1} {#2} }
-
-\NewDocumentCommand \UseExerciseTags {mmmm}
- {
- \xsim_exercise_tags_use:oonnnn
- {\ExerciseType}
- {\ExerciseID}
- {#1}
- {#2}
- {#3}
- {#4}
- }
-
-\NewDocumentCommand \IfExerciseTagSetTF {m+m+m}
- { \xsim_if_tags_value:nTF {#1} {#2} {#3} }
-\NewDocumentCommand \IfExerciseTagSetT {m+m}
- { \xsim_if_tags_value:nT {#1} {#2} }
-\NewDocumentCommand \IfExerciseTagSetF {m+m}
- { \xsim_if_tags_value:nF {#1} {#2} }
-
-\NewDocumentCommand \IfExerciseTopicSetTF {m+m+m}
- { \xsim_if_topic_value:nTF {#1} {#2} {#3} }
-\NewDocumentCommand \IfExerciseTopicSetT {m+m}
- { \xsim_if_topic_value:nT {#1} {#2} }
-\NewDocumentCommand \IfExerciseTopicSetF {m+m}
- { \xsim_if_topic_value:nF {#1} {#2} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \XSIMatbegindocument {+m}
- { \xsim_at_begin_document:n {#1} }
-
-\NewDocumentCommand \XSIMatenddocument {+m}
- { \xsim_at_end_document:n {#1} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \ForEachPrintedExerciseByType {+m}
- { \xsim_foreach_exercise_type_id:nn {print} {#1} }
-
-\NewDocumentCommand \ForEachPrintedExerciseByID {+m}
- { \xsim_foreach_exercise_id_type:nn {print} {#1} }
-
-\NewDocumentCommand \ForEachUsedExerciseByType {+m}
- { \xsim_foreach_exercise_type_id:nn {used} {#1} }
-
-\NewDocumentCommand \ForEachUsedExerciseByID {+m}
- { \xsim_foreach_exercise_id_type:nn {used} {#1} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseTranslations {mm}
- { \xsim_declare_translations:nn {#1} {#2} }
-\@onlypreamble \DeclareExerciseTranslations
-
-\NewDocumentCommand \DeclareExerciseTranslation {mmm}
- { \xsim_declare_translation:nnn {#1} {#2} {#3} }
-\@onlypreamble \DeclareExerciseTranslation
-
-\NewDocumentCommand \ForEachExerciseTranslation {+m}
- { \xsim_for_all_translations_do:n {#1} }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \DeclareExerciseCollection {m}
- { \xsim_new_collection:n {#1} }
-\@onlypreamble \DeclareExerciseCollection
-
-\NewDocumentCommand \collectexercisestype {mm}
- { \xsim_start_collection:nn {#1} {#2} }
-
-\NewDocumentCommand \collectexercises {m}
- { \xsim_start_collection:n {#1} }
-
-\NewDocumentCommand \collectexercisesstop {m}
- { \xsim_stop_collection:n {#1} }
-
-\NewDocumentCommand \printcollection {O{}m}
- { \xsim_print_collection:nn {#1} {#2} }
-
-\NewDocumentCommand \printrandomexercises {O{}m}
- {
- \group_begin:
- \keys_set:nn {xsim/random} {#1}
- \xsim_print_random_list:VnN
- \l_xsim_random_collection_tl
- {#2}
- \l_xsim_random_exclude_list_clist
- \group_end:
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \blank {som}
- {
- \group_begin:
- \IfNoValueF {#2} { \keys_set:nn {xsim/blank} {#2} }
- \mode_if_vertical:TF
- {
- \IfBooleanTF {#1}
- { \xsim_blank:n {#3} }
- {
- \bool_if:NT \l__xsim_blank_linespread_bool
- { \linespread { \l__xsim_blank_linespread_tl } \selectfont }
- \noindent \null \xsim_blank:n {#3} \par
- }
- }
- { \xsim_blank:n {#3} }
- \group_end:
- }
-
-\NewDocumentCommand \examspace { sm }
- {
- \IfBooleanTF {#1}
- { \xsim_examspace:nn { \c_true_bool } {#2} }
- { \xsim_examspace:nn { \c_false_bool } {#2} }
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \gradingtable {O{}}
- {
- \group_begin:
- \keys_set:nn {xsim/grading-table} {#1}
- \xsim_setup_template:nVn {table} \l_xism_grading_table_template_tl
- {
- \providecommand* \ExerciseTableCode {}
- \providecommand* \ExerciseTableType [1] {}
- \providecommand* \ExerciseType {}
- \tl_set_eq:NN \ExerciseType \l_xism_grading_table_exercise_type_tl
- \renewcommand* \ExerciseTableCode {}
- \renewcommand* \ExerciseTableType [1]
- { \XSIMifblankTF { \ExerciseType } {##1} { \ExerciseType } }
- }
- \xsim_use_template:nV {table} \l_xism_grading_table_template_tl
- \group_end:
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \XSIMprint {mO{}mm}
- { \xsim_insert:nenn {#3} { \xsim_normalize_id:n {#4} } {#2} {#1} }
-
-\NewDocumentCommand \XSIMxprint {mO{}mm}
- { \xsim_insert:xxnn {#3} { \xsim_normalize_id:e {#4} } {#2} {#1} }
-
-\NewDocumentCommand \printexercise {O{}mm}
- {
- \clist_map_inline:nn {#3}
- { \xsim_insert:nenn {#2} { \xsim_normalize_id:n {##1} } {#1} {exercise} }
- }
-
-\NewDocumentCommand \xprintexercise {O{}mm}
- {
- \clist_map_inline:nn {#3}
- { \xsim_insert:xxnn {#2} { \xsim_normalize_id:e {##1} } {#1} {exercise} }
- }
-
-\NewDocumentCommand \printsolution {O{}mm}
- {
- \clist_map_inline:nn {#3}
- { \xsim_insert:nenn {#2} { \xsim_normalize_id:n {##1} } {#1} {solution} }
- }
-
-\NewDocumentCommand \xprintsolution {O{}mm}
- {
- \clist_map_inline:nn {#3}
- { \xsim_insert:xxnn {#2} { \xsim_normalize_id:e {##1} } {#1} {solution} }
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \printsolutionstype {sO{}m}
- {
- \IfBooleanTF {#1}
- { \xsim_print_type_solutions:nnn { \c_true_bool } {#2} {#3} }
- { \xsim_print_type_solutions:nnn { \c_false_bool } {#2} {#3} }
- }
-
-\NewDocumentCommand \printsolutions {sO{}}
- {
- \IfBooleanTF {#1}
- { \xsim_print_all_solutions_per_type:nn { \c_true_bool } {#2} }
- { \xsim_print_all_solutions_per_type:nn { \c_false_bool } {#2} }
- }
-
-\NewDocumentCommand \printallsolutions {sO{}}
- {
- \IfBooleanTF {#1}
- { \xsim_print_all_solutions_per_id:nn { \c_true_bool } {#2} }
- { \xsim_print_all_solutions_per_id:nn { \c_false_bool } {#2} }
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \printforexercises {sO{}+mO{}}
- {
- \IfBooleanTF {#1}
- {
- \xsim_foreach_exercise_type:n
- { \xsim_print_type_code:nnnnn { \c_true_bool } {#2} {#4} {##1} {#3} }
- }
- {
- \xsim_foreach_exercise_type:n
- { \xsim_print_type_code:nnnnn { \c_false_bool } {#2} {#4} {##1} {#3} }
- }
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \xsimsetup {+m}
- { \xsim_setup:n {#1} }
-
-% ----------------------------------------------------------------------------
-\NewExpandableDocumentCommand \XSIMifchapterTF {+m+m}
- { \xsim_if_chapter:TF {#1} {#2} }
-
-\NewExpandableDocumentCommand \XSIMifchapterT {+m}
- { \xsim_if_chapter:T {#1} }
-
-\NewExpandableDocumentCommand \XSIMifchapterF {+m}
- { \xsim_if_chapter:F {#1} }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.modules.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.modules.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.modules.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,220 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - modules module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-%
-% this is a pseudo module as it does the actual definitions for the whole
-% module loading stuff; we do this so both packages `xsimverb' and `xsim' can
-% use the `verbwrite' module
-\RequirePackage{scrlfile}
-\ExplSyntaxOn
-
-\msg_new:nnn {xsim} {module-missing}
- {
- You've~ requested~ the~ xsim~ module~ `#1'~ but~ it~ appears~ to~
- be~ missing~ on~ your~ system.~ Maybe~ you've~ misspelled~ the~ name?~
- Loading~ the~ module~ will~ abort~ \msg_line_context:
- }
-
-\msg_new:nnn {xsim} {loading-module}
- { Loading~ module~ `#1'~ ... }
-
-\msg_new:nnn {xsim} {wrong-module-name}
- { The~ module~ file~ name~ is~ `#2'~ but~ it~ provides~ module~ `#1'. }
-
-\msg_new:nnn {xsim} {forbidden-module}
- {
- You've~ requested~ the~ xsim~ module~ `modules'~ \msg_line_context: .~
- This~ module~ is~ a~ pseudo~ module~ which~ may~ not~ be~ loaded~ through~
- the~ module~ loading~ mechansim.
- }
-
-% ----------------------------------------------------------------------------
-
-\cs_generate_variant:Nn \str_if_eq:nnF {xx}
-
-\tl_const:Nn \c__xsim_module_extension_tl {code.tex}
-\tl_const:Nn \c__xsim_module_prefix_tl {xsim}
-
-\seq_new:N \g__xsim_loaded_modules_seq
-\prop_new:N \g__xsim_loaded_modules_prop
-
-\cs_new_protected:Npn \xsim_load_modules:n #1
- { \clist_map_inline:nn {#1} { \xsim_load_module:n {##1} } }
-
-\cs_new_protected:Npn \xsim_load_module:n #1
- {
- \tl_set:Nx \l_tmpa_tl { \tl_trim_spaces:n {#1} }
- \str_if_eq:VnTF \l_tmpa_tl {modules}
- { \msg_error:nn {xsim} {forbidden-module} }
- { \__xsim_load_module:V \l_tmpa_tl }
- }
-
-\cs_new_protected:Npn \__xsim_load_module:n #1
- {
- \xsim_if_module_loaded:nF {#1}
- {
- \xsim_if_module_exist:nTF {#1}
- {
- \__xsim_use_module_hook:nn {#1} {before}
- \msg_info:nnn {xsim} {loading-module} {#1}
- \@onefilewithoptions
- {\c__xsim_module_prefix_tl.#1}[][]
- \c__xsim_module_extension_tl
- \__xsim_use_module_hook:nn {#1} {after}
- }
- { \msg_error:nnn {xsim} {module-missing} {#1} }
- }
- }
-\cs_generate_variant:Nn \__xsim_load_module:n {V}
-
-\prg_new_conditional:Npnn \xsim_if_module_loaded:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \g__xsim_loaded_modules_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_module_exist:n #1 {p,T,F,TF}
- {
- \file_if_exist:nTF
- {\c__xsim_module_prefix_tl.#1.\c__xsim_module_extension_tl}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% --------------------------------------------------------------------------
-% module hooks:
-% #1: module
-% #2: code
-\cs_new_protected:Npn \xsim_after_module:nn #1#2
- {
- \xsim_if_module_loaded:nTF {#1}
- {#2}
- { \__xsim_add_to_module_hook:nnn {#1} {after} {#2} }
- }
-
-% #1: module
-% #2: code
-\cs_new_protected:Npn \xsim_before_module:nn #1#2
- {
- \xsim_if_module_loaded:nF {#1}
- { \__xsim_add_to_module_hook:nnn {#1} {before} {#2} }
- }
-
-% #1: module
-% #2: hook name
-% #3: code
-\cs_new_protected:Npn \__xsim_add_to_module_hook:nnn #1#2#3
- {
- \xsim_if_module_loaded:nF {#1}
- {
- \tl_if_exist:cF {g__xsim_module_#1_#2_hook_tl}
- { \tl_new:c {g__xsim_module_#1_#2_hook_tl} }
- \tl_gput_right:cn {g__xsim_module_#1_#2_hook_tl} {#3}
- }
- }
-
-% #1: module
-% #2: hook name
-\cs_new_protected:Npn \__xsim_use_module_hook:nn #1#2
- {
- \tl_if_exist:cT {g__xsim_module_#1_#2_hook_tl}
- {
- \tl_use:c {g__xsim_module_#1_#2_hook_tl}
- \tl_gclear:c {g__xsim_module_#1_#2_hook_tl}
- }
- }
-
-% --------------------------------------------------------------------------
-
-\tl_new:N \l__xsim_module_date_tl
-\tl_new:N \l__xsim_module_version_tl
-
-\tl_if_exist:NF \c_xsim_date_tl
- { \tl_set:Nx \l__xsim_module_date_tl {\c_xsimverb_date_tl} }
-\tl_if_exist:NF \c_xsim_version_tl
- { \tl_set:Nx \l__xsim_module_version_tl {\c_xsimverb_version_tl} }
-
-\AfterPackage*{xsim}
- {
- \tl_set:Nx \l__xsim_module_date_tl {\c_xsim_date_tl}
- \tl_set:Nx \l__xsim_module_version_tl {\c_xsim_version_tl}
- }
-
-\cs_new_protected:Npn \__xsim_module:nn #1#2
- {
- \seq_gput_right:Nn \g__xsim_loaded_modules_seq {#1}
- \prop_gput:Nnn \g__xsim_loaded_modules_prop {#1} {#2}
- \str_if_eq:xxF
- {\c__xsim_module_prefix_tl.#1.\c__xsim_module_extension_tl}
- {\@currname.\@currext}
- {
- \msg_error:nnnxx {xsim} {wrong-module-name}
- {#1}
- {\@currname.\@currext}
- }
- \ProvidesFile
- {\c__xsim_module_prefix_tl.#1.\c__xsim_module_extension_tl}
- [
- \l__xsim_module_date_tl
- \c_space_tl
- v \l__xsim_module_version_tl
- \c_space_tl
- xsim~ module~ `#1'~ (#2)
- ]
- }
-\cs_generate_variant:Nn \msg_error:nnnn {nnnx}
-
-% --------------------------------------------------------------------------
-% define a xsim module:
-% #1: name
-% #2: description
-\NewDocumentCommand \XSIMmodule {mm}
- { \__xsim_module:nn {#1} {#2} \ExplSyntaxOn }
-
-% --------------------------------------------------------------------------
-% style files
-\NewDocumentCommand \xsimstyle {smO{}}
- {
- \__xsim_module:nn {style.#2} {#3}
- \IfBooleanT {#1} { \ExplSyntaxOn }
- }
-
-% \cs_new_protected:Npn \xsim_style_options:nn #1#2
-% { \keys_define:nn {xsim/#1} {#2} }
-
-\cs_new_protected:Npn \xsim_load_style:n #1
- { \clist_map_inline:nn {#1} { \xsim_load_module:n {style.##1} } }
-
-\keys_define:nn {xsim}
- { load-style .code:n = \xsim_load_style:n {#1} }
-
-\NewDocumentCommand \loadxsimstyle {m}
- { \xsim_load_style:n {#1} }
-
-% --------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.properties.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,540 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - properties module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{properties}{properties of exercises}
-
-\xsim_load_modules:n {base,auxfile}
-
-\msg_new:nnn {xsim} {unknown-property}
- {
- You~ tried~ to~ set~ the~ property~ `#1'~ \msg_line_context: . \\
- This~ property~ does~ not~ exist.~ Check~ for~ a~ typo~ or~ \\
- define~ the~ property~ yourself.
- }
-
-\msg_new:nnn {xsim} {property-unique}
- {
- You~ tried~ to~ set~ the~ property~ `#1'~ \msg_line_context: . \\
- This~ property~ has~ to~ have~ a~ unique~ value~ and~ thus~ \\
- cannot~ be~ set~ to~ `#2'~ since~ this~ value~ is~ already~ talen.
- }
-
-\msg_new:nnn {xsim} {no-boolean-property}
- {
- You~ tried~ to~ check~ the~ boolean~ value~ of~ property~ `#1'~
- \msg_line_context: . \\
- However,~ property~ `#1'~ is~ not~ a~ boolean~ property!
- }
-
-\msg_new:nnn {xsim} {unbalanced-property-list}
- {
- There~ is~ a~ mis-match~ in~ the~ property~ list: \\
- `#1' \\
- \msg_line_context:
- }
-
-\seq_new:N \l__xsim_properties_seq
-\seq_new:N \l__xsim_boolean_properties_seq
-\seq_new:N \l__xsim_unique_properties_seq
-\seq_new:N \l__xsim_noupdate_properties_seq
-\seq_new:N \l__xsim_given_properties_seq
-
-% #1: type
-% #2: id
-% #3: property
-\cs_new_protected:Npn \__xsim_define_property:nnn #1#2#3
- { \xsim_attribute_new:nn {#1!#2} {#3} }
-
-% check if property is set:
-% #1: type
-% #2: id
-% #3: property
-\prg_new_conditional:Npnn \xsim_if_property_set:nnn #1#2#3 {p,T,F,TF}
- {
- \xsim_attribute_if_set:nnTF {#1!#2} {#3}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\prg_generate_conditional_variant:Nnn \xsim_if_property_set:nnn
- {nx,nnx,xx,nV}
- {T,F,TF}
-
-% new property:
-% #1: boolean if unique
-% #2: boolean if boolean
-% #3: boolean if noupdate
-% #4: property name
-\cs_new_protected:Npn \xsim_declare_property:nnnn #1#2#3#4
- {
- \xsim_if_property_exist:nF {#4}
- {
- \seq_put_right:Nn \l__xsim_properties_seq {#4}
- \bool_if:nTF {#3}
- {
- \seq_if_in:NnF \l__xsim_noupdate_properties_seq {#4}
- { \seq_put_right:Nn \l__xsim_noupdate_properties_seq {#4} }
- }
- { \xsim_new_list:n {#4} }
- \bool_if:nTF {#2}
- {
- \xsim_verbose:n
- { Declaring~ new~ boolean~ exercise~ property~ `#4'. }
- \seq_if_in:NnF \l__xsim_boolean_properties_seq {#4}
- { \seq_put_right:Nn \l__xsim_boolean_properties_seq {#4} }
- }
- {
- \bool_if:nTF {#1}
- {
- \xsim_verbose:n
- { Declaring~ new~ unique~ exercise~ property~ `#4'. }
- \seq_if_in:NnF \l__xsim_unique_properties_seq {#4}
- { \seq_put_right:Nn \l__xsim_unique_properties_seq {#4} }
- \seq_new:c {l__xsim_unique_property_#4_values_seq}
- }
- { \xsim_verbose:n { Declaring~ new~ exercise~ property~ `#4'. } }
- }
- \bool_if:nF {#3}
- {
- \xsim_at_end_document:n { \xsim_update_list:n {#4} }
- \xsim_at_begin_document:n { \__xsim_set_property_from_list:n {#4} }
- }
- }
- }
-
-% check if property exists:
-\prg_new_conditional:Npnn \xsim_if_property_exist:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_properties_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_property_exist:nTF {x}
-
-\prg_new_conditional:Npnn \xsim_if_property_noupdate:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_noupdate_properties_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_property_noupdate:nF {V}
-
-\prg_new_conditional:Npnn \xsim_if_property_boolean:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_boolean_properties_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_property_unique:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_unique_properties_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% true if property #1 has been set in the /last/ call of
-% \xsim_set_properties:nnn
-\prg_new_conditional:Npnn \xsim_if_property_given:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_given_properties_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: property
-% #2: value
-\prg_new_conditional:Npnn \xsim_if_property_unique_value:nn #1#2 {p,T,F,TF}
- {
- \xsim_if_property_unique:nTF {#1}
- {
- \seq_if_in:cnTF {l__xsim_unique_property_#1_values_seq} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
-
-% #1: type
-% #2: id
-% #3: property
-% #4: value
-\cs_new_protected:Npn \xsim_set_property:nnnn #1#2#3#4
- {
- \xsim_if_property_exist:nTF {#3} % _p
- {
- \xsim_if_property_set:nnnTF {#1} {#2} {#3} % _p
- {
- \xsim_if_property_unique_value:nnTF {#3} {#4} %_p
- { \msg_warning:nnnn {xsim} {property-unique} {#3} {#4} }
- {
- \xsim_if_property_boolean:nTF {#3} % _p
- { \__xsim_set_boolean_property:nnnn {#1} {#2} {#3} {#4} }
- {
- \xsim_if_property_unique:nTF {#3} % _p
- { \__xsim_set_unique_property:nnnn {#1} {#2} {#3} {#4} }
- { \__xsim_set_property:nnnn {#1} {#2} {#3} {#4} }
- }
- }
- }
- {
- \xsim_if_property_boolean:nTF {#3} % _p
- { \__xsim_set_boolean_property:nnnn {#1} {#2} {#3} {#4} }
- {
- \xsim_if_property_unique:nTF {#3} % _p
- { \__xsim_set_unique_property:nnnn {#1} {#2} {#3} {#4} }
- { \__xsim_set_property:nnnn {#1} {#2} {#3} {#4} }
- }
- }
- }
- { \msg_error:nnn {xsim} {unknown-property} {#3} }
- }
-\cs_generate_variant:Nn \xsim_set_property:nnnn {nnxx,nnnV,nV,nVnx,nnnx,xx,xxnx,nxnx}
-
-% #1: type
-% #2: id
-% #3: property
-% #4: value
-\cs_new_protected:Npn \__xsim_set_boolean_property:nnnn #1#2#3#4
- {
- \str_case_e:nnTF { \str_lowercase:n {#4} }
- {
- {} {}
- {true} {}
- }
- { \__xsim_set_property:nnnn {#1} {#2} {#3} {true} }
- { \__xsim_set_property:nnnn {#1} {#2} {#3} {false} }
- }
-
-% #1: type
-% #2: id
-% #3: property
-% #4: value
-\cs_new_protected:Npn \__xsim_set_unique_property:nnnn #1#2#3#4
- {
- \__xsim_set_property:nnnn {#1} {#2} {#3} {#4}
- \__xsim_set_property_reverse:nnnn {#1} {#2} {#3} {#4}
- }
-
-% #1: type
-% #2: id
-% #3: property
-\cs_new_protected:Npn \__xsim_unset_property:nnn #1#2#3
- {
- \xsim_verbose:n
- { Un-setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'. }
- \__xsim_remove_property_from_list:nnn {#1} {#2} {#3}
- \xsim_attribute_unset:nn {#1!#2} {#3}
- }
-
-% #1: type
-% #2: id
-% #3: property
-\cs_new_protected:Npn \xsim_unset_property:nnn #1#2#3
- {
- \xsim_if_property_exist:nTF {#3}
- { \__xsim_unset_property:nnn {#1} {#2} {#3} }
- { \msg_error:nnn {xsim} {unknown-property} {#3} }
- }
-\cs_generate_variant:Nn \xsim_unset_property:nnn {nx,nnx,nV}
-
-% #1: type
-% #2: id
-% #3: property
-% #4: value
-\cs_new_protected:Npn \__xsim_set_property:nnnn #1#2#3#4
- {
- \xsim_verbose:n
- {
- Setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'~ to~
- value~ `#4'.
- }
- \__xsim_remove_property_from_list:nnn {#1} {#2} {#3}
- % now we can safely add the property to the list:
- \xsim_add_to_list:nn {#3} {#1-#2=={#4}}
- \xsim_attribute_set:nnn {#1!#2} {#3} {#4}
- }
-\cs_generate_variant:Nn \__xsim_set_property:nnnn {VVnV}
-
-% #1: type
-% #2: id
-% #3: property
-% #4: value
-\cs_new_protected:Npn \__xsim_set_property_reverse:nnnn #1#2#3#4
- {
- \xsim_attribute_set:nnn {type:#3} {#4} {#1}
- \xsim_attribute_set:nnn {id:#3} {#4} {#2}
- }
-
-\tl_set:Nx \l__xsim_tmpa_tl { \cs_to_str:N \{ }
-\tl_set:Nx \l__xsim_tmpb_tl { \cs_to_str:N \} }
-\use:x
- {
- \cs_new_protected:Npn
- \exp_not:N \__xsim_extract_property_list_entry:NNNwww
- ##1##2##3##4-##5== \l__xsim_tmpa_tl ##6 \l__xsim_tmpb_tl
- \exp_not:N \q_stop
- }
- {
- \str_set:Nn #1 {#4}
- \str_set:Nn #2 {#5}
- \str_set:Nn #3 {#6}
- }
-
-% #1: type
-% #2: id
-% #3: property
-\cs_new_protected:Npn \__xsim_remove_property_from_list:nnn #1#2#3
- {
- % make sure we change the entry if it has been recorded previously:
- \xsim_foreach_list_entry:nn {#3}
- {
- \__xsim_extract_property_list_entry:NNNwww
- \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop
- \str_if_eq:xnT { \l__xsim_tmpa_str - \l__xsim_tmpb_str } {#1-#2}
- {
- \xsim_remove_from_list:nx {#3}
- { #1-#2 == {\l__xsim_tmpc_str} }
- }
- }
- % make sure we change the entry if it has been set during the current run:
- \xsim_foreach_new_list_entry:nn {#3}
- {
- \__xsim_extract_property_list_entry:NNNwww
- \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop
- \str_if_eq:xnT { \l__xsim_tmpa_str - \l__xsim_tmpb_str } {#1-#2}
- {
- \xsim_remove_from_list:nx {#3}
- { #1-#2 == {\l__xsim_tmpc_str} }
- }
- }
- }
-
-\cs_new_protected:Npn \__xsim_set_property_from_list:n #1
- {
- \xsim_foreach_list_entry:nn {#1}
- {
- \__xsim_extract_property_list_entry:NNNwww
- \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop
- \tl_set_rescan:Nnx \l__xsim_tmpc_tl {} { \l__xsim_tmpc_str }
- \__xsim_set_property:VVnV
- \l__xsim_tmpa_str
- \l__xsim_tmpb_str
- {#1}
- \l__xsim_tmpc_tl
- }
- }
-
-% set properties:
-% #1: type
-% #2: id
-% #3: csv list of properties
-\cs_new_protected:Npn \xsim_set_properties:nnn #1#2#3
- {
- \seq_clear:N \l__xsim_given_properties_seq
- \clist_map_inline:nn {#3}
- {
- \seq_set_split:Nnx \l__xsim_tmpa_seq {=} { \tl_trim_spaces:n {##1} }
- \int_compare:nNnT { \seq_count:N \l__xsim_tmpa_seq } > {2}
- { \msg_error:nnn {xsim} {unbalanced-property-list} {##1} }
- \xsim_set_property:nnxx
- {#1}
- {#2}
- { \seq_item:Nn \l__xsim_tmpa_seq {1} }
- { \seq_item:Nn \l__xsim_tmpa_seq {2} }
- \seq_put_right:Nx \l__xsim_given_properties_seq
- { \seq_item:Nn \l__xsim_tmpa_seq {1} }
- }
- \xsim_property_set_aliases:nn {#1} {#2}
- }
-\cs_generate_variant:Nn \xsim_set_properties:nnn {nnx,nxx,nV,nVx}
-
-% ----------------------------------------------------------------------------
-
-\seq_new:N \g__xsim_property_aliases_seq
-
-% #1: property
-\prg_new_conditional:Npnn \xsim_if_property_alias:n #1 {p,T,F,TF}
- {
- \seq_if_in:NnTF \g__xsim_property_aliases_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: property
-\cs_new:Npn \xsim_property_alias:n #1
- { \xsim_attribute_get:nn {#1} {alias} }
-
-% #1: property
-% #2: alias of
-\cs_new_protected:Npn \xsim_make_property_alias:nn #1#2
- {
- \xsim_if_property_alias:nF {#1}
- {
- \xsim_verbose:n
- { Making~ property~ `#1'~ an~ alias~ of~ property~ `#2'. }
- \xsim_attribute_set:nnn {#1} {alias} {#2}
- \seq_gput_right:Nn \g__xsim_property_aliases_seq {#1}
- }
- }
-
-% #1: type
-% #2: id
-% #3: property
-\cs_new_protected:Npn \xsim_property_set_alias:nnn #1#2#3
- {
- \xsim_if_property_set:nnnF {#1} {#2} {#3}
- {
- \xsim_if_property_set:nnxT {#1} {#2}
- { \xsim_property_alias:n {#3} }
- {
- \xsim_set_property:nnnx {#1} {#2} {#3}
- {
- \xsim_get_property:nnf {#1} {#2}
- { \xsim_property_alias:n {#3} }
- }
- }
- }
- \xsim_if_property_set:nnxT {#1} {#2}
- { \xsim_property_alias:n {#3} }
- {
- \xsim_attribute_set:nnx {alias:#1!#2} {#3}
- {
- \xsim_get_property:nnf {#1} {#2}
- { \xsim_property_alias:n {#3} }
- }
- }
- }
-\cs_generate_variant:Nn \xsim_property_set_alias:nnn {nV}
-
-% #1: type
-% #2: id
-\cs_new_protected:Npn \xsim_property_set_aliases:nn #1#2
- {
- \seq_map_inline:Nn \g__xsim_property_aliases_seq
- { \xsim_property_set_alias:nnn {#1} {#2} {##1} }
- }
-
-% ----------------------------------------------------------------------------
-
-% retrieve properties:
-% #1: type
-% #2: id
-% #3: property
-\cs_new:Npn \xsim_get_property:nnn #1#2#3
- { \xsim_attribute_get:nn {#1!#2} {#3} }
-\cs_generate_variant:Nn \xsim_get_property:nnn {nx,ne,xx,oo,no,nnf,nf,oof,nV}
-
-% #1: property
-% #2: value
-\cs_new:Npn \xsim_get_id_for_property:nn #1#2
- { \xsim_attribute_get:nn {id:#1} {#2} }
-
-% #1: property
-% #2: value
-\cs_new:Npn \xsim_get_type_for_property:nn #1#2
- { \xsim_attribute_get:nn {type:#1} {#2} }
-\cs_generate_variant:Nn \xsim_get_type_for_property:nn {nV}
-
-% #1: id or ID
-\cs_new:Npn \xsim_normalize_id:n #1
- {
- \tl_if_blank:eTF
- { \xsim_get_id_for_property:nn {ID} {#1} }
- {#1}
- { \xsim_get_id_for_property:nn {ID} {#1} }
- }
-\cs_generate_variant:Nn \xsim_normalize_id:n {e}
-
-\cs_new:Npn \__xsim_get_property_tmp:n #1 {}
-\cs_generate_variant:Nn \__xsim_get_property_tmp:n {V}
-
-% #1: type
-% #2: id
-% #3: property
-\cs_new_protected:Npn \xsim_get_property_if_set:nnnTF #1#2#3#4#5
- {
- \group_begin:
- \xsim_if_property_exist:nTF {#3}
- {
- \xsim_if_property_set:nnnTF {#1} {#2} {#3}
- {
- \tl_set:Nx \PropertyValue
- { \xsim_get_property:nnn {#1} {#2} {#3} }
- \cs_set:Npn \__xsim_get_property_tmp:n ##1 {#4}
- \__xsim_get_property_tmp:V \PropertyValue
- }
- {#5}
- }
- { \msg_error:nnn {xsim} {unknown-property} {#3} }
- \group_end:
- }
-\cs_new_protected:Npn \xsim_get_property_if_set:nnnT #1#2#3#4
- { \xsim_get_property_if_set:nnnTF {#1} {#2} {#3} {#4} {} }
-\cs_new_protected:Npn \xsim_get_property_if_set:nnnF #1#2#3#4
- { \xsim_get_property_if_set:nnnTF {#1} {#2} {#3} {} {#4} }
-\cs_generate_variant:Nn \xsim_get_property_if_set:nnnTF {oo}
-
-% #1: type
-% #2: id
-% #3: property
-\prg_new_conditional:Npnn \xsim_if_boolean_property:nnn #1#2#3 {T,F,TF}
- {
- \xsim_if_property_exist:nTF {#3}
- {
- \xsim_if_property_boolean:nTF {#3}
- {
- \xsim_if_property_set:nnnTF {#1} {#2} {#3}
- {
- \bool_if:cTF
- {c_ \xsim_get_property:nnn {#1} {#2} {#3} _bool}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
- { \msg_error:nnn {xsim} {no-boolean-property} {#3} }
- }
- { \msg_error:nnn {xsim} {unknown-property} {#3} }
- }
-\cs_generate_variant:Nn \xsim_if_boolean_property:nnnTF {oo}
-\cs_generate_variant:Nn \xsim_if_boolean_property:nnnF {nV}
-
-\cs_new_protected:Npn \xsim_save_property:nnnN #1#2#3#4
- { \tl_set:No #4 { \cs:w __xsim_property_#2!#1!#3: \cs_end: } }
-\cs_generate_variant:Nn \xsim_save_property:nnnN {nx,xx}
-
-\cs_new_protected:Npn \xsim_gsave_property:nnnN #1#2#3#4
- {
- \xsim_save_property:nnnN {#1} {#2} {#3} #4
- \tl_gset:NV #4 #4
- }
-\cs_generate_variant:Nn \xsim_gsave_property:nnnN {nx,xx,nV}
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
-2020/03/09 - add meaningful error if a comma is missing in the property list
-2020/03/14 - performance optimizations
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,315 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - random module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{random}{randomly select exercises from collections}
-
-\msg_new:nnn {xsim} {random-numbers-unavailable}
- {
- You~ are~ compiling~ your~ document~ using ~XeLaTeX.~ Please~ be~ aware~
- that~ random~ selection~ of~ exercises~ is~ unavailable~ in~ XeLaTeX.~ If~
- you~ use~ this~ feature~ you~ can~ safely~ ignore~ this~ message.
- }
-
-\sys_if_engine_xetex:T
- { \msg_warning:nn {xsim} {random-numbers-unavailable} }
-
-\xsim_load_modules:n {collections}
-
-\tl_new:N \l_xsim_random_collection_tl
-\tl_new:N \l__xsim_print_random_choice_tl
-\tl_const:Nn \c__xsim_print_random_both_tl {both}
-\tl_const:Nn \c__xsim_print_random_exercise_tl {exercise}
-\tl_const:Nn \c__xsim_print_random_solution_tl {solution}
-\seq_new:N \g__xsim_random_list_seq
-\seq_new:N \l__xsim_allowed_exercise_ids_seq
-\int_new:N \g__xsim_random_list_id_int
-\bool_new:N \l__xsim_sort_random_bool
-\clist_new:N \l_xsim_random_exclude_list_clist
-
-% #1: random list id
-% #2: csv list of integers
-\xsim_new_aux_property:cpn {random} #1#2
- {
- \xsim_random_list_if_exist:nF {#1}
- { \xsim_new_random_list:n {#1} }
- \xsim_set_random_list:nn {#1} {#2}
- }
-
-\cs_new_protected:Npn \xsim_new_random_list:n #1
- {
- \xsim_verbose:n {Defining~ new~ random~ list~ `#1'}
- \seq_new:c {g__xsim_random_#1 _seq}
- }
-
-\cs_new_protected:Npn \xsim_set_random_list:nn #1#2
- { \seq_gset_from_clist:cn {g__xsim_random_#1_seq} {#2} }
-
-\cs_new_protected:Npn \xsim_set_random_list_from_seq:nN #1#2
- { \seq_gset_eq:cN {g__xsim_random_#1_seq} #2 }
-
-\cs_new:Npn \xsim_use_random_list:nn #1#2
- { \seq_use:cn {g__xsim_random_#1_seq} {#2} }
-
-\cs_new_protected:Npn \xsim_map_random_list:nn #1#2
- { \seq_map_inline:cn {g__xsim_random_#1_seq} {#2} }
-
-\prg_new_conditional:Npnn \xsim_random_list_if_exist:n #1 {p,T,F,TF}
- {
- \seq_if_exist:cTF {g__xsim_random_#1_seq}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_random_list_if_empty:n #1 {p,T,F,TF}
- {
- \seq_if_empty:cTF {g__xsim_random_#1_seq}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: random list id
-% #2: sequence variable to set list from
-\cs_new_protected:Npn \xsim_save_random_list:nN #1#2
- { % TODO: check if #2 is empty
- \xsim_random_list_if_exist:nF {#1}
- { \xsim_new_random_list:n {#1} }
- \xsim_random_list_if_empty:nT {#1}
- { \xsim_set_random_list_from_seq:nN {#1} #2 }
- \xsim_verbose:n {Saving~ random~ list~ `#1'}
- \xsim_add_property_to_aux:nn {random}
- { {#1} { \xsim_use_random_list:nn {#1} {,} } }
- }
-\cs_generate_variant:Nn \xsim_save_random_list:nN {x}
-
-% #1: collection
-% #2: number of items
-% #3: clist variable of excluded ids
-\cs_new_protected:Npn \xsim_print_random_list:nnN #1#2#3
- {
- \xsim_if_collection_exist:nTF {#1}
- {
- \int_gincr:N \g__xsim_random_list_id_int
- \int_compare:nNnTF { \xsim_collection_count:n {#1} } = {0}
- { \xsim_rerun: }
- {
- % generate seq of allowed ids from collection:
- \xsim_foreach_exercise_id:n
- {
- \tl_set:Nx \l__xsim_tmpa_tl
- { \xsim_get_type_for_property:nn {id} {##1} }
- \xsim_if_in_collection:nVnT {#1} \l__xsim_tmpa_tl {##1}
- {
- \clist_if_in:NnF #3 {##1}
- { \seq_put_right:Nn \l__xsim_allowed_exercise_ids_seq {##1} }
- }
- }
- \int_compare:nNnTF
- {#2}
- >
- { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
- {
- \int_set:Nn \l__xsim_tmpa_int
- { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
- }
- { \int_set:Nn \l__xsim_tmpa_int {#2} }
- % generate random list:
- \xsim_generate_random_list:nnnN
- { \int_to_alph:n { \g__xsim_random_list_id_int } }
- { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
- { \l__xsim_tmpa_int }
- \g__xsim_random_list_seq
- }
- \xsim_save_random_list:xN
- { \int_to_alph:n { \g__xsim_random_list_id_int } }
- \g__xsim_random_list_seq
- \xsim_verbose:x
- {
- Printing~ exercises~ of~ random~ list~
- `\int_to_alph:n { \g__xsim_random_list_id_int }'~ of~
- collection~ `#1'
- }
- \xsim_print_random_exercises:Nn
- \l__xsim_allowed_exercise_ids_seq
- { \int_to_alph:n { \g__xsim_random_list_id_int } }
- }
- { \msg_error:nnn {xsim} {unknown-collection} {#1} }
- }
-\cs_generate_variant:Nn \xsim_print_random_list:nnN {V}
-
-% #1: random list id
-% #2: max number to choose from
-% #3: number of items
-% #4: seq variable
-\cs_new_protected:Npn \xsim_generate_random_list:nnnN #1#2#3#4
- {
- \bool_lazy_or:nnT
- { !\xsim_random_list_if_exist_p:n {#1} }
- { \xsim_random_list_if_empty_p:n {#1} }
- {
- \xsim_verbose:n
- {Generating~ random~ list~ `#1'~ with~ #3~ out~ of~ #2~ items}
- \seq_gclear:N #4
- \int_do_until:nNnn { \seq_count:N #4 } = {#3}
- {
- \tl_set:Nx \l__xsim_tmpa_tl
- { \fp_eval:n { randint(#2) } }
- \seq_if_in:NVF #4
- \l__xsim_tmpa_tl
- { \seq_gput_right:NV #4 \l__xsim_tmpa_tl }
- }
- \bool_if:NT \l__xsim_sort_random_bool
- {
- \seq_sort:Nn #4
- {
- \int_compare:nNnTF {##1} > {##2}
- { \sort_return_swapped: }
- { \sort_return_same: }
- }
- }
- }
- }
-
-% #1: seq variable of ids
-% #2: random list id
-\cs_new_protected:Npn \xsim_print_random_exercises:Nn #1#2
- {
- \bool_lazy_and:nnT
- { \xsim_random_list_if_exist_p:n {#2} }
- { !\xsim_random_list_if_empty_p:n {#2} }
- {
- \xsim_verbose:x
- {
- Printing~
- \l__xsim_print_random_choice_tl \c_space_tl
- \str_if_eq:onT { \l__xsim_print_random_choice_tl } {both}
- { exercises~ and~ solutions~ }
- of~ random~ list~ `#2'
- }
- \xsim_map_random_list:nn {#2}
- {
- \tl_set:Nx \l__xsim_tmpa_tl
- { \seq_item:Nn #1 {##1} }
- \tl_set:Nx \l__xsim_tmpb_tl
- { \xsim_get_type_for_property:nV {id} \l__xsim_tmpa_tl }
- \bool_lazy_or:nnT
- {
- \tl_if_eq_p:NN
- \l__xsim_print_random_choice_tl
- \c__xsim_print_random_both_tl
- }
- {
- \tl_if_eq_p:NN
- \l__xsim_print_random_choice_tl
- \c__xsim_print_random_exercise_tl
- }
- {
- \xsim_if_exercise_exist:VVT
- \l__xsim_tmpb_tl
- \l__xsim_tmpa_tl
- {
- \xsim_insert:VVnn
- \l__xsim_tmpb_tl
- \l__xsim_tmpa_tl
- {}
- {exercise}
- }
- }
- \bool_lazy_or:nnT
- {
- \tl_if_eq_p:NN
- \l__xsim_print_random_choice_tl
- \c__xsim_print_random_both_tl
- }
- {
- \tl_if_eq_p:NN
- \l__xsim_print_random_choice_tl
- \c__xsim_print_random_solution_tl
- }
- {
- \xsim_if_solution_exist:VVT
- \l__xsim_tmpb_tl
- \l__xsim_tmpa_tl
- {
- \xsim_insert:VVnn
- \l__xsim_tmpb_tl
- \l__xsim_tmpa_tl
- {}
- {solution}
- }
- }
- }
- }
- }
-
-\keys_define:nn {xsim/random}
- {
- sort .bool_set:N = \l__xsim_sort_random_bool ,
- sort .initial:n = true ,
- collection .tl_set:N = \l_xsim_random_collection_tl ,
- collection .initial:n = all~exercises ,
- exclude .code:n = \__xsim_exclude_ids:n {#1} ,
- print .choice: ,
- print/exercises .code:n =
- \tl_set:Nn \l__xsim_print_random_choice_tl {exercise} ,
- print/solutions .code:n =
- \tl_set:Nn \l__xsim_print_random_choice_tl {solution} ,
- print/both .code:n =
- \tl_set:Nn \l__xsim_print_random_choice_tl {both} ,
- print/unknown .code:n =
- \msg_warning:nnn {xsim} {print-collection-choice} {#1}
- \tl_set:Nn \l__xsim_print_random_choice_tl {exercise} ,
- print .initial:n = exercises
- }
-
-\cs_new_protected:Npn \__xsim_exclude_ids:n #1
- {
- \seq_clear:N \l__xsim_tmpa_seq
- \clist_map_inline:nn {#1}
- {
- \tl_set:Nx \l__xsim_tmpa_tl
- { \xsim_get_id_for_property:nn {ID} {##1} }
- \tl_if_blank:VTF \l__xsim_tmpa_tl
- { \seq_put_right:Nn \l__xsim_tmpa_seq {##1} }
- {
- \seq_put_right:Nx \l__xsim_tmpa_seq
- { \xsim_get_id_for_property:nn {ID} {##1} }
- }
- }
- \seq_remove_duplicates:N \l__xsim_tmpa_seq
- \clist_set_from_seq:NN
- \l_xsim_random_exclude_list_clist
- \l__xsim_tmpa_seq
- }
-
-% use this in the exclude list:
-% \xsim_get_type_for_property:nn {id} {}
-% or a combination of:
-% \xsim_get_type_for_property:nn {ID} {}
-% \xsim_get_id_for_property:nn {ID} {}
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.solutions.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.solutions.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.solutions.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,414 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - solutions module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{solutions}{managing solutions}
-
-\xsim_load_modules:n {tags,properties}
-
-\bool_new:N \l_xsim_inside_solution_bool
-\bool_new:N \l__xsim_include_question_bool
-\bool_new:N \l__xsim_printsolutions_headings_bool
-\bool_new:N \l__xsim_printsolutions_conditions_bool
-\bool_new:N \l____xsim_this_condition_bool
-
-\seq_new:N \l__xsim_printsolutions_conditions_seq
-
-\int_new:N \l_xsim_printsolutions_section_int
-\int_new:N \l_xsim_printsolutions_chapter_int
-
-\tl_new:N \l__xsim_printsolutions_headings_template_tl
-\tl_new:N \ExerciseSection
-\tl_new:N \ExerciseChapter
-\tl_new:N \l__xsim_printsolutions_collection_tl
-
-% ----------------------------------------------------------------------------
-
-\prg_new_conditional:Npnn \xsim_if_inside_solution: {p,T,F,TF}
- {
- \bool_if:NTF \l_xsim_inside_solution_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-\prg_new_conditional:Npnn \xsim_if_solution_print:n #1 {p,T,F,TF}
- {
- \bool_if:cTF {l__xsim_#1_solution_print_bool}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: type
-% #2: id
-\prg_new_protected_conditional:Npnn \xsim_solution_if_print:nn #1#2 {T,F,TF}
- {
- \bool_set_true:N \l____xsim_print_bool
- \xsim_if_tagged:nnF {#1} {#2}
- { \bool_set_false:N \l____xsim_print_bool }
- \xsim_if_boolean_property:nnnF {#1} {#2} {print}
- { \bool_set_false:N \l____xsim_print_bool }
- \bool_if:cF {l__xsim_#1_solution_print_bool}
- { \bool_set_false:N \l____xsim_print_bool }
- \bool_if:NTF \l____xsim_print_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_solution_if_print:nnT {nV,oo}
-
-% #1: type
-% #2: id
-\prg_new_protected_conditional:Npnn \xsim_if_solution_exist:nn #1#2 {T,F,TF}
- {
- \xsim_if_boolean_property:nnnTF {#1} {#2} {solution}
- { \xsim_if_exist:nnnTF {#1} {#2} {exercise} }
- { \xsim_if_exist:nnnTF {#1} {#2} {solution} }
- { \prg_return_true: }
- { \prg_return_false: }
- }
-\cs_generate_variant:Nn \xsim_if_solution_exist:nnT {VV,oo}
-\cs_generate_variant:Nn \xsim_if_solution_exist:nnTF {oo}
-
-% #1: type
-% #2: options
-\cs_new_protected:Npn \xsim_start_solution:nn #1#2
- {
- \keys_set:xn { xsim/\xsim_get_parameter:nn {#1} {solution-env} } {#2}
- \bool_set_true:N \l_xsim_inside_solution_bool
- \refstepcounter { \xsim_get_parameter:nn {#1} {solution-counter} }
- }
-
-\cs_new_protected:Npn \xsim_stop_solution:n #1 {}
-
-% ----------------------------------------------------------------------------
-
-% #1: conditional base function (three n args)
-% #2: name
-% #3: code (refer to type and id with `#1' and `#2'), #3 refers to the boolean
-% properties use/print
-\cs_new_protected:Npn \xsim_new_solutions_condition:Nnn #1#2#3
- {
- \prg_new_protected_conditional:Npnn #1 ##1##2##3 {T,F,TF}
- {
- \xsim_if_in_list:nnTF {##3} {##1-##2=={true}}
- {
- \__xsim_printsolutions_if_condition:nTF {#2}
- { \__xsim_printsolutions_condition_true: #3 }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
- }
-
-% per section condition:
-\xsim_new_solutions_condition:Nnn \__xsim_if_solutions_per_section:nnn
- {per-section}
- {
- \xsim_if_in_list:nxTF {section-value}
- { #1-#2 == { \int_use:N \l_xsim_printsolutions_section_int } }
- {
- \tl_set:Nx \ExerciseSection
- { \xsim_get_property:nnn {#1} {#2} {section} }
- \prg_return_true:
- }
- { \prg_return_false: }
- }
-
-% per chapter condition:
-\xsim_new_solutions_condition:Nnn \__xsim_if_solutions_per_chapter:nnn
- {per-chapter}
- {
- \xsim_if_in_list:nxTF {chapter-value}
- { #1-#2 == { \int_use:N \l_xsim_printsolutions_chapter_int } }
- {
- \tl_set:Nx \ExerciseChapter
- { \xsim_get_property:nnn {#1} {#2} {chapter} }
- \prg_return_true:
- }
- { \prg_return_false: }
- }
-
-% per collection condition:
-\xsim_new_solutions_condition:Nnn \__xsim_if_solutions_in_collection:nnn
- {per-collection}
- {
- \tl_if_blank:VTF \l__xsim_printsolutions_collection_tl
- { \prg_return_false: }
- {
- \xsim_if_in_collection:VnnTF
- \l__xsim_printsolutions_collection_tl
- {#1}
- {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- }
-
-% ----------------------------------------------------------------------------
-% conditions mechanism
-\cs_new_protected:Npn \__xsim_printsolutions_condition_false:
- { \bool_set_false:N \l__xsim_printsolutions_conditions_bool }
-
-\cs_new_protected:Npn \__xsim_printsolutions_condition_true:
- { \bool_set_true:N \l__xsim_printsolutions_conditions_bool }
-
-% #1: type
-% #2: id
-% #3: boolean property
-\prg_new_conditional:Npnn
- \__xsim_printsolutions_if_conditions:nnn #1#2#3 {T,F,TF}
- {
- \bool_if:NTF \l__xsim_printsolutions_conditions_bool
- { \prg_return_true: }
- {
- \xsim_if_in_list:nnTF {#3} {#1-#2=={true}}
- { \prg_return_false: }
- { \prg_return_true: }
- }
- }
-
-% #1: name
-% #2: condition
-\cs_new_protected:Npn \xsim_declare_printsolutions_condition:nn #1#2
- {
- \bool_new:c {l__xsim_printsolutions_#1_condition_bool}
- \seq_put_right:Nn \l__xsim_printsolutions_conditions_seq {#1}
- \xsim_attribute_set:nnn {printsolutions} {#1} {#2}
- }
-
-\prg_new_conditional:Npnn \__xsim_printsolutions_if_condition:n #1 {T,F,TF}
- {
- \bool_if:cTF {l__xsim_printsolutions_#1_condition_bool}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: name
-% #2: true|false
-\cs_new_protected:Npn \__xsim_printsolutions_condition:nn #1#2
- { \bool_set_eq:cc {l__xsim_printsolutions_#1_condition_bool} {c_#2_bool} }
-
-% false if any condition is false for this solution:
-% #1: type
-% #2: id
-% #3: boolean property
-\prg_new_protected_conditional:Npnn
- \__xsim_printsolutions_check_conditions:nnn #1#2#3 {T,F,TF}
- {
- \__xsim_printsolutions_condition_false:
- \bool_set_true:N \l____xsim_this_condition_bool
- \seq_map_inline:Nn \l__xsim_printsolutions_conditions_seq
- {
- \bool_if:cT {l__xsim_printsolutions_##1_condition_bool}
- {
- \xsim_attribute_get:nn {printsolutions} {##1}
- {#1} {#2} {#3}
- { }
- { \bool_set_false:N \l____xsim_this_condition_bool }
- }
- }
- \bool_if:NTF \l____xsim_this_condition_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-
-% #1: type
-% #2: id
-% #3: boolean property
-% #4: code
-\cs_new_protected:Npn \xsim_if_this_solution_do:nnnn #1#2#3#4
- {
- \xsim_if_solution_exist:nnT {#1} {#2}
- { \__xsim_printsolutions_check_conditions:nnnT {#1} {#2} {#3} {#4} }
- }
-
-% #1: type
-% #2: boolean property
-% #3: code
-\cs_new_protected:Npn \xsim_if_solutions_do:nnn #1#2#3
- {
- \xsim_foreach_exercise_type_id:nn {#2}
- { \xsim_if_this_solution_do:nnnn {#1} {##2} {#2} {#3} }
- }
-
-% ----------------------------------------------------------------------------
-% #1: boolean -- if true only the solutions of printed exercises will be
-% output
-% #2: pre
-% #3: post
-% #4: type
-% #5: code (refer to type with #1 and id with #2)
-\cs_new_protected:Npn \xsim_print_type_code:nnnnn #1#2#3#4#5
- {
- \group_begin:
- \cs_set_protected:Npn \__xsim_print_entry:nn ##1##2 {#5}
- #2
- \bool_set_false:N \l__xsim_tmpa_bool
- \bool_if:nTF {#1}
- {
- \xsim_if_solutions_do:nnn {#4} {print}
- { \bool_set_true:N \l__xsim_tmpa_bool }
- }
- {
- \xsim_if_solutions_do:nnn {#4} {used}
- { \bool_set_true:N \l__xsim_tmpa_bool }
- }
- \tl_set:Nn \ExerciseType {#4}
- \bool_if:NT \l__xsim_tmpa_bool
- {
- \bool_if:NT \l__xsim_printsolutions_headings_bool
- {
- \xsim_use_template:nV
- {heading}
- \l__xsim_printsolutions_headings_template_tl
- }
- }
- \bool_if:nTF {#1}
- {
- \xsim_if_solutions_do:nnn {#4} {print}
- { \__xsim_print_entry:nn {#4} {##2} }
- }
- {
- \xsim_if_solutions_do:nnn {#4} {used}
- { \__xsim_print_entry:nn {#4} {##2} }
- }
- #3
- \group_end:
- }
-
-% #1: boolean -- if true only the solutions of printed exercises will be
-% output
-% #2: options
-% #3: type
-\cs_new_protected:Npn \xsim_print_type_solutions:nnn #1#2#3
- {
- \xsim_print_type_code:nnnnn
- {#1}
- {
- \xsim_verbose:n
- { Printing~ solutions~ for~ exercise~ type~ `#3'. }
- \keys_set:nn {xsim/print-solutions} {#2}
- }
- {}
- {#3}
- { \xsim_insert:nnnn {##1} {##2} {} {solution} }
- }
-
-% #1: boolean -- if true only the solutions of printed exercises will be
-% output
-% #2: options
-\cs_new_protected:Npn \xsim_print_all_solutions_per_type:nn #1#2
- {
- \xsim_foreach_exercise_type:n
- { \xsim_print_type_solutions:nnn {#1} {#2} {##1} }
- }
-
-% #1: boolean -- if true only the solutions of printed exercises will be
-% output
-% #2: options
-\cs_new_protected:Npn \xsim_print_all_solutions_per_id:nn #1#2
- {
- \xsim_verbose:n { Printing~ solutions. }
- \group_begin:
- \keys_set:nn {xsim/print-solutions} {#2}
- \bool_set_false:N \l__xsim_tmpa_bool
- \bool_if:nTF {#1}
- {
- \xsim_foreach_exercise_id_type:nn {print}
- {
- \xsim_if_this_solution_do:nnnn {##1} {##2} {print}
- { \xsim_insert:nnnn {##1} {##2} {} {solution} }
- }
- }
- {
- \xsim_foreach_exercise_id_type:nn {used}
- {
- \xsim_if_this_solution_do:nnnn {##1} {##2} {used}
- { \xsim_insert:nnnn {##1} {##2} {} {solution} }
- }
- }
- \group_end:
- }
-
-% ----------------------------------------------------------------------------
-
-\xsim_declare_printsolutions_condition:nn {per-section}
- { \__xsim_if_solutions_per_section:nnnTF }
-\xsim_declare_printsolutions_condition:nn {per-chapter}
- { \__xsim_if_solutions_per_chapter:nnnTF }
-\xsim_declare_printsolutions_condition:nn {per-collection}
- { \__xsim_if_solutions_in_collection:nnnTF }
-
-% ----------------------------------------------------------------------------
-
-\keys_define:nn {xsim/print-solutions}
- {
- headings .bool_set:N = \l__xsim_printsolutions_headings_bool ,
- headings .initial:n = true ,
- headings-template .tl_set:N = \l__xsim_printsolutions_headings_template_tl ,
- headings-template .initial:n = default ,
- include-exercise .bool_set:N = \l__xsim_include_question_bool ,
- include-exercise .initial:n = false ,
- section .choice: ,
- section/true .code:n =
- \__xsim_printsolutions_condition:nn {per-section} {true}
- \int_set:Nn \l_xsim_printsolutions_section_int { \value {section} } ,
- section/false .code:n =
- \__xsim_printsolutions_condition:nn {per-section} {false} ,
- section/unknown .code:n =
- \__xsim_printsolutions_condition:nn {per-section} {true}
- \int_set:Nn \l_xsim_printsolutions_section_int {#1} ,
- section .default:n = true ,
- section .initial:n = false ,
- chapter .choice: ,
- chapter/true .code:n =
- \__xsim_printsolutions_condition:nn {per-chapter} {true}
- \int_set:Nn \l_xsim_printsolutions_chapter_int { \value {chapter} } ,
- chapter/false .code:n =
- \__xsim_printsolutions_condition:nn {per-chapter} {false} ,
- chapter/unknown .code:n =
- \__xsim_printsolutions_condition:nn {per-chapter} {true}
- \int_set:Nn \l_xsim_printsolutions_chapter_int {#1} ,
- chapter .default:n = true ,
- chapter .initial:n = false ,
- collection .choice: ,
- collection/false .code:n =
- \__xsim_printsolutions_condition:nn {per-collection} {false} ,
- collection/unknown .code:n =
- \xsim_if_collection_exist:nT {#1}
- {
- \__xsim_printsolutions_condition:nn {per-collection} {true}
- \tl_set:Nn \l__xsim_printsolutions_collection_tl {#1}
- } ,
- collection .initial:n = false
- }
-
-% ----------------------------------------------------------------------------
-
-\file_input_stop:
-
-2020/02/23 - resolve bug #56
-2020/03/16 - performance optimizations
Modified: trunk/Master/texmf-dist/tex/latex/xsim/xsim.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.sty 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.sty 2021-01-31 21:33:37 UTC (rev 57572)
@@ -8,15 +8,15 @@
% Web: https://github.com/cgnieder/xsim
% E-Mail: contact at mychemistry.eu
% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
+% Copyright 2017--2021 Clemens Niederberger
%
% This work may be distributed and/or modified under the
-% conditions of the LaTeX Project Public License, either version 1.3
+% conditions of the LaTeX Project Public License, either version 1.3c
% 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.
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008/05/04 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
@@ -25,14 +25,14 @@
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% ----------------------------------------------------------------------------
-\RequirePackage {expl3,xparse,l3keys2e}
+\RequirePackage {l3keys2e,xsimverb}
\ExplSyntaxOn
-\tl_const:Nn \c_xsim_date_tl {2020/04/04}
+\tl_const:Nn \c_xsim_date_tl {2021/01/31}
\tl_const:Nn \c_xsim_version_major_number_tl {0}
-\tl_const:Nn \c_xsim_version_minor_number_tl {19}
-\tl_const:Nn \c_xsim_version_subrelease_tl {b}
+\tl_const:Nn \c_xsim_version_minor_number_tl {20}
+\tl_const:Nn \c_xsim_version_subrelease_tl {}
\tl_const:Nx \c_xsim_version_number_tl
{
\c_xsim_version_major_number_tl .
@@ -52,30 +52,36 @@
{\c_xsim_info_tl}
% --------------------------------------------------------------------------
-
% options, information
-\bool_new:N \g__xsim_final_bool
-\bool_new:N \g__xsim_verbose_bool
-\bool_new:N \g__xsim_debug_bool
-\bool_new:N \g_xsim_clear_aux_bool
-\bool_new:N \g__xsim_write_to_file_bool
-\bool_new:N \g_xsim_use_aux_bool
-\bool_new:N \g__xsim_rerun_bool
-\bool_new:N \g__xsim_blank_bool
+\cs_new_protected:Npn \xsim_bool_provide:N #1
+ { \bool_if_exist:NF #1 { \bool_new:N #1 } }
+
+\xsim_bool_provide:N \g__xsim_final_bool
+\xsim_bool_provide:N \g__xsim_verbose_bool
+\xsim_bool_provide:N \g_xsim_clear_aux_bool
+\xsim_bool_provide:N \g__xsim_write_to_file_bool
+\xsim_bool_provide:N \g_xsim_use_aux_bool
+\xsim_bool_provide:N \g__xsim_rerun_bool
+\xsim_bool_provide:N \g__xsim_debug_bool
+\xsim_bool_provide:N \g__xsim_blank_bool
\keys_define:nn {xsim/package}
{
- final .bool_gset:N = \g__xsim_final_bool ,
- verbose .bool_gset:N = \g__xsim_verbose_bool ,
- debug .bool_gset:N = \g__xsim_debug_bool ,
- clear-aux .bool_gset:N = \g_xsim_clear_aux_bool ,
- no-files .bool_gset_inverse:N = \g__xsim_write_to_file_bool ,
- no-files .initial:n = false ,
- use-aux .bool_gset:N = \g_xsim_use_aux_bool ,
- use-aux .initial:n = false ,
- blank .bool_gset:N = \g__xsim_blank_bool ,
- blank .initial:n = false
+ final .bool_gset:N = \g__xsim_final_bool ,
+ verbose .bool_gset:N = \g__xsim_verbose_bool ,
+ debug .bool_gset:N = \g__xsim_debug_bool ,
+ clear-aux .bool_gset:N = \g_xsim_clear_aux_bool ,
+ use-files .bool_gset:N = \g__xsim_write_to_file_bool ,
+ use-files .initial:n = false ,
+ no-files .choice: ,
+ no-files / true .meta:n = { use-files = false } ,
+ no-files / false .meta:n = { use-files = true } ,
+ no-files .default:n = true ,
+ use-aux .bool_gset:N = \g_xsim_use_aux_bool ,
+ use-aux .initial:n = false ,
+ blank .bool_gset:N = \g__xsim_blank_bool ,
+ blank .initial:n = false
}
\ProcessKeysPackageOptions {xsim/package}
@@ -86,6 +92,7 @@
verbose .code:n = \msg_error:nnn {xsim} {load-time-option} {verbose} ,
debug .code:n = \msg_error:nnn {xsim} {load-time-option} {debug} ,
clear-aux .code:n = \msg_error:nnn {xsim} {load-time-option} {clear-aux} ,
+ use-files .code:n = \msg_error:nnn {xsim} {load-time-option} {use-files} ,
no-files .code:n = \msg_error:nnn {xsim} {load-time-option} {no-files} ,
use-aux .code:n = \msg_error:nnn {xsim} {load-time-option} {use-aux} ,
blank .code:n = \msg_error:nnn {xsim} {load-time-option} {blank}
@@ -115,22 +122,5508 @@
{ \xsim_if_rerun:T { \msg_warning:nn {xsim} {rerun} } }
% --------------------------------------------------------------------------
+% MODULE mechanism
+\msg_new:nnn {xsim} {module-missing}
+ {
+ You've~ requested~ the~ xsim~ module~ `#1'~ but~ it~ appears~ to~
+ be~ missing~ on~ your~ system.~ Maybe~ you've~ misspelled~ the~ name?~
+ Loading~ the~ module~ will~ abort~ \msg_line_context:
+ }
-% load module mechanism:
-\tl_set:Nn \l_tmpa_tl {code.tex}
-\@onefilewithoptions {xsim.modules} [][] \l_tmpa_tl
+\msg_new:nnn {xsim} {loading-module}
+ { Loading~ module~ `#1'~ ... }
+\msg_new:nnn {xsim} {wrong-module-name}
+ { The~ module~ file~ name~ is~ `#2'~ but~ it~ provides~ module~ `#1'. }
+
+\msg_new:nnn {xsim} {forbidden-module}
+ {
+ You've~ requested~ the~ xsim~ module~ `modules'~ \msg_line_context: .~
+ This~ module~ is~ a~ pseudo~ module~ which~ may~ not~ be~ loaded~ through~
+ the~ module~ loading~ mechansim.
+ }
+
+% ----------------------------------------------------------------------------
+
+\cs_generate_variant:Nn \str_if_eq:nnF {xx}
+
+\tl_const:Nn \c__xsim_module_extension_tl {code.tex}
+\tl_const:Nn \c__xsim_module_prefix_tl {xsim}
+
+\cs_new_protected:Npn \xsim_load_module:n #1
+ {
+ \tl_set:Nx \l_tmpa_tl { \tl_trim_spaces:n {#1} }
+ \str_if_eq:VnTF \l_tmpa_tl {modules}
+ { \msg_error:nn {xsim} {forbidden-module} }
+ { \__xsim_load_module:V \l_tmpa_tl }
+ }
+
+\cs_new_protected:Npn \__xsim_load_module:n #1
+ {
+ \xsim_if_module_loaded:nF {#1}
+ {
+ \xsim_if_module_exist:nTF {#1}
+ {
+ \__xsim_module_hook_use:nn {#1} {before}
+ \msg_info:nnn {xsim} {loading-module} {#1}
+ \@onefilewithoptions
+ {\c__xsim_module_prefix_tl.#1}[][]
+ \c__xsim_module_extension_tl
+ \__xsim_module_hook_use:nn {#1} {after}
+ }
+ { \msg_error:nnn {xsim} {module-missing} {#1} }
+ }
+ }
+\cs_generate_variant:Nn \__xsim_load_module:n {V}
+
+\tl_new:N \g__xsim_modules_loaded_tl
+
+\prg_new_conditional:Npnn \xsim_if_module_loaded:n #1 {p,T,F,TF}
+ {
+ \tl_if_in:NnTF \g__xsim_modules_loaded_tl {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_module_exist:n #1 {p,T,F,TF}
+ {
+ \file_if_exist:nTF
+ {\c__xsim_module_prefix_tl.#1.\c__xsim_module_extension_tl}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
% --------------------------------------------------------------------------
-\xsim_load_modules:n {definitions}
+% module hooks:
+% #1: module
+% #2: code
+\cs_new_protected:Npn \xsim_module_after:nn #1#2
+ {
+ \xsim_if_module_loaded:nTF {#1}
+ {#2}
+ { \__xsim_add_to_module_hook:nnn {#1} {after} {#2} }
+ }
-\AtEndDocument
+% #1: module
+% #2: code
+\cs_new_protected:Npn \xsim_module_before:nn #1#2
{
- \xsim_do_rerun:
- \xsim_close_aux:
+ % TODO: error in T case?
+ \xsim_if_module_loaded:nF {#1}
+ { \__xsim_add_to_module_hook:nnn {#1} {before} {#2} }
}
+% #1: module
+% #2: hook name
+% #3: code
+\cs_new_protected:Npn \__xsim_add_to_module_hook:nnn #1#2#3
+ {
+ \xsim_if_module_loaded:nF {#1}
+ {
+ \tl_if_exist:cF {g__xsim_module_hook_#1_#2_tl}
+ { \tl_new:c {g__xsim_module_hook_#1_#2_tl} }
+ \tl_gput_right:cn {g__xsim_module_hook_#1_#2_tl} {#3}
+ }
+ }
+
+% #1: module
+% #2: hook name
+\cs_new_protected:Npn \__xsim_module_hook_use:nn #1#2
+ {
+ \tl_if_exist:cT {g__xsim_module_hook_#1_#2_tl}
+ {
+ \tl_use:c {g__xsim_module_hook_#1_#2_tl}
+ \tl_gclear:c {g__xsim_module_hook_#1_#2_tl}
+ }
+ }
+\cs_generate_variant:Nn \__xsim_module_hook_use:nn {V}
+
% --------------------------------------------------------------------------
+
+\tl_new:N \l__xsim_module_date_tl
+\tl_new:N \l__xsim_module_version_tl
+
+\tl_if_exist:NF \c_xsim_date_tl
+ { \tl_set:Nx \l__xsim_module_date_tl {\c_xsimverb_date_tl} }
+\tl_if_exist:NF \c_xsim_version_tl
+ { \tl_set:Nx \l__xsim_module_version_tl {\c_xsimverb_version_tl} }
+
+\hook_gput_code:nnn {package/after/xsim} {xsim}
+ {
+ \tl_set:NV \l__xsim_module_date_tl \c_xsim_date_tl
+ \tl_set:NV \l__xsim_module_version_tl \c_xsim_version_tl
+ }
+
+\cs_new_protected:Npn \__xsim_module:nn #1#2
+ {
+ \str_if_eq:xxF
+ {\c__xsim_module_prefix_tl.#1.\c__xsim_module_extension_tl}
+ {\@currname.\@currext}
+ {
+ \msg_error:nnnxx {xsim} {wrong-module-name}
+ {#1}
+ {\@currname.\@currext}
+ }
+ \ProvidesFile
+ {\c__xsim_module_prefix_tl.#1.\c__xsim_module_extension_tl}
+ [
+ \l__xsim_module_date_tl
+ \c_space_tl
+ v \l__xsim_module_version_tl
+ \c_space_tl
+ xsim~ module~ `#1'~ (#2)
+ ]
+ }
+\cs_generate_variant:Nn \msg_error:nnnn {nnnx}
+
+% --------------------------------------------------------------------------
+% define a xsim module:
+% #1: if star: expl3 mode
+% #2: name
+% #3: description
+\NewDocumentCommand \xsimstyle {smO{}}
+ {
+ \__xsim_module:nn {style.#2} {#3}
+ \IfBooleanT {#1} { \ExplSyntaxOn }
+ }
+
+% \cs_new_protected:Npn \xsim_style_options:nn #1#2
+% { \keys_define:nn {xsim/#1} {#2} }
+
+\cs_new_protected:Npn \xsim_load_style:n #1
+ { \clist_map_inline:nn {#1} { \xsim_load_module:n {style.##1} } }
+
+\keys_define:nn {xsim}
+ { load-style .code:n = \xsim_load_style:n {#1} }
+
+\NewDocumentCommand \loadxsimstyle {m}
+ { \xsim_load_style:n {#1} }
+
+% --------------------------------------------------------------------------
+% define internal xsim modules:
+\tl_new:N \g_xsim_module_tl
+\tl_new:N \g__xsim_module_stop_tl
+
+\cs_new_protected:Npn \xsim_stop_module:n #1
+ { \tl_gput_right:Nn \g__xsim_module_stop_tl {{#1}} }
+
+% #1: name
+% #2: description
+\cs_set_protected:Npn \XSIMmodule #1#2
+ {
+ \msg_log:nnnn {xsim} {loading-module} {#1} {#2}
+ \tl_gput_right:Nn \g__xsim_modules_loaded_tl {{#1}}
+ \tl_gset:Nn \g_xsim_module_tl {#1}
+ \__xsim_module_hook_use:nn {#1} {before}
+ \tl_map_inline:Nn \g__xsim_module_stop_tl
+ {
+ \str_if_eq:nnT {##1} {#1}
+ { \tl_map_break:n { \__xsim_gobble_module:w } }
+ }
+ }
+
+\cs_set_protected:Npn \XSIMmoduleend
+ { \__xsim_module_hook_use:Vn \g_xsim_module_tl {after} }
+
+\cs_new_protected:Npn \__xsim_gobble_module:w #1 \XSIMmoduleend {}
+
+% --------------------------------------------------------------------------
+\XSIMmodule{base}{basic functionality of the package}
+
+% \tl_new:N \g_xsim_end_document_hook_tl
+% \tl_new:N \g_xsim_begin_document_hook_tl
+
+% \hook_gput_code:nnn {begindocument} {xsim}
+% { \tl_use:N \g_xsim_begin_document_hook_tl }
+% \hook_gput_code:nnn {enddocument} {xsim}
+% { \tl_use:N \g_xsim_end_document_hook_tl }
+
+% \cs_new_protected:Npn \xsim_at_begin_document:n #1
+% { \tl_gput_right:Nn \g_xsim_begin_document_hook_tl {#1} }
+
+% \cs_new_protected:Npn \xsim_at_end_document:n #1
+% { \tl_gput_right:Nn \g_xsim_end_document_hook_tl {#1} }
+
+\cs_new_protected:Npn \xsim_at_begin_document:n #1
+ { \hook_gput_code:nnn {begindocument} {xsim} {#1} }
+
+\cs_new_protected:Npn \xsim_before_begin_document:n #1
+ { \hook_gput_code:nnn {begindocument/before} {xsim} {#1} }
+
+\cs_new_protected:Npn \xsim_at_end_document:n #1
+ { \hook_gput_code:nnn {enddocument} {xsim} {#1} }
+
+\cs_new_protected:Npn \xsim_before_end_document:n #1
+ { \hook_gput_code:nnn {enddocument/before} {xsim} {#1} }
+
+% ----------------------------------------------------------------------------
+
+% variants of kernel functions:
+\cs_generate_variant:Nn \seq_set_split:Nnn {Nnx,NV}
+\cs_generate_variant:Nn \seq_gset_split:Nnn {c,cVx,cnx}
+\cs_generate_variant:Nn \seq_use:Nn {cV}
+\cs_generate_variant:Nn \seq_count:N {c}
+\cs_generate_variant:Nn \seq_if_empty:NT {c}
+\cs_generate_variant:Nn \seq_if_in:NnT {cV}
+\cs_generate_variant:Nn \seq_gremove_all:Nn {cV}
+\cs_generate_variant:Nn \seq_gput_right:Nn {cV}
+\cs_generate_variant:Nn \seq_set_from_clist:Nn {c,Nx}
+\cs_generate_variant:Nn \prop_put:Nnn {Nnx,cxx}
+\cs_generate_variant:Nn \prop_gput:Nnn {Nx,Nnx,cxx}
+\cs_generate_variant:Nn \prop_item:Nn {c}
+\cs_generate_variant:Nn \prop_if_in:NnTF {Nx}
+\cs_generate_variant:Nn \use:nn {nx}
+\cs_generate_variant:Nn \file_input:n {V,x}
+\cs_generate_variant:Nn \file_if_exist:nT {V,x}
+\cs_generate_variant:Nn \file_if_exist:nTF {V}
+\cs_generate_variant:Nn \msg_error:nnnnn {nnnxx}
+\cs_generate_variant:Nn \msg_warning:nnn {nnV}
+\cs_generate_variant:Nn \keys_define:nn {nx}
+\cs_generate_variant:Nn \keys_set:nn {xn,nx}
+\cs_generate_variant:Nn \text_titlecase:n {e}
+\cs_generate_variant:Nn \tl_if_eq:nnTF {ee,ff,V}
+\cs_generate_variant:Nn \tl_if_eq:nnT {x}
+\cs_generate_variant:Nn \tl_if_blank:nTF {f,e}
+\cs_generate_variant:Nn \tl_set_rescan:Nnn {Nnx}
+\cs_generate_variant:Nn \iow_now:Nn {NV}
+\cs_generate_variant:Nn \str_if_eq:nnT {x}
+\cs_generate_variant:Nn \str_if_eq:nnF {xx}
+\cs_generate_variant:Nn \str_if_eq_p:nn {e}
+\cs_generate_variant:Nn \prg_new_protected_conditional:Npnn {c}
+\cs_generate_variant:Nn \clist_map_inline:nn {V}
+
+% ----------------------------------------------------------------------------
+% temporary variables:
+\tl_new:N \l__xsim_tmpa_tl
+\tl_new:N \l__xsim_tmpb_tl
+\tl_new:N \l__xsim_tmpc_tl
+\tl_new:N \l__xsim_tmpd_tl
+
+\str_new:N \l__xsim_tmpa_str
+\str_new:N \l__xsim_tmpb_str
+\str_new:N \l__xsim_tmpc_str
+
+\bool_new:N \l__xsim_tmpa_bool
+\bool_new:N \l__xsim_tmpb_bool
+\bool_new:N \l__xsim_tmpc_bool
+
+\dim_new:N \l__xsim_tmpa_dim
+\dim_new:N \l__xsim_tmpb_dim
+\dim_new:N \l__xsim_tmpc_dim
+
+\seq_new:N \l__xsim_tmpa_seq
+\seq_new:N \l__xsim_tmpb_seq
+\seq_new:N \l__xsim_tmpc_seq
+
+\int_new:N \l__xsim_tmpa_int
+\int_new:N \l__xsim_tmpb_int
+\int_new:N \l__xsim_tmpc_int
+
+\fp_new:N \l__xsim_tmpa_fp
+\fp_new:N \l__xsim_tmpb_fp
+\fp_new:N \l__xsim_tmpc_fp
+
+\box_new:N \l__xsim_tmpa_box
+\box_new:N \l__xsim_tmpb_box
+\box_new:N \l__xsim_tmpc_box
+
+\clist_new:N \l__xsim_tmpa_clist
+\clist_new:N \l__xsim_tmpb_clist
+\clist_new:N \l__xsim_tmpc_clist
+
+% ----------------------------------------------------------------------------
+
+\prg_new_conditional:Npnn \xsim_if_komascript: {T,F,TF}
+ {
+ \cs_if_exist:cTF {KOMAClassName}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% ----------------------------------------------------------------------------
+
+\cs_if_exist:NF \xsim_if_final:T
+ {
+ \prg_new_conditional:Npnn \xsim_if_final: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_final_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+ \prg_new_conditional:Npnn \xsim_if_verbose: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_verbose_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_debug: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_debug_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_package_blank: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_blank_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_rerun: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_rerun_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_write_to_files: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_write_to_file_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_clear_aux: {p,T,F,TF}
+ {
+ \xsim_if_final:TF
+ { \prg_return_false: }
+ {
+ \bool_if:NTF \g_xsim_clear_aux_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+
+\cs_if_exist:NF \xsim_verbose:n
+ {
+ \cs_new_protected:Npn \xsim_verbose:n #1
+ { \xsim_if_verbose:T { \msg_info:nnn {xsim} {verbose} {#1} } }
+ \cs_generate_variant:Nn \xsim_verbose:n {x}
+ }
+
+\cs_new_protected:Npn \xsim_rerun:
+ { \bool_gset_true:N \g__xsim_rerun_bool }
+
+\prg_new_conditional:Npnn \xsim_if_chapter: {p,T,F,TF}
+ {
+ \bool_lazy_and:nnTF
+ { \cs_if_exist_p:N \chapter }
+ { \cs_if_exist_p:N \c at chapter }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% ----------------------------------------------------------------------------
+
+\msg_new:nnn {xsim} {attribute-not-set}
+ { The~ attribute~ `#1'~ is~ not~ set~ \msg_line_context: }
+
+% #1: attribute
+% #2: item
+\cs_new_protected:Npn \xsim_attribute_new:nn #1#2
+ { \cs_new:cpn {____xsim_attribute_ \tl_to_str:n {#1::#2} :} {} }
+
+% #1: attribute
+% #2: item
+% #3: value
+\cs_new_protected:Npn \xsim_attribute_set:nnn #1#2#3
+ {
+ \cs_gset:cpx
+ {____xsim_attribute_ \tl_to_str:n {#1::#2} :}
+ { \exp_not:n { \exp_not:n {#3} } }
+ }
+\cs_generate_variant:Nn \xsim_attribute_set:nnn {nnx}
+
+% #1: attribute
+% #2: item
+\cs_new_protected:Npn \xsim_attribute_unset:nn #1#2
+ { \cs_undefine:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} }
+
+% #1: attribute
+% #2: item
+\cs_new:Npn \xsim_attribute_get:nn #1#2
+ {
+ \cs_if_exist:cTF {____xsim_attribute_ \tl_to_str:n {#1::#2} :}
+ { \use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} }
+ {
+ \xsim_if_debug:T
+ { \msg_expandable_error:nnn {xsim} {attribute-not-set} {#1::#2} }
+ }
+ }
+
+% #1: attribute
+% #2: item
+\prg_new_conditional:Npnn \xsim_attribute_if_set:nn #1#2 {p,T,F,TF}
+ {
+ \cs_if_exist:cTF {____xsim_attribute_ \tl_to_str:n {#1::#2} :}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: attribute
+% #2: item
+\prg_new_conditional:Npnn \__xsim_if_attribute_eq:nnn #1#2#3 {p,T,F,TF}
+ {
+ \tl_if_eq:enTF
+ { \use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :} }
+ {#3}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: attribute
+% #2: item
+\cs_new_protected:Npn \xsim_attribute_show:nn #1#2
+ {
+ \iow_term:n {}
+ \iow_term:x
+ {
+ \c_space_tl \c_space_tl
+ \tl_to_str:n {#1::#2}
+ \c_space_tl \c_space_tl == \c_space_tl \c_space_tl
+ {\use:c {____xsim_attribute_ \tl_to_str:n {#1::#2} :}}
+ }
+ \iow_term:n {}
+ }
+
+% ----------------------------------------------------------------------------
+
+\cs_new_protected:Npn \xsim_setup:n #1
+ { \keys_set:nn {xsim} {#1} }
+
+\XSIMmoduleend
+\XSIMmodule{auxfile}{writing stuff to an auxiliary file}
+
+\prg_new_conditional:Npnn \xsim_if_use_aux: {p,T,F,TF}
+ {
+ \bool_if:NTF \g_xsim_use_aux_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new_protected:Npn \xsim_write_to_aux:n #1
+ {
+ \legacy_if:nT {@filesw}
+ {
+ \xsim_if_use_aux:TF
+ { \iow_now:Nn \@auxout {#1} }
+ { \iow_now:Nn \l__xsim_aux_file_iow {#1} }
+ }
+ }
+\cs_generate_variant:Nn \xsim_write_to_aux:n {x}
+
+% --------------------------------------------------------------------------
+
+\cs_new_protected:Npn \XSIM #1 { \use:c {XSIMaux#1} }
+
+\cs_new_protected:Npn \xsim_new_aux_property:cpn #1
+ { \cs_new_protected:cpn {XSIMaux#1} }
+
+\cs_new_protected:Npn \xsim_add_property_to_aux:nn #1#2
+ {
+ \xsim_verbose:n { Writing~ command~ \XSIM {#1}~ to~ aux~ file }
+ \xsim_write_to_aux:x { \token_to_str:N \XSIM {#1} #2 }
+ }
+
+\xsim_at_begin_document:n
+ {
+ \iow_now:Nx \@auxout
+ { \token_to_str:N \providecommand \token_to_str:N \XSIM [1] {} }
+ }
+
+% ----------------------------------------------------------------------------
+
+\xsim_if_use_aux:F
+ {
+ \iow_new:N \l__xsim_aux_file_iow
+ \hook_gput_code:nnn {begindocument} {xsim}
+ { \iow_open:Nn \l__xsim_aux_file_iow { \c_sys_jobname_str .xsim } }
+ }
+
+\cs_new_protected:Npn \xsim_close_aux:
+ {
+ \xsim_if_use_aux:F
+ {
+ \iow_close:N \l__xsim_aux_file_iow
+ \legacy_if:nT {@filesw}
+ { \iow_now:Nx \@auxout { \token_to_str:N \XSIM {readaux} } }
+ }
+ }
+
+\xsim_new_aux_property:cpn {readaux}
+ {
+ \file_if_exist:nT { \c_sys_jobname_str .xsim }
+ { \file_input:n { \c_sys_jobname_str .xsim } }
+ }
+
+% ----------------------------------------------------------------------------
+% list for recording values that need to be written to the aux file and
+% updated at begin document
+
+\str_new:N \l__xsim_split_aux_lists_str
+\keys_define:nn {xsim}
+ {
+ split-aux-lists .code:n = \str_set:Nn \l__xsim_split_aux_lists_str {#1} ,
+ split-aux-lists .initial:n = ||
+ }
+
+% define list:
+% #1: name
+\cs_new_protected:Npn \xsim_new_list:n #1
+ {
+ \xsim_verbose:n { Defining~ new~ auxfile~ list~ `#1'. }
+ \seq_new:c {g__xsim_list_#1_seq}
+ \seq_new:c {g__xsim_list_recorded_#1_seq}
+ \xsim_new_aux_property:cpn {#1} ##1
+ {
+ \tl_if_blank:nF {##1}
+ {
+ \seq_gset_split:cVx {g__xsim_list_#1_seq}
+ \l__xsim_split_aux_lists_str
+ { \tl_to_str:n {##1} }
+ \seq_map_inline:cn {g__xsim_list_#1_seq}
+ { \xsim_attribute_set:nnn {#1} {####1} {} }
+ }
+ }
+ \xsim_at_begin_document:n { \xsim_set_list:n {#1} }
+ }
+
+% #1: name
+\cs_new_protected:Npn \xsim_set_list:n #1
+ {
+ \seq_gclear:c {g__xsim_list_recorded_#1_seq}
+ \seq_set_eq:Nc \l__xsim_tmpa_seq {g__xsim_list_#1_seq}
+ \seq_map_inline:Nn \l__xsim_tmpa_seq
+ {
+ \str_set:Nn \l__xsim_tmpa_str {##1}
+ \seq_gput_right:cV {g__xsim_list_recorded_#1_seq} \l__xsim_tmpa_str
+ }
+ \seq_gremove_duplicates:c {g__xsim_list_recorded_#1_seq}
+ }
+
+% add to or remove from list:
+% #1: name
+% #2: entry
+\cs_new_protected:Npn \xsim_add_to_list:nn #1#2
+ {
+ \xsim_verbose:n { Adding~ `#2'~ to~ list~ `#1'. }
+ \str_set:Nn \l__xsim_tmpa_str {#2}
+ \xsim_attribute_set:nnn {#1} {#2} {}
+ \seq_if_in:cVT {g__xsim_list_#1_seq} \l__xsim_tmpa_str
+ { \seq_gremove_all:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str }
+ \seq_gput_right:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str
+ }
+\cs_generate_variant:Nn \xsim_add_to_list:nn {nx}
+
+% #1: name
+% #2: entry
+\cs_new_protected:Npn \xsim_remove_from_list:nn #1#2
+ {
+ \xsim_verbose:n { Removing~ `#2'~ to~ list~ `#1'. }
+ \str_set:Nn \l__xsim_tmpa_str {#2}
+ \xsim_attribute_if_set:nnT {#1} {#2}
+ { \xsim_attribute_unset:nn {#1} {#2} }
+ \seq_if_in:cVT {g__xsim_list_#1_seq} \l__xsim_tmpa_str
+ { \seq_gremove_all:cV {g__xsim_list_#1_seq} \l__xsim_tmpa_str }
+ \seq_if_in:cVT {g__xsim_list_recorded#1_seq} \l__xsim_tmpa_str
+ { \seq_gremove_all:cV {g__xsim_list_recorded_#1_seq} \l__xsim_tmpa_str }
+ }
+\cs_generate_variant:Nn \xsim_remove_from_list:nn {nx}
+
+% check if in list:
+% #1: name
+% #2: entry
+\prg_new_conditional:Npnn \xsim_if_in_list:nn #1#2 {p,T,F,TF}
+ {
+ \xsim_attribute_if_set:nnTF {#1} {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_if_in_list:nn {nx} {T,TF}
+
+\bool_new:N \l__xsim_empty_lists_bool
+\cs_new_protected:Npn \xsim_empty_lists:
+ { \bool_set_true:N \l__xsim_empty_lists_bool }
+
+% update list (should be used inside \xsim_at_end_document:n):
+% #1: name
+\cs_new_protected:Npn \xsim_update_list:n #1
+ {
+ \xsim_verbose:n { Updating~ list~ `#1'. }
+ \seq_gremove_duplicates:c {g__xsim_list_#1_seq}
+ \seq_gremove_duplicates:c {g__xsim_list_recorded_#1_seq}
+ \str_set:Nx \l__xsim_tmpa_str
+ { \seq_use:cn {g__xsim_list_#1_seq} {} }
+ \str_set:Nx \l__xsim_tmpb_str
+ { \seq_use:cn {g__xsim_list_recorded_#1_seq} {} }
+ \str_if_eq:NNF \l__xsim_tmpa_str \l__xsim_tmpb_str
+ { \xsim_rerun: }
+ \bool_if:NF \l__xsim_empty_lists_bool
+ {
+ \xsim_add_property_to_aux:nn {#1}
+ { { \seq_use:cV {g__xsim_list_#1_seq} \l__xsim_split_aux_lists_str } }
+ }
+ }
+
+% loop over list:
+% #1: name
+% #2: code
+\cs_new_protected:Npn \xsim_foreach_list_entry:nn #1#2
+ { \seq_map_inline:cn {g__xsim_list_recorded_#1_seq} {#2} }
+
+\cs_new_protected:Npn \xsim_foreach_new_list_entry:nn #1#2
+ { \seq_map_inline:cn {g__xsim_list_#1_seq} {#2} }
+
+% length of a list:
+% #1: name
+\cs_new:Npn \xsim_list_count:n #1
+ { \seq_count:c {g__xsim_list_recorded_#1_seq} }
+
+% item of a list:
+% #1: name
+% #2: integer
+\cs_new:Npn \xsim_list_item:nn #1#2
+ { \seq_item:cn {g__xsim_list_recorded_#1_seq} {#2} }
+
+\XSIMmoduleend
+\XSIMmodule{properties}{properties of exercises}
+
+\msg_new:nnn {xsim} {unknown-property}
+ {
+ You~ tried~ to~ set~ the~ property~ `#1'~ \msg_line_context: . \\
+ This~ property~ does~ not~ exist.~ Check~ for~ a~ typo~ or~ \\
+ define~ the~ property~ yourself.
+ }
+
+\msg_new:nnn {xsim} {property-unique}
+ {
+ You~ tried~ to~ set~ the~ property~ `#1'~ \msg_line_context: . \\
+ This~ property~ has~ to~ have~ a~ unique~ value~ and~ thus~ \\
+ cannot~ be~ set~ to~ `#2'~ since~ this~ value~ is~ already~ taken.
+ }
+
+\msg_new:nnn {xsim} {no-boolean-property}
+ {
+ You~ tried~ to~ check~ the~ boolean~ value~ of~ property~ `#1'~
+ \msg_line_context: . \\
+ However,~ property~ `#1'~ is~ not~ a~ boolean~ property!
+ }
+
+\msg_new:nnn {xsim} {unbalanced-property-list}
+ {
+ There~ is~ a~ mis-match~ in~ the~ property~ list: \\
+ `#1' \\
+ \msg_line_context:
+ }
+
+% ----------------------------------------------------------------------------
+\seq_new:N \l__xsim_properties_seq
+\seq_new:N \l__xsim_boolean_properties_seq
+\seq_new:N \l__xsim_unique_properties_seq
+\seq_new:N \l__xsim_noupdate_properties_seq
+\seq_new:N \l__xsim_given_properties_seq
+
+% #1: type
+% #2: id
+% #3: property
+\cs_new_protected:Npn \__xsim_define_property:nnn #1#2#3
+ { \xsim_attribute_new:nn {#1!#2} {#3} }
+
+% check if property is set:
+% #1: type
+% #2: id
+% #3: property
+\prg_new_conditional:Npnn \xsim_if_property_set:nnn #1#2#3 {p,T,F,TF}
+ {
+ \xsim_attribute_if_set:nnTF {#1!#2} {#3}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_if_property_set:nnn
+ {ne,nne,ee,nV}
+ {p,T,F,TF}
+
+% new property:
+% #1: boolean if unique
+% #2: boolean if boolean
+% #3: boolean if noupdate
+% #4: property name
+\cs_new_protected:Npn \xsim_declare_property:nnnn #1#2#3#4
+ {
+ \xsim_if_property_exist:nF {#4}
+ {
+ \seq_put_right:Nn \l__xsim_properties_seq {#4}
+ \bool_if:nTF {#3}
+ {
+ \seq_if_in:NnF \l__xsim_noupdate_properties_seq {#4}
+ { \seq_put_right:Nn \l__xsim_noupdate_properties_seq {#4} }
+ }
+ { \xsim_new_list:n {#4} }
+ \bool_if:nTF {#2}
+ {
+ \xsim_verbose:n
+ { Declaring~ new~ boolean~ exercise~ property~ `#4'. }
+ \seq_if_in:NnF \l__xsim_boolean_properties_seq {#4}
+ { \seq_put_right:Nn \l__xsim_boolean_properties_seq {#4} }
+ }
+ {
+ \bool_if:nTF {#1}
+ {
+ \xsim_verbose:n
+ { Declaring~ new~ unique~ exercise~ property~ `#4'. }
+ \seq_if_in:NnF \l__xsim_unique_properties_seq {#4}
+ { \seq_put_right:Nn \l__xsim_unique_properties_seq {#4} }
+ \seq_new:c {l__xsim_unique_property_#4_values_seq}
+ }
+ { \xsim_verbose:n { Declaring~ new~ exercise~ property~ `#4'. } }
+ }
+ \bool_if:nF {#3}
+ {
+ \xsim_at_end_document:n { \xsim_update_list:n {#4} }
+ \xsim_at_begin_document:n { \__xsim_set_property_from_list:n {#4} }
+ }
+ }
+ }
+
+% ----------------------------------------------------------------------------
+% check if property exists:
+\prg_new_conditional:Npnn \xsim_if_property_exist:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_properties_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_property_exist:nTF {x}
+
+\prg_new_conditional:Npnn \xsim_if_property_noupdate:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_noupdate_properties_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_property_noupdate:nF {V}
+
+\prg_new_conditional:Npnn \xsim_if_property_boolean:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_boolean_properties_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_property_unique:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_unique_properties_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% true if property #1 has been set in the /last/ call of
+% \xsim_set_properties:nnn
+\prg_new_conditional:Npnn \xsim_if_property_given:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_given_properties_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: property
+% #2: value
+\prg_new_conditional:Npnn \xsim_if_property_unique_value:nn #1#2 {p,T,F,TF}
+ {
+ \xsim_if_property_unique:nTF {#1}
+ {
+ \seq_if_in:cnTF {l__xsim_unique_property_#1_values_seq} {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+
+% #1: code
+\cs_new_protected:Npn \xsim_foreach_property:n #1
+ { \seq_map_inline:Nn \l__xsim_properties_seq {#1} }
+
+% ----------------------------------------------------------------------------
+% #1: type
+% #2: id
+% #3: property
+% #4: value
+\cs_new_protected:Npn \xsim_set_property:nnnn #1#2#3#4
+ {
+ \xsim_if_property_unique:nTF {#3}
+ {
+ \xsim_if_property_unique_value:nnTF {#3} {#4}
+ { \msg_warning:nnnn {xsim} {property-unique} {#3} {#4} }
+ { \__xsim_set_unique_property:nnnn {#1} {#2} {#3} {#4} }
+ }
+ {
+ \xsim_if_property_boolean:nTF {#3}
+ { \__xsim_set_boolean_property:nnnn {#1} {#2} {#3} {#4} }
+ { \__xsim_set_property:nnnn {#1} {#2} {#3} {#4} }
+ }
+ }
+\cs_generate_variant:Nn \xsim_set_property:nnnn {nnee,nnnV,nV,nVne,nnne,ee,eene,nene}
+
+% #1: type
+% #2: id
+% #3: property
+% #4: value
+\cs_new_protected:Npn \__xsim_set_boolean_property:nnnn #1#2#3#4
+ {
+ \str_case_e:nnTF { \str_lowercase:n {#4} }
+ {
+ {} {}
+ {true} {}
+ }
+ { \__xsim_set_property:nnnn {#1} {#2} {#3} {true} }
+ { \__xsim_set_property:nnnn {#1} {#2} {#3} {false} }
+ }
+
+% #1: type
+% #2: id
+% #3: property
+% #4: value
+\cs_new_protected:Npn \__xsim_set_unique_property:nnnn #1#2#3#4
+ {
+ \__xsim_set_property:nnnn {#1} {#2} {#3} {#4}
+ \__xsim_set_property_reverse:nnnn {#1} {#2} {#3} {#4}
+ }
+
+% #1: type
+% #2: id
+% #3: property
+\cs_new_protected:Npn \__xsim_unset_property:nnn #1#2#3
+ {
+ \xsim_verbose:n
+ { Un-setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'. }
+ \xsim_if_property_noupdate:nF {#3}
+ { \__xsim_remove_property_from_list:nnn {#1} {#2} {#3} }
+ \xsim_attribute_unset:nn {#1!#2} {#3}
+ }
+
+% #1: type
+% #2: id
+% #3: property
+\cs_new_protected:Npn \xsim_unset_property:nnn #1#2#3
+ {
+ \xsim_if_property_exist:nTF {#3}
+ { \__xsim_unset_property:nnn {#1} {#2} {#3} }
+ { \msg_error:nnn {xsim} {unknown-property} {#3} }
+ }
+\cs_generate_variant:Nn \xsim_unset_property:nnn {nx,nnx,nV}
+
+% #1: type
+% #2: id
+% #3: property
+% #4: value
+\cs_new_protected:Npn \__xsim_set_property:nnnn #1#2#3#4
+ {
+ \xsim_verbose:n
+ {
+ Setting~ property~ `#3'~ of~ exercise~ type~ `#1'~ id~ `#2'~ to~
+ value~ `#4'.
+ }
+ \xsim_if_property_noupdate:nF {#3}
+ {
+ \__xsim_remove_property_from_list:nnn {#1} {#2} {#3}
+ \xsim_add_to_list:nn {#3} {#1-#2=={#4}}
+ }
+ \xsim_attribute_set:nnn {#1!#2} {#3} {#4}
+ }
+\cs_generate_variant:Nn \__xsim_set_property:nnnn {VVnV}
+
+% #1: type
+% #2: id
+% #3: property
+% #4: value
+\cs_new_protected:Npn \__xsim_set_property_reverse:nnnn #1#2#3#4
+ {
+ \xsim_attribute_set:nnn {type:#3} {#4} {#1}
+ \xsim_attribute_set:nnn {id:#3} {#4} {#2}
+ }
+
+\tl_set:Nx \l__xsim_tmpa_tl { \cs_to_str:N \{ }
+\tl_set:Nx \l__xsim_tmpb_tl { \cs_to_str:N \} }
+\use:x
+ {
+ \cs_new_protected:Npn
+ \exp_not:N \__xsim_extract_property_list_entry:NNNwww
+ ##1##2##3##4-##5== \l__xsim_tmpa_tl ##6 \l__xsim_tmpb_tl
+ \exp_not:N \q_stop
+ }
+ {
+ \str_set:Nn #1 {#4}
+ \str_set:Nn #2 {#5}
+ \str_set:Nn #3 {#6}
+ }
+
+% #1: type
+% #2: id
+% #3: property
+\cs_new_protected:Npn \__xsim_remove_property_from_list:nnn #1#2#3
+ {
+ % make sure we change the entry if it has been recorded previously:
+ \xsim_foreach_list_entry:nn {#3}
+ {
+ \__xsim_extract_property_list_entry:NNNwww
+ \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop
+ \str_if_eq:xnT { \l__xsim_tmpa_str - \l__xsim_tmpb_str } {#1-#2}
+ {
+ \xsim_remove_from_list:nx {#3}
+ { #1-#2 == {\l__xsim_tmpc_str} }
+ }
+ }
+ % make sure we change the entry if it has been set during the current run:
+ \xsim_foreach_new_list_entry:nn {#3}
+ {
+ \__xsim_extract_property_list_entry:NNNwww
+ \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop
+ \str_if_eq:xnT { \l__xsim_tmpa_str - \l__xsim_tmpb_str } {#1-#2}
+ {
+ \xsim_remove_from_list:nx {#3}
+ { #1-#2 == {\l__xsim_tmpc_str} }
+ }
+ }
+ }
+
+\seq_new:N \g_xsim_used_order_seq
+\seq_new:N \g_xsim_printed_order_seq
+
+\cs_new_protected:Npn \__xsim_set_property_from_list:n #1
+ {
+ \xsim_foreach_list_entry:nn {#1}
+ {
+ \__xsim_extract_property_list_entry:NNNwww
+ \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str ##1 \q_stop
+ \tl_set_rescan:Nnx \l__xsim_tmpa_tl {} { \l__xsim_tmpa_str }
+ \tl_set_rescan:Nnx \l__xsim_tmpb_tl {} { \l__xsim_tmpb_str }
+ \tl_set_rescan:Nnx \l__xsim_tmpc_tl {} { \l__xsim_tmpc_str }
+ \str_if_eq:nnT {#1} {used}
+ {
+ \str_if_eq:VnT \l__xsim_tmpc_str {true}
+ {
+ \seq_gput_right:Nx \g_xsim_used_order_seq
+ { \l__xsim_tmpa_tl - \l__xsim_tmpb_tl }
+ }
+ }
+ \str_if_eq:nnT {#1} {printed}
+ {
+ \str_if_eq:VnT \l__xsim_tmpc_str {true}
+ {
+ \seq_gput_right:Nx \g_xsim_printed_order_seq
+ { \l__xsim_tmpa_tl - \l__xsim_tmpb_tl }
+ }
+ }
+ \__xsim_set_property:VVnV
+ \l__xsim_tmpa_str
+ \l__xsim_tmpb_str
+ {#1}
+ \l__xsim_tmpc_tl
+ }
+ }
+
+% set properties:
+% #1: type
+% #2: id
+% #3: csv list of properties
+\cs_new_protected:Npn \xsim_set_properties:nnn #1#2#3
+ {
+ \cs_set_protected:Npn \__xsim_tmp:n ##1
+ { \xsim_set_property:nnnn {#1} {#2} {##1} {} }
+ \cs_set_protected:Npn \__xsim_tmp:nn ##1##2
+ { \xsim_set_property:nnnn {#1} {#2} {##1} {##2} }
+ \keyval_parse:NNn
+ \__xsim_tmp:n
+ \__xsim_tmp:nn
+ {#3}
+ \xsim_property_set_aliases:nn {#1} {#2}
+ }
+\cs_generate_variant:Nn \xsim_set_properties:nnn {nne,nee,nV,nVe}
+
+% ----------------------------------------------------------------------------
+
+\seq_new:N \g__xsim_property_aliases_seq
+
+% #1: property
+\prg_new_conditional:Npnn \xsim_if_property_alias:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \g__xsim_property_aliases_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: property
+\cs_new:Npn \xsim_property_alias:n #1
+ { \xsim_attribute_get:nn {#1} {alias} }
+
+% #1: property
+% #2: alias of
+\cs_new_protected:Npn \xsim_make_property_alias:nn #1#2
+ {
+ \xsim_if_property_alias:nF {#1}
+ {
+ \xsim_verbose:n
+ { Making~ property~ `#1'~ an~ alias~ of~ property~ `#2'. }
+ \xsim_attribute_set:nnn {#1} {alias} {#2}
+ \seq_gput_right:Nn \g__xsim_property_aliases_seq {#1}
+ }
+ }
+
+% #1: type
+% #2: id
+% #3: property
+\cs_new_protected:Npn \xsim_property_set_alias:nnn #1#2#3
+ {
+ \xsim_if_property_set:nneT {#1} {#2}
+ { \xsim_property_alias:n {#3} }
+ {
+ \xsim_attribute_set:nnx {alias:#1!#2} {#3}
+ {
+ \xsim_get_property:nnf {#1} {#2}
+ { \xsim_property_alias:n {#3} }
+ }
+ \xsim_if_property_set:nnnF {#1} {#2} {#3}
+ {
+ \xsim_set_property:nnne {#1} {#2} {#3}
+ {
+ \xsim_get_property:nnf {#1} {#2}
+ { \xsim_property_alias:n {#3} }
+ }
+ }
+ }
+ }
+\cs_generate_variant:Nn \xsim_property_set_alias:nnn {nV}
+
+% #1: type
+% #2: id
+\cs_new_protected:Npn \xsim_property_set_aliases:nn #1#2
+ {
+ \seq_map_inline:Nn \g__xsim_property_aliases_seq
+ { \xsim_property_set_alias:nnn {#1} {#2} {##1} }
+ }
+
+% ----------------------------------------------------------------------------
+% retrieve properties:
+% #1: type
+% #2: id
+% #3: property
+\cs_new:Npn \xsim_get_property:nnn #1#2#3
+ { \xsim_attribute_get:nn {#1!#2} {#3} }
+\cs_generate_variant:Nn \xsim_get_property:nnn {nx,ne,xx,oo,no,nnf,nf,oof,nV}
+
+% #1: property
+% #2: value
+\cs_new:Npn \xsim_get_id_for_property:nn #1#2
+ { \xsim_attribute_get:nn {id:#1} {#2} }
+
+% #1: ID
+% #2: variable
+\cs_new_protected:Npn \xsim_get_type_for_id:nN #1#2
+ {
+ \xsim_foreach_list_entry:nn {idtypes}
+ {
+ \__xsim_extract_property_list_entry:NNNwww
+ \l__xsim_tmpa_str \l__xsim_tmpb_str \l__xsim_tmpc_str -##1 \q_stop
+ \str_if_eq:VnT \l__xsim_tmpb_str {#1}
+ {
+ \str_set_eq:NN #2 \l__xsim_tmpc_str
+ \seq_map_break:
+ }
+ }
+ }
+
+% #1: property
+% #2: value
+\cs_new:Npn \xsim_get_type_for_property:nn #1#2
+ { \xsim_attribute_get:nn {type:#1} {#2} }
+\cs_generate_variant:Nn \xsim_get_type_for_property:nn {nV}
+
+% #1: id or ID
+\cs_new:Npn \xsim_normalize_id:n #1
+ {
+ \tl_if_blank:eTF
+ { \xsim_get_id_for_property:nn {ID} {#1} }
+ {#1}
+ { \xsim_get_id_for_property:nn {ID} {#1} }
+ }
+\cs_generate_variant:Nn \xsim_normalize_id:n {e}
+
+\tl_new:N \l_xsim_property_value_tl
+\tl_new:N \PropertyValue
+
+\cs_new:Npn \__xsim_tmp:n #1 {#1}
+\cs_generate_variant:Nn \__xsim_tmp:n {V}
+
+% #1: type
+% #2: id
+% #3: property
+\cs_new_protected:Npn \xsim_get_property_if_set:nnnTF #1#2#3#4#5
+ {
+ \xsim_if_property_exist:nTF {#3}
+ {
+ \xsim_if_property_set:nnnTF {#1} {#2} {#3}
+ {
+ \tl_set:Nx \l_xsim_property_value_tl
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+ \tl_set_eq:NN \PropertyValue \l_xsim_property_value_tl
+ \cs_set:Npn \__xsim_tmp:n ##1 {#4}
+ \__xsim_tmp:V \l_xsim_property_value_tl
+ }
+ {#5}
+ }
+ { \msg_error:nnn {xsim} {unknown-property} {#3} }
+ }
+\cs_generate_variant:Nn \xsim_get_property_if_set:nnnTF {oo}
+
+\cs_new_protected:Npn \xsim_get_property_if_set:nnnT #1#2#3#4
+ { \xsim_get_property_if_set:nnnTF {#1} {#2} {#3} {#4} {} }
+
+\cs_new_protected:Npn \xsim_get_property_if_set:nnnF #1#2#3#4
+ { \xsim_get_property_if_set:nnnTF {#1} {#2} {#3} {} {#4} }
+
+% #1: type
+% #2: id
+% #3: property
+\prg_new_conditional:Npnn \xsim_if_boolean_property:nnn #1#2#3 {T,F,TF}
+ {
+ \xsim_if_property_exist:nTF {#3}
+ {
+ \xsim_if_property_boolean:nTF {#3}
+ {
+ \xsim_if_property_set:nnnTF {#1} {#2} {#3}
+ {
+ \bool_if:cTF
+ {c_ \xsim_get_property:nnn {#1} {#2} {#3} _bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+ { \msg_error:nnn {xsim} {no-boolean-property} {#3} }
+ }
+ { \msg_error:nnn {xsim} {unknown-property} {#3} }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_if_boolean_property:nnn {oo,nV} {T,F,TF}
+
+\cs_new_protected:Npn \xsim_save_property:nnnN #1#2#3#4
+ { \tl_set:Nx #4 { \xsim_get_property:nnn {#1} {#2} {#3} } }
+\cs_generate_variant:Nn \xsim_save_property:nnnN {nx,xx}
+
+\cs_new_protected:Npn \xsim_gsave_property:nnnN #1#2#3#4
+ {
+ \xsim_save_property:nnnN {#1} {#2} {#3} #4
+ \tl_gset:NV #4 #4
+ }
+\cs_generate_variant:Nn \xsim_gsave_property:nnnN {nx,xx,nV}
+
+\XSIMmoduleend
+\XSIMmodule{environments}{generic code for exercise and solution environments}
+
+\xsim_if_write_to_files:F
+ {
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_false_bool }
+ { \c_false_bool }
+ {solution-body}
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_false_bool }
+ { \c_false_bool }
+ {exercise-body}
+ }
+
+\tl_new:N \l__xsim_file_name_signature_tl
+\tl_new:N \l__xsim_file_path_tl
+\tl_new:N \l__xsim_file_path_and_name_tl
+\tl_new:N \l__xsim_file_name_tl
+\tl_new:N \l__xsim_file_extension_tl
+\tl_new:N \l__xsim_solution_tl
+\bool_new:N \l__xsim_options_given_bool
+\bool_new:N \l__xsim_insert_mode_bool
+
+\tl_new:N \ExerciseText
+\tl_set:Nn \ExerciseText { \msg_error:nn {xsim} {only-in-solution} }
+
+% ----------------------------------------------------------------------------
+
+\msg_new:nnn {xsim} {only-in-solution}
+ {
+ You~ can't~ use~ \token_to_str:N \ExerciseText \c_space_tl inside~ an~
+ exercise.~ It~ is~ only~ allowed~ inside~ solution~ environments!
+ }
+
+% ----------------------------------------------------------------------------
+
+\keys_define:nn {xsim}
+ {
+ path .tl_set:N = \l__xsim_file_path_tl ,
+ file-extension .tl_set:N = \l__xsim_file_extension_tl ,
+ file-extension .initial:n = tex
+ }
+
+% ----------------------------------------------------------------------------
+
+\tl_const:Nn \c__xsim_comment_line_tl { \c__xsim_percent_char_tl }
+\tl_const:Nn \c__xsim_comment_line_fill_tl { \prg_replicate:nn {72} {-} }
+\tl_const:Nn \c__xsim_comment_line_indent_tl { \c_space_tl \c_space_tl }
+
+\cs_new:Npn \__xsim_comment_line_and_feed:n #1
+ { \__xsim_comment_line:n {#1} ^^J }
+
+\cs_new:Npn \__xsim_comment_line:n #1
+ {
+ \c__xsim_comment_line_tl
+ \tl_if_blank:nF {#1} { \c_space_tl }
+ #1
+ }
+
+\cs_new:Npn \__xsim_two_digits:n #1
+ { \int_compare:nT { #1 < 10 } {0} \int_eval:n {#1} }
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+\cs_new_protected:Npn \__xsim_set_file_signature:nnn #1#2#3
+ { \tl_set:Nn \l__xsim_file_name_signature_tl {#1-#2-#3} }
+\cs_generate_variant:Nn \__xsim_set_file_signature:nnn {nx,nV}
+
+\tl_set:Nn \l__xsim_file_name_tl
+ { \c_sys_jobname_str - \l__xsim_file_name_signature_tl -body . \l__xsim_file_extension_tl }
+
+\tl_set:Nn \l__xsim_file_path_and_name_tl
+ {
+ \tl_if_blank:VF \l__xsim_file_path_tl
+ { \l__xsim_file_path_tl / }
+ \l__xsim_file_name_tl
+ }
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+% #4: file name
+% #5: path
+\cs_new_protected:Npn \__xsim_file_info:nnnnn #1#2#3#4#5
+ {
+ \tl_set:Nx \l_xsim_file_begin_tl
+ {
+ \__xsim_comment_line_and_feed:n { \c__xsim_comment_line_fill_tl }
+ \__xsim_comment_line_and_feed:n {file~ `#4'}
+ \tl_if_blank:nF {#5}
+ {
+ \__xsim_comment_line_and_feed:n
+ { \c__xsim_comment_line_indent_tl in~ folder~ `#5/'}
+ }
+ \__xsim_comment_line_and_feed:n {}
+ \__xsim_comment_line_and_feed:n
+ {
+ \c__xsim_comment_line_indent_tl
+ \c__xsim_comment_line_indent_tl
+ #3~ of~ type~ `#1'~ with~ id~ `#2'
+ }
+ \__xsim_comment_line_and_feed:n {}
+ \__xsim_comment_line_and_feed:n
+ {generated~ by~ the~ `\@currenvir'~ environment~ of~ the}
+ \__xsim_comment_line_and_feed:n
+ {
+ \c__xsim_comment_line_indent_tl
+ `xsim'~ package~ v \c_xsim_version_tl
+ \c_space_tl (\c_xsim_date_tl)
+ }
+ \__xsim_comment_line_and_feed:n
+ {
+ from~ source~ `\c_sys_jobname_str'~ on~
+ \int_use:N \c_sys_year_int /
+ \__xsim_two_digits:n { \c_sys_month_int } /
+ \__xsim_two_digits:n { \c_sys_day_int } ~
+ \msg_line_context:
+ }
+ \__xsim_comment_line:n { \c__xsim_comment_line_fill_tl }
+ }
+ }
+\cs_generate_variant:Nn \__xsim_file_info:nnnnn {nnnVV}
+
+% ----------------------------------------------------------------------------
+% #1: type
+% #2: id
+% #3: exercise|solution
+% #4: potential environment body
+\cs_new_protected:Npn \xsim_save_environment_body:nnnn #1#2#3#4
+ {
+ \xsim_if_write_to_files:TF
+ { \__xsim_write_environment_body:nnn {#1} {#2} {#3} }
+ { \__xsim_save_environment_body:nnnn {#1} {#2} {#3} {#4} }
+ }
+
+\cs_new_protected:Npn \xsim_save_environment_body_end:
+ {
+ \xsim_if_write_to_files:TF
+ { \__xsim_write_environment_body_end: }
+ { \__xsim_save_environment_body_end: }
+ }
+
+% writing to files:
+% #1: type
+% #2: id
+% #3: exercise|solution
+\cs_new_protected:Npn \__xsim_write_environment_body:nnn #1#2#3
+ {
+ \xsim_verbose:n
+ { Starting~ to~ write~ #3~ environment~ type~ `#1'~ id~ `#2' }
+ \__xsim_set_file_signature:nnn {#1} {#2} {#3}
+ \__xsim_file_info:nnnVV {#1} {#2} {#3}
+ \l__xsim_file_name_tl
+ \l__xsim_file_path_tl
+ \int_zero:N \l_xsim_line_gobble_int
+ \xsim_file_write_start:nV
+ { \l__xsim_options_given_bool }
+ \l__xsim_file_path_and_name_tl
+ }
+
+\cs_new_protected:Npn \__xsim_write_environment_body_end:
+ { \xsim_file_write_stop: }
+
+% saving to property lists:
+% #1: type
+% #2: id
+% #3: exercise|solution
+% #4: environment body
+\cs_new_protected:Npn \__xsim_save_environment_body:nnnn #1#2#3#4
+ {
+ \xsim_verbose:n { Saving~ #3~ environment~ type~ `#1'~ id~ `#2' }
+ \xsim_set_property:nnnn {#1} {#2} {#3-body} {#4}
+ \xsim_if_exchange:nnnF {#1} {#2} {#3}
+ { \xsim_set_property:nnnn {#1} {#2} {solution-body} {#3} }
+ }
+
+\cs_new:Npn \__xsim_save_environment_body_end: { }
+
+% ----------------------------------------------------------------------------
+% #1: type
+% #2: exercise|solution
+% #3: hook
+\cs_new_protected:Npn \xsim_new_hook:nnn #1#2#3
+ {
+ \xsim_verbose:n { Defining~ new~ #1~ (#2)~ hook~ `#3' }
+ \tl_new:c {l__xsim_#1_#2_#3_hook_tl}
+ \keys_define:nx {xsim}
+ {
+ \xsim_get_parameter:nn {#1} {#2-env}/#3-hook .tl_set:N =
+ \exp_not:c {l__xsim_#1_#2_#3_hook_tl}
+ }
+ }
+
+% #1: type
+% #2: exercise|solution
+% #3: hook
+\cs_new:Npn \xsim_use_hook:nnn #1#2#3
+ { \exp_not:v {l__xsim_#1_#2_#3_hook_tl} }
+
+% #1: type
+% #2: exercise|solution
+% #3: hook
+% #4: code
+\cs_new_protected:Npn \xsim_set_hook:nnnn #1#2#3#4
+ {
+ \xsim_verbose:n { Setting~ #1~ (#2)~ hook~ `#3' }
+ \tl_set:cn {l__xsim_#1_#2_#3_hook_tl} {#4}
+ }
+
+% #1: type
+% #2: exercise|solution
+% #3: hook
+% #4: code
+\cs_new_protected:Npn \xsim_addto_hook:nnnn #1#2#3#4
+ {
+ \xsim_verbose:n { Adding~ to~ #1~ (#2)~ hook~ `#3' }
+ \tl_put_right:cn {l__xsim_#1_#2_#3_hook_tl} {#4}
+ }
+
+% ----------------------------------------------------------------------------
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+% #4: potential enironment body
+\cs_new_protected:Npn \xsim_start_environment:nnnn #1#2#3#4
+ { \xsim_save_environment_body:nnnn {#1} {#2} {#3} {#4} }
+\cs_generate_variant:Nn \xsim_start_environment:nnnn {nV}
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+\cs_new_protected:Npn \xsim_stop_environment:nnn #1#2#3
+ {
+ \xsim_save_environment_body_end:
+ \xsim_if_print:nnnTF {#1} {#2} {#3}
+ { \xsim_typeset_environment:nnn {#1} {#2} {#3} }
+ { \xsim_use_hook:nnn {#1} {#3} {print-false} }
+ }
+\cs_generate_variant:Nn \xsim_stop_environment:nnn {nV}
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+\cs_new_protected:Npn \xsim_typeset_environment:nnn #1#2#3
+ {
+ \tl_set:Nn \ExerciseType {#1}
+ \tl_set:Nn \ExerciseID {#2}
+ \xsim_verbose:n
+ { Typesetting~ #3~ environment~ type~ `#1'~ id~ `#2' }
+ \xsim_use_hook:nnn {#1} {#3} {pre}
+ \xsim_use_template:nx
+ {begin}
+ { \xsim_get_parameter:nn {#1} {#3-template} }
+ \xsim_use_hook:nnn {#1} {#3} {begin}
+ \xsim_input:nnn {#1} {#2} {#3}
+ \xsim_use_hook:nnn {#1} {#3} {end}
+ \xsim_use_template:nx
+ {end}
+ { \xsim_get_parameter:nn {#1} {#3-template} }
+ \xsim_use_hook:nnn {#1} {#3} {post}
+ }
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+\prg_new_conditional:Npnn \xsim_if_exchange:nnn #1#2#3 {T,F,TF}
+ {
+ \str_if_eq:nnTF {#3} {solution}
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {solution}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+\prg_new_protected_conditional:Npnn \xsim_if_exist:nnn #1#2#3 {T,F,TF}
+ {
+ \xsim_if_write_to_files:TF
+ {
+ \__xsim_set_file_signature:nnn {#1} {#2} {#3}
+ \file_if_exist:VTF \l__xsim_file_path_and_name_tl
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ {
+ \xsim_if_property_exist:nTF {#3-body}
+ {
+ \xsim_if_property_set:nnnTF {#1} {#2} {#3-body}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+ }
+
+% #1: type
+% #2: id
+% #3: options
+% #4: exercise|solution
+\cs_new_protected:Npn \xsim_insert:nnnn #1#2#3#4
+ {
+ \xsim_if_exist:nnnT {#1} {#2} {#4}
+ {
+ \xsim_verbose:n
+ { Inserting~ #4~ type~ `#1'~ id~ `#2'. }
+ \group_begin:
+ \xsim_insert_mode:
+ \tl_gset:Nx \g_xsim_exercise_id_tl {#2}
+ \tl_gset:Nn \g_xsim_exercise_type_tl {#1}
+ \use:c {xsim_start_#4:nn} {#1} {#3}
+ \xsim_typeset_environment:nnn {#1} {#2} {#4}
+ \use:c {xsim_stop_#4:n} {#1} {}
+ \group_end:
+ }
+ }
+\cs_generate_variant:Nn \xsim_insert:nnnn {nV,VV,nnnV,xx,ne}
+
+% #1: type
+% #2: id
+% #3: exercise|solution
+\cs_new_protected:Npn \xsim_input:nnn #1#2#3
+ {
+ \xsim_if_exchange:nnnTF {#1} {#2} {#3}
+ { \__xsim_set_file_signature:nnn {#1} {#2} {exercise} }
+ { \__xsim_set_file_signature:nnn {#1} {#2} {#3} }
+ \xsim_if_write_to_files:TF
+ {
+ \file_if_exist:nTF { \exp_not:V \l__xsim_file_path_and_name_tl }
+ { \file_input:n { \exp_not:V \l__xsim_file_path_and_name_tl } }
+ {
+ \xsim_verbose:n
+ { File~ `\l__xsim_file_path_and_name_tl'~ doesn't~ exist. }
+ }
+ }
+ {
+ \xsim_if_exchange:nnnTF {#1} {#2} {#3}
+ { \xsim_get_property:nnn {#1} {#2} {exercise-body} }
+ { \xsim_get_property:nnn {#1} {#2} {#3-body} }
+ }
+ }
+\cs_generate_variant:Nn \xsim_input:nnn {oo}
+
+\prg_new_conditional:Npnn \xsim_if_insert_mode: {T,F,TF}
+ {
+ \bool_if:NTF \l__xsim_insert_mode_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new_protected:Npn \xsim_insert_mode:
+ { \bool_set_true:N \l__xsim_insert_mode_bool }
+
+% ----------------------------------------------------------------------------
+
+% #1: type
+% #2: exercise|solution
+\cs_new_protected:Npn \xsim_new_environment:nn #1#2
+ {
+ \xsim_verbose:n { Defining~ #2~ environment~ type~ `#1'. }
+ \xsim_new_hook:nnn {#1} {#2} {pre}
+ \xsim_new_hook:nnn {#1} {#2} {begin}
+ \xsim_new_hook:nnn {#1} {#2} {end}
+ \xsim_new_hook:nnn {#1} {#2} {post}
+ \xsim_new_hook:nnn {#1} {#2} {print-false}
+ \xsim_if_write_to_files:TF
+ {
+ \NewDocumentEnvironment
+ { \xsim_get_parameter:nn {#1} {#2-env} } {!o}
+ {
+ \IfNoValueTF {##1}
+ {
+ \bool_set_false:N \l__xsim_options_given_bool
+ \use:c {xsim_start_#2:nn} {#1} {}
+ }
+ {
+ \bool_set_true:N \l__xsim_options_given_bool
+ \use:c {xsim_start_#2:nn} {#1} {##1}
+ }
+ \xsim_start_environment:nVnn {#1} \g_xsim_exercise_id_tl {#2} { }
+ }
+ {
+ \xsim_stop_environment:nVn {#1} \g_xsim_exercise_id_tl {#2}
+ \use:c {xsim_stop_#2:n} {#1}
+ }
+ }
+ {
+ \NewDocumentEnvironment
+ { \xsim_get_parameter:nn {#1} {#2-env} } {o+b}
+ {
+ \IfNoValueTF {##1}
+ {
+ \bool_set_false:N \l__xsim_options_given_bool
+ \use:c {xsim_start_#2:nn} {#1} {}
+ }
+ {
+ \bool_set_true:N \l__xsim_options_given_bool
+ \use:c {xsim_start_#2:nn} {#1} {##1}
+ }
+ \xsim_start_environment:nVnn {#1} \g_xsim_exercise_id_tl {#2} {##2}
+ }
+ {
+ \xsim_stop_environment:nVn {#1} \g_xsim_exercise_id_tl {#2}
+ \use:c {xsim_stop_#2:n} {#1}
+ }
+ }
+ }
+
+\XSIMmoduleend
+\XSIMmodule{templates}{templates for typesetting exercises}
+
+\msg_new:nnn {xsim} {unknown-template}
+ {
+ You~ are~ trying~ to~ load~ the~ template~ `#2'~ (template~ type~ `#1')~
+ \msg_line_context: .~ This~ template~ does~ not~ seem~ to~ be~ defined.~
+ I~ am~ using~ the~ template~ `#3'~ (template~ type~ `#1')~ instead.
+ }
+
+\msg_new:nnn {xsim} {template-type-exists}
+ { The~ template~ type~ `#1'~ already~ exists~ \msg_line_context: }
+
+% ----------------------------------------------------------------------------
+\seq_new:N \l__xsim_template_types_seq
+
+% #1: template type
+\cs_new_protected:Npn \xsim_new_template_type:n #1
+ {
+ \seq_if_in:NnTF \l__xsim_template_types_seq {#1}
+ { \msg_error:nnn {xsim} {template-type-exists} {#1} }
+ {
+ \xsim_verbose:n { Declaring~ new~ template~ type~ `#1'. }
+ \seq_put_right:Nn \l__xsim_template_types_seq {#1}
+ }
+ }
+
+% #1: template type
+% #2: template name
+% #3: code
+\cs_new_protected:Npn \__xsim_add_template:nnn #1#2#3
+ {
+ \xsim_verbose:n { Defining~ new~ template~ `#2'~ of~ type~ `#1'. }
+ \tl_new:c {l__xsim_template_#1_#2_setup_tl}
+ \xsim_attribute_set:nnn {template::#1} {#2} {#3}
+ }
+
+\prg_new_conditional:Npnn \xsim_if_template_exist:nn #1#2 {T,F,TF}
+ {
+ \xsim_attribute_if_set:nnTF {template::#1} {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: template type
+% #2: template name
+\cs_new_protected:Npn \__xsim_get_template:nn #1#2
+ { \xsim_attribute_get:nn {template::#1} {#2} }
+
+% ----------------------------------------------------------------------------
+
+% environment templates (types `begin' and `end'):
+\xsim_new_template_type:n {begin}
+\xsim_new_template_type:n {end}
+
+% #1: template name
+% #2: begin code
+% #3: end code
+\cs_new_protected:Npn \xsim_declare_environment_template:nnn #1#2#3
+ {
+ \__xsim_add_template:nnn {begin} {#1}
+ {
+ \__xsim_start_template:nn {begin} {#1}
+ \__xsim_start_template:nn {end} {#1}
+ #2
+ }
+ \__xsim_add_template:nnn {end} {#1}
+ {
+ #3
+ \__xsim_stop_template:nn {end} {#1}
+ \__xsim_stop_template:nn {begin} {#1}
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+% heading templates for the solution list (type `heading'):
+\xsim_new_template_type:n {heading}
+
+% #1: template name
+% #2: code
+\cs_new_protected:Npn \xsim_declare_heading_template:nn #1#2
+ {
+ \__xsim_add_template:nnn {heading} {#1}
+ {
+ \__xsim_start_template:nn {heading} {#1}
+ #2
+ \__xsim_stop_template:nn {heading} {#1}
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+% grading table templates (type `table'):
+\xsim_new_template_type:n {table}
+
+% #1: template name
+% #2: code
+\cs_new_protected:Npn \xsim_declare_table_template:nn #1#2
+ {
+ \__xsim_add_template:nnn {table} {#1}
+ {
+ \__xsim_start_template:nn {table} {#1}
+ #2
+ \__xsim_stop_template:nn {table} {#1}
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+% using templates:
+% setup up the next usage of `template name':
+% #1: template type
+% #2: template name
+% #3: setup code
+\cs_new_protected:Npn \xsim_setup_template:nnn #1#2#3
+ { \tl_set:cn {l__xsim_template_#1_#2_setup_tl} {#3} }
+\cs_generate_variant:Nn \xsim_setup_template:nnn {nnV,nVn}
+
+% #1: template type
+% #2: template name
+\cs_new_protected:Npn \__xsim_setup_template:nn #1#2
+ { \tl_use:c {l__xsim_template_#1_#2_setup_tl} }
+
+% #1: template type
+% #2: template name
+\cs_new_protected:Npn \__xsim_clear_template_setup:nn #1#2
+ { \tl_clear:c {l__xsim_template_#1_#2_setup_tl} }
+
+% #1: template type
+% #2: template name
+\cs_new_protected:Npn \__xsim_start_template:nn #1#2
+ { \group_begin: \__xsim_setup_template:nn {#1} {#2} }
+
+% #1: template type
+% #2: template name
+\cs_new_protected:Npn \__xsim_stop_template:nn #1#2
+ { \group_end: \__xsim_clear_template_setup:nn {#1} {#2} }
+
+% #1: template type
+% #2: template name
+\cs_new_protected:Npn \xsim_use_template:nn #1#2
+ {
+ \xsim_if_template_exist:nnTF {#1} {#2}
+ { \__xsim_get_template:nn {#1} {#2} }
+ {
+ \msg_warning:nnnnn {xsim} {unknown-template} {#1} {#2} {default}
+ \__xsim_get_template:nn {#1} {default}
+ }
+ }
+\cs_generate_variant:Nn \xsim_use_template:nn {nx,nV}
+
+\XSIMmoduleend
+\XSIMmodule{tags}{tagging of exercises}
+
+\seq_new:N \l__xsim_tag_types_seq
+\bool_new:N \l____xsim_tagged_bool
+
+\msg_new:nnn {xsim} {tag-exists}
+ { The~ tag~ type~ `#1'~ already~ exists.~ I~ am~ doing~ nothing. }
+
+\msg_new:nnn {xsim} {tag-unknown}
+ { The~ tag~ type~ `#1'~ is~ not~ defined.~ Check~ for~ a~ typo. }
+
+% #1: name
+\cs_new_protected:Npn \xsim_new_tag_type:n #1
+ {
+ \xsim_verbose:n { Declaring~ new~ tag~ type~ `#1'. }
+ \seq_put_right:Nn \l__xsim_tag_types_seq {#1}
+ \seq_remove_duplicates:N \l__xsim_tag_types_seq
+ \seq_new:c {l__xsim_chosen_tags_#1_seq}
+ \bool_new:c {l__xsim_ignore_untagged_#1_bool}
+ \bool_new:c {l____xsim_tagged_#1_bool}
+ \keys_define:nn {xsim}
+ {
+ #1/ignore-untagged .bool_set:c = {l__xsim_ignore_untagged_#1_bool} ,
+ #1/ignore-untagged .initial:n = true ,
+ #1 .code:n =
+ \seq_set_from_clist:cn {l__xsim_chosen_tags_#1_seq} {##1}
+ }
+ \prg_new_protected_conditional:cpnn {xsim_if_#1_value:n} ##1 {T,F,TF}
+ {
+ \seq_if_in:cnTF {l__xsim_chosen_tags_#1_seq} {##1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_false_bool }
+ { \c_false_bool }
+ {#1}
+ \xsim_declare_printsolutions_condition:nn {#1}
+ { \__xsim_printsolutions_if_tagged:nnnnTF {#1} }
+ \keys_define:nn {xsim/print-solutions}
+ {
+ #1 .choice: ,
+ #1/false .code:n =
+ \__xsim_printsolutions_condition:nn {#1} {false} ,
+ #1/true .code:n =
+ \__xsim_printsolutions_condition:nn {#1} {true} ,
+ #1/unknown .code:n =
+ \keys_set:nn {xsim} { #1 = ##1 }
+ \__xsim_printsolutions_condition:nn {#1} {true} ,
+ #1 .initial:n = false
+ }
+ }
+
+% #1: tag type
+\prg_new_protected_conditional:Npnn \xsim_if_tag_type_exist:n #1 {T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_tag_types_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_if_tag_type_exist:n {V} {TF}
+
+% #1: tag type
+% #2: exercise type
+% #3: id
+% #4: print|use
+\prg_new_protected_conditional:Npnn
+ \__xsim_printsolutions_if_tagged:nnnn #1#2#3#4 {T,F,TF}
+ {
+ \xsim_if_in_list:nnTF {#4} {#2-#3=={true}}
+ {
+ \__xsim_printsolutions_if_condition:nTF {#1}
+ {
+ \__xsim_printsolutions_condition_true:
+ \xsim_if_tagged:nnnTF {#2} {#3} {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+
+% #1: exercise type
+% #2: id
+% #3: tag type
+\prg_new_protected_conditional:Npnn \xsim_if_tagged:nnn #1#2#3 {T,F,TF}
+ {
+ \bool_set_false:c {l____xsim_tagged_#3_bool}
+ \seq_if_empty:cTF {l__xsim_chosen_tags_#3_seq}
+ { \bool_set_true:c {l____xsim_tagged_#3_bool} }
+ {
+ \seq_set_from_clist:Nx
+ \l__xsim_tmpa_seq
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+ \seq_if_empty:NTF \l__xsim_tmpa_seq
+ {
+ \bool_set_eq:cc
+ {l____xsim_tagged_#3_bool}
+ {l__xsim_ignore_untagged_#3_bool}
+ }
+ {
+ \seq_map_inline:Nn \l__xsim_tmpa_seq
+ {
+ \seq_if_in:cnT {l__xsim_chosen_tags_#3_seq} {##1}
+ {
+ \bool_set_true:c {l____xsim_tagged_#3_bool}
+ \seq_map_break:
+ }
+ }
+ }
+ }
+ \bool_if:cTF {l____xsim_tagged_#3_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: exercise type
+% #2: id
+% #3: tag type
+% #4: tag values
+\prg_new_protected_conditional:Npnn \xsim_has_tags:nnnn #1#2#3#4 {T,F,TF}
+ {
+ \bool_set_false:c {l____xsim_tagged_#3_bool}
+ \seq_set_from_clist:Nn \l__xsim_tmpa_seq {#4}
+ \seq_if_empty:NTF \l__xsim_tmpa_seq
+ {% no tag values given:
+ \bool_set_true:c {l____xsim_tagged_#3_bool}
+ }
+ {
+ \seq_set_from_clist:Nx
+ \l__xsim_tmpb_seq
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+ \seq_if_empty:NTF \l__xsim_tmpb_seq
+ {% exercise has no tag values given
+ % \bool_set_eq:cc
+ % {l____xsim_tagged_#3_bool}
+ % {l__xsim_ignore_untagged_#3_bool}
+ \bool_set_false:c {l____xsim_tagged_#3_bool}
+ }
+ {
+ \seq_map_inline:Nn \l__xsim_tmpb_seq
+ {
+ \seq_if_in:NnT \l__xsim_tmpa_seq {##1}
+ {
+ \bool_set_true:c {l____xsim_tagged_#3_bool}
+ \seq_map_break:
+ }
+ }
+ }
+ }
+ \bool_if:cTF {l____xsim_tagged_#3_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_has_tags:nnnn {nnVV} {T}
+
+% #1: exercise type
+% #2: id
+\prg_new_protected_conditional:Npnn \xsim_if_tagged:nn #1#2 {T,F,TF}
+ {
+ \bool_set_true:N \l____xsim_tagged_bool
+ \seq_map_inline:Nn \l__xsim_tag_types_seq
+ {
+ \xsim_if_tagged:nnnF {#1} {#2} {##1}
+ {
+ \bool_set_false:N \l____xsim_tagged_bool
+ \seq_map_break:
+ }
+ }
+ \bool_if:NTF \l____xsim_tagged_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+
+% #1: exercise type
+% #2: id
+% #3: tag type
+% #4: code
+\cs_new_protected:Npn \xsim_foreach_exercise_tag:nnnn #1#2#3#4
+ {
+ \seq_set_from_clist:Nx \l__xsim_tmpa_seq
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+ \seq_map_inline:Nn \l__xsim_tmpa_seq {#4}
+ }
+\cs_generate_variant:Nn \xsim_foreach_exercise_tag:nnnn {oo}
+
+% #1: exercise type
+% #2: id
+% #3: tag type
+% #4: sep
+\cs_new_protected:Npn \xsim_exercise_tags_use:nnnn #1#2#3#4
+ {
+ \seq_set_from_clist:Nx \l__xsim_tmpa_seq
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+ \seq_use:Nn \l__xsim_tmpa_seq {#4}
+ }
+\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnn {oo}
+
+% #1: exercise type
+% #2: id
+% #3: tag type
+% #4: sep between two
+% #5: sep between more than two
+% #6: sep between last two
+\cs_new_protected:Npn \xsim_exercise_tags_use:nnnnnn #1#2#3#4#5#6
+ {
+ \seq_set_from_clist:Nx \l__xsim_tmpa_seq
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+ \seq_use:Nnnn \l__xsim_tmpa_seq {#4} {#5} {#6}
+ }
+\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnn {oo}
+\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnnnn {oo}
+
+\XSIMmoduleend
+\XSIMmodule{goals}{counting of points and bonus points}
+
+\msg_new:nnn {xsim} {goal-unknown}
+ { The~ goal~ `#1'~ has~ never~ been~ declared~ \msg_line_context: }
+
+\seq_new:N \l__xsim_goals_seq
+\tl_new:N \l_xism_grading_table_template_tl
+\tl_new:N \l_xism_grading_table_exercise_type_tl
+
+% #1: name
+\cs_new_protected:Npn \xsim_declare_exercise_goal:n #1
+ {
+ \xsim_if_goal_exist:nF {#1}
+ {
+ \xsim_verbose:n { Declaring~ new~ goal~ `#1'. }
+ \xsim_declare_property:nnnn
+ { \c_false_bool } { \c_false_bool } { \c_false_bool } {#1}
+ \xsim_declare_property:nnnn
+ { \c_false_bool } { \c_false_bool } { \c_false_bool } {user#1}
+ \xsim_declare_property:nnnn
+ { \c_false_bool } { \c_false_bool } { \c_false_bool } {body#1}
+ \seq_put_right:Nn \l__xsim_goals_seq {#1}
+ \fp_gzero_new:c {g__xsim_goal_#1_fp}
+ \fp_new:c {l__xsim_temporary_#1_fp}
+ \bool_new:c {l__xsim_temporary_#1_bool}
+ \bool_new:c {l__xsim_goal_#1_given_bool}
+ \fp_gzero_new:c {l__xsim_current_goal_#1_fp}
+ \fp_if_exist:cF {g__xsim_total_goal_#1_fp}
+ { \fp_new:c {g__xsim_total_goal_#1_fp} }
+ \fp_if_exist:cF {g__xsim_total_goal_recorded_#1_fp}
+ { \fp_new:c {g__xsim_total_goal_recorded_#1_fp} }
+ \xsim_before_begin_document:n
+ {
+ \xsim_foreach_exercise_type:n
+ { \xsim_goal_init:nn {##1} {#1} }
+ }
+ }
+ }
+
+% #1: type
+% #2: goal
+\cs_new_protected:Npn \xsim_goal_init:nn #1#2
+ {
+ \fp_gzero_new:c {g__xsim_#1_goal_#2_fp}
+ \fp_if_exist:cF {g__xsim_total_#1_goal_#2_fp}
+ { \fp_new:c {g__xsim_total_#1_goal_#2_fp} }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_goal_exist:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_goals_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_goal_given:n #1 {p,T,F,TF}
+ {
+ \bool_if:cTF {l__xsim_goal_#1_given_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new_protected:Npn \xsim_goal_given:n #1
+ { \bool_set_true:c {l__xsim_goal_#1_given_bool} }
+
+% #1: exercise type
+% #2: id
+% #3: goal
+\cs_new_protected:Npn \xsim_update_goal:nnn #1#2#3
+ {
+ \xsim_if_goal_exist:nT {#3}
+ {
+ \fp_gadd:cn {g__xsim_goal_#3_fp}
+ { \xsim_get_property:nnn {#1} {#2} {#3} + 0 }
+ \fp_gadd:cn {g__xsim_#1_goal_#3_fp}
+ { \xsim_get_property:nnn {#1} {#2} {#3} + 0 }
+ }
+ }
+
+% #1: exercise type
+% #2: id
+\cs_new_protected:Npn \xsim_update_goals:nn #1#2
+ {
+ \xsim_foreach_goal:n
+ { \xsim_update_goal:nnn {#1} {#2} {##1} }
+ }
+\cs_generate_variant:Nn \xsim_update_goals:nn {nV}
+
+\cs_new_protected:Npn \xsim_foreach_goal:n #1
+ { \seq_map_inline:Nn \l__xsim_goals_seq {#1} }
+
+
+% #1: exercise type
+% #2: id
+% #3: goal
+% #4: value
+\cs_new_protected:Npn \xsim_addto_goal:nnnn #1#2#3#4
+ {
+ \xsim_if_goal_exist:nT {#3}
+ {
+ \xsim_verbose:n { Adding~ `#4'~ to~ `#3'~ goal~ of~ #1~ #2 }
+ \fp_set:Nn \l__xsim_tmpa_fp
+ { \xsim_get_property:nnn {#1} {#2} {body#3} + 0 + #4 }
+ \xsim_set_property:nnne {#1} {#2} {body#3}
+ { \fp_to_decimal:N \l__xsim_tmpa_fp }
+ }
+ }
+\cs_generate_variant:Nn \xsim_addto_goal:nnnn {xx,nVnx}
+
+% #1: exercise type
+% #2: id
+% #3: goal
+% #4: relation and value
+\prg_new_conditional:Npnn \xsim_if_goal_value:nnnn #1#2#3#4 {p,T,F,TF}
+ {
+ \fp_compare:nTF
+ { (0 + \xsim_get_property:nnn {#1} {#2} {#3}) #4 }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_goal_value:nnnnTF {xx}
+
+% ----------------------------------------------------------------------------
+% a function which can be used to modify how the numbers of a goal are
+% printed:
+\cs_new_protected:Npn \__xsim_print_goal:n #1 {#1}
+\cs_generate_variant:Nn \__xsim_print_goal:n {x}
+
+% #1: value
+% #2: value == 1
+% #3: value != 1
+\cs_new_protected:Npn \xsim_print_goal:nnn #1#2#3
+ {
+ \__xsim_print_goal:x { \fp_to_decimal:n {#1} }
+ \fp_compare:nTF { (#1) = 1 } {#2} {#3}
+ }
+
+% #1: exercise type
+% #2: goal
+% #3: sum == 1
+% #4: sum != 1
+\cs_new_protected:Npn \xsim_print_goal_sum:nnnn #1#2#3#4
+ { \xsim_print_goal:nnn { \use:c {g__xsim_total_#1_goal_#2_fp} } {#3} {#4} }
+
+% #1: goal
+% #2: sum == 1
+% #3: sum != 1
+\cs_new_protected:Npn \xsim_print_total_goal_sum:nnn #1#2#3
+ { \xsim_print_goal:nnn { \use:c {g__xsim_total_goal_#1_fp} } {#2} {#3} }
+
+% ----------------------------------------------------------------------------
+% the same as the last to functions but for a list of goals:
+
+% #1: fp variable to be set
+% #2: list of goals (separated with +)
+% #3: function to be applied to goal names
+\cs_new_protected:Npn \__xsim_exercise_goals_sum_aux:Nnn #1#2#3
+ {
+ \seq_set_split:Nnn \l__xsim_tmpa_seq {+} {#2}
+ \seq_set_map:NNn \l__xsim_tmpb_seq \l__xsim_tmpa_seq {#3}
+ \fp_set:Nn #1 { \seq_use:Nn \l__xsim_tmpb_seq {+} }
+ }
+
+% #1: fp variable
+% #2: exercise type
+% #3: list of goals (separated with +)
+\cs_new_protected:Npn \__xsim_exercise_goals_sum:Nnn #1#2#3
+ {
+ \__xsim_exercise_goals_sum_aux:Nnn #1 {#3}
+ { \use:c {g__xsim_total_#2_goal_ \tl_trim_spaces:n {##1} _fp} }
+ }
+
+% #1: fp variable
+% #2: list of goals (separated with +)
+\cs_new_protected:Npn \__xsim_exercise_goals_sum:Nn #1#2
+ {
+ \__xsim_exercise_goals_sum_aux:Nnn #1 {#2}
+ { \use:c {g__xsim_total_goal_ \tl_trim_spaces:n {##1} _fp} }
+ }
+
+% #1: exercise type
+% #2: list of goals (separated with +)
+% #3: sum == 1
+% #4: sum != 1
+\cs_new_protected:Npn \xsim_print_goals_sum:nnnn #1#2#3#4
+ {
+ \__xsim_exercise_goals_sum:Nnn \l__xsim_tmpa_fp {#1} {#2}
+ \xsim_print_goal:nnn { \l__xsim_tmpa_fp } {#3} {#4}
+ }
+
+% #1: list of goals (separated with +)
+% #2: sum == 1
+% #3: sum != 1
+\cs_new_protected:Npn \xsim_print_total_goals_sum:nnn #1#2#3
+ {
+ \__xsim_exercise_goals_sum:Nn \l__xsim_tmpa_fp {#1}
+ \xsim_print_goal:nnn { \l__xsim_tmpa_fp } {#2} {#3}
+ }
+
+% ----------------------------------------------------------------------------
+% #1: exercise type
+% #2: goal
+% #3: relation and value
+\prg_new_conditional:Npnn \xsim_if_goal_sum:nnn #1#2#3 {p,T,F,TF}
+ {
+ \fp_compare:nTF
+ { ( \use:c {g__xsim_total_#1_goal_#2_fp} ) #3 }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: exercise type
+% #2: list of goals (separated with +)
+% #3: relation and value
+\prg_new_protected_conditional:Npnn \xsim_if_goals_sum:nnn #1#2#3 {T,F,TF}
+ {
+ \__xsim_exercise_goals_sum:Nnn \l__xsim_tmpa_fp {#1} {#2}
+ \fp_compare:nTF
+ { ( \l__xsim_tmpa_fp ) #3 }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: goal
+% #2: relation and value
+\prg_new_conditional:Npnn \xsim_if_total_goal_sum:nn #1#2 {p,T,F,TF}
+ {
+ \fp_compare:nTF
+ { ( \use:c {g__xsim_total_goal_#1_fp} ) #2 }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: list of goals (separated with +)
+% #2: relation and value
+\prg_new_protected_conditional:Npnn \xsim_if_total_goals_sum:nn #1#2 {T,F,TF}
+ {
+ \__xsim_exercise_goals_sum:Nn \l__xsim_tmpa_fp {#1}
+ \fp_compare:nTF
+ { ( \l__xsim_tmpa_fp ) #2 }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% ----------------------------------------------------------------------------
+% #1: exercise type
+% #2: goal
+% #3: value
+\xsim_new_aux_property:cpn {goal} #1#2#3
+ { \fp_gset:cn {g__xsim_total_#1_goal_#2_fp} {#3} }
+
+% #1: goal
+% #2: value
+\xsim_new_aux_property:cpn {totalgoal} #1#2
+ { \fp_gset:cn {g__xsim_total_goal_#1_fp} {#2} }
+
+\xsim_at_begin_document:n
+ { \xsim_foreach_goal:n { \xsim_get_total_goal:n {#1} } }
+
+% #1: goal
+\cs_new_protected:Npn \xsim_get_total_goal:n #1
+ {
+ \fp_gset_eq:cc
+ {g__xsim_total_goal_recorded_#1_fp}
+ {g__xsim_total_goal_#1_fp}
+ }
+
+\xsim_at_end_document:n { \xsim_save_goals: }
+
+\cs_new_protected:Npn \xsim_save_goals:
+ {
+ \xsim_foreach_goal:n
+ {
+ \xsim_foreach_exercise_type:n
+ {
+ \xsim_add_property_to_aux:nn {goal}
+ { {####1} {##1} { \fp_to_decimal:c {g__xsim_####1_goal_##1_fp} } }
+ }
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \fp_to_decimal:c {g__xsim_total_goal_##1_fp} }
+ \tl_set:Nx \l__xsim_tmpb_tl
+ { \fp_to_decimal:c {g__xsim_total_goal_recorded_##1_fp} }
+ \tl_if_eq:NNF \l__xsim_tmpa_tl \l__xsim_tmpb_tl { \xsim_rerun: }
+ \xsim_add_property_to_aux:nn {totalgoal}
+ { {##1} { \fp_to_decimal:c {g__xsim_goal_##1_fp} } }
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+\keys_define:nn {xsim}
+ {
+ goal-print .code:n =
+ \cs_set_protected:Npn \__xsim_print_goal:n ##1 {#1} ,
+ grading-table/template .tl_set:N = \l_xism_grading_table_template_tl ,
+ grading-table/template .initial:n = default ,
+ grading-table/type .tl_set:N = \l_xism_grading_table_exercise_type_tl ,
+ grading-table/type .initial:n =
+ }
+
+\XSIMmoduleend
+\XSIMmodule{exercises}{main exercises definitions}
+
+\seq_new:N \l__xsim_exercise_types_seq
+\seq_new:N \l__xsim_parameters_seq
+\seq_new:N \l__xsim_fixed_parameters_seq
+\seq_new:N \l__xsim_mandatory_parameters_seq
+\int_gzero_new:N \g_xsim_id_int
+\int_gzero_new:N \g_xsim_max_id_int
+\tl_new:N \l_xsim_current_id_tl
+\tl_new:N \g_xsim_exercise_id_tl
+\tl_new:N \g_xsim_exercise_type_tl
+\tl_new:N \ExerciseID
+\tl_new:N \ExerciseType
+
+% ----------------------------------------------------------------------------
+
+\msg_new:nnn {xsim} {parameter-fixed}
+ {
+ You~ tried~ to~ set~ parameter~ `#2'~ for~ type~ `#1'~ \msg_line_context:
+ . ~ However,~ parameter~ `#2'~ is~ a~ fixed~ parameter~ that~ already~
+ has~ been~ set~ for~ type~ `#1'.~ Its~ value~ can't~ be~ changed!
+ }
+
+\msg_new:nnn {xsim} {type-exists}
+ {
+ You~ try~ to~ define~ exercise~ type~ `#1'~ \msg_line_context: .~
+ However,~ the~ exercise~ type~ `#1'~ already~ exists.
+ }
+
+\msg_new:nnn {xsim} {mandatory-parameter}
+ {
+ You~ forget~ to~ set~ the~ mandatory~ parameter~ `#1'~ when~ defining~
+ exercise~ type~ `#2'.
+ }
+
+\msg_new:nnn {xsim} {unknown-parameter}
+ {
+ You~ tried~ to~ retrieve~ the~ parameter~ `#1'~ \msg_line_context: . \\
+ This~ parameter~ does~ not~ exist.~ Check~ for~ a~ typo~ or~ \\
+ define~ the~ parameter~ yourself.
+ }
+
+\msg_new:nnn {xsim} {parameter-undefined}
+ {
+ You~ tried~ to~ set~ the~ parameter~ `#2'~ for~ exercise~ type~ `#1'~
+ \msg_line_context: . \\
+ This~ parameter~ does~ not~ exist.~ Check~ for~ a~ typo~ or~ \\
+ define~ the~ parameter~ yourself.
+ }
+
+\msg_new:nnn {xsim} {parameter-value}
+ {
+ A~ parameter~ needs~ to~ be~ set~ to~ a~ (possibly~ empty)~ value! \\
+ Not~ setting~ parameter~ `#2'~ for~ exercise~ type~ `#1'~
+ \msg_line_context: .
+ }
+
+% ----------------------------------------------------------------------------
+% #1: type
+% #2: parameter
+% #3: value
+\cs_new_protected:Npn \__xsim_set_parameter_type:nnn #1#2#3
+ { \xsim_attribute_set:nnn {#1} {#2} {#3} }
+
+% #1: type
+% #2: parameter
+\cs_new:Npn \xsim_get_parameter:nn #1#2
+ { \xsim_attribute_get:nn {#1} {#2} }
+\cs_generate_variant:Nn \xsim_get_parameter:nn {o}
+
+% #1: type
+% #2: parameter
+\prg_new_conditional:Npnn \xsim_if_parameter_set:nn #1#2 {p,T,F,TF}
+ {
+ \xsim_attribute_if_set:nnTF {#1} {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% ----------------------------------------------------------------------------
+
+\xsim_new_list:n {types}
+\xsim_new_list:n {idtypes}
+
+% #1: true|false (fixed parameter)
+% #2: true|false (mandatory parameter)
+% #3: parameter name
+\cs_new_protected:Npn \xsim_declare_parameter:nnn #1#2#3
+ {
+ \xsim_verbose:n { Declaring~ parameter~ `#3'. }
+ \xsim_if_parameter_exist:nF {#3}
+ {
+ \seq_put_right:Nn \l__xsim_parameters_seq {#3}
+ \bool_if:cT {c_#1_bool}
+ { \seq_put_right:Nn \l__xsim_fixed_parameters_seq {#3} }
+ \bool_if:cT {c_#2_bool}
+ { \seq_put_right:Nn \l__xsim_mandatory_parameters_seq {#3} }
+ }
+ }
+
+\cs_new_protected:Npn \xsim_remove_parameter:n #1
+ {
+ \xsim_verbose:n { Removing~ parameter~ `#1'. }
+ \xsim_if_parameter_exist:nT {#1}
+ { \seq_remove_all:Nn \l__xsim_parameters_seq {#1} }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_parameter_exist:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_parameters_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_parameter_exist:nT {x}
+
+\prg_new_conditional:Npnn \xsim_if_parameter_fixed:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_fixed_parameters_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: type
+% #2: csv list of parameters
+\cs_new_protected:Npn \xsim_set_parameters:nn #1#2
+ {
+ \cs_set_protected:Npn \__xsim_set_parameter:n ##1
+ { \msg_warning:nnnn {xsim} {parameter-value} {#1} {##1} }
+ \cs_set_protected:Npn \__xsim_set_parameter:nn ##1##2
+ { \xsim_set_parameter:nnn {#1} {##1} {##2} }
+ \keyval_parse:NNn
+ \__xsim_set_parameter:n
+ \__xsim_set_parameter:nn
+ {#2}
+ }
+\cs_generate_variant:Nn \xsim_set_parameters:nn {nx}
+
+% #1: type
+\cs_new_protected:Npn \xsim_check_mandatory_parameters:n #1
+ {
+ \seq_map_inline:Nn \l__xsim_mandatory_parameters_seq
+ {
+ \xsim_if_parameter_set:nnF {#1} {##1}
+ { \msg_error:nnnn {xsim} {mandatory-parameter} {##1} {#1} }
+ }
+ }
+
+% #1: type
+\prg_new_conditional:Npnn \xsim_if_type:n #1 {p,T,F,TF}
+ {
+ \seq_if_in:NnTF \l__xsim_exercise_types_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: type
+% #2: parameter
+% #3: value
+\cs_new_protected:Npn \xsim_set_parameter:nnn #1#2#3
+ {
+ \xsim_if_parameter_exist:nTF {#2}
+ {
+ \xsim_if_parameter_fixed:nTF {#1}
+ {
+ \xsim_if_parameter_set:nnTF {#1} {#2}
+ {
+ \msg_warning:nnnn {xsim} {parameter-fixed} {#1} {#2}
+ \xsim_verbose:n
+ {
+ Not~ setting~ already~ set~ and~ fixed~ parameter~ `#2'~
+ for~ type~ `#1'.
+ }
+ }
+ {
+ \xsim_verbose:n
+ { Setting~ parameter~ `#2'~ for~ type~ `#1'~ to~ `#3'. }
+ \__xsim_set_parameter_type:nnn {#1} {#2} {#3}
+ }
+ }
+ {
+ \xsim_verbose:n
+ { Setting~ parameter~ `#2'~ for~ type~ `#1'~ to~ `#3'. }
+ \__xsim_set_parameter_type:nnn {#1} {#2} {#3}
+ }
+ }
+ { \msg_error:nnnn {xsim} {parameter-undefined} {#1} {#2} }
+ }
+\cs_generate_variant:Nn \xsim_set_parameter:nnn {nnx,nxx}
+
+\cs_new:Npn \__xsim_get_parameter_tmp:n #1 {}
+\cs_generate_variant:Nn \__xsim_get_parameter_tmp:n {V}
+
+% #1: type
+% #2: parameter
+\cs_new_protected:Npn \xsim_get_parameter_if_set:nnTF #1#2#3#4
+ {
+ \group_begin:
+ \xsim_if_parameter_exist:nTF {#2}
+ {
+ \xsim_if_parameter_set:nnTF {#1} {#2}
+ {
+ \tl_set:Nx \ParameterValue
+ { \xsim_get_parameter:nn {#1} {#2} }
+ \cs_set:Npn \__xsim_get_parameter_tmp:n ##1 {#3}
+ \__xsim_get_parameter_tmp:V \ParameterValue
+ }
+ {#4}
+ }
+ { \msg_error:nnn {xsim} {unknown-parameter} {#2} }
+ \group_end:
+ }
+\cs_new_protected:Npn \xsim_get_parameter_if_set:nnT #1#2#3
+ { \xsim_get_parameter_if_set:nnTF {#1} {#2} {#3} {} }
+\cs_new_protected:Npn \xsim_get_parameter_if_set:nnF #1#2#3
+ { \xsim_get_parameter_if_set:nnTF {#1} {#2} {} {#3} }
+\cs_generate_variant:Nn \xsim_get_parameter_if_set:nnTF {o}
+
+% ----------------------------------------------------------------------------
+% inside the argument `#1' refers to the type
+\cs_new_protected:Npn \xsim_foreach_exercise_type:n #1
+ { \xsim_foreach_new_list_entry:nn {types} {#1} }
+
+\cs_new_protected:Npn \xsim_foreach_exercise_id:n #1
+ { \int_step_inline:nnnn {1} {1} { \g_xsim_max_id_int } {#1} }
+
+% #1: macro name
+% #2: 0 to 9 times `n' (= number of arguments of internal item)
+% #3: code; may contain a suiting \__xsim_loop_item:<nnn>
+\cs_new_protected:Npn \xsim_define_loop_macro:Nnn #1#2#3
+ {
+ \xsim_verbose:n { Defining~ loop~ macro~ #1 }
+ \cs_new_protected:Npn #1 ##1##2
+ { \cs_set:cn {__xsim_loop_item:#2} {##2} #3 }
+ }
+
+\cs_new:Npn \__xsim_loop_item:nnnnnn #1#2#3#4#5#6 {}
+\cs_generate_variant:Nn \__xsim_loop_item:nnnnnn {VVxxxx}
+
+% #1: type
+% #2: id
+% #3: boolean property
+\cs_new_protected:Npn \__xsim_deliver_exercise_details:nnn #1#2#3
+ {
+ \tl_if_blank:nTF {#3}
+ { \use:n }
+ { \xsim_if_in_list:nnT {#3} {#1-#2=={true}} }
+ {
+ \tl_set_rescan:Nnx \ExerciseType {} {#1}
+ \tl_set_rescan:Nnx \ExerciseID {} {#2}
+ \__xsim_loop_item:VVxxxx
+ \ExerciseType % #1
+ \ExerciseID % #2
+ { \xsim_get_property:nnn {#1} {#2} {counter} } % #3
+ { \xsim_get_property:nnn {#1} {#2} {subtitle} } % #4
+ { \xsim_get_property:nnn {#1} {#2} {points} } % #5
+ { \xsim_get_property:nnn {#1} {#2} {bonus-points} } % #6
+ }
+ }
+
+% #1: boolean property
+% #2: loop code
+\xsim_define_loop_macro:Nnn \xsim_foreach_exercise_type_id:nn
+ {nnnnnn}
+ {
+ \xsim_foreach_exercise_type:n
+ {
+ \xsim_foreach_exercise_id:n
+ { \__xsim_deliver_exercise_details:nnn {##1} {####1} {#1} }
+ }
+ }
+
+\xsim_define_loop_macro:Nnn \xsim_foreach_exercise_id_type:nn
+ {nnnnnn}
+ {
+ \xsim_foreach_exercise_id:n
+ {
+ \xsim_foreach_exercise_type:n
+ { \__xsim_deliver_exercise_details:nnn {####1} {##1} {#1} }
+ }
+ }
+
+\cs_new:Npn \__xsim_loop_item:nn #1#2 {}
+\cs_generate_variant:Nn \__xsim_loop_item:nn {VV}
+
+\xsim_define_loop_macro:Nnn \xsim_foreach_exercise:nn
+ {nn}
+ {
+ \cs_set:Npn \__xsim_tmpa:w ##1-##2 \q_stop {##1}
+ \cs_set:Npn \__xsim_tmpb:w ##1-##2 \q_stop {##2}
+ \seq_map_inline:cn {g_xsim_#1_order_seq}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl { \__xsim_tmpa:w ##1 \q_stop }
+ \tl_set:Nx \l__xsim_tmpb_tl { \__xsim_tmpb:w ##1 \q_stop }
+ \__xsim_loop_item:VV \l__xsim_tmpa_tl \l__xsim_tmpb_tl
+ }
+ }
+
+% ----------------------------------------------------------------------------
+\cs_new_protected:Npn \xsim_define_exercise_type_variables:n #1
+ {
+ \seq_put_right:Nn \l__xsim_exercise_types_seq {#1}
+ \bool_new:c {l__xsim_#1_solution_print_bool}
+ \bool_new:c {l__xsim_#1_exercise_print_bool}
+ \bool_new:c {l__xsim_#1_exercise_use_bool}
+ }
+
+\cs_new_protected:Npn \xsim_define_counters:n #1
+ {
+ \xsim_verbose:n { Defining~ counters~ for~ new~ exercise~ type~ `#1' }
+ \cs_if_exist:cF { c@ \xsim_get_parameter:nn {#1} {counter} }
+ { \newcounter { \xsim_get_parameter:nn {#1} {counter} } }
+ \cs_if_exist:cF { c@ \xsim_get_parameter:nn {#1} {solution-counter} }
+ { \newcounter { \xsim_get_parameter:nn {#1} {solution-counter} } }
+ \cs_if_exist:cF { c@ number of \xsim_get_parameter:nn {#1} {exercise-env} s }
+ { \newcounter { number of \xsim_get_parameter:nn {#1} {exercise-env} s } }
+ \xsim_if_parameter_set:nnT {#1} {within}
+ {
+ \counterwithin
+ { \xsim_get_parameter:nn {#1} {counter} }
+ { \xsim_get_parameter:nn {#1} {within} }
+ }
+ \xsim_if_parameter_set:nnT {#1} {the-counter}
+ {
+ \cs_set:cpx { the \xsim_get_parameter:nn {#1} {counter} }
+ { \xsim_get_parameter:nn {#1} {the-counter} }
+ }
+ }
+
+% #1: type
+% #2: id
+\cs_new_protected:Npn \xsim_step_exercise_counter:nn #1#2
+ {
+ \refstepcounter { \xsim_get_parameter:nn {#1} {counter} }
+ \xsim_set_properties:nne {#1} {#2}
+ {
+ counter = \use:c { the \xsim_get_parameter:nn {#1} {counter} } ,
+ counter-value = \arabic { \xsim_get_parameter:nn {#1} {counter} }
+ }
+ }
+\cs_generate_variant:Nn \xsim_step_exercise_counter:nn {nV}
+
+% #1: type
+\cs_new_protected:Npn \xsim_declare_exercise_type:nn #1#2
+ {
+ \xsim_if_type:nTF {#1}
+ { \msg_error:nnn {xsim} {type-exists} {#1} }
+ {
+ \xsim_verbose:n { Declaring~ new~ exercise~ type~ `#1'. }
+ \xsim_define_exercise_type_variables:n {#1}
+ \xsim_add_to_list:nn {types} {#1}
+ \xsim_set_parameters:nn {#1} {#2}
+ \xsim_set_parameter:nnx {#1} {number}
+ { number of \xsim_get_parameter:nn {#1} {exercise-env} s }
+ \xsim_check_mandatory_parameters:n {#1}
+ \xsim_if_parameter_set:nnF {#1} {exercises-name}
+ {
+ \xsim_set_parameters:nn {#1}
+ { exercises-name = \xsim_get_parameter:nn {#1} {exercise-name} s }
+ }
+ \xsim_if_parameter_set:nnF {#1} {solutions-name}
+ {
+ \xsim_set_parameters:nn {#1}
+ { solutions-name = \xsim_get_parameter:nn {#1} {solution-name} s }
+ }
+ \xsim_if_parameter_set:nnF {#1} {counter}
+ {
+ \xsim_set_parameters:nx {#1}
+ { counter = \xsim_get_parameter:nn {#1} {exercise-env} }
+ }
+ \xsim_if_parameter_set:nnF {#1} {solution-counter}
+ {
+ \xsim_set_parameters:nx {#1}
+ { solution-counter = \xsim_get_parameter:nn {#1} {solution-env} }
+ }
+ \xsim_define_counters:n {#1}
+ \xsim_verbose:n { Defining~ options~ for~ new~ exercise~ type~ `#1' }
+ \keys_define:nx {xsim}
+ {
+ \xsim_get_parameter:nn {#1} {solution-env} / print
+ .bool_set:N = \exp_not:c {l__xsim_#1_solution_print_bool} ,
+ \xsim_get_parameter:nn {#1} {solution-env} / print
+ .initial:n = false ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / print
+ .bool_set:N = \exp_not:c {l__xsim_#1_exercise_print_bool} ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / print
+ .initial:n = true ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / use
+ .bool_set:N = \exp_not:c {l__xsim_#1_exercise_use_bool} ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / use
+ .initial:n = true ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / collect .choice: ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / collect / true .code:n =
+ \keys_set:nn
+ { xsim / \xsim_get_parameter:nn {#1} {exercise-env} }
+ { use = false , print = false } ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / collect / false .code:n =
+ \keys_set:nn
+ { xsim / \xsim_get_parameter:nn {#1} {exercise-env} }
+ { use = true , print = true } ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / collect .default:n = true ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / collect .initial:n = false ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / within .code:n =
+ \exp_not:N \counterwithin { \xsim_get_parameter:nn {#1} {counter} } {####1},
+ \xsim_get_parameter:nn {#1} {exercise-env} / the-counter .code:n =
+ \cs_set:cpn {the \xsim_get_parameter:nn {#1} {counter} } {####1} ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / template
+ .code:n = \xsim_set_parameter:nnn {#1} {exercise-template} {####1} ,
+ \xsim_get_parameter:nn {#1} {solution-env} / template
+ .code:n = \xsim_set_parameter:nnn {#1} {solution-template} {####1} ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / name
+ .code:n = \xsim_set_parameter:nnn {#1} {exercise-name} {####1} ,
+ \xsim_get_parameter:nn {#1} {exercise-env} s / name
+ .code:n = \xsim_set_parameter:nnn {#1} {exercises-name} {####1} ,
+ \xsim_get_parameter:nn {#1} {solution-env} / name
+ .code:n = \xsim_set_parameter:nnn {#1} {solution-name} {####1} ,
+ \xsim_get_parameter:nn {#1} {solution-env} s / name
+ .code:n = \xsim_set_parameter:nnn {#1} {solutions-name} {####1} ,
+ \xsim_get_parameter:nn {#1} {exercise-env} / heading
+ .code:n = \xsim_set_parameter:nnn {#1} {exercise-heading} {####1} ,
+ \xsim_get_parameter:nn {#1} {solution-env} / heading
+ .code:n = \xsim_set_parameter:nnn {#1} {solution-heading} {####1}
+ }
+ \xsim_new_environment:nn {#1} {exercise}
+ \xsim_new_environment:nn {#1} {solution}
+ }
+ }
+
+% #1: type
+% #2: id
+\prg_new_conditional:Npnn \xsim_if_exercise_exist:nn #1#2 {T,F,TF}
+ {
+ \xsim_if_exist:nnnTF {#1} {#2} {exercise}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_exercise_exist:nnT {VV}
+
+% ----------------------------------------------------------------------------
+% define boolean properties <do> and <done> (<done> is a noupdate property)
+% and the conditional:
+% \xsim_if_<do>:nnTF
+%
+% #1: <do>
+% #2: <done>
+\cs_new_protected:Npn \__xsim_new_exercise_mode:nn #1#2
+ {
+ % boolean:
+ \xsim_declare_property:nnnn
+ { \c_false_bool } { \c_true_bool } { \c_false_bool } {#1}
+ % boolean, noupdate:
+ \xsim_declare_property:nnnn
+ { \c_false_bool } { \c_true_bool } { \c_true_bool } {(#2)}
+ % boolean:
+ \xsim_declare_property:nnnn
+ { \c_false_bool } { \c_true_bool } { \c_false_bool } {#2}
+ % ##1: type
+ % ##2: id
+ % ##3: exercise|solution
+ \prg_new_protected_conditional:cpnn {xsim_if_#1:nnn} ##1##2##3 {T,F,TF}
+ {
+ \use:c {xsim_##3_if_#1:nnTF} {##1} {##2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+\cs_generate_variant:Nn \prg_new_protected_conditional:Npnn {c}
+\cs_generate_variant:Nn \prg_generate_conditional_variant:Nnn {c}
+
+\__xsim_new_exercise_mode:nn {use} {used}
+\__xsim_new_exercise_mode:nn {print} {printed}
+
+% #1: type
+% #2: options
+\cs_new_protected:Npn \xsim_exercise_setup:nn #1#2
+ {
+ \int_gincr:N \g_xsim_id_int
+ \int_compare:nF { \g_xsim_max_id_int > \g_xsim_id_int }
+ { \int_gset_eq:NN \g_xsim_max_id_int \g_xsim_id_int }
+ \tl_gset:Nx \g_xsim_exercise_id_tl { \int_use:N \g_xsim_id_int }
+ \tl_gset:Nn \g_xsim_exercise_type_tl {#1}
+ \xsim_add_to_list:nx {idtypes} { \g_xsim_exercise_id_tl == {#1} }
+ \xsim_foreach_goal:n
+ {
+ \xsim_if_property_set:nVnT {#1} \g_xsim_exercise_id_tl {##1}
+ {
+ \bool_set_true:c {l__xsim_temporary_##1_bool}
+ \fp_set:cn {l__xsim_temporary_##1_fp}
+ { \xsim_get_property:nVn {#1} \g_xsim_exercise_id_tl {##1} }
+ \xsim_unset_property:nVn {#1} \g_xsim_exercise_id_tl {##1}
+ }
+ }
+ \xsim_set_properties:nVe {#1} \g_xsim_exercise_id_tl
+ {
+ % properties set by the user:
+ \exp_not:n {#2} ,
+ % properties which need to have certain values:
+ id = \g_xsim_exercise_id_tl ,
+ printed = false ,
+ used = false
+ }
+ \xsim_foreach_goal:n
+ {
+ \xsim_if_property_set:nVnT {#1} \g_xsim_exercise_id_tl {##1}
+ {
+ \xsim_set_property:nVne {#1} \g_xsim_exercise_id_tl {user##1}
+ { \xsim_get_property:nVn {#1} \g_xsim_exercise_id_tl {##1} }
+ }
+ \bool_if:cT {l__xsim_temporary_##1_bool}
+ {
+ \xsim_set_property:nVne {#1} \g_xsim_exercise_id_tl {##1}
+ { \fp_to_decimal:c {l__xsim_temporary_##1_fp} }
+ }
+ }
+ }
+
+\prg_new_conditional:Npnn \xsim_exercise_if_use:nn #1#2 {T,F,TF}
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {(used)}
+ { \prg_return_false: }
+ {
+ \xsim_if_insert_mode:TF
+ {
+ \xsim_if_property_set:nnnTF {#1} {#2} {use}
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {use}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ {
+ \bool_if:cTF {l__xsim_#1_exercise_use_bool}
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+ }
+ {
+ \xsim_if_property_set:nnnTF {#1} {#2} {use}
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {use}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ {
+ \bool_if:cTF {l__xsim_#1_exercise_use_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+ }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_exercise_if_use:nn {nV} {T,TF}
+
+% #1: type
+% #2: ID
+\cs_new_protected:Npn \xsim_exercise_use_setup:nn #1#2
+ {
+ \stepcounter { \xsim_get_parameter:nn {#1} {number} }
+ \xsim_step_exercise_counter:nn {#1} {#2}
+ \xsim_set_properties:nne {#1} {#2}
+ {
+ section-value = \arabic{section} ,
+ section = \thesection ,
+ page-value = \arabic{page} ,
+ sectioning =
+ { \cs_if_exist:NTF \thechapter { \arabic {chapter} } {0} }
+ { \arabic {section} }
+ { \arabic {subsection} }
+ { \arabic {subsubsection} }
+ { \arabic {paragraph} } ,
+ page = \thepage
+ }
+ \xsim_if_property_exist:nT {chapter}
+ {
+ \xsim_set_properties:nne {#1} {#2}
+ {
+ chapter-value = \arabic{chapter} ,
+ chapter = \thechapter
+ }
+ }
+ }
+\cs_generate_variant:Nn \xsim_exercise_use_setup:nn {nV}
+
+\prg_new_conditional:Npnn \xsim_exercise_if_print:nn #1#2 {T,F,TF}
+ {
+ \xsim_if_tagged:nnTF {#1} {#2}
+ {
+ \xsim_if_insert_mode:TF
+ { \prg_return_true: }
+ {
+ \bool_if:cTF {l__xsim_#1_exercise_print_bool}
+ {
+ \xsim_if_property_set:nnnTF {#1} {#2} {print}
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {print}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_true: }
+ }
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {print}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+ }
+ { \prg_return_false: }
+ }
+\prg_generate_conditional_variant:Nnn \xsim_exercise_if_print:nn {nV} {T,TF}
+
+% #1: type
+% #2: ID
+\cs_new_protected:Npn \xsim_exercise_print_setup:nn #1#2
+ {
+ \xsim_foreach_goal:n
+ {
+ \xsim_if_property_set:nnnT {#1} {#2} {body##1}
+ { \xsim_set_property:nnnn {#1} {#2} {body##1} {0} }
+ }
+ }
+\cs_generate_variant:Nn \xsim_exercise_print_setup:nn {nV}
+
+% #1: type
+% #2: options
+\cs_new_protected:Npn \xsim_start_exercise:nn #1#2
+ {
+ \xsim_if_insert_mode:F { \xsim_exercise_setup:nn {#1} {#2} }
+ \xsim_exercise_if_use:nVT {#1} \g_xsim_exercise_id_tl
+ { \xsim_exercise_use_setup:nV {#1} \g_xsim_exercise_id_tl }
+ \xsim_exercise_if_print:nVT {#1} \g_xsim_exercise_id_tl
+ { \xsim_exercise_print_setup:nV {#1} \g_xsim_exercise_id_tl }
+ \tl_set_eq:NN \ExerciseID \g_xsim_exercise_id_tl
+ \tl_set:Nn \ExerciseType {#1}
+ \xsim_verbose:x
+ { Starting~ exercise~ type~ `#1' with~ id~ ` \g_xsim_exercise_id_tl '. }
+ \xsim_if_insert_mode:F { \xsim_collect:nV {#1} \g_xsim_exercise_id_tl }
+ }
+
+% #1: type
+\cs_new_protected:Npn \xsim_stop_exercise:n #1
+ {
+ \tl_set_eq:NN \ExerciseID \g_xsim_exercise_id_tl
+ \tl_set:Nn \ExerciseType {#1}
+ \xsim_if_insert_mode:F
+ {
+ \xsim_foreach_goal:n
+ {
+ \xsim_if_property_set:nVnTF {#1} \g_xsim_exercise_id_tl {##1}
+ {
+ \fp_set:Nn \l__xsim_tmpa_fp
+ { \xsim_get_property:nVn {#1} \g_xsim_exercise_id_tl {body##1} + 0 }
+ \fp_set:Nn \l__xsim_tmpb_fp
+ { \xsim_get_property:nVn {#1} \g_xsim_exercise_id_tl {user##1} + 0 }
+ \fp_set:Nn \l__xsim_tmpa_fp { \l__xsim_tmpa_fp + \l__xsim_tmpb_fp }
+ \xsim_set_property:nVne {#1} \g_xsim_exercise_id_tl {##1}
+ { \fp_to_decimal:N \l__xsim_tmpa_fp }
+ }
+ {
+ \xsim_if_property_set:nVnT {#1} \g_xsim_exercise_id_tl {body##1}
+ { \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl {##1} {0} }
+ }
+ }
+ }
+ \xsim_exercise_if_print:nVT {#1} \g_xsim_exercise_id_tl
+ {
+ \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl {(printed)} {true}
+ \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl {printed} {true}
+ }
+ \xsim_exercise_if_use:nVT {#1} \g_xsim_exercise_id_tl
+ {
+ \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl {(used)} {true}
+ \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl {used} {true}
+ \xsim_update_goals:nV {#1} \g_xsim_exercise_id_tl
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+\xsim_new_aux_property:cpn {total-number} #1
+ { \int_gset:Nn \g_xsim_max_id_int {#1} }
+
+\hook_gput_code:nnn {begindocument/before} {xsim}
+ {
+ \xsim_foreach_exercise_type:n
+ {
+ \tl_new:c { number of #1 s }
+ \tl_gset:cn { number of #1 s } {0}
+ \xsim_new_aux_property:cpn {#1} ##1
+ { \tl_gset:cn { number of #1 s } {##1} }
+ }
+ }
+
+\xsim_at_begin_document:n
+ {
+ \xsim_foreach_exercise_type:n
+ {
+ \xsim_write_to_aux:x
+ { \token_to_str:N \providecommand \token_to_str:N \numberof #1 s {} }
+ }
+ }
+
+\xsim_at_end_document:n
+ {
+ \xsim_if_clear_aux:T
+ {
+ \int_compare:nNnF { \g_xsim_max_id_int } = { \g_xsim_id_int }
+ { \xsim_empty_lists: }
+ }
+ \xsim_add_property_to_aux:nn {total-number} { { \int_use:N \g_xsim_id_int } }
+ \xsim_foreach_exercise_type:n
+ {
+ \xsim_add_property_to_aux:nn {#1}
+ { { \arabic { \xsim_get_parameter:nn {#1} {number} } } }
+ }
+ \xsim_update_list:n {types}
+ \xsim_update_list:n {idtypes}
+ }
+
+\XSIMmoduleend
+\XSIMmodule{solutions}{managing solutions}
+
+\bool_new:N \l_xsim_inside_solution_bool
+\bool_new:N \l__xsim_include_question_bool
+\bool_new:N \l__xsim_printsolutions_headings_bool
+\bool_new:N \l__xsim_printsolutions_conditions_bool
+\bool_new:N \l____xsim_this_condition_bool
+
+\seq_new:N \l__xsim_printsolutions_conditions_seq
+
+\int_new:N \l_xsim_printsolutions_section_int
+\int_new:N \l_xsim_printsolutions_chapter_int
+
+\tl_new:N \l__xsim_printsolutions_headings_template_tl
+\tl_new:N \ExerciseSection
+\tl_new:N \ExerciseChapter
+\tl_new:N \l__xsim_printsolutions_collection_tl
+
+% ----------------------------------------------------------------------------
+
+\prg_new_conditional:Npnn \xsim_if_inside_solution: {p,T,F,TF}
+ {
+ \bool_if:NTF \l_xsim_inside_solution_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_if_solution_print:n #1 {p,T,F,TF}
+ {
+ \bool_if:cTF {l__xsim_#1_solution_print_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\bool_new:N \l____xsim_print_bool
+
+% #1: type
+% #2: id
+\prg_new_protected_conditional:Npnn \xsim_solution_if_print:nn #1#2 {T,F,TF}
+ {
+ \bool_set_true:N \l____xsim_print_bool
+ \xsim_if_tagged:nnF {#1} {#2}
+ { \bool_set_false:N \l____xsim_print_bool }
+ \xsim_if_boolean_property:nnnF {#1} {#2} {(used)}
+ { \bool_set_false:N \l____xsim_print_bool }
+ \bool_if:cF {l__xsim_#1_solution_print_bool}
+ { \bool_set_false:N \l____xsim_print_bool }
+ \bool_if:NTF \l____xsim_print_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_solution_if_print:nnT {nV,oo}
+
+% #1: type
+% #2: id
+\prg_new_protected_conditional:Npnn \xsim_if_solution_exist:nn #1#2 {T,F,TF}
+ {
+ \xsim_if_boolean_property:nnnTF {#1} {#2} {solution}
+ { \xsim_if_exist:nnnTF {#1} {#2} {exercise} }
+ { \xsim_if_exist:nnnTF {#1} {#2} {solution} }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_solution_exist:nnT {VV,oo}
+\cs_generate_variant:Nn \xsim_if_solution_exist:nnTF {oo}
+
+% #1: type
+% #2: options
+\cs_new_protected:Npn \xsim_start_solution:nn #1#2
+ {
+ \keys_set:xn { xsim/\xsim_get_parameter:nn {#1} {solution-env} } {#2}
+ \bool_set_true:N \l_xsim_inside_solution_bool
+ \refstepcounter { \xsim_get_parameter:nn {#1} {solution-counter} }
+ }
+
+\cs_new_protected:Npn \xsim_stop_solution:n #1 {}
+
+% ----------------------------------------------------------------------------
+
+% #1: conditional base function (three n args)
+% #2: name
+% #3: code (refer to type and id with `#1' and `#2'), #3 refers to the boolean
+% properties use/print
+\cs_new_protected:Npn \xsim_new_solutions_condition:Nnn #1#2#3
+ {
+ \prg_new_protected_conditional:Npnn #1 ##1##2##3 {T,F,TF}
+ {
+ \xsim_if_in_list:nnTF {##3} {##1-##2=={true}}
+ {
+ \__xsim_printsolutions_if_condition:nTF {#2}
+ { \__xsim_printsolutions_condition_true: #3 }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+ }
+
+% per section condition:
+\xsim_new_solutions_condition:Nnn \__xsim_if_solutions_per_section:nnn
+ {per-section}
+ {
+ \xsim_if_in_list:nxTF {section-value}
+ { #1-#2 == { \int_use:N \l_xsim_printsolutions_section_int } }
+ {
+ \tl_set:Nx \ExerciseSection
+ { \xsim_get_property:nnn {#1} {#2} {section} }
+ \prg_return_true:
+ }
+ { \prg_return_false: }
+ }
+
+% per chapter condition:
+\xsim_new_solutions_condition:Nnn \__xsim_if_solutions_per_chapter:nnn
+ {per-chapter}
+ {
+ \xsim_if_in_list:nxTF {chapter-value}
+ { #1-#2 == { \int_use:N \l_xsim_printsolutions_chapter_int } }
+ {
+ \tl_set:Nx \ExerciseChapter
+ { \xsim_get_property:nnn {#1} {#2} {chapter} }
+ \prg_return_true:
+ }
+ { \prg_return_false: }
+ }
+
+% per collection condition:
+\xsim_new_solutions_condition:Nnn \__xsim_if_solutions_in_collection:nnn
+ {per-collection}
+ {
+ \tl_if_blank:VTF \l__xsim_printsolutions_collection_tl
+ { \prg_return_false: }
+ {
+ \xsim_if_in_collection:VnnTF
+ \l__xsim_printsolutions_collection_tl
+ {#1}
+ {#2}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+
+% ----------------------------------------------------------------------------
+% conditions mechanism
+\cs_new_protected:Npn \__xsim_printsolutions_condition_false:
+ { \bool_set_false:N \l__xsim_printsolutions_conditions_bool }
+
+\cs_new_protected:Npn \__xsim_printsolutions_condition_true:
+ { \bool_set_true:N \l__xsim_printsolutions_conditions_bool }
+
+% #1: type
+% #2: id
+% #3: boolean property
+\prg_new_conditional:Npnn
+ \__xsim_printsolutions_if_conditions:nnn #1#2#3 {T,F,TF}
+ {
+ \bool_if:NTF \l__xsim_printsolutions_conditions_bool
+ { \prg_return_true: }
+ {
+ \xsim_if_in_list:nnTF {#3} {#1-#2=={true}}
+ { \prg_return_false: }
+ { \prg_return_true: }
+ }
+ }
+
+% #1: name
+% #2: condition
+\cs_new_protected:Npn \xsim_declare_printsolutions_condition:nn #1#2
+ {
+ \bool_new:c {l__xsim_printsolutions_#1_condition_bool}
+ \seq_put_right:Nn \l__xsim_printsolutions_conditions_seq {#1}
+ \xsim_attribute_set:nnn {printsolutions} {#1} {#2}
+ }
+
+\prg_new_conditional:Npnn \__xsim_printsolutions_if_condition:n #1 {T,F,TF}
+ {
+ \bool_if:cTF {l__xsim_printsolutions_#1_condition_bool}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: name
+% #2: true|false
+\cs_new_protected:Npn \__xsim_printsolutions_condition:nn #1#2
+ { \bool_set_eq:cc {l__xsim_printsolutions_#1_condition_bool} {c_#2_bool} }
+
+% false if any condition is false for this solution:
+% #1: type
+% #2: id
+% #3: boolean property
+\prg_new_protected_conditional:Npnn
+ \__xsim_printsolutions_check_conditions:nnn #1#2#3 {T,F,TF}
+ {
+ \__xsim_printsolutions_condition_false:
+ \bool_set_true:N \l____xsim_this_condition_bool
+ \seq_map_inline:Nn \l__xsim_printsolutions_conditions_seq
+ {
+ \bool_if:cT {l__xsim_printsolutions_##1_condition_bool}
+ {
+ \xsim_attribute_get:nn {printsolutions} {##1}
+ {#1} {#2} {#3}
+ { }
+ { \bool_set_false:N \l____xsim_this_condition_bool }
+ }
+ }
+ \bool_if:NTF \l____xsim_this_condition_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+
+% #1: type
+% #2: id
+% #3: boolean property
+% #4: code
+\cs_new_protected:Npn \xsim_if_this_solution_do:nnnn #1#2#3#4
+ {
+ \xsim_if_solution_exist:nnT {#1} {#2}
+ { \__xsim_printsolutions_check_conditions:nnnT {#1} {#2} {#3} {#4} }
+ }
+\cs_generate_variant:Nn \xsim_if_this_solution_do:nnnn {nV}
+
+% #1: type
+% #2: boolean property
+% #3: code
+\cs_new_protected:Npn \xsim_if_solutions_do:nnn #1#2#3
+ {
+ \xsim_foreach_exercise:nn {#2}
+ {
+ \str_if_eq:nnT {#1} {##1}
+ {
+ \xsim_if_this_solution_do:nnnn
+ {#1}
+ {##2}
+ {#2}
+ {#3}
+ }
+ }
+ }
+\cs_generate_variant:Nn \str_if_eq:nnT {nV}
+
+% ----------------------------------------------------------------------------
+% #1: boolean -- if true only the solutions of printed exercises will be
+% output
+% #2: pre
+% #3: post
+% #4: type
+% #5: code (refer to type with #1 and id with #2)
+\cs_new_protected:Npn \xsim_print_type_code:nnnnn #1#2#3#4#5
+ {
+ \group_begin:
+ \cs_set_protected:Npn \__xsim_print_entry:nn ##1##2 {#5}
+ #2
+ \bool_set_false:N \l__xsim_tmpa_bool
+ \bool_if:nTF {#1}
+ {
+ \xsim_if_solutions_do:nnn {#4} {printed}
+ { \bool_set_true:N \l__xsim_tmpa_bool }
+ }
+ {
+ \xsim_if_solutions_do:nnn {#4} {used}
+ { \bool_set_true:N \l__xsim_tmpa_bool }
+ }
+ \tl_set:Nn \ExerciseType {#4}
+ \bool_if:NT \l__xsim_tmpa_bool
+ {
+ \bool_if:NT \l__xsim_printsolutions_headings_bool
+ {
+ \xsim_use_template:nV
+ {heading}
+ \l__xsim_printsolutions_headings_template_tl
+ }
+ }
+ \bool_if:nTF {#1}
+ {
+ \xsim_if_solutions_do:nnn {#4} {printed}
+ { \__xsim_print_entry:nn {#4} {##2} }
+ }
+ {
+ \xsim_if_solutions_do:nnn {#4} {used}
+ { \__xsim_print_entry:nn {#4} {##2} }
+ }
+ #3
+ \group_end:
+ }
+
+% #1: boolean -- if true only the solutions of printed exercises will be
+% output
+% #2: options
+% #3: type
+\cs_new_protected:Npn \xsim_print_type_solutions:nnn #1#2#3
+ {
+ \xsim_print_type_code:nnnnn
+ {#1}
+ {
+ \xsim_verbose:n
+ { Printing~ solutions~ for~ exercise~ type~ `#3'. }
+ \keys_set:nn {xsim/print-solutions} {#2}
+ }
+ {}
+ {#3}
+ { \xsim_insert:nnnn {##1} {##2} {} {solution} }
+ }
+
+% #1: boolean -- if true only the solutions of printed exercises will be
+% output
+% #2: options
+\cs_new_protected:Npn \xsim_print_all_solutions_per_type:nn #1#2
+ {
+ \xsim_foreach_exercise_type:n
+ { \xsim_print_type_solutions:nnn {#1} {#2} {##1} }
+ }
+
+% #1: boolean -- if true only the solutions of printed exercises will be
+% output
+% #2: options
+\cs_new_protected:Npn \xsim_print_all_solutions_per_id:nn #1#2
+ {
+ \xsim_verbose:n { Printing~ solutions. }
+ \group_begin:
+ \keys_set:nn {xsim/print-solutions} {#2}
+ \bool_set_false:N \l__xsim_tmpa_bool
+ \bool_if:nTF {#1}
+ {
+ \xsim_foreach_exercise_id_type:nn {print}
+ {
+ \xsim_if_this_solution_do:nnnn {##1} {##2} {print}
+ { \xsim_insert:nnnn {##1} {##2} {} {solution} }
+ }
+ }
+ {
+ \xsim_foreach_exercise_id_type:nn {used}
+ {
+ \xsim_if_this_solution_do:nnnn {##1} {##2} {used}
+ { \xsim_insert:nnnn {##1} {##2} {} {solution} }
+ }
+ }
+ \group_end:
+ }
+
+% ----------------------------------------------------------------------------
+
+\xsim_declare_printsolutions_condition:nn {per-section}
+ { \__xsim_if_solutions_per_section:nnnTF }
+\xsim_declare_printsolutions_condition:nn {per-chapter}
+ { \__xsim_if_solutions_per_chapter:nnnTF }
+\xsim_declare_printsolutions_condition:nn {per-collection}
+ { \__xsim_if_solutions_in_collection:nnnTF }
+
+% ----------------------------------------------------------------------------
+
+\keys_define:nn {xsim/print-solutions}
+ {
+ headings .bool_set:N = \l__xsim_printsolutions_headings_bool ,
+ headings .initial:n = true ,
+ headings-template .tl_set:N = \l__xsim_printsolutions_headings_template_tl ,
+ headings-template .initial:n = default ,
+ include-exercise .bool_set:N = \l__xsim_include_question_bool ,
+ include-exercise .initial:n = false ,
+ section .choice: ,
+ section/true .code:n =
+ \__xsim_printsolutions_condition:nn {per-section} {true}
+ \int_set:Nn \l_xsim_printsolutions_section_int { \value {section} } ,
+ section/false .code:n =
+ \__xsim_printsolutions_condition:nn {per-section} {false} ,
+ section/unknown .code:n =
+ \__xsim_printsolutions_condition:nn {per-section} {true}
+ \int_set:Nn \l_xsim_printsolutions_section_int {#1} ,
+ section .default:n = true ,
+ section .initial:n = false ,
+ chapter .choice: ,
+ chapter/true .code:n =
+ \__xsim_printsolutions_condition:nn {per-chapter} {true}
+ \int_set:Nn \l_xsim_printsolutions_chapter_int { \value {chapter} } ,
+ chapter/false .code:n =
+ \__xsim_printsolutions_condition:nn {per-chapter} {false} ,
+ chapter/unknown .code:n =
+ \__xsim_printsolutions_condition:nn {per-chapter} {true}
+ \int_set:Nn \l_xsim_printsolutions_chapter_int {#1} ,
+ chapter .default:n = true ,
+ chapter .initial:n = false ,
+ collection .choice: ,
+ collection/false .code:n =
+ \__xsim_printsolutions_condition:nn {per-collection} {false} ,
+ collection/unknown .code:n =
+ \xsim_if_collection_exist:nT {#1}
+ {
+ \__xsim_printsolutions_condition:nn {per-collection} {true}
+ \tl_set:Nn \l__xsim_printsolutions_collection_tl {#1}
+ } ,
+ collection .initial:n = false
+ }
+
+\XSIMmoduleend
+\XSIMmodule{collections}{collect exercises and print collected exercises}
+
+\seq_new:N \g__xsim_collections_seq
+\bool_new:N \l____xsim_active_bool
+
+\msg_new:nnn {xsim} {collection-exists}
+ {
+ The~ collection~ `#1'~ you're~ trying~ to~ define~ \msg_line_context:
+ \c_space_tl already~ exists.
+ }
+
+\msg_new:nnn {xsim} {collection-unknown}
+ {
+ The~ collection~ `#1'~ does~ not~ seem~ to~ exist~ \msg_line_context: .
+ If~ this~ is~ not¨ a~ typo~ define~ it~ first.
+ }
+
+\msg_new:nnn {xsim} {collection-activate}
+ {
+ The~ collection~ `#1'~ is~ already~ active~ \msg_line_context: .~
+ Not~ activating~ it~ now.
+ }
+
+\msg_new:nnn {xsim} {collection-deactivate}
+ {
+ The~ collection~ `#1'~ is~ not~ active~ \msg_line_context: .~
+ Not~ deactivating~ it~ now.
+ }
+
+\msg_new:nnn {xsim} {print-collection-choice}
+ {
+ The~ choice~ `#1'~ neither~ exists~ for~ `print-collection/print'~ nor~
+ for~ `random/print'.~ I'm~ using~ `exercises'~ instead~ \msg_line_context: .
+ }
+
+% ----------------------------------------------------------------------------
+\xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_false_bool }
+ { \c_false_bool }
+ {collections}
+
+% #1: collection name
+% #2: conditions: clist of <tag>=<value>
+\cs_new_protected:Npn \xsim_new_collection:nn #1#2
+ {
+ \xsim_if_collection_exist:nTF {#1}
+ { \msg_error:nnn {xsim} {collection-exists} {#1} }
+ {
+ \xsim_verbose:n { Declaring~ new~ collection~ `#1'. }
+ \xsim_attribute_new:nn {collection} {#1}
+ \xsim_attribute_set:nnn {collection} {#1} { \c_false_bool }
+ \xsim_attribute_new:nn {collection:conditions} {#1}
+ \xsim_attribute_set:nnn {collection:conditions} {#1} {#2}
+ \seq_gput_right:Nn \g__xsim_collections_seq {#1}
+ \xsim_new_list:n {collection:#1}
+ \xsim_at_end_document:n
+ { \xsim_update_list:n {collection:#1} }
+ }
+ }
+
+% #1: collection name
+\prg_new_conditional:Npnn \xsim_if_collection_exist:n #1 {T,F,TF}
+ {
+ \seq_if_in:NnTF \g__xsim_collections_seq {#1}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new_protected:Npn \xsim_foreach_collection:n #1
+ { \seq_map_inline:Nn \g__xsim_collections_seq {#1} }
+
+\cs_new:Npn \xsim_collection_map_break: { \seq_map_break: }
+
+% ----------------------------------------------------------------------------
+% #1: collection name
+\prg_new_conditional:Npnn \xsim_if_collection_active:n #1 {T,F,TF}
+ {
+ \xsim_attribute_if_set:nnTF {collection} {#1}
+ {
+ \bool_if:nTF
+ { \xsim_attribute_get:nn {collection} {#1} }
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ { \prg_return_false: }
+ }
+
+% #1: collection name
+\cs_new_protected:Npn \xsim_activate_collection:n #1
+ {
+ \xsim_if_collection_exist:nTF {#1}
+ {
+ \xsim_if_collection_active:nTF {#1}
+ { \msg_warning:nnn {xsim} {collection-activate} {#1} }
+ {
+ \xsim_verbose:n { Activating~ collection~ `#1'. }
+ \xsim_attribute_set:nnn {collection} {#1} { \c_true_bool }
+ }
+ }
+ { \msg_error:nnn {xsim} {collection-unknown} {#1} }
+ }
+
+% #1: collection name
+\cs_new_protected:Npn \xsim_deactivate_collection:n #1
+ {
+ \xsim_if_collection_exist:nTF {#1}
+ {
+ \xsim_if_collection_active:nTF {#1}
+ {
+ \xsim_verbose:n { Deactivating~ collection~ `#1'. }
+ \xsim_attribute_set:nnn {collection} {#1} { \c_false_bool }
+ }
+ { \msg_warning:nnn {xsim} {collection-deactivate} {#1} }
+ }
+ { \msg_error:nnn {xsim} {collection-unknown} {#1} }
+ }
+
+% #1: csv list of collections
+% #2: type
+\cs_new_protected:Npn \xsim_collect_type_start:nn #1#2
+ {
+ \group_begin:
+ \keys_set:nn {xsim} { #2/collect = true }
+ \clist_map_inline:nn {#1}
+ {
+ \xsim_if_collection_active:nF {##1}
+ { \xsim_activate_collection:n {##1} }
+ }
+ }
+
+% #1: csv list of collections
+\cs_new_protected:Npn \xsim_collect_start:n #1
+ {
+ \group_begin:
+ \xsim_foreach_exercise_type:n
+ {
+ \keys_set:nx {xsim}
+ { \xsim_get_parameter:nn {##1} {exercise-env} / collect = true }
+ }
+ \clist_map_inline:nn {#1}
+ {
+ \xsim_if_collection_active:nF {##1}
+ { \xsim_activate_collection:n {##1} }
+ }
+ }
+
+% #1: csv list of collections
+\cs_new_protected:Npn \xsim_collect_stop:n #1
+ {
+ \clist_map_inline:nn {#1} { \xsim_deactivate_collection:n {##1} }
+ \group_end:
+ }
+
+\keys_define:nn {xsim}
+ {
+ collect .code:n =
+ \xsim_foreach_exercise_type:n
+ {
+ \keys_set:nx {xsim}
+ { \xsim_get_parameter:nn {##1} {exercise-env} / collect = #1 }
+ } ,
+ collect .default:n = true ,
+ collect .initial:n = false
+ }
+
+% ----------------------------------------------------------------------------
+% #1: collection name
+% #2: type
+% #3: ID
+\prg_new_conditional:Npnn \xsim_if_in_collection:nnn #1#2#3 {T,F,TF}
+ {
+ \xsim_if_in_list:nnTF {collection:#1} {#2-#3}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+\cs_generate_variant:Nn \xsim_if_in_collection:nnnTF {V}
+\cs_generate_variant:Nn \xsim_if_in_collection:nnnT {x,nV}
+
+\cs_new:Npn \xsim_collection_count:n #1
+ { \xsim_list_count:n {collection:#1} }
+
+\bool_new:N \l____xsim_collection_condition_bool
+
+% #1: collection name
+% #2: type
+% #3: ID
+\prg_new_protected_conditional:Npnn \xsim_collection_conditions_if:nnn #1#2#3 {T,F,TF}
+ {
+ \bool_set_false:N \l____xsim_collection_condition_bool
+ \clist_set:Nx \l__xsim_tmpa_clist
+ { \xsim_attribute_get:nn {collection:conditions} {#1} }
+ \clist_if_empty:NTF \l__xsim_tmpa_clist
+ { \bool_set_true:N \l____xsim_collection_condition_bool }
+ {
+ \clist_map_inline:Vn
+ \l__xsim_tmpa_clist
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \__xsim_get_condition_tag:w ##1 \q_stop }
+ \tl_set:Nx \l__xsim_tmpb_tl
+ { \__xsim_get_condition_values:w ##1 \q_stop }
+ \xsim_if_tag_type_exist:VTF \l__xsim_tmpa_tl
+ {
+ \xsim_has_tags:nnVVT {#2} {#3} \l__xsim_tmpa_tl \l__xsim_tmpb_tl
+ {
+ \bool_set_true:N \l____xsim_collection_condition_bool
+ \clist_map_break:
+ }
+ }
+ { \msg_warning:nnV {xsim} {tag-unknown} \l__xsim_tmpa_tl }
+ }
+ }
+ \bool_if:NTF \l____xsim_collection_condition_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\cs_new:Npn \__xsim_get_condition_tag:w #1=#2 \q_stop {#1}
+\cs_new:Npn \__xsim_get_condition_values:w #1=#2 \q_stop {#2}
+
+% #1: type
+% #2: ID
+\cs_new_protected:Npn \xsim_collect:nn #1#2
+ {
+ \xsim_foreach_collection:n
+ {
+ \xsim_if_collection_active:nT {##1}
+ {
+ \xsim_collection_conditions_if:nnnT {##1} {#1} {#2}
+ { \xsim_add_to_collection:nnn {##1} {#1} {#2} }
+ }
+ }
+ }
+\cs_generate_variant:Nn \xsim_collect:nn {nV}
+
+% #1: collection name
+% #2: type
+% #3: ID
+\cs_new_protected:Npn \xsim_add_to_collection:nnn #1#2#3
+ {
+ \xsim_verbose:n
+ { Adding~ exercise~ type~ `#2'~ ID~ `#3'~ to~ collection~ `#1'. }
+ \clist_set:Nx \l__xsim_tmpa_clist
+ { \xsim_get_property:nnn {#2} {#3} {collections} }
+ \clist_if_in:NnF \l__xsim_tmpa_clist {#1}
+ { \clist_put_right:Nn \l__xsim_tmpa_clist {#1} }
+ \xsim_set_property:nnnV {#2} {#3} {collections} \l__xsim_tmpa_clist
+ \xsim_add_to_list:nn {collection:#1} {#2-#3}
+ }
+
+% ----------------------------------------------------------------------------
+\bool_new:N \l__xsim_printcollection_headings_bool
+\tl_new:N \l__xsim_printcollection_headings_template_tl
+\tl_new:N \l__xsim_print_collection_choice_tl
+
+\keys_define:nn {xsim/print-collection}
+ {
+ headings .bool_set:N = \l__xsim_printcollection_headings_bool ,
+ headings .initial:n = false ,
+ headings-template .tl_set:N = \l__xsim_printcollection_headings_template_tl ,
+ headings-template .initial:n = collection ,
+ print .tl_set:N = \l__xsim_print_collection_choice_tl ,
+ print .initial:n = exercises
+ }
+
+% #1: options
+% #2: collection name
+\cs_new_protected:Npn \xsim_print_collection:nn #1#2
+ {
+ \group_begin:
+ \keys_set:nn {xsim/print-collection} {#1}
+ \clist_clear:N \l__xsim_tmpa_clist
+ \clist_clear:N \l__xsim_tmpb_clist
+ \xsim_foreach_exercise_type_id:nn {}
+ {
+ \xsim_get_property_if_set:nnnT {##1} {##2} {collections}
+ {
+ \clist_if_in:NnT \l_xsim_property_value_tl {#2}
+ {
+ \str_set:Nn \l__xsim_tmpa_str {##1}
+ \clist_put_right:NV \l__xsim_tmpa_clist \l__xsim_tmpa_str
+ \clist_put_right:Nn \l__xsim_tmpb_clist {##2}
+ }
+ }
+ }
+ \xsim_foreach_exercise_type:n
+ {
+ \bool_if:NT \l__xsim_printcollection_headings_bool
+ {
+ \clist_if_in:NnT \l__xsim_tmpa_clist {##1}
+ {
+ \tl_set:Nn \ExerciseType {##1}
+ \xsim_use_template:nV
+ {heading}
+ \l__xsim_printcollection_headings_template_tl
+ }
+ }
+ \clist_map_inline:Nn \l__xsim_tmpa_clist
+ {
+ \str_if_eq:nnT {##1} {####1}
+ {
+ \clist_pop:NN \l__xsim_tmpa_clist \l__xsim_tmpa_tl
+ \clist_pop:NN \l__xsim_tmpb_clist \l__xsim_tmpb_tl
+ \str_case:Vn \l__xsim_print_collection_choice_tl
+ {
+ {exercises} { \xsim_insert:nVnn {##1} \l__xsim_tmpb_tl {} {exercise} }
+ {solutions} { \xsim_insert:nVnn {##1} \l__xsim_tmpb_tl {} {solution} }
+ {both} {
+ \xsim_insert:nVnn {##1} \l__xsim_tmpb_tl {} {exercise}
+ \xsim_insert:nVnn {##1} \l__xsim_tmpb_tl {} {solution}
+ }
+ }
+ }
+ }
+ }
+ \group_end:
+ }
+
+% ----------------------------------------------------------------------------
+\xsim_new_collection:nn {all~ exercises} {}
+\xsim_activate_collection:n {all~ exercises}
+
+\XSIMmoduleend
+\XSIMmodule{blanks}{add blanks, cloze}
+
+\bool_new:N \l__xsim_blank_width_bool
+\bool_new:N \l__xsim_blank_linespread_bool
+\bool_new:N \l__xsim_fill_blank_bool
+\tl_new:N \l__xsim_blank_linespread_tl
+\tl_new:N \l__xsim_blank_scale_tl
+\dim_new:N \l__xsim_blank_dim
+\dim_new:N \l__xsim_blank_line_increment_dim
+\dim_new:N \l__xsim_blank_line_minimum_length_dim
+\box_new:N \l__xsim_blank_box
+
+\cs_new_protected:Npn \xsim_write_cloze_blank:n #1 {#1}
+\cs_new_protected:Npn \xsim_write_cloze_filled:n #1 {#1}
+
+\keys_define:nn {xsim/blank}
+ {
+ blank-style .code:n =
+ \cs_set_protected:Npn \xsim_write_cloze_blank:n ##1 {#1} ,
+ blank-style .initial:n = \underline {#1} ,
+ filled-style .code:n =
+ \cs_set_protected:Npn \xsim_write_cloze_filled:n ##1 {#1} ,
+ filled-style .initial:n = \underline {#1} ,
+ style .meta:n =
+ {
+ blank-style = #1 ,
+ filled-style = #1
+ } ,
+ fill .bool_set:N = \l__xsim_fill_blank_bool ,
+ fill .initial:n = false ,
+ scale .tl_set:N = \l__xsim_blank_scale_tl ,
+ scale .initial:n = 1 ,
+ width .code:n =
+ {
+ \bool_set_true:N \l__xsim_blank_width_bool
+ \dim_set:Nn \l__xsim_blank_dim {#1}
+ } ,
+ linespread .code:n =
+ \bool_set_true:N \l__xsim_blank_linespread_bool
+ \tl_set:Nn \l__xsim_blank_linespread_tl {#1} ,
+ linespread .initial:n = 1 ,
+ line-increment .dim_set:N = \l__xsim_blank_line_increment_dim ,
+ line-increment .initial:n = 0.001\linewidth ,
+ line-minimum-length .dim_set:N = \l__xsim_blank_line_minimum_length_dim ,
+ line-minimum-length .initial:n = 2em
+ }
+
+\cs_new_protected:Npn \xsim_blank:n #1
+ {
+ \box_clear:N \l__xsim_blank_box
+ \mode_if_math:TF
+ { \hbox_set:Nn \l__xsim_blank_box { $ \m at th \mathpalette{}{#1} $ } }
+ { \hbox_set:Nn \l__xsim_blank_box {#1} }
+ \bool_lazy_or:nnTF
+ { \xsim_if_inside_solution_p: }
+ { \l__xsim_fill_blank_bool }
+ { \xsim_write_cloze_filled:n {#1} }
+ {
+ \bool_if:NTF \l__xsim_blank_width_bool
+ { \__xsim_blank_skip:V \l__xsim_blank_dim }
+ { \__xsim_blank_skip:n { \box_wd:N \l__xsim_blank_box } }
+ }
+ }
+
+\cs_new_protected:Npn \__xsim_blank_skip:n #1
+ {
+ \bool_if:NTF \l__xsim_blank_width_bool
+ { \dim_set:Nn \l__xsim_tmpa_dim {#1} }
+ {
+ \fp_set:Nn \l__xsim_tmpa_fp
+ { \dim_to_fp:n {#1} * \l__xsim_blank_scale_tl }
+ \dim_set:Nn \l__xsim_tmpa_dim { \fp_to_dim:N \l__xsim_tmpa_fp }
+ }
+ \dim_compare:nTF
+ { \l__xsim_tmpa_dim > \l__xsim_blank_line_minimum_length_dim }
+ {
+ \mode_if_math:TF
+ { \xsim_write_cloze_blank:n { \skip_horizontal:N \l__xsim_tmpa_dim } }
+ {
+ \dim_do_while:nn { \l__xsim_tmpa_dim > \c_zero_dim }
+ {
+ % I wonder what the correct l3 way would be -- if there is
+ % one, yet:
+ % \tex_hfil:D
+ \tex_penalty:D \hyphenpenalty
+ % \tex_hfilneg:D
+ \dim_compare:nTF
+ { \l__xsim_tmpa_dim < \l__xsim_blank_line_increment_dim }
+ { \xsim_write_cloze_blank:n { \skip_horizontal:N \l__xsim_tmpa_dim } }
+ {
+ \xsim_write_cloze_blank:n
+ { \skip_horizontal:N \l__xsim_blank_line_increment_dim }
+ }
+ \dim_sub:Nn \l__xsim_tmpa_dim { \l__xsim_blank_line_increment_dim }
+ }
+ }
+ }
+ {
+ \xsim_write_cloze_blank:n
+ { \skip_horizontal:N \l__xsim_blank_line_minimum_length_dim }
+ }
+ }
+\cs_generate_variant:Nn \__xsim_blank_skip:n {V}
+
+\XSIMmoduleend
+\XSIMmodule{grades}{distribute goal sums to grades}
+
+\msg_new:nnn {xsim} {grade-unknown}
+ { The~ grade~ `#1'~ has~ never~ been~ declared~ \msg_line_context: }
+
+\bool_new:N \l__xsim_grades_half_bool
+\fp_new:N \l__xsim_grade_round_fp
+\fp_zero:N \l__xsim_grade_round_fp
+\prop_new:N \l__xsim_relative_grades_prop
+\tl_new:N \l__xsim_grade_split_tl
+
+\cs_new:Npn \__xsim_fp_round_to_half:n #1
+ { round( 2*(#1),0)/2 }
+
+\cs_new:Npn \__xsim_grades_round:n #1
+ { round ( #1 , \l__xsim_grade_round_fp ) }
+
+% #1: factor
+% #2: goal sum
+\cs_new:Npn \__xsim_grade_rounded:nn #1#2
+ {
+ \bool_if:NTF \l__xsim_grades_half_bool
+ { \__xsim_fp_round_to_half:n }
+ { \__xsim_grades_round:n }
+ { (#1) * (#2) }
+ }
+
+\cs_new_protected:Npn \xsim_declare_relative_grades:n #1
+ {
+ \seq_set_split:NVn \l__xsim_tmpa_seq \l__xsim_grade_split_tl {#1}
+ \seq_map_inline:Nn \l__xsim_tmpa_seq
+ { \__xsim_declare_relative_grade:w ##1 \q_stop }
+ \xsim_verbose:n {Declaring~ relative~ grade~ distribution}
+ }
+
+\cs_new_protected:Npn \__xsim_declare_relative_grade:w #1 = #2 \q_stop
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl { \tl_trim_spaces:n {#1} }
+ \tl_set:Nx \l__xsim_tmpb_tl { \tl_trim_spaces:n {#2} }
+ \prop_put:NVV \l__xsim_relative_grades_prop
+ \l__xsim_tmpa_tl
+ \l__xsim_tmpb_tl
+ }
+
+% #1: grade
+% #2: sum of points
+% #3: code after grade requirement if == 1
+% #4: code after grade requirement if != 1
+\cs_new_protected:Npn \xsim_get_grade:nnnn #1#2#3#4
+ {
+ \prop_get:NnNTF \l__xsim_relative_grades_prop {#1} \l__xsim_tmpa_tl
+ {
+ \xsim_print_goal:nnn
+ {
+ min(
+ \__xsim_grade_rounded:nn
+ { \l__xsim_tmpa_tl }
+ {#2} ,
+ #2
+ )
+ }
+ {#3}
+ {#4}
+ }
+ { \msg_error:nnn {xsim} {grade-unknown} {#1} }
+ }
+
+% #1: grade
+% #2: goal
+% #3: code after grade requirement if == 1
+% #4: code after grade requirement if != 1
+\cs_new_protected:Npn \xsim_get_grade_goal:nnnn #1#2#3#4
+ {
+ \xsim_if_goal_exist:nTF {#2}
+ {
+ \xsim_get_grade:nnnn
+ {#1}
+ { \use:c {g__xsim_total_goal_#2_fp} }
+ {#3}
+ {#4}
+ }
+ { \msg_error:nnn {xsim} {goal-unknown} {#2} }
+ }
+
+% #1: grade
+% #2: goal list (separated with +)
+% #3: code after grade requirement if == 1
+% #4: code after grade requirement if != 1
+\cs_new_protected:Npn \xsim_get_grade_requirement:nnnn #1#2#3#4
+ {
+ \seq_set_split:Nnn \l__xsim_tmpa_seq {+} {#2}
+ \fp_zero:N \l__xsim_tmpa_fp
+ \seq_map_inline:Nn \l__xsim_tmpa_seq
+ {
+ \fp_add:Nn \l__xsim_tmpa_fp
+ { \use:c {g__xsim_total_goal_\tl_trim_spaces:n {##1} _fp} }
+ }
+ \xsim_get_grade:nnnn {#1} { \l__xsim_tmpa_fp } {#3} {#4}
+ }
+
+% #1: grade
+% #2: code after grade requirement if == 1
+% #3: code after grade requirement if != 1
+\cs_new_protected:Npn \xsim_get_absolute_grade_requirement:nnn #1#2#3
+ {
+ \fp_zero:N \l__xsim_tmpa_fp
+ \xsim_foreach_goal:n
+ {
+ \fp_add:Nn \l__xsim_tmpa_fp
+ { \use:c {g__xsim_total_goal_##1_fp} }
+ }
+ \xsim_get_grade:nnnn {#1} { \l__xsim_tmpa_fp } {#2} {#3}
+ }
+
+\keys_define:nn {xsim/grades}
+ {
+ round .fp_set:N = \l__xsim_grade_round_fp ,
+ half .bool_set:N = \l__xsim_grades_half_bool ,
+ split .tl_set:N = \l__xsim_grade_split_tl ,
+ split .initial:n = {,}
+ }
+
+\XSIMmoduleend
+\XSIMmodule{random}{randomly select exercises from collections}
+
+\msg_new:nnn {xsim} {random-numbers-unavailable}
+ {
+ You~ are~ compiling~ your~ document~ using ~XeLaTeX.~ Please~ be~ aware~
+ that~ random~ selection~ of~ exercises~ is~ unavailable~ in~ XeLaTeX.~ If~
+ you~ use~ this~ feature~ you~ can~ safely~ ignore~ this~ message.
+ }
+
+\sys_if_engine_xetex:T
+ { \msg_warning:nn {xsim} {random-numbers-unavailable} }
+
+\tl_new:N \l_xsim_random_collection_tl
+\tl_new:N \l__xsim_print_random_choice_tl
+\seq_new:N \g__xsim_random_list_seq
+\seq_new:N \l__xsim_allowed_exercise_ids_seq
+\int_new:N \g__xsim_random_list_id_int
+\bool_new:N \l__xsim_sort_random_bool
+\clist_new:N \l_xsim_random_exclude_list_clist
+
+% #1: random list id
+% #2: csv list of integers
+\xsim_new_aux_property:cpn {random} #1#2
+ {
+ \xsim_random_list_if_exist:nF {#1}
+ { \xsim_new_random_list:n {#1} }
+ \xsim_set_random_list:nn {#1} {#2}
+ }
+
+\cs_new_protected:Npn \xsim_new_random_list:n #1
+ {
+ \xsim_verbose:n {Defining~ new~ random~ list~ `#1'}
+ \seq_new:c {g__xsim_random_#1 _seq}
+ }
+
+\cs_new_protected:Npn \xsim_set_random_list:nn #1#2
+ { \seq_gset_from_clist:cn {g__xsim_random_#1_seq} {#2} }
+
+\cs_new_protected:Npn \xsim_set_random_list_from_seq:nN #1#2
+ { \seq_gset_eq:cN {g__xsim_random_#1_seq} #2 }
+
+\cs_new:Npn \xsim_use_random_list:nn #1#2
+ { \seq_use:cn {g__xsim_random_#1_seq} {#2} }
+
+\cs_new_protected:Npn \xsim_map_random_list:nn #1#2
+ { \seq_map_inline:cn {g__xsim_random_#1_seq} {#2} }
+
+\prg_new_conditional:Npnn \xsim_random_list_if_exist:n #1 {p,T,F,TF}
+ {
+ \seq_if_exist:cTF {g__xsim_random_#1_seq}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_random_list_if_empty:n #1 {p,T,F,TF}
+ {
+ \seq_if_empty:cTF {g__xsim_random_#1_seq}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: random list id
+% #2: sequence variable to set list from
+\cs_new_protected:Npn \xsim_save_random_list:nN #1#2
+ { % TODO: check if #2 is empty
+ \xsim_random_list_if_exist:nF {#1}
+ { \xsim_new_random_list:n {#1} }
+ \xsim_random_list_if_empty:nT {#1}
+ { \xsim_set_random_list_from_seq:nN {#1} #2 }
+ \xsim_verbose:n {Saving~ random~ list~ `#1'}
+ \xsim_add_property_to_aux:nn {random}
+ { {#1} { \xsim_use_random_list:nn {#1} {,} } }
+ }
+\cs_generate_variant:Nn \xsim_save_random_list:nN {x}
+
+% #1: collection
+% #2: number of items
+% #3: clist variable of excluded ids
+\cs_new_protected:Npn \xsim_print_random_list:nnN #1#2#3
+ {
+ \xsim_if_collection_exist:nTF {#1}
+ {
+ \int_gincr:N \g__xsim_random_list_id_int
+ \int_compare:nNnTF { \xsim_collection_count:n {#1} } = {0}
+ {
+ % TODO: message
+ \xsim_rerun:
+ }
+ {
+ % generate seq of allowed ids from collection:
+ \xsim_foreach_exercise_id:n
+ {
+ \xsim_get_type_for_id:nN {##1} \l__xsim_tmpa_str
+ \tl_set_rescan:Nnx \l__xsim_tmpa_tl {} { \l__xsim_tmpa_str }
+ \xsim_if_in_collection:nVnT {#1} \l__xsim_tmpa_tl {##1}
+ {
+ \clist_if_in:NnF #3 {##1}
+ { \seq_put_right:Nn \l__xsim_allowed_exercise_ids_seq {##1} }
+ }
+ }
+ \int_compare:nNnTF
+ {#2}
+ >
+ { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
+ {
+ \int_set:Nn \l__xsim_tmpa_int
+ { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
+ }
+ { \int_set:Nn \l__xsim_tmpa_int {#2} }
+ % generate random list:
+ \xsim_generate_random_list:nnnN
+ { \int_to_alph:n { \g__xsim_random_list_id_int } }
+ { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
+ { \l__xsim_tmpa_int }
+ \g__xsim_random_list_seq
+ }
+ \xsim_save_random_list:xN
+ { \int_to_alph:n { \g__xsim_random_list_id_int } }
+ \g__xsim_random_list_seq
+ \xsim_verbose:x
+ {
+ Printing~ exercises~ of~ random~ list~
+ `\int_to_alph:n { \g__xsim_random_list_id_int }'~ of~
+ collection~ `#1'
+ }
+ \xsim_print_random_exercises:Nn
+ \l__xsim_allowed_exercise_ids_seq
+ { \int_to_alph:n { \g__xsim_random_list_id_int } }
+ }
+ { \msg_error:nnn {xsim} {unknown-collection} {#1} }
+ }
+\cs_generate_variant:Nn \xsim_print_random_list:nnN {V}
+
+% #1: random list id
+% #2: max number to choose from
+% #3: number of items
+% #4: seq variable
+\cs_new_protected:Npn \xsim_generate_random_list:nnnN #1#2#3#4
+ {
+ \bool_lazy_or:nnT
+ { !\xsim_random_list_if_exist_p:n {#1} }
+ { \xsim_random_list_if_empty_p:n {#1} }
+ {
+ \xsim_verbose:n
+ {Generating~ random~ list~ `#1'~ with~ #3~ out~ of~ #2~ items}
+ \seq_gclear:N #4
+ \int_compare:nNnF {#2} = 0
+ {
+ \int_do_until:nNnn { \seq_count:N #4 } = {#3}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \fp_eval:n { randint(#2) } }
+ \seq_if_in:NVF #4
+ \l__xsim_tmpa_tl
+ { \seq_gput_right:NV #4 \l__xsim_tmpa_tl }
+ }
+ }
+ \bool_if:NT \l__xsim_sort_random_bool
+ {
+ \seq_gsort:Nn #4
+ {
+ \int_compare:nNnTF {##1} > {##2}
+ { \sort_return_swapped: }
+ { \sort_return_same: }
+ }
+ }
+ }
+ }
+
+% #1: seq variable of ids
+% #2: random list id
+\cs_new_protected:Npn \xsim_print_random_exercises:Nn #1#2
+ {
+ \seq_if_empty:NF #1
+ {
+ \bool_lazy_and:nnT
+ { \xsim_random_list_if_exist_p:n {#2} }
+ { !\xsim_random_list_if_empty_p:n {#2} }
+ {
+ \xsim_verbose:x
+ {
+ Printing~
+ \str_case:Vn \l__xsim_print_random_choice_tl
+ {
+ {exercises} {exercises~}
+ {solutions} {solutions~}
+ {both} { exercises~ and~ solutions~ }
+ }
+ of~ random~ list~ `#2'.
+ }
+ \xsim_map_random_list:nn {#2}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \seq_item:Nn #1 {##1} }
+ \tl_set:Nx \l__xsim_tmpb_tl
+ { \xsim_get_type_for_property:nV {id} \l__xsim_tmpa_tl }
+ \bool_set_false:N \l__xsim_tmpa_bool
+ \bool_set_false:N \l__xsim_tmpb_bool
+ \str_case:VnF \l__xsim_print_random_choice_tl
+ {
+ {exercises} { \bool_set_true:N \l__xsim_tmpa_bool }
+ {solutions} { \bool_set_true:N \l__xsim_tmpb_bool }
+ {both} {
+ \bool_set_true:N \l__xsim_tmpa_bool
+ \bool_set_true:N \l__xsim_tmpb_bool
+ }
+ }
+ {
+ \msg_warning:nnV {xsim}
+ {print-collection-choice}
+ \l__xsim_print_random_choice_tl
+ }
+ \bool_if:NT \l__xsim_tmpa_bool
+ {
+ \xsim_if_exercise_exist:VVT
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {
+ \xsim_insert:VVnn
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {}
+ {exercise}
+ }
+ }
+ \bool_if:NT \l__xsim_tmpb_bool
+ {
+ \xsim_if_solution_exist:VVT
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {
+ \xsim_insert:VVnn
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {}
+ {solution}
+ }
+ }
+ }
+ }
+ }
+ }
+
+\keys_define:nn {xsim/random}
+ {
+ sort .bool_set:N = \l__xsim_sort_random_bool ,
+ sort .initial:n = true ,
+ collection .tl_set:N = \l_xsim_random_collection_tl ,
+ collection .initial:n = all~exercises ,
+ exclude .code:n = \__xsim_exclude_ids:n {#1} ,
+ print .tl_set:N = \l__xsim_print_random_choice_tl ,
+ print .initial:n = exercises
+ }
+
+\cs_new_protected:Npn \__xsim_exclude_ids:n #1
+ {
+ \seq_clear:N \l__xsim_tmpa_seq
+ \clist_map_inline:nn {#1}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \xsim_get_id_for_property:nn {ID} {##1} }
+ \tl_if_blank:VTF \l__xsim_tmpa_tl
+ { \seq_put_right:Nn \l__xsim_tmpa_seq {##1} }
+ {
+ \seq_put_right:Nx \l__xsim_tmpa_seq
+ { \xsim_get_id_for_property:nn {ID} {##1} }
+ }
+ }
+ \seq_remove_duplicates:N \l__xsim_tmpa_seq
+ \clist_set_from_seq:NN
+ \l_xsim_random_exclude_list_clist
+ \l__xsim_tmpa_seq
+ }
+
+\XSIMmoduleend
+\XSIMmodule{translations}{language settings for XSIM}
+
+\RequirePackage{translations}
+
+\msg_new:nnn {xsim} {language-not-defined}
+ {
+ You~ chose~ the~ language~ `#1'~ which~ is~ not~ defined~ by~ xsim.~
+ `english'~ is~ used~ instead.~ If~ you~ just~ mistyped~ try~ again!~
+ Otherwise~ contact~ the~ author~ and~ he'll~ probably~ add~ your~
+ language.
+ }
+
+\msg_new:nnn {xsim} {empty-translation}
+ {
+ No~ translation~ provided~ for~ key~ `#1'~ in~ language~ `#2'~
+ \msg_line_context: .
+ }
+
+% --------------------------------------------------------------------------
+
+\bool_new:N \l__xsim_language_auto_bool
+\bool_set_true:N \l__xsim_language_auto_bool
+% this token list will hold the chosen language for xsim; since the
+% language is either chosen automatically or by option it is only available at
+% begin document
+\tl_new:N \l_xsim_language_tl
+\tl_set:Nn \l_xsim_language_tl {english}
+\tl_new:N \l__xsim_current_language_tl
+
+\tl_const:Nn \c__xsim_keyword_prefix_tl {xsim-keyword-}
+
+% ----------------------------------------------------------------------------
+
+\prop_new:N \g_xsim_translations_prop
+
+% translate the key #1
+\cs_new:Npn \xsim_translate:n #1
+ {
+ \bool_if:NTF \l__xsim_language_auto_bool
+ { \GetTranslation { \c__xsim_keyword_prefix_tl #1 } }
+ {
+ \GetTranslationFor
+ { \l_xsim_language_tl }
+ { \c__xsim_keyword_prefix_tl #1 }
+ }
+ }
+
+\xsim_at_begin_document:n
+ {
+ \bool_if:NTF \l__xsim_language_auto_bool
+ {
+ \tl_set:Nx \l_xsim_language_tl
+ { \@trnslt at language{\@trnslt at current@language} }
+ }
+ {
+ \tl_set_eq:NN
+ \l_xsim_language_tl
+ \l__xsim_current_language_tl
+ }
+ }
+
+% ----------------------------------------------------------------------------
+% #1: language
+% #2: keyword
+% #3: translation
+\cs_new_protected:Npn \xsim_declare_translation:nnn #1#2#3
+ {
+ \xsim_verbose:n
+ { Declaring~ `#1'~ tranlation~ of~ `#2':~ `#3'. }
+ \declaretranslation
+ {#1}
+ { \c__xsim_keyword_prefix_tl #2 }
+ {#3}
+ \prop_gput:Nnn \g_xsim_translations_prop {#2(#1)} {#3}
+ }
+\cs_generate_variant:Nn \xsim_declare_translation:nnn {V,VnV}
+
+% #1: key
+% #2: csv list: { <lang1> = <translation1> , <lang2> = <translation2> }
+\cs_new_protected:Npn \xsim_declare_translations:nn #1#2
+ {
+ \cs_set_protected:Npn \__xsim_declare_translation:n ##1
+ { \msg_warning:nnnn {xsim} {empty-translation} {#1} {##1} }
+ \cs_set_protected:Npn \__xsim_declare_translation:nn ##1##2
+ { \xsim_declare_translation:nnn {##1} {#1} {##2} }
+ \keyval_parse:NNn
+ \__xsim_declare_translation:n
+ \__xsim_declare_translation:nn
+ {#2}
+ }
+
+\cs_new:Npn \__xsim_parse_translate_list_entry:nnn #1#2#3 {}
+
+\cs_new_protected:Npn \__xsim_parse_translate_list_entry:www #1(#2)\q_mark#3\q_stop
+ { \__xsim_parse_translate_list_entry:nnn {#1} {#2} {#3} }
+
+\cs_new_protected:Npn \xsim_for_all_translations_do:n #1
+ {
+ \cs_set:Npn \__xsim_parse_translate_list_entry:nnn ##1##2##3 {#1}
+ \prop_map_inline:Nn \g_xsim_translations_prop
+ { \__xsim_parse_translate_list_entry:www ##1 \q_mark ##2 \q_stop }
+ }
+
+% ----------------------------------------------------------------------------
+
+\keys_define:nn {xsim}
+ {
+ language .value_required:n = true ,
+ language .code:n =
+ \tl_if_eq:nnTF {#1} {auto}
+ { \bool_set_true:N \l__xsim_language_auto_bool }
+ {
+ \bool_set_false:N \l__xsim_language_auto_bool
+ \tl_set:Nn \l__xsim_current_language_tl {#1}
+ } ,
+ language .initial:n = auto
+ }
+
+\XSIMmoduleend
+\XSIMmodule{interface}{user interface}
+
+\msg_new:nnn {xsim} {remove}
+ {
+ The~ command~ #2 is~ deprecated.~ As~ of~ version~ #1~ it~ serves~ no~
+ purpose~ and~ does~ nothing.
+ }
+
+\msg_new:nnn {xsim} {deprecate}
+ {
+ The~ command~ #2 is~ deprecated.~ As~ of~ version~ #1~ it~ serves~ no~
+ purpose~ and~ does~ nothing.~ Use~ #3 instead.
+ }
+
+\cs_new_protected:Npn \xsim_remove:nN #1#2
+ { \msg_warning:nnnn {xsim} {remove} {#1} {#2} }
+
+\cs_new_protected:Npn \xsim_deprecate:nNN #1#2#3
+ { \msg_warning:nnnn {xsim} {remove} {#1} {#2} {#3} }
+
+% ----------------------------------------------------------------------------
+\NewDocumentCommand \DeclareExerciseEnvironmentTemplate {m+m+m}
+ { \xsim_declare_environment_template:nnn {#1} {#2} {#3} }
+\@onlypreamble \DeclareExerciseEnvironmentTemplate
+
+\NewDocumentCommand \DeclareExerciseHeadingTemplate {m+m}
+ { \xsim_declare_heading_template:nn {#1} {#2} }
+\@onlypreamble \DeclareExerciseHeadingTemplate
+
+\NewDocumentCommand \DeclareExerciseTableTemplate {m+m}
+ { \xsim_declare_table_template:nn {#1} {#2} }
+\@onlypreamble \DeclareExerciseTableTemplate
+
+\NewDocumentCommand \UseExerciseTemplate {mm}
+ { \xsim_use_template:nn {#1} {#2} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseType {mm}
+ { \xsim_declare_exercise_type:nn {#1} {#2} }
+\@onlypreamble \DeclareExerciseType
+
+\NewExpandableDocumentCommand \numberofusedexercises {}
+ { \int_use:N \g_xsim_max_id_int }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \IfExistSolutionTF {+m+m}
+ { \xsim_if_solution_exist:ooTF {\ExerciseType} {\ExerciseID} {#1} {#2} }
+
+\NewDocumentCommand \IfExistSolutionT {+m}
+ { \IfExistSolutionTF {#1} {} }
+
+\NewDocumentCommand \IfExistSolutionF {+m}
+ { \IfExistSolutionTF {} {#1} }
+
+\NewExpandableDocumentCommand \IfInsideSolutionTF {+m+m}
+ { \xsim_if_inside_solution:TF {#1} {#2} }
+
+\NewExpandableDocumentCommand \IfInsideSolutionT {+m}
+ { \IfInsideSolutionTF {#1} {} }
+
+\NewExpandableDocumentCommand \IfInsideSolutionF {+m}
+ { \IfInsideSolutionTF {} {#1} }
+
+\NewExpandableDocumentCommand \IfSolutionPrintTF {+m+m}
+ { \xsim_if_solution_print:nTF {\ExerciseType} {#1} {#2} }
+
+\NewExpandableDocumentCommand \IfSolutionPrintT {+m}
+ { \IfSolutionPrintTF {#1} {} }
+
+\NewExpandableDocumentCommand \IfSolutionPrintF {+m}
+ { \IfSolutionPrintTF {} {#1} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseProperty {t!st-m}
+ {
+ \IfBooleanTF {#2}
+ {
+ \IfBooleanTF {#3}
+ {
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_true_bool }
+ { \c_true_bool }
+ {#4}
+ }
+ {
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_true_bool }
+ { \c_false_bool }
+ {#4}
+ }
+ }
+ {
+ \IfBooleanTF {#1}
+ {
+ \IfBooleanTF {#3}
+ {
+ \xsim_declare_property:nnnn
+ { \c_true_bool }
+ { \c_false_bool }
+ { \c_true_bool }
+ {#4}
+ }
+ {
+ \xsim_declare_property:nnnn
+ { \c_true_bool }
+ { \c_false_bool }
+ { \c_false_bool }
+ {#4}
+ }
+ }
+ {
+ \IfBooleanTF {#3}
+ {
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_false_bool }
+ { \c_true_bool }
+ {#4}
+ }
+ {
+ \xsim_declare_property:nnnn
+ { \c_false_bool }
+ { \c_false_bool }
+ { \c_false_bool }
+ {#4}
+ }
+ }
+ }
+ }
+\@onlypreamble \DeclareExerciseProperty
+
+\NewDocumentCommand \DeclareExercisePropertyAlias {mm}
+ { \xsim_make_property_alias:nn {#1} {#2} }
+\@onlypreamble \DeclareExercisePropertyAlias
+
+\NewDocumentCommand \SetExerciseProperty {m+m}
+ { \xsim_set_property:eenn {\ExerciseType} {\ExerciseID} {#1} {#2} }
+
+\NewDocumentCommand \SetExpandedExerciseProperty {m+m}
+ { \xsim_set_property:eene {\ExerciseType} {\ExerciseID} {#1} {#2} }
+
+\NewDocumentCommand \ExerciseSetProperty {mmm+m}
+ { \xsim_set_property:nnnn {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \ExerciseSetExpandedProperty {mmm+m}
+ { \xsim_set_property:nnne {#1} {#2} {#3} {#4} }
+
+\NewExpandableDocumentCommand \IfExercisePropertyExistTF {+m+m+m}
+ { \xsim_if_property_exist:nTF {#1} {#2} {#3} }
+
+\NewExpandableDocumentCommand \IfExercisePropertyExistT {+m+m}
+ { \IfExercisePropertyExistTF {#1} {#2} {} }
+
+\NewExpandableDocumentCommand \IfExercisePropertyExistF {+m+m}
+ { \IfExercisePropertyExistTF {#1} {} {#2} }
+
+\NewDocumentCommand \IfExercisePropertySetTF {m+m+m}
+ { \xsim_if_property_set:eenTF {\ExerciseType} {\ExerciseID} {#1} {#2} {#3} }
+
+\NewDocumentCommand \IfExercisePropertySetT {m+m}
+ { \IfExercisePropertySetTF {#1} {#2} {} }
+
+\NewDocumentCommand \IfExercisePropertySetF {m+m}
+ { \IfExercisePropertySetTF {#1} {} {#2} }
+
+\NewExpandableDocumentCommand \GetExerciseProperty {m}
+ { \xsim_get_property:oon {\ExerciseType} {\ExerciseID} {#1} }
+
+\NewExpandableDocumentCommand \GetExerciseAliasProperty {m}
+ {
+ \xsim_get_property:oof
+ {\ExerciseType}
+ {\ExerciseID}
+ { \xsim_property_alias:n {#1} }
+ }
+
+\NewDocumentCommand \GetExercisePropertyTF {m+m+m}
+ {
+ \xsim_get_property_if_set:oonTF {\ExerciseType} {\ExerciseID} {#1}
+ {#2}
+ {#3}
+ }
+
+\NewDocumentCommand \GetExercisePropertyT {m+m}
+ { \GetExercisePropertyTF {#1} {#2} {} }
+\NewDocumentCommand \GetExercisePropertyF {m+m+m}
+ { \GetExercisePropertyTF {#1} {} {#2} }
+
+\NewExpandableDocumentCommand \GetExerciseIdForProperty {mm}
+ { \xsim_get_id_for_property:nn {#1} {#2} }
+
+\NewExpandableDocumentCommand \GetExerciseTypeForProperty {mm}
+ { \xsim_get_type_for_property:nn {#1} {#2} }
+
+\NewExpandableDocumentCommand \IfExerciseBooleanPropertyTF {+m+m+m}
+ {
+ \xsim_if_boolean_property:oonTF {\ExerciseType} {\ExerciseID} {#1}
+ {#2}
+ {#3}
+ }
+
+\NewExpandableDocumentCommand \IfExerciseBooleanPropertyT {+m+m}
+ { \IfExerciseBooleanPropertyTF {#1} {#2} {} }
+\NewExpandableDocumentCommand \IfExerciseBooleanPropertyF {+m+m}
+ { \IfExerciseBooleanPropertyTF {#1} {} {#2} }
+
+\NewDocumentCommand \SaveExerciseProperty {mm}
+ { \xsim_save_property:xxnN {\ExerciseType} {\ExerciseID} {#1} #2 }
+
+\NewDocumentCommand \GlobalSaveExerciseProperty {mm}
+ { \xsim_gsave_property:xxnN {\ExerciseType} {\ExerciseID} {#1} #2 }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseParameter {st!m}
+ {
+ \IfBooleanTF {#1} % fixed
+ {
+ \IfBooleanTF {#2} % mandatory
+ { \xsim_declare_parameter:nnn {true} {true} {#3} }
+ { \xsim_declare_parameter:nnn {true} {false} {#3} }
+ }
+ {
+ \IfBooleanTF {#2} % mandatory
+ { \xsim_declare_parameter:nnn {false} {true} {#3} }
+ { \xsim_declare_parameter:nnn {false} {false} {#3} }
+ }
+ }
+
+\NewExpandableDocumentCommand \GetExerciseParameter {m}
+ { \xsim_get_parameter:on {\ExerciseType} {#1} }
+
+\NewDocumentCommand \SetExerciseParameter {mmm}
+ { \xsim_set_parameter:nnn {#1} {#2} {#3} }
+
+\NewDocumentCommand \SetExerciseParameters {mm}
+ { \xsim_set_parameters:nn {#1} {#2} }
+
+\NewExpandableDocumentCommand \GetExerciseName {}
+ {
+ \IfInsideSolutionTF
+ { \GetExerciseParameter {solution-name} }
+ { \GetExerciseParameter {exercise-name} }
+ }
+
+\NewExpandableDocumentCommand \GetExerciseHeadingF {m}
+ {
+ \IfInsideSolutionTF
+ {
+ \IfExerciseParameterSetTF {solution-heading}
+ { \GetExerciseParameter {solution-heading} }
+ {#1}
+ }
+ {
+ \IfExerciseParameterSetTF {exercise-heading}
+ { \GetExerciseParameter {exercise-heading} }
+ {#1}
+ }
+ }
+
+\NewDocumentCommand \GetExerciseBody {m}
+ { \xsim_input:oon { \ExerciseType } { \ExerciseID } {#1} }
+
+\NewExpandableDocumentCommand \IfExerciseParameterSetTF {+m+m+m}
+ { \xsim_if_parameter_set:nnTF {\ExerciseType} {#1} {#2} {#3} }
+
+\NewExpandableDocumentCommand \IfExerciseParameterSetT {+m+m}
+ { \IfExerciseParameterSetTF {#1} {#2} {} }
+
+\NewExpandableDocumentCommand \IfExerciseParameterSetF {+m+m}
+ { \IfExerciseParameterSetTF {#1} {} {#2} }
+
+\NewExpandableDocumentCommand \ExerciseParameterIfSetTF {+m+m+m+m}
+ { \xsim_if_parameter_set:nnTF {#1} {#2} {#3} {#4} }
+
+\NewExpandableDocumentCommand \ExerciseParameterIfSetT {+m+m+m}
+ { \ExerciseParameterIfSetTF {#1} {#2} {#3} {} }
+
+\NewExpandableDocumentCommand \ExerciseParameterIfSetF {+m+m+m}
+ { \ExerciseParameterIfSetTF {#1} {#2} {} {#3} }
+
+\NewDocumentCommand \GetExerciseParameterTF {m+m+m}
+ { \xsim_get_parameter_if_set:onTF {\ExerciseType} {#1} {#2} {#3} }
+
+\NewDocumentCommand \GetExerciseParameterT {m+m}
+ { \GetExerciseParameterTF {#1} {#2} {} }
+
+\NewDocumentCommand \GetExerciseParameterF {m+m+m}
+ { \GetExerciseParameterTF {#1} {} {#2} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \ExercisePropertyIfSetTF {mmm+m+m}
+ { \xsim_if_property_set:nnnTF {#1} {#2} {#3} {#4} {#5} }
+
+\NewDocumentCommand \ExercisePropertyIfSetT {mmm+m}
+ { \ExercisePropertyIfSetTF {#1} {#2} {#3} {#4} {} }
+
+\NewDocumentCommand \ExercisePropertyIfSetF {mmm+m}
+ { \ExercisePropertyIfSetTF {#1} {#2} {#3} {} {#4} }
+
+\NewExpandableDocumentCommand \ExercisePropertyGet {mmm}
+ { \xsim_get_property:nnn {#1} {#2} {#3} }
+
+\NewExpandableDocumentCommand \ExercisePropertyGetAlias {mm}
+ { \xsim_get_property:nnf {#1} {#2} { \xsim_property_alias:n {#1} } }
+
+\NewDocumentCommand \ExercisePropertySave {mmmm}
+ { \xsim_save_property:nnnN {#1} {#2} {#3} #4 }
+
+\NewDocumentCommand \ExercisePropertyGlobalSave {mmmm}
+ { \xsim_gsave_property:nnnN {#1} {#2} {#3} #4 }
+
+\NewExpandableDocumentCommand \ExerciseParameterGet {mm}
+ { \xsim_get_parameter:nn {#1} {#2} }
+
+% ----------------------------------------------------------------------------
+
+\NewExpandableDocumentCommand \XSIMtranslate {m}
+ { \xsim_translate:n {#1} }
+
+\NewExpandableDocumentCommand \XSIMexpandcode {+m}
+ { \use:e {#1} }
+
+\NewExpandableDocumentCommand \XSIMmixedcase {m}
+ { \text_titlecase:e {#1} }
+
+\NewDocumentCommand \XSIMputright {mm}
+ { \tl_put_right:Nn #1 {#2} }
+
+\NewExpandableDocumentCommand \XSIMifeqTF {+m+m+m+m}
+ { \tl_if_eq:eeTF {#1} {#2} {#3} {#4} }
+
+\NewExpandableDocumentCommand \XSIMifeqT {+m+m+m}
+ { \XSIMifeqTF {#1} {#2} {#3} {} }
+
+\NewExpandableDocumentCommand \XSIMifeqF {+m+m+m}
+ { \XSIMifeqTF {#1} {#2} {} {#3} }
+
+\NewExpandableDocumentCommand \XSIMifblankTF {+m+m+m}
+ { \tl_if_blank:eTF {#1} {#2} {#3} }
+
+\NewExpandableDocumentCommand \XSIMifblankT {+m+m}
+ { \XSIMifblankTF {#1} {#2} {} }
+
+\NewExpandableDocumentCommand \XSIMifblankF {+m+m}
+ { \XSIMifblankTF {#1} {} {#2} {} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseGoal {m}
+ { \xsim_declare_exercise_goal:n {#1} }
+\@onlypreamble \DeclareExerciseGoal
+
+\NewDocumentCommand \IfExerciseGoalTF {mm+m+m}
+ {
+ \xsim_if_goal_value:xxnnTF
+ {\ExerciseType} {\ExerciseID} {#1}
+ {#2}
+ {#3} {#4}
+ }
+
+\NewDocumentCommand \IfExerciseGoalT {mm+m}
+ { \IfExerciseGoalTF {#1} {#2} {#3} {} }
+
+\NewDocumentCommand \IfExerciseGoalF {mm+m}
+ { \IfExerciseGoalTF {#1} {#2} {} {#3} }
+
+\NewDocumentCommand \IfExerciseGoalSingularTF {mmm}
+ { \IfExerciseGoalTF {#1} {=1} {#2} {#3} }
+
+\NewDocumentCommand \IfExerciseGoalSingularT {mm}
+ { \IfExerciseGoalT {#1} {=1} {#2} }
+
+\NewDocumentCommand \IfExerciseGoalSingularF {mm}
+ { \IfExerciseGoalF {#1} {=1} {#2} }
+
+\NewDocumentCommand \IfExerciseTypeGoalsSumTF {mmm+m+m}
+ { \xsim_if_goals_sum:nnnTF {#1} {#2} {#3} {#4} {#5} }
+
+\NewDocumentCommand \IfExerciseTypeGoalsSumT {mmm+m}
+ { \IfExerciseTypeGoalsSumTF {#1} {#2} {#3} {#4} {} }
+
+\NewDocumentCommand \IfExerciseTypeGoalsSumF {mmm+m}
+ { \IfExerciseTypeGoalsSumTF {#1} {#2} {#3} {} {#4} }
+
+\NewDocumentCommand \IfExerciseGoalsSumTF {mm+m+m}
+ { \xsim_if_total_goals_sum:nnTF {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \IfExerciseGoalsSumT {mm+m}
+ { \IfExerciseGoalsSumTF {#1} {#2} {#3} {} }
+
+\NewDocumentCommand \IfExerciseGoalsSumF {mm+m}
+ { \IfExerciseGoalsSumTF {#1} {#2} {} {#3} }
+
+\NewDocumentCommand \TotalExerciseTypeGoal {mmmm}
+ { \xsim_print_goal_sum:nnnn {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \TotalExerciseTypeGoals {mmmm}
+ { \xsim_print_goals_sum:nnnn {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \TotalExerciseGoal {mmm}
+ { \xsim_print_total_goal_sum:nnn {#1} {#2} {#3} }
+
+\NewDocumentCommand \TotalExerciseGoals {mmm}
+ { \xsim_print_total_goals_sum:nnn {#1} {#2} {#3} }
+
+\NewDocumentCommand \AddtoExerciseTypeGoal {mmmm}
+ { \xsim_addto_goal:nnnn {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \AddtoExerciseGoal {mm}
+ { \xsim_addto_goal:xxnn {\ExerciseType} {\ExerciseID} {#1} {#2} }
+
+\NewDocumentCommand \ExerciseGoalValuePrint {mmm}
+ { \xsim_print_goal:nnn {#1} {#2} {#3} }
+
+\NewDocumentCommand \AddtoExerciseTypeGoalPrint {mmmmmm}
+ {
+ \xsim_addto_goal:nnnn {#1} {#2} {#3} {#4}
+ \xsim_print_goal:nnn {#4} {#5} {#6}
+ }
+
+\NewDocumentCommand \AddtoExerciseGoalPrint {mmmm}
+ {
+ \xsim_addto_goal:xxnn {\ExerciseType} {\ExerciseID} {#1} {#2}
+ \xsim_print_goal:nnn {#2} {#3} {#4}
+ }
+
+% ----------------------------------------------------------------------------
+\NewDocumentCommand \DeclareGradeDistribution {m}
+ { \xsim_declare_relative_grades:n {#1} }
+
+\NewDocumentCommand \GetGradeRequirementForGoal {mmmm}
+ { \xsim_get_grade_goal:nnnn {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \GetGradeRequirementForGoals {mmmm}
+ { \xsim_get_grade_requirement:nnnn {#1} {#2} {#3} {#4} }
+
+\NewDocumentCommand \GetGradeRequirement {mmm}
+ { \xsim_get_absolute_grade_requirement:nnn {#1} {#2} {#3} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseTagging {m}
+ { \xsim_new_tag_type:n {#1} }
+\@onlypreamble \DeclareExerciseTagging
+
+\NewDocumentCommand \ProvideExerciseTagging {m}
+ {
+ \xsim_if_tag_type_exist:nTF {#1}
+ { \msg_warning:nnn {xsim} {tag-exists} {#1} }
+ { \xsim_new_tag_type:n {#1} }
+ }
+
+\NewDocumentCommand \ForEachExerciseTag {m+m}
+ { \xsim_foreach_exercise_tag:oonn {\ExerciseType} {\ExerciseID} {#1} {#2} }
+
+\NewDocumentCommand \ListExerciseTags {mm}
+ { \xsim_exercise_tags_use:oonn {\ExerciseType} {\ExerciseID} {#1} {#2} }
+
+\NewDocumentCommand \UseExerciseTags {mmmm}
+ {
+ \xsim_exercise_tags_use:oonnnn
+ {\ExerciseType}
+ {\ExerciseID}
+ {#1}
+ {#2}
+ {#3}
+ {#4}
+ }
+
+\NewDocumentCommand \IfExerciseTagSetTF {m+m+m}
+ { \xsim_if_tags_value:nTF {#1} {#2} {#3} }
+\NewDocumentCommand \IfExerciseTagSetT {m+m}
+ { \xsim_if_tags_value:nT {#1} {#2} }
+\NewDocumentCommand \IfExerciseTagSetF {m+m}
+ { \xsim_if_tags_value:nF {#1} {#2} }
+
+\NewDocumentCommand \IfExerciseTopicSetTF {m+m+m}
+ { \xsim_if_topic_value:nTF {#1} {#2} {#3} }
+\NewDocumentCommand \IfExerciseTopicSetT {m+m}
+ { \xsim_if_topic_value:nT {#1} {#2} }
+\NewDocumentCommand \IfExerciseTopicSetF {m+m}
+ { \xsim_if_topic_value:nF {#1} {#2} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \XSIMatbegindocument {+m}
+ { \xsim_at_begin_document:n {#1} }
+
+\NewDocumentCommand \XSIMatenddocument {+m}
+ { \xsim_at_end_document:n {#1} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \ForEachPrintedExerciseByType {+m}
+ { \xsim_foreach_exercise_type_id:nn {printed} {#1} }
+
+\tl_new:N \XSIMtmp
+
+\NewDocumentCommand \ForEachPrintedExerciseByID {+m}
+ {
+ \tl_set_eq:NN \XSIMtmp \ExerciseType
+ \xsim_foreach_exercise_id_type:nn {print} {#1}
+ \tl_set_eq:NN \ExerciseType \XSIMtmp
+ \tl_clear:N \XSIMtmp
+ }
+
+\NewDocumentCommand \ForEachUsedExerciseByType {+m}
+ {
+ \tl_set_eq:NN \XSIMtmp \ExerciseType
+ \xsim_foreach_exercise_type_id:nn {used} {#1}
+ \tl_set_eq:NN \ExerciseType \XSIMtmp
+ \tl_clear:N \XSIMtmp
+ }
+
+\NewDocumentCommand \ForEachUsedExerciseByID {+m}
+ {
+ \tl_set_eq:NN \XSIMtmp \ExerciseType
+ \xsim_foreach_exercise_id_type:nn {used} {#1}
+ \tl_set_eq:NN \ExerciseType \XSIMtmp
+ \tl_clear:N \XSIMtmp
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseTranslations {mm}
+ { \xsim_declare_translations:nn {#1} {#2} }
+\@onlypreamble \DeclareExerciseTranslations
+
+\NewDocumentCommand \DeclareExerciseTranslation {mmm}
+ { \xsim_declare_translation:nnn {#1} {#2} {#3} }
+\@onlypreamble \DeclareExerciseTranslation
+
+\NewDocumentCommand \ForEachExerciseTranslation {+m}
+ { \xsim_for_all_translations_do:n {#1} }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \DeclareExerciseCollection {om}
+ {
+ \IfNoValueTF {#1}
+ { \xsim_new_collection:nn {#2} {} }
+ {
+ \xsim_new_collection:nn {#2} {#1}
+ \xsim_activate_collection:n {#2}
+ }
+ }
+\@onlypreamble \DeclareExerciseCollection
+
+\NewDocumentCommand \activatecollection {m}
+ { \xsim_activate_collection:n {#1} }
+
+\NewDocumentCommand \deactivatecollection {m}
+ { \xsim_deactivate_collection:n {#1} }
+
+% \NewDocumentCommand \collectexercisestype {mm}
+% { \xsim_collect_type_start:nn {#1} {#2} }
+
+\NewDocumentCommand \collectexercises {m}
+ { \xsim_collect_start:n {#1} }
+
+\NewDocumentCommand \collectexercisesstop {m}
+ { \xsim_collect_stop:n {#1} }
+
+\NewDocumentCommand \printcollection {O{}m}
+ { \xsim_print_collection:nn {#1} {#2} }
+
+\NewDocumentCommand \printrandomexercises {O{}m}
+ {
+ \group_begin:
+ \keys_set:nn {xsim/random} {#1}
+ \xsim_print_random_list:VnN
+ \l_xsim_random_collection_tl
+ {#2}
+ \l_xsim_random_exclude_list_clist
+ \group_end:
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \blank {som}
+ {
+ \group_begin:
+ \IfNoValueF {#2} { \keys_set:nn {xsim/blank} {#2} }
+ \mode_if_vertical:TF
+ {
+ \IfBooleanTF {#1}
+ { \xsim_blank:n {#3} }
+ {
+ \bool_if:NT \l__xsim_blank_linespread_bool
+ { \linespread { \l__xsim_blank_linespread_tl } \selectfont }
+ \noindent \null \xsim_blank:n {#3} \par
+ }
+ }
+ { \xsim_blank:n {#3} }
+ \group_end:
+ }
+
+\NewDocumentCommand \examspace { sm }
+ {
+ \IfBooleanTF {#1}
+ { \xsim_examspace:nn { \c_true_bool } {#2} }
+ { \xsim_examspace:nn { \c_false_bool } {#2} }
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \gradingtable {O{}}
+ {
+ \group_begin:
+ \keys_set:nn {xsim/grading-table} {#1}
+ \xsim_setup_template:nVn {table} \l_xism_grading_table_template_tl
+ {
+ \providecommand* \ExerciseTableCode {}
+ \providecommand* \ExerciseTableType [1] {}
+ \providecommand* \ExerciseType {}
+ \tl_set_eq:NN \ExerciseType \l_xism_grading_table_exercise_type_tl
+ \renewcommand* \ExerciseTableCode {}
+ \renewcommand* \ExerciseTableType [1]
+ {
+ \XSIMifblankTF { \l_xism_grading_table_exercise_type_tl }
+ {##1}
+ { \l_xism_grading_table_exercise_type_tl }
+ }
+ }
+ \xsim_use_template:nV {table} \l_xism_grading_table_template_tl
+ \group_end:
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \XSIMprint {mO{}mm}
+ { \xsim_insert:nenn {#3} { \xsim_normalize_id:n {#4} } {#2} {#1} }
+
+\NewDocumentCommand \XSIMxprint {mO{}mm}
+ { \xsim_insert:xxnn {#3} { \xsim_normalize_id:e {#4} } {#2} {#1} }
+
+\NewDocumentCommand \printexercise {O{}mm}
+ {
+ \clist_map_inline:nn {#3}
+ { \xsim_insert:nenn {#2} { \xsim_normalize_id:n {##1} } {#1} {exercise} }
+ }
+
+\NewDocumentCommand \xprintexercise {O{}mm}
+ {
+ \clist_map_inline:nn {#3}
+ { \xsim_insert:xxnn {#2} { \xsim_normalize_id:e {##1} } {#1} {exercise} }
+ }
+
+\NewDocumentCommand \printsolution {O{}mm}
+ {
+ \clist_map_inline:nn {#3}
+ { \xsim_insert:nenn {#2} { \xsim_normalize_id:n {##1} } {#1} {solution} }
+ }
+
+\NewDocumentCommand \xprintsolution {O{}mm}
+ {
+ \clist_map_inline:nn {#3}
+ { \xsim_insert:xxnn {#2} { \xsim_normalize_id:e {##1} } {#1} {solution} }
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \printsolutionstype {sO{}m}
+ {
+ \IfBooleanTF {#1}
+ { \xsim_print_type_solutions:nnn { \c_true_bool } {#2} {#3} }
+ { \xsim_print_type_solutions:nnn { \c_false_bool } {#2} {#3} }
+ }
+
+\NewDocumentCommand \printsolutions {sO{}}
+ {
+ \IfBooleanTF {#1}
+ { \xsim_print_all_solutions_per_type:nn { \c_true_bool } {#2} }
+ { \xsim_print_all_solutions_per_type:nn { \c_false_bool } {#2} }
+ }
+
+\NewDocumentCommand \printallsolutions {sO{}}
+ {
+ \IfBooleanTF {#1}
+ { \xsim_print_all_solutions_per_id:nn { \c_true_bool } {#2} }
+ { \xsim_print_all_solutions_per_id:nn { \c_false_bool } {#2} }
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \printforexercises {sO{}+mO{}}
+ {
+ \IfBooleanTF {#1}
+ {
+ \xsim_foreach_exercise_type:n
+ { \xsim_print_type_code:nnnnn { \c_true_bool } {#2} {#4} {##1} {#3} }
+ }
+ {
+ \xsim_foreach_exercise_type:n
+ { \xsim_print_type_code:nnnnn { \c_false_bool } {#2} {#4} {##1} {#3} }
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \xsimsetup {+m}
+ { \xsim_setup:n {#1} }
+
+% ----------------------------------------------------------------------------
+\NewExpandableDocumentCommand \XSIMifchapterTF {+m+m}
+ { \xsim_if_chapter:TF {#1} {#2} }
+
+\NewExpandableDocumentCommand \XSIMifchapterT {+m}
+ { \xsim_if_chapter:T {#1} }
+
+\NewExpandableDocumentCommand \XSIMifchapterF {+m}
+ { \xsim_if_chapter:F {#1} }
+
+\XSIMmoduleend
+\XSIMmodule{definitions}{definition of user commands}
+
+% not exactly a user choice: the `exercises' environments rely on them:
+\DeclareExerciseParameter*!{exercise-env}
+\DeclareExerciseParameter*!{solution-env}
+\DeclareExerciseParameter !{exercise-name}
+\DeclareExerciseParameter !{solution-name}
+\DeclareExerciseParameter {exercises-name}
+\DeclareExerciseParameter {solutions-name}
+\DeclareExerciseParameter !{exercise-template}
+\DeclareExerciseParameter !{solution-template}
+\DeclareExerciseParameter* {counter}
+\DeclareExerciseParameter* {solution-counter}
+\DeclareExerciseParameter* {number}
+\DeclareExerciseParameter {within}
+\DeclareExerciseParameter {the-counter}
+
+% these are additional - but are used in the `default' environment
+% template:
+\DeclareExerciseParameter {exercise-heading}
+\DeclareExerciseParameter {solution-heading}
+
+% ----------------------------------------------------------------------------
+
+% not exactly a user choice, must be present at various places:
+\DeclareExerciseProperty! {id}
+\DeclareExerciseProperty! {ID}
+\DeclareExerciseProperty {counter}
+\DeclareExerciseProperty {counter-value}
+\DeclareExerciseProperty * {solution}
+\XSIMifchapterT{
+ \DeclareExerciseProperty {chapter-value}
+ \DeclareExerciseProperty {chapter}
+}
+\DeclareExerciseProperty {section-value}
+\DeclareExerciseProperty {section}
+\DeclareExerciseProperty {sectioning}
+
+% those are additional and wouldn't *need* to be present except for
+% pre-defined templates which make use of them (the page and page-value
+% property actually needs to be defined for xsim to be able to save the
+% corresponding values):
+\DeclareExerciseProperty {subtitle}
+\DeclareExerciseProperty {points}
+\DeclareExerciseProperty {bonus-points}
+\DeclareExerciseProperty {page-value}
+\DeclareExerciseProperty {page}
+
+\DeclareExercisePropertyAlias {ID} {id}
+
+% ----------------------------------------------------------------------------
+
+\DeclareExerciseTagging {tags}
+\DeclareExerciseTagging {topics}
+
+\xsimsetup{tags/ignore-untagged=false}
+
+% ----------------------------------------------------------------------------
+
+\DeclareExerciseGoal {points}
+\DeclareExerciseGoal {bonus-points}
+
+\NewDocumentCommand \printgoal {m}
+ { \ExerciseGoalValuePrint {#1} {} {} }
+
+\NewDocumentCommand \points {m}
+ {
+ \ExerciseGoalValuePrint {#1}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+\NewDocumentCommand \addpoints {sm}
+ {
+ \AddtoExerciseGoal {points} {#2}
+ \IfBooleanF {#1} { \points {#2} }
+ }
+
+\NewDocumentCommand \printpoints {m}
+ {
+ \TotalExerciseTypeGoal {#1} {points}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+\NewDocumentCommand \printtotalpoints {}
+ {
+ \TotalExerciseGoal {points}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+\NewDocumentCommand \addbonus {sm}
+ {
+ \AddtoExerciseGoal {bonus-points} {#2}
+ \IfBooleanF {#1} { \points {#2} }
+ }
+
+\NewDocumentCommand \printbonus {m}
+ {
+ \TotalExerciseTypeGoal {#1} {bonus-points}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+\NewDocumentCommand \printtotalbonus {}
+ {
+ \TotalExerciseGoal {bonus-points}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+% ----------------------------------------------------------------------------
+\NewDocumentCommand \pointsforgrade {m}
+ {
+ \GetGradeRequirementForGoal {#1} {points}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+\NewDocumentCommand \goalsforgrade {mm}
+ {
+ \GetGradeRequirementForGoals {#2} {#1}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+\NewDocumentCommand \totalgoalforgrade {m}
+ {
+ \GetGradeRequirement {#1}
+ { \, \XSIMtranslate {point} }
+ { \, \XSIMtranslate {points} }
+ }
+
+% ----------------------------------------------------------------------------
+
+\xsim_if_package_blank:F
+ {
+ \DeclareExerciseType {exercise} {
+ exercise-env = exercise ,
+ solution-env = solution ,
+ exercise-name = \XSIMtranslate {exercise} ,
+ exercises-name = \XSIMtranslate {exercises} ,
+ solution-name = \XSIMtranslate {solution} ,
+ solutions-name = \XSIMtranslate {solutions} ,
+ exercise-template = default ,
+ solution-template = default ,
+ exercise-heading = \subsection* ,
+ solution-heading = \subsection*
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+\DeclareExerciseEnvironmentTemplate {default}
+ {
+ \GetExerciseHeadingF { \subsection* }
+ {
+ \XSIMmixedcase { \GetExerciseName } \nobreakspace
+ \GetExerciseProperty {counter}
+ \IfInsideSolutionF
+ {
+ \IfExercisePropertySetT {subtitle}
+ { ~ { \normalfont \itshape \GetExerciseProperty {subtitle} } }
+ }
+ }
+ \GetExercisePropertyT {points}
+ {
+ \marginpar
+ {
+ \IfInsideSolutionF { \rule {1.2cm} {1pt} \slash }
+ \printgoal {\PropertyValue}
+ \GetExercisePropertyT {bonus-points}
+ { \nobreakspace ( + \printgoal {\PropertyValue} ) }
+ \nobreakspace\XSIMtranslate {point-abbr}
+ }
+ }
+ }
+ { \par }
+
+% ----------------------------------------------------------------------------
+
+\DeclareExerciseHeadingTemplate {none} {}
+
+\DeclareExerciseHeadingTemplate {default}
+ { \section* { \XSIMtranslate {default-heading} } }
+
+\DeclareExerciseHeadingTemplate {collection}
+ { \section* { \XSIMtranslate {collection-heading} } }
+
+\DeclareExerciseHeadingTemplate {per-section}
+ { \section* { \XSIMtranslate {per-section-heading} } }
+
+\DeclareExerciseHeadingTemplate {per-chapter}
+ { \section* { \XSIMtranslate {per-chapter-heading} } }
+
+% ----------------------------------------------------------------------------
+
+\RequirePackage{array,booktabs}
+
+\DeclareExerciseTableTemplate {default*}
+ {
+ \XSIMputright \ExerciseTableCode
+ {
+ \toprule
+ \XSIMifblankF { \ExerciseType }
+ { \XSIMmixedcase { \GetExerciseParameter {exercise-name} } }
+ &
+ }
+ \ForEachUsedExerciseByType
+ {
+ \XSIMifeqT {#1} { \ExerciseTableType {#1} }
+ {
+ \XSIMifblankT { \ExerciseTableType {} }
+ {
+ \XSIMputright \ExerciseTableCode
+ {
+ \XSIMmixedcase
+ { \ExerciseParameterGet {#1} {exercise-name} ~ }
+ }
+ }
+ \XSIMputright \ExerciseTableCode { #3 & }
+ }
+ }
+ \XSIMputright \ExerciseTableCode
+ {
+ \XSIMtranslate {total} \\
+ \midrule \XSIMmixedcase { \XSIMtranslate {points} } &
+ }
+ \ForEachUsedExerciseByType
+ {
+ \XSIMifeqT {#1} { \ExerciseTableType {#1} }
+ {
+ \XSIMputright \ExerciseTableCode
+ { \XSIMifblankTF {#5} {\printgoal{0}} {\printgoal{#5}} & }
+ }
+ }
+ \XSIMputright \ExerciseTableCode
+ {
+ \XSIMifblankTF { \ExerciseType }
+ { \TotalExerciseGoal {points} {} {} }
+ { \TotalExerciseTypeGoal { \ExerciseType } {points} {} {} }
+ \\ \midrule
+ \XSIMtranslate {reached} &
+ }
+ \ForEachUsedExerciseByType
+ {
+ \XSIMifeqT {#1} { \ExerciseTableType {#1} }
+ { \XSIMputright \ExerciseTableCode {&} }
+ }
+ \XSIMputright \ExerciseTableCode { \\ \bottomrule }
+ \edef \numberofcolumns
+ {
+ \XSIMifblankTF { \ExerciseType }
+ {\numberofusedexercises}
+ {\csname numberof \ExerciseType s\endcsname}
+ }
+ \XSIMifeqF {\numberofcolumns} {0}
+ {
+ \begin {tabular} {l*{\numberofcolumns}{c}c}
+ \ExerciseTableCode
+ \end {tabular}
+ }
+ }
+
+\DeclareExerciseTableTemplate {default}
+ {
+ \XSIMputright \ExerciseTableCode
+ {
+ \toprule
+ \XSIMifblankF { \ExerciseType }
+ { \XSIMmixedcase { \GetExerciseParameter {exercise-name} } }
+ &
+ \XSIMmixedcase { \XSIMtranslate {points} } &
+ \XSIMtranslate {reached} \\
+ \midrule
+ }
+ \ForEachUsedExerciseByType
+ {
+ \XSIMifeqT {#1} { \ExerciseTableType {#1} }
+ {
+ \XSIMifblankT { \ExerciseTableType {} }
+ {
+ \XSIMputright \ExerciseTableCode
+ {
+ \XSIMmixedcase
+ { \ExerciseParameterGet {#1} {exercise-name} ~ }
+ }
+ }
+ \XSIMputright \ExerciseTableCode
+ { #3 & \XSIMifblankTF {#5} {\printgoal{0}} {\printgoal{#5}} & \\ }
+ }
+ }
+ \XSIMputright \ExerciseTableCode
+ {
+ \midrule
+ \XSIMtranslate {total} &
+ \XSIMifblankTF { \ExerciseType }
+ { \TotalExerciseGoal {points} {} {} }
+ { \TotalExerciseTypeGoal { \ExerciseType } {points} {} {} } &
+ \\ \bottomrule
+ }
+ \XSIMexpandcode
+ {
+ \noexpand \begin {tabular} {\XSIMifblankTF{\ExerciseType}{l}{c}cc}
+ \noexpand \ExerciseTableCode
+ \noexpand \end {tabular}
+ }
+ }
+
+% ----------------------------------------------------------------------------
+
+\DeclareExerciseTranslations {exercise} {
+ Fallback = exercise ,
+ English = exercise ,
+ French = exercice ,
+ German = \"Ubung
+}
+
+\DeclareExerciseTranslations {exercises} {
+ Fallback = exercises ,
+ English = exercises ,
+ French = exercices ,
+ German = \"Ubungen
+}
+
+\DeclareExerciseTranslations {question} {
+ Fallback = question ,
+ English = question ,
+ French = question ,
+ German = Aufgabe
+}
+
+\DeclareExerciseTranslations {questions} {
+ Fallback = questions ,
+ English = questions ,
+ French = questions ,
+ German = Aufgaben
+}
+
+\DeclareExerciseTranslations {solution} {
+ Fallback = solution ,
+ English = solution ,
+ French = solution ,
+ German = L\"osung
+}
+
+\DeclareExerciseTranslations {solutions} {
+ Fallback = solutions ,
+ English = solutions ,
+ French = solutions ,
+ German = L\"osungen
+}
+
+\DeclareExerciseTranslations {point-abbr} {
+ Fallback = p. ,
+ English = p. ,
+ French = p. ,
+ German = P.
+}
+
+\DeclareExerciseTranslations {point} {
+ Fallback = point ,
+ English = point ,
+ French = point ,
+ German = Punkt
+}
+
+\DeclareExerciseTranslations {points} {
+ Fallback = points ,
+ English = points ,
+ French = points ,
+ German = Punkte
+}
+
+\DeclareExerciseTranslations {reached} {
+ Fallback = reached ,
+ English = reached ,
+ French = obtenus ,
+ German = erreicht
+}
+
+\DeclareExerciseTranslations {total} {
+ Fallback = total ,
+ English = total ,
+ French = total ,
+ German = insgesamt
+}
+
+\DeclareExerciseTranslations {default-heading} {
+ Fallback = \XSIMmixedcase { \GetExerciseParameter {solutions-name} }~
+ to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
+ English = \XSIMmixedcase { \GetExerciseParameter {solutions-name} }~
+ to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
+ French = \XSIMmixedcase { \GetExerciseParameter {solutions-name} ~
+ des~ \GetExerciseParameter {exercises-name} } ,
+ German = \XSIMmixedcase { \GetExerciseParameter {solutions-name} }~
+ zu~ den~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} }
+}
+
+\DeclareExerciseTranslations {collection-heading} {
+ Fallback = \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
+ English = \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
+ French = \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ,
+ German = \XSIMmixedcase { \GetExerciseParameter {exercises-name} }
+}
+
+\DeclareExerciseTranslations {per-section-heading} {
+ Fallback = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
+ to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
+ of~ Section \nobreakspace \ExerciseSection ,
+ English = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
+ to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
+ of~ Section \nobreakspace \ExerciseSection ,
+ French = \XSIMmixedcase { \GetExerciseParameter {solutions-name} ~
+ des~ \GetExerciseParameter {exercises-name} ~ de~ la~
+ section \nobreakspace \ExerciseSection } ,
+ German = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
+ zu~ den~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} }~
+ in~ Abschnitt \nobreakspace \ExerciseSection
+}
+
+\DeclareExerciseTranslations {per-chapter-heading} {
+ Fallback = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
+ to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
+ of~ Chapter \nobreakspace \ExerciseChapter ,
+ English = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
+ to~ the~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
+ of~ Chapter \nobreakspace \ExerciseChapter ,
+ French = \XSIMmixedcase { \GetExerciseParameter {solutions-name} ~
+ des~ \GetExerciseParameter {exercises-name} ~
+ du~ chapitre \nobreakspace \ExerciseChapter } ,
+ German = \XSIMmixedcase { \GetExerciseParameter {solutions-name} } ~
+ zu~ den~ \XSIMmixedcase { \GetExerciseParameter {exercises-name} } ~
+ in~ Kapitel \nobreakspace \ExerciseChapter
+}
+
+\XSIMmoduleend
+% finish package:
+\hook_gput_code:nnn {enddocument} {toplevel} { \xsim_close_aux:\xsim_do_rerun: }
+%----------------------------------------------------------------------------
\file_input_stop:
-
-2020/02/20 - implement issue #31 (blank package option)
-2020/02/21 - don't allow package options to be set with \xsimsetup
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.style.layouts.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.style.layouts.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.style.layouts.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,121 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - layouts style
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\xsimstyle{layouts}[2019/10/12]
-
-\RequirePackage{needspace}
-
-\DeclareExerciseEnvironmentTemplate{runin}
- {%
- \par\vspace{\baselineskip}
- \Needspace*{2\baselineskip}
- \noindent
- \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}%
- \GetExercisePropertyT{subtitle}{ \textit{#1}} % <<< notice the space
- \IfInsideSolutionF{%
- \GetExercisePropertyT{points}{%
- \marginpar{%
- \printgoal{\PropertyValue}%
- \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
- \,\IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}}%
- }%
- }%
- }%
- }
- {}
-
-\RequirePackage{array}
-
-\DeclareExerciseEnvironmentTemplate{margin}
- {%
- \trivlist
- \item[\llap{%
- \smash{%
- \tabular[t]{@{}r@{}}
- \textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}
- \IfExercisePropertySetT{points}{%
- \tabularnewline
- (%
- \printgoal{\GetExerciseProperty{points}}%
- \GetExercisePropertyT{bonus-points}{+\printgoal{#1}}%
- \,\XSIMtranslate{point-abbr}%
- )%
- }%
- \endtabular
- }%
- }]\relax
- }
- {\endtrivlist}
-
-\DeclareExerciseEnvironmentTemplate{inline}
- {%
- \textbf{\GetExerciseProperty{counter}}%
- \IfInsideSolutionF{%
- \GetExercisePropertyT{points}{ % <<< notice the space
- (\printgoal{\PropertyValue}%
- \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
- \,\IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}})%
- }%
- } % <<< notice the space
- }
- {}
-
-\DeclareExerciseEnvironmentTemplate{minimal}
- {\par\UseExerciseTemplate{begin}{inline}}
- {\UseExerciseTemplate{end}{inline}\par}
-
-\DeclareExerciseEnvironmentTemplate{centered}
- {%
- \par\vspace{\baselineskip}
- \Needspace*{2\baselineskip}
- \noindent
- \hfil\textbf{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}}%
- \GetExercisePropertyT{subtitle}{ \textit{#1}}\hfil
- \par\noindent
- \IfInsideSolutionF{%
- \GetExercisePropertyT{points}{%
- \marginpar{%
- \printgoal{\PropertyValue}%
- \GetExercisePropertyT{bonus-points}{+\printgoal{\PropertyValue}}%
- \,\IfExerciseGoalSingularTF{points}
- {\XSIMtranslate{point}}
- {\XSIMtranslate{points}}%
- }%
- }%
- }%
- }
- {}
-
-% ----------------------------------------------------------------------------
-\endinput
-
-2020/02/23 - added: inline, centered
- - adapt to removed \par from the generic environments
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.tags.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.tags.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.tags.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,211 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - tags module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{tags}{tagging of exercises}
-
-\xsim_load_modules:n {properties}
-
-\seq_new:N \l__xsim_tag_types_seq
-\bool_new:N \l____xsim_tagged_bool
-
-\cs_new_protected:Npn \xsim_set_seq_from_clist:Nn #1#2
- {
- \seq_clear:N #1
- \clist_map_inline:nn {#2}
- { \tl_if_blank:nF {##1} { \seq_put_right:Nn #1 {##1} } }
- }
-\cs_generate_variant:Nn \xsim_set_seq_from_clist:Nn {c,Nx}
-
-\msg_new:nnn {xsim} {tag-exists}
- { The~ tag~ type~ `#1'~ already~ exists.~ I~ am~ doing~ nothing. }
-
-% #1: name
-\cs_new_protected:Npn \xsim_new_tag_type:n #1
- {
- \xsim_verbose:n { Declaring~ new~ tag~ type~ `#1'. }
- \seq_put_right:Nn \l__xsim_tag_types_seq {#1}
- \seq_remove_duplicates:N \l__xsim_tag_types_seq
- \seq_new:c {l__xsim_chosen_tags_#1_seq}
- \bool_new:c {l__xsim_ignore_untagged_#1_bool}
- \bool_new:c {l____xsim_tagged_#1_bool}
- \keys_define:nn {xsim}
- {
- #1/ignore-untagged .bool_set:c = {l__xsim_ignore_untagged_#1_bool} ,
- #1/ignore-untagged .initial:n = true ,
- #1 .code:n =
- \xsim_set_seq_from_clist:cn {l__xsim_chosen_tags_#1_seq} {##1}
- }
- \prg_new_protected_conditional:cpnn {xsim_if_#1_value:n} ##1 {T,F,TF}
- {
- \seq_if_in:cnTF {l__xsim_chosen_tags_#1_seq} {##1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- \xsim_declare_property:nnnn
- { \c_false_bool }
- { \c_false_bool }
- { \c_false_bool }
- {#1}
- \xsim_declare_printsolutions_condition:nn {#1}
- { \__xsim_printsolutions_if_tagged:nnnnTF {#1} }
- \keys_define:nn {xsim/print-solutions}
- {
- #1 .choice: ,
- #1/false .code:n =
- \__xsim_printsolutions_condition:nn {#1} {false} ,
- #1/true .code:n =
- \__xsim_printsolutions_condition:nn {#1} {true} ,
- #1/unknown .code:n =
- \keys_set:nn {xsim} { #1 = ##1 }
- \__xsim_printsolutions_condition:nn {#1} {true} ,
- #1 .initial:n = false
- }
- }
-
-% #1: tag type
-\prg_new_protected_conditional:Npnn \xsim_if_tag_type_exist:n #1 {T,F,TF}
- {
- \seq_if_in:NnTF \l__xsim_tag_types_seq {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: tag type
-% #2: exercise type
-% #3: id
-% #4: print|use
-\prg_new_protected_conditional:Npnn
- \__xsim_printsolutions_if_tagged:nnnn #1#2#3#4 {T,F,TF}
- {
- \xsim_if_in_list:nnTF {#4} {#2-#3=={true}}
- {
- \__xsim_printsolutions_if_condition:nTF {#1}
- {
- \__xsim_printsolutions_condition_true:
- \xsim_if_tagged:nnnTF {#2} {#3} {#1}
- { \prg_return_true: }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
- { \prg_return_false: }
- }
-
-% #1: exercise type
-% #2: id
-% #3: tag type
-\prg_new_protected_conditional:Npnn \xsim_if_tagged:nnn #1#2#3 {T,F,TF}
- {
- \bool_set_false:c {l____xsim_tagged_#3_bool}
- \seq_if_empty:cTF {l__xsim_chosen_tags_#3_seq}
- { \bool_set_true:c {l____xsim_tagged_#3_bool} }
- {
- \xsim_set_seq_from_clist:Nx
- \l__xsim_tmpa_seq
- { \xsim_get_property:nnn {#1} {#2} {#3} }
- \seq_if_empty:NTF \l__xsim_tmpa_seq
- {
- \bool_set_eq:cc
- {l____xsim_tagged_#3_bool}
- {l__xsim_ignore_untagged_#3_bool}
- }
- {
- \seq_map_inline:Nn \l__xsim_tmpa_seq
- {
- \seq_if_in:cnT {l__xsim_chosen_tags_#3_seq} {##1}
- {
- \bool_set_true:c {l____xsim_tagged_#3_bool}
- \seq_map_break:
- }
- }
- }
- }
- \bool_if:cTF {l____xsim_tagged_#3_bool}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: exercise type
-% #2: id
-\prg_new_protected_conditional:Npnn \xsim_if_tagged:nn #1#2 {T,F,TF}
- {
- \bool_set_true:N \l____xsim_tagged_bool
- \seq_map_inline:Nn \l__xsim_tag_types_seq
- {
- \xsim_if_tagged:nnnF {#1} {#2} {##1}
- {
- \bool_set_false:N \l____xsim_tagged_bool
- \seq_map_break:
- }
- }
- \bool_if:NTF \l____xsim_tagged_bool
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-
-% #1: exercise type
-% #2: id
-% #3: tag type
-% #4: code
-\cs_new_protected:Npn \xsim_foreach_exercise_tag:nnnn #1#2#3#4
- {
- \xsim_set_seq_from_clist:Nx \l__xsim_tmpa_seq
- { \xsim_get_property:nnn {#1} {#2} {#3} }
- \seq_map_inline:Nn \l__xsim_tmpa_seq {#4}
- }
-\cs_generate_variant:Nn \xsim_foreach_exercise_tag:nnnn {oo}
-
-% #1: exercise type
-% #2: id
-% #3: tag type
-% #4: sep
-\cs_new_protected:Npn \xsim_exercise_tags_use:nnnn #1#2#3#4
- {
- \xsim_set_seq_from_clist:Nx \l__xsim_tmpa_seq
- { \xsim_get_property:nnn {#1} {#2} {#3} }
- \seq_use:Nn \l__xsim_tmpa_seq {#4}
- }
-\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnn {oo}
-
-% #1: exercise type
-% #2: id
-% #3: tag type
-% #4: sep between two
-% #5: sep between more than two
-% #6: sep between last two
-\cs_new_protected:Npn \xsim_exercise_tags_use:nnnnnn #1#2#3#4#5#6
- {
- \xsim_set_seq_from_clist:Nx \l__xsim_tmpa_seq
- { \xsim_get_property:nnn {#1} {#2} {#3} }
- \seq_use:Nnnn \l__xsim_tmpa_seq {#4} {#5} {#6}
- }
-\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnn {oo}
-\cs_generate_variant:Nn \xsim_exercise_tags_use:nnnnnn {oo}
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.templates.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.templates.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.templates.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,182 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - templates module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{templates}{templates for typesetting exercises}
-
-\xsim_load_modules:n {base}
-
-\msg_new:nnn {xsim} {unknown-template}
- {
- You~ are~ trying~ to~ load~ the~ template~ `#2'~ (template~ type~ `#1')~
- \msg_line_context: .~ This~ template~ does~ not~ seem~ to~ be~ defined.~
- I~ am~ using~ the~ template~ `#3'~ (template~ type~ `#1')~ instead.
- }
-
-\msg_new:nnn {xsim} {template-type-exists}
- { The~ template~ type~ `#1'~ already~ exists~ \msg_line_context: }
-
-% ----------------------------------------------------------------------------
-\seq_new:N \l__xsim_template_types_seq
-
-% #1: template type
-\cs_new_protected:Npn \xsim_new_template_type:n #1
- {
- \seq_if_in:NnTF \l__xsim_template_types_seq {#1}
- { \msg_error:nnn {xsim} {template-type-exists} {#1} }
- {
- \xsim_verbose:n { Declaring~ new~ template~ type~ `#1'. }
- \seq_put_right:Nn \l__xsim_template_types_seq {#1}
- }
- }
-
-% #1: template type
-% #2: template name
-% #3: code
-\cs_new_protected:Npn \__xsim_add_template:nnn #1#2#3
- {
- \xsim_verbose:n { Defining~ new~ template~ `#2'~ of~ type~ `#1'. }
- \tl_new:c {l__xsim_template_#1_#2_setup_tl}
- \xsim_attribute_set:nnn {template::#1} {#2} {#3}
- }
-
-\prg_new_conditional:Npnn \xsim_if_template_exist:nn #1#2 {T,F,TF}
- {
- \xsim_attribute_if_set:nnTF {template::#1} {#2}
- { \prg_return_true: }
- { \prg_return_false: }
- }
-
-% #1: template type
-% #2: template name
-\cs_new_protected:Npn \__xsim_get_template:nn #1#2
- { \xsim_attribute_get:nn {template::#1} {#2} }
-
-% ----------------------------------------------------------------------------
-
-% environment templates (types `begin' and `end'):
-\xsim_new_template_type:n {begin}
-\xsim_new_template_type:n {end}
-
-% #1: template name
-% #2: begin code
-% #3: end code
-\cs_new_protected:Npn \xsim_declare_environment_template:nnn #1#2#3
- {
- \__xsim_add_template:nnn {begin} {#1}
- {
- \__xsim_start_template:nn {begin} {#1}
- \__xsim_start_template:nn {end} {#1}
- #2
- }
- \__xsim_add_template:nnn {end} {#1}
- {
- #3
- \__xsim_stop_template:nn {end} {#1}
- \__xsim_stop_template:nn {begin} {#1}
- }
- }
-
-% ----------------------------------------------------------------------------
-
-% heading templates for the solution list (type `heading'):
-\xsim_new_template_type:n {heading}
-
-% #1: template name
-% #2: code
-\cs_new_protected:Npn \xsim_declare_heading_template:nn #1#2
- {
- \__xsim_add_template:nnn {heading} {#1}
- {
- \__xsim_start_template:nn {heading} {#1}
- #2
- \__xsim_stop_template:nn {heading} {#1}
- }
- }
-
-% ----------------------------------------------------------------------------
-
-% grading table templates (type `table'):
-\xsim_new_template_type:n {table}
-
-% #1: template name
-% #2: code
-\cs_new_protected:Npn \xsim_declare_table_template:nn #1#2
- {
- \__xsim_add_template:nnn {table} {#1}
- {
- \__xsim_start_template:nn {table} {#1}
- #2
- \__xsim_stop_template:nn {table} {#1}
- }
- }
-
-% ----------------------------------------------------------------------------
-
-% using templates:
-% setup up the next usage of `template name':
-% #1: template type
-% #2: template name
-% #3: setup code
-\cs_new_protected:Npn \xsim_setup_template:nnn #1#2#3
- { \tl_set:cn {l__xsim_template_#1_#2_setup_tl} {#3} }
-\cs_generate_variant:Nn \xsim_setup_template:nnn {nnV,nVn}
-
-% #1: template type
-% #2: template name
-\cs_new_protected:Npn \__xsim_setup_template:nn #1#2
- { \tl_use:c {l__xsim_template_#1_#2_setup_tl} }
-
-% #1: template type
-% #2: template name
-\cs_new_protected:Npn \__xsim_clear_template_setup:nn #1#2
- { \tl_clear:c {l__xsim_template_#1_#2_setup_tl} }
-
-% #1: template type
-% #2: template name
-\cs_new_protected:Npn \__xsim_start_template:nn #1#2
- { \group_begin: \__xsim_setup_template:nn {#1} {#2} }
-
-% #1: template type
-% #2: template name
-\cs_new_protected:Npn \__xsim_stop_template:nn #1#2
- { \group_end: \__xsim_clear_template_setup:nn {#1} {#2} }
-
-% #1: template type
-% #2: template name
-\cs_new_protected:Npn \xsim_use_template:nn #1#2
- {
- \xsim_if_template_exist:nnTF {#1} {#2}
- { \__xsim_get_template:nn {#1} {#2} }
- {
- \msg_warning:nnnnn {xsim} {unknown-template} {#1} {#2} {default}
- \__xsim_get_template:nn {#1} {default}
- }
- }
-\cs_generate_variant:Nn \xsim_use_template:nn {nx,nV}
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.translations.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.translations.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.translations.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,147 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - translations module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{translations}{language settings for XSIM}
-
-\RequirePackage{translations}
-
-\msg_new:nnn {xsim} {language-not-defined}
- {
- You~ chose~ the~ language~ `#1'~ which~ is~ not~ defined~ by~ xsim.~
- `english'~ is~ used~ instead.~ If~ you~ just~ mistyped~ try~ again!~
- Otherwise~ contact~ the~ author~ and~ he'll~ probably~ add~ your~ language.
- }
-
-% --------------------------------------------------------------------------
-
-\bool_new:N \l__xsim_language_auto_bool
-\bool_set_true:N \l__xsim_language_auto_bool
-% this token list will hold the chosen language for xsim; since the
-% language is either chosen automatically or by option it is only available at
-% begin document
-\tl_new:N \l_xsim_language_tl
-\tl_set:Nn \l_xsim_language_tl {english}
-\tl_new:N \l__xsim_current_language_tl
-
-\tl_const:Nn \c__xsim_keyword_prefix_tl {xsim-keyword-}
-
-% ----------------------------------------------------------------------------
-
-\prop_new:N \g_xsim_translations_prop
-
-% translate the key #1
-\cs_new:Npn \xsim_translate:n #1
- {
- \bool_if:NTF \l__xsim_language_auto_bool
- { \GetTranslation { \c__xsim_keyword_prefix_tl #1 } }
- {
- \GetTranslationFor
- { \l_xsim_language_tl }
- { \c__xsim_keyword_prefix_tl #1 }
- }
- }
-
-\xsim_at_begin_document:n
- {
- \bool_if:NTF \l__xsim_language_auto_bool
- {
- \tl_set:Nx \l_xsim_language_tl
- { \@trnslt at language{\@trnslt at current@language} }
- }
- {
- \tl_set_eq:NN
- \l_xsim_language_tl
- \l__xsim_current_language_tl
- }
- }
-
-% ----------------------------------------------------------------------------
-% #1: keyword
-% #2: language
-% #3: translation
-\cs_new_protected:Npn \__xsim_declare_translation:nw #1#2=#3\q_stop
- {
- \tl_set:Nx \l__xsim_tmpa_tl { \tl_trim_spaces:n {#2} }
- \tl_set:Nx \l__xsim_tmpb_tl { \tl_trim_spaces:n {#3} }
- \xsim_declare_translation:VnV
- \l__xsim_tmpa_tl
- {#1}
- \l__xsim_tmpb_tl
- }
-
-% #1: language
-% #2: keyword
-% #3: translation
-\cs_new_protected:Npn \xsim_declare_translation:nnn #1#2#3
- {
- \xsim_verbose:n
- { Declaring~ `#1'~ tranlation~ of~ `#2':~ `#3'. }
- \declaretranslation
- {#1}
- { \c__xsim_keyword_prefix_tl #2 }
- {#3}
- \prop_gput:Nnn \g_xsim_translations_prop {#2(#1)} {#3}
- }
-\cs_generate_variant:Nn \xsim_declare_translation:nnn {V,VnV}
-
-% #1: key
-% #2: csv list: { <lang1> = <translation1> , <lang2> = <translation2> }
-\cs_new_protected:Npn \xsim_declare_translations:nn #1#2
- {
- \clist_map_inline:nn {#2}
- { \__xsim_declare_translation:nw {#1} ##1 \q_stop }
- }
-
-\cs_new:Npn \__xsim_parse_translate_list_entry:nnn #1#2#3 {}
-
-\cs_new_protected:Npn \__xsim_parse_translate_list_entry:www #1(#2)\q_mark#3\q_stop
- { \__xsim_parse_translate_list_entry:nnn {#1} {#2} {#3} }
-
-\cs_new_protected:Npn \xsim_for_all_translations_do:n #1
- {
- \cs_set:Npn \__xsim_parse_translate_list_entry:nnn ##1##2##3 {#1}
- \prop_map_inline:Nn \g_xsim_translations_prop
- { \__xsim_parse_translate_list_entry:www ##1 \q_mark ##2 \q_stop }
- }
-
-% ----------------------------------------------------------------------------
-
-\keys_define:nn {xsim}
- {
- language .value_required:n = true ,
- language .code:n =
- \tl_if_eq:nnTF {#1} {auto}
- { \bool_set_true:N \l__xsim_language_auto_bool }
- {
- \bool_set_false:N \l__xsim_language_auto_bool
- \tl_set:Nn \l__xsim_current_language_tl {#1}
- } ,
- language .initial:n = auto
- }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Deleted: trunk/Master/texmf-dist/tex/latex/xsim/xsim.verbwrite.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsim.verbwrite.code.tex 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsim.verbwrite.code.tex 2021-01-31 21:33:37 UTC (rev 57572)
@@ -1,217 +0,0 @@
-% ----------------------------------------------------------------------------
-% the XSIM package - verbwrite module
-%
-% eXercise Sheets IMproved
-%
-% ----------------------------------------------------------------------------
-% Clemens Niederberger
-% Web: https://github.com/cgnieder/xsim
-% E-Mail: contact at mychemistry.eu
-% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
-%
-% 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 Clemens Niederberger.
-% ----------------------------------------------------------------------------
-% If you have any ideas, questions, suggestions or bugs to report, please
-% feel free to contact me.
-% ----------------------------------------------------------------------------
-\XSIMmodule{verbwrite}{write contents of environments verbatim to files}
-
-\xsim_load_modules:n {base}
-
-\iow_new:N \l__xsim_file_contents_iow
-\tl_new:N \l_xsim_file_begin_tl
-\tl_new:N \l_xsim_file_end_tl
-\int_new:N \l_xsim_line_gobble_int
-\int_zero:N \l_xsim_line_gobble_int
-
-\tl_const:Nx \c__xsim_backslash_char_tl { \cs_to_str:N \\ }
-
-\group_begin:
- \char_set_catcode_other:n {37}
- \tl_const:Nn \c__xsim_percent_char_tl {%}
-\group_end:
-
-% ----------------------------------------------------------------------------
-
-% the `final' option will prevent writing to files:
-% #1: write stream
-% #2: file name
-\cs_new_protected:Npn \__xsim_open_stream:Nn #1#2
- {
- \file_if_exist:nTF {#2}
- { \xsim_if_final:F { \iow_open:Nn #1 {#2} } }
- {
- % \g__xsim_final_bool is a global variable; however, if it is true and
- % the exercise file doesn't exist, yet, we need to set it locally to
- % false in order to ensure that the file is correctly written and the
- % stream closed afterwards
- \bool_set_false:N \g__xsim_final_bool
- \iow_open:Nn #1 {#2}
- }
- }
-
-% #1: write stream
-\cs_new_protected:Npn \__xsim_close_stream:N #1
- { \xsim_if_final:F { \iow_close:N #1 } }
-
-% #1: write stream
-% #2: contents
-\cs_new_protected:Npn \__xsim_write_to_stream:Nn #1#2
- {
- \xsim_if_final:F
- {
- % remove the /one/ space token with catcode 10 that is inserted if
- % no options are given to the surrounding environment:
- \tl_set:Nn \l__xsim_tmpa_tl {#2}
- \tl_remove_once:Nn \l__xsim_tmpa_tl {~}
- % \tl_show:N \l__xsim_tmpa_tl
- % \int_show:n { \tl_count:N \l__xsim_tmpa_tl }
- % \tl_analysis_show:N \l__xsim_tmpa_tl
- \int_zero:N \l__xsim_tmpa_int
- \int_while_do:nn { \l__xsim_tmpa_int < \l_xsim_line_gobble_int }
- {
- \int_incr:N \l__xsim_tmpa_int
- \tl_set:Nx \l__xsim_tmpa_tl { \tl_tail:N \l__xsim_tmpa_tl }
- }
- \iow_now:NV #1 \l__xsim_tmpa_tl
- }
- }
-\cs_generate_variant:Nn \__xsim_write_to_stream:Nn {Nx}
-
-\cs_new:Npn \__xsim_tab: { \c_space_tl \c_space_tl }
-\cs_new:Npn \__xsim_par: { ^^J ^^J }
-
-% the following is inspired by the definition of the `filecontents'
-% environment:
-% #1: boolean - if true an active eol needs to be inserted before
-% starting to write
-% #2: file name
-\cs_new_protected:Npn \xsim_file_write_start:nn #1#2
- {
- % we need to insert an active ^^M if no options are given
- % see http://tex.stackexchange.com/q/9035/5049 reasons
- \use:nx
- { \__xsim_file_write_start:n {#2} }
- { \bool_if:nF {#1} { \exp_not:V \c__xsim_active_eol_tl } }
- }
-\cs_generate_variant:Nn \xsim_file_write_start:nn {nV}
-
-\cs_new_protected:Npn \__xsim_set_verb_catcodes:
- {
- \seq_map_inline:Nn \l_char_special_seq
- { \char_set_catcode_other:N ##1 }
- \int_step_inline:nnnn {128} {1} {255}
- { \char_set_catcode_letter:n {##1} }
- }
-
-\group_begin:
-\char_set_catcode_active:n {13} % ^^M (carriage return, endlinechar)
-\char_set_catcode_active:n {12} % ^^L (form feed)
-\char_set_catcode_active:n {9} % ^^I (horizontal tab)
-%
-\tl_const:Nn \c__xsim_active_eol_tl {^^M} %
-%
-% #1: file name
-\cs_new_protected:Npn \__xsim_file_write_start:n #1 %
- { %
- \group_begin: %
- \xsim_if_final:TF %
- { \xsim_verbose:x { Not~ (re-)writing~ file~ `#1'. } } %
- { \xsim_verbose:x { (Re-)writing~ file~ `#1'. } } %
- \__xsim_open_stream:Nn \l__xsim_file_contents_iow {#1} %
- \tl_if_blank:VF \l_xsim_file_begin_tl %
- { %
- \xsim_if_final:F %
- { %
- \iow_now:Nx \l__xsim_file_contents_iow %
- { \l_xsim_file_begin_tl } %
- } %
- } %
- \__xsim_set_verb_catcodes: %
- \tl_set:Nx \l__xsim_tmpa_tl %
- { \c__xsim_backslash_char_tl end \cs_to_str:N \{ \@currenvir \cs_to_str:N \} } %
- \use:x %
- { %
- \cs_set:cpn {__xsim_tmpa:www} %
- ####1 \l__xsim_tmpa_tl %
- ####2 \l__xsim_tmpa_tl %
- ####3 \exp_not:N \q_stop: %
- } %
- { %
- \tl_if_blank:nTF {##3} %
- { \__xsim_write_to_stream:Nn \l__xsim_file_contents_iow {##1} } %
- { %
- \cs_set:Npx \__xsim_M:w { \exp_not:N \end {\@currenvir} } %
- \char_set_active_eq:nN {13} \__xsim_M:w %
- % the last line is `##1 \end{\@currenvir} ##2':
- \tl_if_blank:nF {##1} %
- { \__xsim_write_to_stream:Nn \l__xsim_file_contents_iow {##1} }%
- \tl_if_blank:nF {##2} %
- {} %
- } %
- ^^M %
- } %
- \char_set_catcode_active:n {13} %
- \char_set_catcode_active:n {12} %
- \char_set_catcode_active:n {9} %
- \cs_set:Npx \__xsim_M:w ##1 ^^M %
- { %
- \exp_not:N \__xsim_tmpa:www ##1 %
- \l__xsim_tmpa_tl %
- \l__xsim_tmpa_tl %
- \exp_not:N \q_stop: %
- } %
- \char_set_active_eq:nN {13} \__xsim_M:w %
- \char_set_active_eq:nN {12} \__xsim_par: %
- \char_set_active_eq:nN {9} \__xsim_tab: %
- } %
-\group_end:
-
-\cs_new_protected:Npn \xsim_file_write_stop:
- {
- \tl_if_blank:VF \l_xsim_file_end_tl
- {
- \xsim_if_final:F
- {
- \iow_now:Nx \l__xsim_file_contents_iow
- { \l_xsim_file_end_tl }
- }
- }
- \__xsim_close_stream:N \l__xsim_file_contents_iow
- \group_end:
- }
-
-% ----------------------------------------------------------------------------
-
-\NewDocumentCommand \XSIMfilewritestart {sm}
- {
- \IfBooleanTF {#1}
- { \xsim_file_write_start:nn { \c_false_bool } {#2} }
- { \xsim_file_write_start:nn { \c_true_bool } {#2} }
- }
-
-\NewDocumentCommand \XSIMfilewritestop {}
- { \xsim_file_write_stop: }
-
-\NewDocumentCommand \XSIMsetfilebegin {+m}
- { \tl_set:Nn \l_xsim_file_begin_tl {#1} }
-
-\NewDocumentCommand \XSIMsetfileend {+m}
- { \tl_set:Nn \l_xsim_file_end_tl {#1} }
-
-\NewDocumentCommand \XSIMgobblechars {m}
- { \int_set:Nn \l_xsim_line_gobble_int {#1} }
-
-% ----------------------------------------------------------------------------
-\file_input_stop:
Modified: trunk/Master/texmf-dist/tex/latex/xsim/xsimverb.sty
===================================================================
--- trunk/Master/texmf-dist/tex/latex/xsim/xsimverb.sty 2021-01-31 17:36:15 UTC (rev 57571)
+++ trunk/Master/texmf-dist/tex/latex/xsim/xsimverb.sty 2021-01-31 21:33:37 UTC (rev 57572)
@@ -8,15 +8,15 @@
% Web: https://github.com/cgnieder/xsim
% E-Mail: contact at mychemistry.eu
% ----------------------------------------------------------------------------
-% Copyright 2017--2020 Clemens Niederberger
+% Copyright 2017--2021 Clemens Niederberger
%
% This work may be distributed and/or modified under the
-% conditions of the LaTeX Project Public License, either version 1.3
+% conditions of the LaTeX Project Public License, either version 1.3c
% 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.
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2008/05/04 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
@@ -25,14 +25,13 @@
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% ----------------------------------------------------------------------------
-
-\RequirePackage {expl3}
+\RequirePackage {l3keys2e}
\ExplSyntaxOn
-\tl_const:Nn \c_xsimverb_date_tl {2019/12/29}
+\tl_const:Nn \c_xsimverb_date_tl {2021/01/31}
\tl_const:Nn \c_xsimverb_version_major_number_tl {0}
-\tl_const:Nn \c_xsimverb_version_minor_number_tl {1}
-\tl_const:Nn \c_xsimverb_version_subrelease_tl {a}
+\tl_const:Nn \c_xsimverb_version_minor_number_tl {3}
+\tl_const:Nn \c_xsimverb_version_subrelease_tl {}
\tl_const:Nx \c_xsimverb_version_number_tl
{
\c_xsimverb_version_major_number_tl .
@@ -51,9 +50,6 @@
{\c_xsimverb_version_tl}
{\c_xsimverb_info_tl}
-\@ifpackageloaded {xsim} { \file_input_stop: } {}
-\RequirePackage {xparse,l3keys2e}
-
% options, information
\cs_new_protected:Npn \xsimverb_bool_provide:N #1
@@ -65,33 +61,251 @@
\xsimverb_bool_provide:N \g__xsim_write_to_file_bool
\xsimverb_bool_provide:N \g_xsim_use_aux_bool
\xsimverb_bool_provide:N \g__xsim_rerun_bool
+\xsimverb_bool_provide:N \g__xsim_debug_bool
+\xsimverb_bool_provide:N \g__xsim_blank_bool
\keys_define:nn {xsimverb}
{
- final .bool_gset:N = \g__xsim_final_bool ,
- verbose .bool_gset:N = \g__xsim_verbose_bool ,
- clear-aux .bool_gset:N = \g_xsim_clear_aux_bool ,
- no-files .bool_gset_inverse:N = \g__xsim_write_to_file_bool ,
- no-files .initial:n = false ,
- use-aux .bool_gset:N = \g_xsim_use_aux_bool ,
- use-aux .initial:n = false
+ final .bool_gset:N = \g__xsim_final_bool ,
+ verbose .bool_gset:N = \g__xsim_verbose_bool ,
+ debug .bool_gset:N = \g__xsim_debug_bool ,
+ clear-aux .bool_gset:N = \g_xsim_clear_aux_bool ,
+ use-files .bool_gset:N = \g__xsim_write_to_file_bool ,
+ use-files .initial:n = false ,
+ no-files .choice: ,
+ no-files / true .meta:n = { use-files = false } ,
+ no-files / false .meta:n = { use-files = true } ,
+ no-files .default:n = true ,
+ use-aux .bool_gset:N = \g_xsim_use_aux_bool ,
+ use-aux .initial:n = false ,
+ blank .bool_gset:N = \g__xsim_blank_bool ,
+ blank .initial:n = false
}
\ProcessKeysPackageOptions {xsimverb}
-% --------------------------------------------------------------------------
+\cs_if_exist:NF \xsim_if_final:T
+ {
+ \prg_new_conditional:Npnn \xsim_if_final: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_final_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
-% load module mechanism:
-\tl_set:Nn \l_tmpa_tl {code.tex}
-\@onefilewithoptions {xsim.modules} [][] \l_tmpa_tl
+ \prg_new_conditional:Npnn \xsim_if_verbose: {p,T,F,TF}
+ {
+ \bool_if:NTF \g__xsim_verbose_bool
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+ }
+\cs_if_exist:NF \xsim_verbose:n
+ {
+ \cs_new_protected:Npn \xsim_verbose:n #1
+ { \xsim_if_verbose:T { \msg_info:nnn {xsim} {verbose} {#1} } }
+ \cs_generate_variant:Nn \xsim_verbose:n {x}
+ }
+
% --------------------------------------------------------------------------
+% #1: name
+% #2: description
+\cs_set_protected:Npn \XSIMmodule #1#2 {}
+\cs_set_protected:Npn \XSIMmoduleend {}
-\xsim_load_module:n {verbwrite}
-
% --------------------------------------------------------------------------
-\file_input_stop:
+\XSIMmodule{verbwrite}{write contents of environments verbatim to files}
-2018/01/31 - define xsim's options as dummy options to prevent possible errors
- caused by undefined booleans
-2019/12/29 - adapt to update of xsim
+\int_new:N \l__xsimverb_tmpa_int
+\tl_new:N \l__xsimverb_tmpa_tl
+
+\iow_new:N \l__xsim_file_contents_iow
+\tl_new:N \l_xsim_file_begin_tl
+\tl_new:N \l_xsim_file_end_tl
+\int_new:N \l_xsim_line_gobble_int
+\int_zero:N \l_xsim_line_gobble_int
+
+\tl_const:Nx \c__xsim_backslash_char_tl { \cs_to_str:N \\ }
+
+\group_begin:
+ \char_set_catcode_other:n {37}
+ \tl_const:Nn \c__xsim_percent_char_tl {%}
+\group_end:
+
+% ----------------------------------------------------------------------------
+\bool_new:N \l__xsim_stream_open_bool
+% the `final' option will prevent writing to files:
+% #1: write stream
+% #2: file name
+\cs_new_protected:Npn \__xsim_open_stream:Nn #1#2
+ {
+ \file_if_exist:nTF {#2}
+ {
+ \xsim_if_final:F
+ {
+ \bool_set_true:N \l__xsim_stream_open_bool
+ \iow_open:Nn #1 {#2}
+ }
+ }
+ {
+ \bool_set_true:N \l__xsim_stream_open_bool
+ \iow_open:Nn #1 {#2}
+ }
+ }
+
+% #1: write stream
+\cs_new_protected:Npn \__xsim_close_stream:N #1
+ { \bool_if:NT \l__xsim_stream_open_bool { \iow_close:N #1 } }
+
+% #1: write stream
+% #2: contents
+\cs_new_protected:Npn \__xsim_write_to_stream:Nn #1#2
+ {
+ \xsim_if_final:F
+ {
+ % remove the /one/ space token with catcode 10 that is inserted if
+ % no options are given to the surrounding environment:
+ \tl_set:Nn \l__xsimverb_tmpa_tl {#2}
+ \tl_remove_once:Nn \l__xsimverb_tmpa_tl {~}
+ % \tl_show:N \l__xsimverb_tmpa_tl
+ % \int_show:n { \tl_count:N \l__xsimverb_tmpa_tl }
+ % \tl_analysis_show:N \l__xsimverb_tmpa_tl
+ \int_zero:N \l__xsimverb_tmpa_int
+ \int_while_do:nn { \l__xsimverb_tmpa_int < \l_xsim_line_gobble_int }
+ {
+ \int_incr:N \l__xsimverb_tmpa_int
+ \tl_set:Nx \l__xsimverb_tmpa_tl { \tl_tail:N \l__xsimverb_tmpa_tl }
+ }
+ \iow_now:NV #1 \l__xsimverb_tmpa_tl
+ }
+ }
+\cs_generate_variant:Nn \__xsim_write_to_stream:Nn {Nx}
+\cs_generate_variant:Nn \iow_now:Nn {NV}
+
+\cs_new:Npn \__xsim_tab: { \c_space_tl \c_space_tl }
+\cs_new:Npn \__xsim_par: { ^^J ^^J }
+
+% the following is inspired by the definition of the `filecontents'
+% environment:
+% #1: boolean - if true an active eol needs to be inserted before
+% starting to write
+% #2: file name
+\cs_new_protected:Npn \xsim_file_write_start:nn #1#2
+ {
+ % we need to insert an active ^^M if no options are given
+ % see http://tex.stackexchange.com/q/9035/5049 reasons
+ \use:nx
+ { \__xsim_file_write_start:n {#2} }
+ { \bool_if:nF {#1} { \exp_not:V \c__xsim_active_eol_tl } }
+ }
+\cs_generate_variant:Nn \xsim_file_write_start:nn {nV}
+\cs_generate_variant:Nn \use:nn {nx}
+
+\cs_new_protected:Npn \__xsim_set_verb_catcodes:
+ {
+ \seq_map_inline:Nn \l_char_special_seq
+ { \char_set_catcode_other:N ##1 }
+ \int_step_inline:nnnn {128} {1} {255}
+ { \char_set_catcode_letter:n {##1} }
+ }
+
+\group_begin:
+\char_set_catcode_active:n {13} % ^^M (carriage return, endlinechar)
+\char_set_catcode_active:n {12} % ^^L (form feed)
+\char_set_catcode_active:n {9} % ^^I (horizontal tab)
+%
+\tl_const:Nn \c__xsim_active_eol_tl {^^M} %
+%
+% #1: file name
+\cs_new_protected:Npn \__xsim_file_write_start:n #1 %
+ { %
+ \group_begin: %
+ \xsim_if_final:TF %
+ { \xsim_verbose:x { Not~ (re-)writing~ file~ `#1'. } } %
+ { \xsim_verbose:x { (Re-)writing~ file~ `#1'. } } %
+ \__xsim_open_stream:Nn \l__xsim_file_contents_iow {#1} %
+ \tl_if_blank:VF \l_xsim_file_begin_tl %
+ { %
+ \xsim_if_final:F %
+ { %
+ \iow_now:Nx \l__xsim_file_contents_iow %
+ { \exp_not:V \l_xsim_file_begin_tl } %
+ } %
+ } %
+ \__xsim_set_verb_catcodes: %
+ \tl_set:Nx \l__xsimverb_tmpa_tl %
+ { \c__xsim_backslash_char_tl end \cs_to_str:N \{ \@currenvir \cs_to_str:N \} } %
+ \use:x %
+ { %
+ \cs_set:cpn {__xsim_tmpa:www} %
+ ####1 \l__xsimverb_tmpa_tl %
+ ####2 \l__xsimverb_tmpa_tl %
+ ####3 \exp_not:N \q_stop: %
+ } %
+ { %
+ \tl_if_blank:nTF {##3} %
+ { \__xsim_write_to_stream:Nn \l__xsim_file_contents_iow {##1} } %
+ { %
+ \cs_set:Npx \__xsim_M:w { \exp_not:N \end {\@currenvir} } %
+ \char_set_active_eq:nN {13} \__xsim_M:w %
+ % the last line is `##1 \end{\@currenvir} ##2':
+ \tl_if_blank:nF {##1} %
+ { \__xsim_write_to_stream:Nn \l__xsim_file_contents_iow {##1} }%
+ \tl_if_blank:nF {##2} %
+ {} %
+ } %
+ ^^M %
+ } %
+ \char_set_catcode_active:n {13} %
+ \char_set_catcode_active:n {12} %
+ \char_set_catcode_active:n {9} %
+ \cs_set:Npx \__xsim_M:w ##1 ^^M %
+ { %
+ \exp_not:N \__xsim_tmpa:www ##1 %
+ \l__xsimverb_tmpa_tl %
+ \l__xsimverb_tmpa_tl %
+ \exp_not:N \q_stop: %
+ } %
+ \char_set_active_eq:nN {13} \__xsim_M:w %
+ \char_set_active_eq:nN {12} \__xsim_par: %
+ \char_set_active_eq:nN {9} \__xsim_tab: %
+ } %
+\group_end:
+
+\cs_new_protected:Npn \xsim_file_write_stop:
+ {
+ \tl_if_blank:VF \l_xsim_file_end_tl
+ {
+ \xsim_if_final:F
+ {
+ \iow_now:Nx \l__xsim_file_contents_iow
+ { \exp_not:V \l_xsim_file_end_tl }
+ }
+ }
+ \__xsim_close_stream:N \l__xsim_file_contents_iow
+ \group_end:
+ }
+
+% ----------------------------------------------------------------------------
+
+\NewDocumentCommand \XSIMfilewritestart {sm}
+ {
+ \IfBooleanTF {#1}
+ { \xsim_file_write_start:nn { \c_false_bool } {#2} }
+ { \xsim_file_write_start:nn { \c_true_bool } {#2} }
+ }
+
+\NewDocumentCommand \XSIMfilewritestop {}
+ { \xsim_file_write_stop: }
+
+\NewDocumentCommand \XSIMsetfilebegin {+m}
+ { \tl_set:Nn \l_xsim_file_begin_tl {#1} }
+
+\NewDocumentCommand \XSIMsetfileend {+m}
+ { \tl_set:Nn \l_xsim_file_end_tl {#1} }
+
+\NewDocumentCommand \XSIMgobblechars {m}
+ { \int_set:Nn \l_xsim_line_gobble_int {#1} }
+
+\XSIMmoduleend
More information about the tex-live-commits
mailing list.