From d2e50e76ef7e64efa460c918c4c751262c063476 Mon Sep 17 00:00:00 2001
From: Norbert Preining <preining@logic.at>
Date: Sat, 13 Oct 2012 09:39:42 +0000
Subject: new latex packages exsheets (12Oct)

git-svn-id: svn://tug.org/texlive/trunk@27953 c570f23f-e606-0410-a88d-b1316a301751
---
 Master/texmf-dist/tex/latex/exsheets/exsheets.sty | 2045 +++++++++++++++++++++
 1 file changed, 2045 insertions(+)
 create mode 100644 Master/texmf-dist/tex/latex/exsheets/exsheets.sty

(limited to 'Master/texmf-dist/tex/latex/exsheets/exsheets.sty')

diff --git a/Master/texmf-dist/tex/latex/exsheets/exsheets.sty b/Master/texmf-dist/tex/latex/exsheets/exsheets.sty
new file mode 100644
index 00000000000..db748f1baf5
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/exsheets/exsheets.sty
@@ -0,0 +1,2045 @@
+% ----------------------------------------------------------------------------
+% the EXSHEETS package
+% 
+%   Yet another package for the creation of exercise sheets
+% 
+% ----------------------------------------------------------------------------
+% Clemens Niederberger
+% Web:    https://bitbucket.org/cgnieder/exsheets/
+% E-Mail: contact@mychemistry.eu
+% ----------------------------------------------------------------------------
+% Copyright 2011-2012 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.
+% ----------------------------------------------------------------------------
+% The exsheets package consists of the files
+%  - exsheets.sty, exsheets_headings.def, exsheets_headings.cfg,
+%    exsheets_tasks.def, exsheets_tasks.cfg, exsheets_configurations.cfg,
+%  - exsheets_en.tex, exsheets_en.pdf,
+%  - README
+% ----------------------------------------------------------------------------
+% If you have any ideas, questions, suggestions or bugs to report, please
+% feel free to contact me.
+% ----------------------------------------------------------------------------
+\def\exsheets@date{2012/10/08}
+\def\exsheets@version{0.2b}
+
+\RequirePackage { expl3 , xparse }
+\ProvidesExplPackage
+  {exsheets}
+  {\exsheets@date}
+  {\exsheets@version}
+  {Yet another package for the creation of exercise sheets and exams.}
+
+% ----------------------------------------------------------------------------
+% temporary variables
+\tl_new:N    \l__exsheets_tmpa_tl
+\tl_new:N    \l__exsheets_tmpb_tl
+\tl_new:N    \l__exsheets_tmpc_tl
+\int_new:N   \l__exsheets_tmpa_int
+\int_new:N   \l__exsheets_tmpb_int
+\dim_new:N   \l__exsheets_tmpa_dim
+\seq_new:N   \l__exsheets_tmpa_seq
+\fp_new:N    \l__exsheets_tmpa_fp
+\clist_new:N \l__exsheets_tmpa_clist
+
+% ----------------------------------------------------------------------------
+% messages
+\msg_new:nnn { exsheets} { totalpoints }
+  {
+    You~need~to~activate~"points/parse"~if~you~want~to~use~
+    \token_to_str:N \totalpoints .~I~will~do~nothing~instead.
+  }
+
+\msg_new:nnn { exsheets} { headings }
+  {
+    You~requested~the~headings~instance~`#1'~which~is~not~defined.~Did~you~
+    forget~to~use~the~package~option~`load-headings'?~Anyway,~I~will~use~the~
+    instance~`block'~instead~and~pretend~nothing~happened.
+  }
+
+\msg_new:nnn { exsheets } { random }
+  {
+    You~asked~me~to~select~#1~questions~from~file~#2~but~there~are~only~#3.~
+    I'll~select~all~of~them.
+  }
+
+\msg_new:nnn { exsheets } { only-inside-question }
+  {
+    The~command~\token_to_str:N #1 \c_space_tl can~only~be~used~inside~
+    the~question~environment.
+  }
+
+\msg_new:nnn { exsheets } { loading-configurations }
+  { Loading~custom~configurations~file~`exsheets_configurations.cgf'. }
+
+\msg_new:nnn { exsheets } { deprecated-command }
+  {
+    The~command~"~\token_to_str:N #1 \c_space_tl"~is~deprecated.~
+    Use~"~\token_to_str:N #2 \c_space_tl"~instead.
+  }
+
+\msg_new:nnn { exsheets } { grade-missing }
+  { The~grade~`#1'~has~never~been~declared. }
+
+\msg_new:nnn { exsheets } { grade-parse }
+  {
+    I~cannot~calculate~the~points~for~grade~`#1'~since~you're~using~the~option~
+    `points/parse=false'.
+  }
+
+\cs_new:Npn \exsheets_depr_cmd:nn #1#2
+  {
+    \cs_new:Npn #1
+      { \msg_warning:nnnn { exsheets } { deprecated-command } { #1 } { #2 } #2 }
+  }
+
+% ----------------------------------------------------------------------------
+\RequirePackage
+  { xtemplate , l3sort , l3keys2e , xcolor , etoolbox , environ , lcg , silence }
+
+% ----------------------------------------------------------------------------
+% color:
+\xdefinecolor { exsheetsblue } { rgb } { 0.02 , 0.04 , 0.48 }
+\xdefinecolor { exsheetsred  } { rgb } { 0.65 , 0.04 , 0.07 }
+\tl_new:N   \g__exsheets_color_tl
+\tl_gset:Nn \g__exsheets_color_tl { exsheetsblue }
+
+% ----------------------------------------------------------------------------
+% how are questions/solutions/... counted?
+\bool_new:N      \l__exsheets_print_number_bool
+\bool_set_true:N \l__exsheets_print_number_bool
+
+\tl_new:N  \l__exsheets_qu_counter_pattern_tl
+\tl_set:Nn \l__exsheets_qu_counter_pattern_tl { qu. }
+\tl_new:N  \l__exsheets_qu_counter_interpretation_tl
+\tl_new:N  \l__exsheets_counter_patterns_tl
+\tl_new:N  \l__exsheets_current_pattern_interpretation_tl
+\tl_new:N  \l__exsheets_current_pattern_tl
+
+\RequirePackage { cntformats }
+
+\cs_if_exist:NT \thechapter
+  {
+    \AddCounterPattern* [ exsheets ] { chapter } { ch }
+    \ReadCounterFrom [ exsheets ] { chapter } \l__exsheets_counter_ch_int
+  }
+
+\AddCounterPattern* [ exsheets ] { section } { se }
+\ReadCounterFrom [ exsheets ] { section } \l__exsheets_counter_sec_int
+
+\NewCounterPattern* [ exsheets ] { question } { qu }
+\ReadCounterFrom [ exsheets ] { question } \l__exsheets_counter_qu_int
+
+% ----------------------------------------------------------------------------
+% (also) package options:
+\bool_new:N \l__exsheets_load_headings_bool
+\bool_new:N \l__exsheets_load_tasks_bool
+\bool_new:N \l__exsheets_solutions_by_ref_bool
+\bool_new:N \l__exsheets_questions_totoc_bool
+\bool_new:N \l__exsheets_solutions_totoc_bool
+
+\tl_new:N   \l__exsheets_heading_instance_tl
+\tl_set:Nn  \l__exsheets_heading_instance_tl { block }
+\tl_new:N   \l__exsheets_heading_title_user_format_tl
+\tl_set:Nn  \l__exsheets_heading_title_user_format_tl { \normalsize\bfseries }
+\tl_new:N   \l__exsheets_questions_toclevel_tl
+\tl_set:Nn  \l__exsheets_questions_toclevel_tl { subsection }
+\tl_new:N   \l__exsheets_solutions_toclevel_tl
+\tl_set:Nn  \l__exsheets_solutions_toclevel_tl { subsection }
+
+\AtBeginDocument{
+  \cs_if_exist:NF \phantomsection
+    { \cs_new:Npn \phantomsection {} }
+}
+
+\keys_define:nn { exsheets }
+  {
+    color                     .tl_gset:N  = \g__exsheets_color_tl ,
+    counter-format            .code:n     =
+      \SaveCounterPattern [ exsheets ]
+        \l__exsheets_qu_counter_pattern_tl
+        \l__exsheets_qu_counter_interpretation_tl
+        { #1 } ,
+    counter-within            .code:n     = \@addtoreset{question}{#1} ,
+    headings                  .tl_set:N   = \l__exsheets_heading_instance_tl ,
+    load-headings             .bool_set:N = \l__exsheets_load_headings_bool ,
+    headings-format           .tl_set:N   = \l__exsheets_heading_title_user_format_tl ,
+    load-tasks                .bool_set:N = \l__exsheets_load_tasks_bool ,
+    use-ref                   .bool_set:N = \l__exsheets_solutions_by_ref_bool ,
+    totoc                     .choice: ,
+    totoc / true              .code:n     =
+      \bool_set_true:N \l__exsheets_questions_totoc_bool
+      \bool_set_true:N \l__exsheets_solutions_totoc_bool ,
+    totoc / false             .code:n     =
+      \bool_set_false:N \l__exsheets_questions_totoc_bool
+      \bool_set_false:N \l__exsheets_solutions_totoc_bool ,
+    totoc                     .default:n  = true ,
+    questions-totoc           .bool_set:N = \l__exsheets_questions_totoc_bool ,
+    solutions-totoc           .bool_set:N = \l__exsheets_solutions_totoc_bool ,
+    toc-level                 .code:n     =
+      \tl_set:Nn \l__exsheets_questions_toclevel_tl { #1 }
+      \tl_set:Nn \l__exsheets_solutions_toclevel_tl { #1 } ,
+    questions-toc-level       .tl_set:N   = \l__exsheets_questions_toclevel_tl ,
+    solutions-toc-level       .tl_set:N   = \l__exsheets_solutions_toclevel_tl
+  }
+\keys_set:nn { exsheets} { counter-format = qu. }
+
+% process package options:
+\ProcessKeysOptions { exsheets }
+
+% ----------------------------------------------------------------------------
+% points for exercises
+\bool_new:N       \l__exsheets_points_questions_default_bool
+\bool_set_false:N \l__exsheets_points_questions_default_bool
+\bool_new:N       \l__exsheets_parse_points_bool
+\bool_set_true:N  \l__exsheets_parse_points_bool
+\bool_new:N       \l__exsheets_points_name_bool
+\bool_set_true:N  \l__exsheets_points_name_bool
+\bool_new:N       \l__exsheets_points_separate_bonus_bool
+
+\fp_new:N         \g__exsheets_points_sum_fp
+\fp_new:N         \l__exsheets_points_default_fp
+\fp_set:Nn        \l__exsheets_points_default_fp { 1 }
+\fp_new:N         \l__exsheets_question_points_fp
+\fp_new:N         \g__exsheets_total_points_fp
+\fp_new:N         \g__exsheets_bonus_sum_fp
+\fp_new:N         \l__exsheets_question_bonus_fp
+\fp_new:N         \g__exsheets_total_bonus_fp
+
+\tl_new:N         \l__exsheets_points_name_tl
+\tl_set:Nn        \l__exsheets_points_name_tl { P. }
+\tl_new:N         \l__exsheets_points_name_plural_tl
+\tl_set:Nn        \l__exsheets_points_name_plural_tl { P. }
+\tl_new:N         \l__exsheets_bonus_name_tl
+\tl_set:Nn        \l__exsheets_bonus_name_tl { P. }
+\tl_new:N         \l__exsheets_bonus_name_plural_tl
+\tl_set:Nn        \l__exsheets_bonus_name_plural_tl { P. }
+\tl_new:N         \l__exsheets_points_number_format_tl
+\tl_new:N         \l__exsheets_bonus_number_format_tl
+\tl_new:N         \l__exsheets_points_pre_bonus_marker_tl
+\tl_set:Nn        \l__exsheets_points_pre_bonus_marker_tl { (+ }
+\tl_new:N         \l__exsheets_points_post_bonus_marker_tl
+\tl_set:Nn        \l__exsheets_points_post_bonus_marker_tl { ) }
+
+\cs_new_nopar:Npn \exsheets_set_points_name:n #1
+  {
+    \tl_if_in:nnTF { #1 } { / }
+      { \__exsheets_set_points_name_aux:nn #1 \q_stop }
+      { \__exsheets_set_points_name_aux:nn #1 / \q_stop }
+  }
+
+\cs_new_nopar:Npn \__exsheets_set_points_name_aux:nn #1/#2 \q_stop
+  {
+    \tl_set:Nn \l__exsheets_points_name_tl { #1 }
+    \tl_set:Nn \l__exsheets_points_name_plural_tl { #1#2 }
+  }
+
+\cs_new_nopar:Npn \exsheets_set_bonus_name:n #1
+  {
+    \tl_if_in:nnTF { #1 } { / }
+      { \__exsheets_set_bonus_name_aux:nn #1 \q_stop }
+      { \__exsheets_set_bonus_name_aux:nn #1 / \q_stop }
+  }
+
+\cs_new_nopar:Npn \__exsheets_set_bonus_name_aux:nn #1/#2 \q_stop
+  {
+    \tl_set:Nn \l__exsheets_bonus_name_tl { #1 }
+    \tl_set:Nn \l__exsheets_bonus_name_plural_tl { #1#2 }
+  }
+
+% FIXME: \fp_add will deprecate!
+\cs_new_nopar:Npn \exsheets_add_points:n #1
+  { \fp_gadd:Nn \g__exsheets_points_sum_fp { #1 } }
+\cs_generate_variant:Nn \exsheets_add_points:n { V }
+
+\cs_new_nopar:Npn \exsheets_add_bonus:n #1
+  { \fp_gadd:Nn \g__exsheets_bonus_sum_fp { #1 } }
+\cs_generate_variant:Nn \exsheets_add_bonus:n { V }
+
+\cs_new_nopar:Npn \exsheets@sum@of@points #1
+  { \fp_gset:Nn \g__exsheets_total_points_fp { #1 } }
+
+\cs_new_nopar:Npn \exsheets@sum@of@bonus #1
+  { \fp_gset:Nn \g__exsheets_total_bonus_fp { #1 } }
+
+\cs_new_nopar:Npn \exsheets_parse_points:n #1
+  {
+    \group_begin:
+      \tl_use:N \l__exsheets_points_number_format_tl
+        {
+          \bool_if:NTF \l__exsheets_parse_points_bool
+            { \exsheets_num:n { \fp_to_decimal:n { #1 } } }
+            { \use:n { \fp_to_decimal:n { #1 } } }
+        }
+    \group_end:
+  }
+\cs_generate_variant:Nn \exsheets_parse_points:n { V }
+
+\cs_new_nopar:Npn \exsheets_parse_bonus:n #1
+  {
+    \group_begin:
+      \tl_use:N \l__exsheets_bonus_number_format_tl
+        {
+          \bool_if:NTF \l__exsheets_parse_points_bool
+            { \exsheets_num:n { \fp_to_decimal:n { #1 } } }
+            { \use:n { \fp_to_decimal:n { #1 } } }
+        }
+    \group_end:
+  }
+\cs_generate_variant:Nn \exsheets_parse_bonus:n { V }
+
+\cs_new_nopar:Npn \exsheets_num:n #1
+  {
+    \group_begin:
+      \fp_set:Nn \l__exsheets_tmpa_tl { #1 }
+      \fp_to_tl:N \l__exsheets_tmpa_tl
+    \group_end:
+  }
+\cs_generate_variant:Nn \exsheets_num:n { x }
+
+\cs_new_nopar:Npn \exsheets_points_name:n #1
+  {
+    \bool_if:NT \l__exsheets_points_name_bool
+      {
+        \,
+        \hbox:n
+          {
+            \bool_if:NTF \l__exsheets_parse_points_bool
+              {
+                \tl_if_eq:nnTF { #1 } { ?? }
+                  { \tl_use:N \l__exsheets_points_name_plural_tl }
+                  {
+                    \fp_compare:nTF { #1 <=  1 }
+                      { \tl_use:N \l__exsheets_points_name_tl }
+                      { \tl_use:N \l__exsheets_points_name_plural_tl }
+                  }
+              }
+              { \tl_use:N \l__exsheets_points_name_plural_tl }
+          }
+      }
+  }
+\cs_generate_variant:Nn \exsheets_points_name:n { V }
+
+\cs_new_nopar:Npn \exsheets_bonus_name:n #1
+  {
+    \bool_if:NT \l__exsheets_points_name_bool
+      {
+        \,
+        \hbox:n
+          {
+            \bool_if:NTF \l__exsheets_parse_points_bool
+              {
+                \tl_if_eq:nnTF { #1 } { ?? }
+                  { \tl_use:N \l__exsheets_bonus_name_plural_tl }
+                  {
+                    \fp_compare:nTF { #1 <=  1 }
+                      { \tl_use:N \l__exsheets_bonus_name_tl }
+                      { \tl_use:N \l__exsheets_bonus_name_plural_tl }
+                  }
+              }
+              { \tl_use:N \l__exsheets_bonus_name_plural_tl }
+          }
+      }
+  }
+\cs_generate_variant:Nn \exsheets_bonus_name:n { V }
+
+\NewDocumentCommand \addpoints { sm }
+  {
+    \bool_if:NTF \l__exsheets_inside_question_bool
+      {
+        \exsheets_add_points:n { #2 }
+        \IfBooleanF { #1 } { \exsheets_print_points:n { #2 } }
+      }
+      { \msg_error:nnn { exsheets } { only-inside-question } { \addpoints } }
+  }
+
+\NewDocumentCommand \addbonus { sm }
+  {
+    \bool_if:NTF \l__exsheets_inside_question_bool
+      {
+        \exsheets_add_bonus:n { #2 }
+        \IfBooleanF { #1 } { \exsheets_print_bonus:n { #2 } }
+      }
+      { \msg_error:nnn { exsheets } { only-inside-question } { \addbonus } }
+  }
+
+\NewDocumentCommand \points { sm }
+  {
+    \IfBooleanTF { #1 }
+      { \exsheets_parse_points:n { #2 } }
+      { \exsheets_print_points:n { #2 } }
+  }
+
+\NewDocumentCommand \bonus { sm }
+  {
+    \IfBooleanTF { #1 }
+      { \exsheets_parse_bonus:n { #2 } }
+      { \exsheets_print_bonus:n { #2 } }
+  }
+
+\cs_new_nopar:Npn \exsheets_print_points:n #1
+  {
+    \exsheets_parse_points:n { #1 }
+    \exsheets_points_name:n { #1 }
+  }
+\cs_generate_variant:Nn \exsheets_print_points:n { V }
+
+\cs_new_nopar:Npn \exsheets_print_bonus:n #1
+  {
+    \exsheets_parse_bonus:n { #1 }
+    \exsheets_bonus_name:n { #1 }
+  }
+\cs_generate_variant:Nn \exsheets_print_bonus:n { V }
+
+\NewDocumentCommand \pointssum { s }
+  {
+    \IfBooleanTF { #1 }
+      { \exsheets_parse_points:n { \g__exsheets_total_points_fp } }
+      { \exsheets_print_points:n { \g__exsheets_total_points_fp } }
+  }
+
+\NewDocumentCommand \bonussum { s }
+  {
+    \IfBooleanTF { #1 }
+      { \exsheets_parse_bonus:n { \g__exsheets_total_bonus_fp } }
+      { \exsheets_print_bonus:n { \g__exsheets_total_bonus_fp } }
+  }
+
+\NewDocumentCommand \currentpointssum { s }
+  {
+    \IfBooleanTF { #1 }
+      { \exsheets_parse_points:n { \g__exsheets_points_sum_fp } }
+      { \exsheets_print_points:n { \g__exsheets_points_sum_fp } }
+  }
+
+\NewDocumentCommand \currentbonussum { s }
+  {
+    \IfBooleanTF { #1 }
+      { \exsheets_parse_bonus:n { \g__exsheets_bonus_sum_fp } }
+      { \exsheets_print_bonus:n { \g__exsheets_bonus_sum_fp } }
+  }
+
+\NewDocumentCommand \totalpoints { s }
+  {
+    \exsheets_totalpoints:
+    \IfBooleanF { #1 }
+      {
+        \bool_if:nT
+          {
+            \l__exsheets_points_separate_bonus_bool ||
+            \fp_compare_p:n { \g__exsheets_total_bonus_fp = 0 }
+          }
+          { \exsheets_points_name:n { \g__exsheets_total_points_fp } }
+      }
+    \exsheets_totalbonus:
+    \IfBooleanF { #1 }
+      {
+        \fp_compare:nF { \g__exsheets_total_bonus_fp = 0 }
+          {
+            \bool_if:NTF \l__exsheets_points_separate_bonus_bool
+              { \exsheets_bonus_name:n { \g__exsheets_total_bonus_fp } }
+              {
+                \exsheets_points_name:n
+                  { \g__exsheets_total_points_fp + \g__exsheets_total_bonus_fp }
+              }
+          }
+      }
+  }
+
+\exsheets_depr_cmd:nn { \sumpoints } { \totalpoints* }
+
+\cs_new_nopar:Npn \exsheets_totalpoints:
+  {
+    \bool_if:NTF \l__exsheets_parse_points_bool
+      {
+        \fp_compare:nTF { \g__exsheets_total_points_fp = 0 }
+          { ?? \, \exsheets_points_name:n { ?? } }
+          {
+            \exsheets_parse_points:n
+              { \g__exsheets_total_points_fp }
+          }
+      }
+      { \msg_warning:nn { exsheets } { totalpoints } }
+  }
+
+\cs_new_nopar:Npn \exsheets_totalbonus:
+  {
+    \bool_if:NT \l__exsheets_parse_points_bool
+      {
+        \fp_compare:nF { \g__exsheets_total_bonus_fp = 0 }
+          {
+            \tl_use:N \c_space_tl
+            \tl_use:N \l__exsheets_points_pre_bonus_marker_tl
+            \exsheets_parse_bonus:n
+              { \g__exsheets_total_bonus_fp }
+            \tl_use:N \l__exsheets_points_post_bonus_marker_tl
+          }
+      }
+  }
+
+\keys_define:nn { exsheets / points }
+  {
+    name                 .code:n     =
+      \exsheets_set_points_name:n { #1 }
+      \exsheets_set_bonus_name:n { #1 } ,
+    name-plural          .code:n     =
+      \tl_set:Nn \l__exsheets_points_name_plural_tl { #1 }
+      \tl_set:Nn \l__exsheets_bonus_name_plural_tl { #1 } ,
+    bonus-name           .code:n     = \exsheets_set_bonus_name:n { #1 } ,
+    bonus-plural         .tl_set:N   = \l__exsheets_bonus_name_plural_tl ,
+    pre-bonus            .tl_set:N   = \l__exsheets_points_pre_bonus_marker_tl ,
+    post-bonus           .tl_set:N   = \l__exsheets_points_post_bonus_marker_tl ,
+    use-name             .bool_set:N = \l__exsheets_points_name_bool ,
+    number-format        .tl_set:N   = \l__exsheets_points_number_format_tl ,
+    bonus-format         .tl_set:N   = \l__exsheets_bonus_number_format_tl ,
+    parse                .bool_set:N = \l__exsheets_parse_points_bool ,
+    separate-bonus       .bool_set:N = \l__exsheets_points_separate_bonus_bool
+  }
+
+% ----------------------------------------------------------------------------
+% Noten-Verteilung
+\prop_new:N \l__exsheets_relgrades_prop
+\fp_new:N   \l__exsheets_grade_round_fp
+\fp_zero:N  \l__exsheets_grade_round_fp
+\bool_new:N \l__exsheets_grades_half_bool
+
+\cs_new:Npn \__exsheets_fp_round_to_half:n #1
+  { round( 2*(#1),0)/2 }
+
+\cs_new:Npn \__exsheets_grades_round:n #1
+  { round ( #1 , \l__exsheets_grade_round_fp ) }
+
+\cs_new:Npn \__exsheets_grade_rounded:
+  {
+    \bool_if:NTF { \l__exsheets_grades_half_bool }
+      { \__exsheets_fp_round_to_half:n }
+      { \__exsheets_grades_round:n }
+    { \g__exsheets_total_points_fp * \l__exsheets_tmpa_fp }
+  }
+
+\cs_new:Npn \exsheets_strip_braces:N #1
+  { \exp_after:wN \__exsheets_strip_braces:w \exp_after:wN #1#1 \q_stop }
+\cs_new:Npn \__exsheets_strip_braces:w #1#2 \q_stop
+  { \tl_set:Nn #1 { #2 } }
+
+\cs_new:Npn \__exsheets_declare_relgrades:n #1
+  {
+    \clist_set:Nn \l__exsheets_tmpa_clist { #1 }
+    \clist_map_inline:Nn \l__exsheets_tmpa_clist
+      { \__exsheets_declare_relgrade:w ##1 \q_stop }
+  }
+
+\cs_new:Npn \__exsheets_declare_relgrade:w #1 = #2 \q_stop
+  {
+    \tl_set:Nn \l__exsheets_tmpa_tl { #1 }
+    \tl_set:Nn \l__exsheets_tmpb_tl { #2 }
+    \tl_trim_spaces:N \l__exsheets_tmpa_tl
+    \exsheets_strip_braces:N \l__exsheets_tmpa_tl
+    \tl_trim_spaces:N \l__exsheets_tmpb_tl
+    \exsheets_strip_braces:N \l__exsheets_tmpb_tl
+    \prop_put:NVV \l__exsheets_relgrades_prop
+      \l__exsheets_tmpa_tl
+      \l__exsheets_tmpb_tl
+  }
+
+\NewDocumentCommand \DeclareRelGrades { m }
+  { \__exsheets_declare_relgrades:n { #1 } }
+\@onlypreamble\DeclareRelGrades
+
+\cs_new:Npn \__exsheets_grade:nn #1#2
+  {
+    \prop_get:NnNTF \l__exsheets_relgrades_prop { #2 } \l__exsheets_tmpa_fp
+      {
+        \bool_if:NTF \l__exsheets_parse_points_bool
+          {
+            \exsheets_parse_points:n
+              { min( \__exsheets_grade_rounded: , \g__exsheets_total_points_fp ) }
+            \int_compare:nT { #1 = 1 }
+              {
+                \exsheets_points_name:n
+                  { min( \__exsheets_grade_rounded: , \g__exsheets_total_points_fp ) }
+              }
+          }
+          { \msg_warning:nnn { exsheets } { grade-parse } { #1 } \textbf{??} }
+      }
+      { \msg_warning:nnn { exsheets } { grade-missing } { #1 } \textbf{??} }
+  }
+
+\NewDocumentCommand \grade { sm }
+  {
+    \IfBooleanTF { #1 }
+      { \__exsheets_grade:nn { 0 } { #2 } }
+      { \__exsheets_grade:nn { 1 } { #2 } }
+  }
+
+\keys_define:nn { exsheets / grades }
+  {
+    round .fp_set:N   = \l__exsheets_grade_round_fp ,
+    half  .bool_set:N = \l__exsheets_grades_half_bool
+  }
+
+% ----------------------------------------------------------------------------
+% Aufgaben und Lösungen
+
+% Einteilung in Klassen und Themen
+\prop_new:N        \g__exsheets_questions_class_prop
+\prop_new:N        \g__exsheets_classes_prop
+\prop_new:N        \g__exsheets_classes_active_prop
+\prop_new:N        \g__exsheets_questions_topic_prop
+\prop_new:N        \g__exsheets_topics_prop
+\prop_new:N        \g__exsheets_topics_active_prop
+
+\bool_new:N        \g__exsheets_questions_use_bool
+\bool_gset_true:N  \g__exsheets_questions_use_bool
+\bool_new:N        \l__exsheets_questions_use_bool
+\bool_set_true:N   \l__exsheets_questions_use_bool
+\bool_new:N        \l__exsheets_questions_deactivate_bool
+\bool_new:N        \l__exsheets_questions_class_bool
+\bool_set_false:N  \l__exsheets_questions_class_bool
+\bool_new:N        \g__exsheets_use_classes_bool
+\bool_gset_false:N \g__exsheets_use_classes_bool
+\bool_new:N        \l__exsheets_class_active_bool
+\bool_new:N        \l__exsheets_questions_topic_bool
+\bool_set_false:N  \l__exsheets_questions_topic_bool
+\bool_new:N        \g__exsheets_use_topics_bool
+\bool_gset_false:N \g__exsheets_use_topics_bool
+\bool_new:N        \l__exsheets_topic_active_bool
+\bool_new:N        \l__exsheets_solutions_use_bool
+\bool_set_true:N   \l__exsheets_solutions_use_bool
+
+\tl_new:N          \l__exsheets_questions_class_tl
+\tl_new:N          \l__exsheets_questions_topic_tl
+
+\dim_new:N         \l__exsheets_questions_skip_below_dim
+\dim_set:Nn        \l__exsheets_questions_skip_below_dim { .5\baselineskip }
+\dim_new:N         \l__exsheets_solutions_skip_below_dim
+\dim_set:Nn        \l__exsheets_solutions_skip_below_dim { .5\baselineskip }
+
+\cs_new_nopar:Npn \exsheets_glue:N #1
+  { \cleaders \vbox:n {} \skip_vertical:N #1 }
+
+\keys_define:nn { exsheets }
+  {
+    use-classes .code:n =
+      {
+        \bool_gset_true:N \g__exsheets_use_classes_bool
+        \__exsheets_activate_classes:n { #1 }
+      } ,
+    use-topics .code:n =
+      {
+        \bool_gset_true:N \g__exsheets_use_topics_bool
+        \__exsheets_activate_topics:n { #1 }
+      } ,
+    skip-below .code:n =
+      \dim_set:Nn \l__exsheets_questions_skip_below_dim { #1 }
+      \dim_set:Nn \l__exsheets_solutions_skip_below_dim { #1 }
+  }
+
+\cs_new:Npn \__exsheets_activate_classes:n #1
+  {
+    \prop_gclear:N \g__exsheets_classes_active_prop
+    \seq_set_split:Nnn \l__exsheets_tmpa_seq { , } { #1 }
+    \seq_map_inline:Nn \l__exsheets_tmpa_seq
+      {
+        \prop_gput:Nnn \g__exsheets_classes_active_prop
+          { ##1 } { \__exsheets_dummy: }
+      }
+  }
+
+\cs_new:Npn \__exsheets_activate_topics:n #1
+  {
+    \prop_gclear:N \g__exsheets_topics_active_prop
+    \seq_set_split:Nnn \l__exsheets_tmpa_seq { , } { #1 }
+    \seq_map_inline:Nn \l__exsheets_tmpa_seq
+      {
+        \prop_gput:Nnn \g__exsheets_topics_active_prop
+          { ##1 } { \__exsheets_dummy: }
+      }
+  }
+
+\cs_new_nopar:Npn \__exsheets_questions_use_classes:
+  {
+    % is there a class provided?
+    \bool_if:NT \l__exsheets_questions_class_bool
+      {
+        % add class to questions property
+        \prop_gput:Nff \g__exsheets_questions_class_prop
+          { \int_to_arabic:n { \g__exsheets_questions_id_int } }
+          { \l__exsheets_questions_class_tl }
+        % add to classes list, if it's a new one
+        \prop_get:NoN \g__exsheets_classes_prop
+          { \l__exsheets_questions_class_tl }
+          \l__exsheets_tmpa_tl
+        \tl_if_eq:NNT \l__exsheets_tmpa_tl \q_no_value
+          {
+            \prop_gput:Nfn \g__exsheets_classes_prop
+              { \l__exsheets_questions_class_tl }
+              { \__exsheets_dummy: }
+          }
+      }
+    % are we using classes?
+    \bool_if:NT \g__exsheets_use_classes_bool
+      {
+        % is this question an active one?
+        \prop_get:NoN \g__exsheets_classes_active_prop
+          { \l__exsheets_questions_class_tl }
+          \l__exsheets_tmpa_tl
+        \tl_if_eq:NNTF \l__exsheets_tmpa_tl \q_no_value
+          {
+            \bool_set_false:N \l__exsheets_class_active_bool
+            \bool_set_false:N \l__exsheets_questions_print_bool
+          }
+          { \bool_set_true:N \l__exsheets_class_active_bool }
+      }
+  }
+
+\cs_new_nopar:Npn \__exsheets_questions_use_topics:
+  {
+    % is there a topic provided?
+    \bool_if:NT \l__exsheets_questions_topic_bool
+      {
+        % add topic to questions property
+        \prop_gput:Nff \g__exsheets_questions_topic_prop
+          { \int_to_arabic:n { \g__exsheets_questions_id_int } }
+          { \l__exsheets_questions_topic_tl }
+        % add to topics list, if it's a new one
+        \prop_get:NoN \g__exsheets_topics_prop
+          { \l__exsheets_questions_topic_tl }
+          \l__exsheets_tmpa_tl
+        \tl_if_eq:NNT \l__exsheets_tmpa_tl \q_no_value
+          {
+            \prop_gput:Nfn \g__exsheets_topics_prop
+              { \l__exsheets_questions_topic_tl }
+              { \__exsheets_dummy: }
+          }
+      }
+    % are we using topics?
+    \bool_if:NT \g__exsheets_use_topics_bool
+      {
+        % is this question an active one?
+        \prop_get:NoN \g__exsheets_topics_active_prop
+          { \l__exsheets_questions_topic_tl }
+          \l__exsheets_tmpa_tl
+        \tl_if_eq:NNTF \l__exsheets_tmpa_tl \q_no_value
+          {
+            \bool_set_false:N \l__exsheets_topic_active_bool
+            \bool_set_false:N \l__exsheets_questions_print_bool
+          }
+          { \bool_set_true:N \l__exsheets_topic_active_bool }
+      }
+    \int_set:Nn \l__exsheets_counter_qu_int { \arabic{question} }
+  }
+
+\cs_new_nopar:Npn \__exsheets_solutions_use_classes:
+  {
+    % are we using classes?
+    \bool_if:NT \g__exsheets_use_classes_bool
+      {
+        % is the question to this solution an active one?
+        % get question number from ID
+        \prop_get:NoN \g__exsheets_questions_id_prop
+          { \g__exsheets_questions_current_id_tl } \l__exsheets_tmpa_tl
+        % get question class from number
+        \prop_get:NoN \g__exsheets_questions_class_prop
+          { \l__exsheets_tmpa_tl } \l__exsheets_tmpb_tl
+        % test if class is active
+        \prop_get:NoN \g__exsheets_classes_active_prop
+          { \l__exsheets_tmpb_tl } \l__exsheets_tmpc_tl
+        \tl_if_eq:NNTF \l__exsheets_tmpc_tl \q_no_value
+          { \bool_set_false:N \l__exsheets_solutions_use_bool }
+          { \bool_set_true:N \l__exsheets_solutions_use_bool }
+      }
+  }
+
+\cs_new_nopar:Npn \__exsheets_solutions_use_topics:
+  {
+    % are we using topics?
+    \bool_if:NTF \g__exsheets_use_topics_bool
+      {
+        % is the question to this solution an active one?
+        % get question number from ID
+        \prop_get:NoN \g__exsheets_questions_id_prop
+          { \g__exsheets_questions_current_id_tl } \l__exsheets_tmpa_tl
+        % get question topic from number
+        \prop_get:NoN \g__exsheets_questions_topic_prop
+          { \l__exsheets_tmpa_tl } \l__exsheets_tmpb_tl
+        % test if topic is active
+        \prop_get:NoN \g__exsheets_topics_active_prop
+          { \l__exsheets_tmpb_tl } \l__exsheets_tmpc_tl
+        \tl_if_eq:NNT \l__exsheets_tmpc_tl \q_no_value
+          { \bool_set_false:N \l__exsheets_solutions_use_bool }
+      }
+      {
+        \bool_if:NF \g__exsheets_use_classes_bool
+          { \bool_set_true:N \l__exsheets_solutions_use_bool }
+      }
+  }
+
+% ----------------------------------------------------------------------------
+% die 'question' Umgebung
+\tl_new:N         \l__exsheets_questions_name_tl
+\tl_set:Nn        \l__exsheets_questions_name_tl { Question }
+\tl_new:N         \l__exsheets_exsheets_name_tl
+\tl_set:Nn        \l__exsheets_exsheets_name_tl { Exercise }
+
+\bool_new:N       \l__exsheets_questions_print_bool
+\bool_set_true:N  \l__exsheets_questions_print_bool
+\bool_new:N       \l__exsheets_inside_question_bool
+
+\int_new:N        \g__exsheets_questions_id_int
+\int_gzero:N      \g__exsheets_questions_id_int
+
+\NewEnviron { __exsheets_questions_internal: }
+  {
+    \cspreto { BODY } { \ifhmode \vspace*{0pt} \fi }
+    \csappto { BODY }
+      {
+        \par
+        \dim_compare:nNnT { \parskip } = { 0pt }
+          { \exsheets_glue:N \l__exsheets_questions_skip_below_dim }
+      }
+    \bool_if:nT
+      {
+        \l__exsheets_questions_print_bool &&
+        \g__exsheets_questions_use_bool &&
+        !\l__exsheets_questions_deactivate_bool
+      }
+      {
+        \__exsheets_save_number_in:N \g__exsheets_question_number_prop
+        \BODY
+      }
+  }
+
+\prop_new:N \g__exsheets_questions_id_prop
+
+\tl_new:N   \l__exsheets_questions_id_tl
+\tl_new:N   \g__exsheets_questions_current_id_tl
+\tl_new:N   \l__exsheets_title_tl
+
+\bool_new:N \l__exsheets_points_not_given_bool
+
+\cs_new:Npn \__exsheets_read_points:w #1+#2+#3 \q_stop
+  {
+    \tl_if_blank:nTF { #1 }
+      { \fp_zero:N \l__exsheets_question_points_fp }
+      { \fp_set:Nn \l__exsheets_question_points_fp { #1 } }
+    \tl_if_blank:nTF { #2 }
+      { \fp_zero:N \l__exsheets_question_bonus_fp }
+      {
+        \tl_if_blank:nTF { #3 }
+          { \fp_zero:N \l__exsheets_question_bonus_fp }
+          { \fp_set:Nn \l__exsheets_question_bonus_fp { #2 } }
+      }
+  }
+\cs_new:Npn \__exsheets_read_points:n #1
+  { \__exsheets_read_points:w #1++ \q_stop }
+
+\NewDocumentEnvironment { question } { og }
+  {
+    \bool_set_true:N \l__exsheets_inside_question_bool
+    \bool_if:NT \l__exsheets_questions_use_bool
+      { \bool_gset_true:N \g__exsheets_questions_use_bool }
+    % Optionen:
+    \IfNoValueF { #1 } { \keys_set:nn { exsheets / question } { #1 } }
+    % Punktevergabe:
+    \IfNoValueTF { #2 }
+      {
+        \__exsheets_read_points:n { 0 }
+        \bool_if:NT \l__exsheets_points_questions_default_bool
+          {
+            \fp_set_eq:NN
+              \l__exsheets_question_points_fp
+              \l__exsheets_points_default_fp
+          }
+      }
+      { \__exsheets_read_points:n { #2 } }
+    % ID:
+    \int_gincr:N \g__exsheets_questions_id_int
+    \tl_if_blank:VTF \l__exsheets_questions_id_tl
+      {
+        \prop_gput:NVV \g__exsheets_questions_id_prop
+          \g__exsheets_questions_id_int
+          \g__exsheets_questions_id_int
+        \tl_gset:Nx \g__exsheets_questions_current_id_tl
+          { \int_use:N \g__exsheets_questions_id_int }
+      }
+      {
+        \prop_gput:NVV \g__exsheets_questions_id_prop
+          \l__exsheets_questions_id_tl
+          \g__exsheets_questions_id_int
+        \tl_gset:Nx \g__exsheets_questions_current_id_tl
+          { \tl_use:N \l__exsheets_questions_id_tl }
+      }
+    % Auswahl der Frage:
+    \__exsheets_select_question:V \g__exsheets_questions_current_id_tl
+    \bool_if:nT
+      {
+        \g__exsheets_questions_use_bool &&
+        !\l__exsheets_questions_deactivate_bool
+      }
+      {
+        \__exsheets_questions_use_classes:
+        \__exsheets_questions_use_topics:
+        \bool_if:nT
+          {
+            ( \l__exsheets_class_active_bool && \l__exsheets_topic_active_bool ) ||
+            ( \l__exsheets_class_active_bool && !\g__exsheets_use_topics_bool ) ||
+            ( !\g__exsheets_use_classes_bool && \l__exsheets_topic_active_bool ) ||
+            ( !\g__exsheets_use_classes_bool && !\g__exsheets_use_topics_bool )
+          }
+          { \refstepcounter{question} }
+        \cs_if_exist:NT \chapter
+          { \int_set:Nn \l__exsheets_counter_ch_int { \arabic{chapter} } }
+        \int_set:Nn \l__exsheets_counter_sec_int { \arabic{section} }
+        \int_set:Nn \l__exsheets_counter_qu_int { \arabic{question} }
+        \bool_if:nT
+          {
+            (
+              \l__exsheets_points_questions_default_bool &&
+              \l__exsheets_parse_points_bool
+            ) ||
+            (
+              \l__exsheets_parse_points_bool &&
+              \l__exsheets_questions_print_bool
+            )
+          }
+          {
+            \exsheets_add_points:V \l__exsheets_question_points_fp
+            \exsheets_add_bonus:V  \l__exsheets_question_bonus_fp
+          }
+        \bool_if:NT \l__exsheets_questions_print_bool
+          {
+            \bool_if:NTF \l__exsheets_exam_bool
+              { \tl_set_eq:NN \l__exsheets_title_tl \l__exsheets_questions_name_tl }
+              { \tl_set_eq:NN \l__exsheets_title_tl \l__exsheets_exsheets_name_tl }
+            \__exsheets_use_heading:VVVnn
+              \l__exsheets_heading_instance_tl
+              \l__exsheets_title_tl
+              \l__exsheets_qu_counter_interpretation_tl
+              { \l__exsheets_question_points_fp }
+              { \l__exsheets_question_bonus_fp }
+          }
+      }
+    \__exsheets_questions_internal:
+  }
+  { \end__exsheets_questions_internal: }
+
+% current question number:
+\prop_new:N \g__exsheets_question_number_prop
+
+\cs_new_protected:Npn \exsheets@save@number #1#2
+  { \expandafter\global\expandafter\edef\csname exsheets@question@#1\endcsname{#2} }
+
+\cs_new:Npn \__exsheets_save_number_in:N #1
+  {
+    \bool_if:NTF \l__exsheets_print_number_bool
+      {
+        \cs_if_exist:NTF \thechapter
+          {
+            \prop_gput:Nfx #1
+              { \int_use:N \g__exsheets_questions_id_int }
+              { \arabic{chapter}-\arabic{section}-\arabic{question} }
+            \iow_now:Nx \@auxout
+              {
+                \exsheets@save@number
+                  { \g__exsheets_questions_current_id_tl }
+                  { \arabic{chapter}-\arabic{section}-\arabic{question} }
+              }
+          }
+          {
+            \prop_gput:Nfx #1
+              { \int_use:N \g__exsheets_questions_id_int }
+              { -\arabic{section}-\arabic{question} }
+            \iow_now:Nx \@auxout
+              {
+                \exsheets@save@number
+                  { \g__exsheets_questions_current_id_tl }
+                  { -\arabic{section}-\arabic{question} }
+              }
+          }
+      }
+      {
+        \cs_if_exist:NTF \thechapter
+          {
+            \prop_gput:Nfx #1
+              { \int_use:N \g__exsheets_questions_id_int }
+              { @@@\arabic{chapter}-\arabic{section}-\arabic{question} }
+            \iow_now:Nx \@auxout
+              {
+                \exsheets@save@number
+                  { \g__exsheets_questions_current_id_tl }
+                  { @@@\arabic{chapter}-\arabic{section}-\arabic{question} }
+              }
+          }
+          {
+            \prop_gput:Nfx #1
+              { \int_use:N \g__exsheets_questions_id_int }
+              { @@@-\arabic{section}-\arabic{question} }
+            \iow_now:Nx \@auxout
+              {
+                \exsheets@save@number
+                  { \g__exsheets_questions_current_id_tl }
+                  { @@@-\arabic{section}-\arabic{question} }
+              }
+          }
+      }
+  }
+
+\cs_new:Npn \__exsheets_restore_number_from_and_do:Nnn #1#2#3
+  {
+    \prop_get:NnN #1 { #2 } \l__exsheets_tmpc_tl
+    \tl_if_eq:NNF \l__exsheets_tmpc_tl \q_no_value
+      {
+        \exp_after:wN
+        \__exsheets_read_number:w \l__exsheets_tmpc_tl \q_stop
+        #3
+      }
+    % use \exsheets_read_counter_settings:V \l__exsheets_qu_counter_format_tl
+    % afterwards to print the number
+  }
+\cs_generate_variant:Nn \__exsheets_restore_number_from_and_do:Nnn { NV }
+
+\NewDocumentCommand \QuestionNumber { m }
+  { \exsheets_question_number:c { exsheets@question@#1 } }
+
+\cs_new:Npn \exsheets_question_number:N #1
+  {
+    \cs_if_exist:NTF #1
+      {
+        \exp_after:wN \__exsheets_get_question_number:w #1 \q_stop
+        \ReadCounterPatternFrom [ exsheets ] \l__exsheets_qu_counter_pattern_tl
+      }
+      { \textbf{??} }
+  }
+\cs_generate_variant:Nn \exsheets_question_number:N { c }
+
+\cs_new:Npn \__exsheets_get_question_number:w #1-#2-#3 \q_stop
+  {
+    \cs_if_exist:NT \thechapter
+      { \int_set:Nn \l__exsheets_counter_ch_int { #1 } }
+    \int_set:Nn \l__exsheets_counter_sec_int { #2 }
+    \int_set:Nn \l__exsheets_counter_qu_int { #3 }
+  }
+
+% ----------------------------------------------------------------------------
+% title of a question:
+\input { exsheets_headings.def }
+\bool_if:NT \l__exsheets_load_headings_bool
+  {
+    \RequirePackage { amssymb }
+    \input { exsheets_headings.cfg }
+  }
+% #1: instance
+% #2: title
+% #3: number
+% #4: points
+% #5: bonus
+\cs_new_nopar:Npn \__exsheets_use_heading:nnnnn #1#2#3#4#5
+  {
+    \IfInstanceExistTF { exsheets-heading } { #1 }
+      { \UseInstance { exsheets-heading } { #1 } }
+      {
+        \msg_warning:nnx { exsheets} { headings } { #1 }
+        \UseInstance { exsheets-heading } { block }
+      }
+    { #2 } { #3 } { #4 } { #5 }
+  }
+\cs_generate_variant:Nn \__exsheets_use_heading:nnnnn { V , VV , VVV }
+
+\bool_new:N       \l__exsheets_exam_bool
+\bool_set_false:N \l__exsheets_exam_bool
+\bool_new:N       \l__exsheets_questions_runin_bool
+\bool_set_false:N \l__exsheets_questions_runin_bool
+
+% options for the questions:
+\keys_define:nn { exsheets / question }
+  {
+    type            .choice: ,
+    type / exam     .code:n      =
+      \bool_set_true:N \l__exsheets_exam_bool ,
+    type / exercise .code:n      =
+      \bool_set_false:N \l__exsheets_exam_bool ,
+    name            .code:n      =
+      \tl_set:Nn \l__exsheets_exsheets_name_tl { #1 }
+      \tl_set:Nn \l__exsheets_questions_name_tl { #1 } ,
+    print           .bool_set:N  = \l__exsheets_questions_print_bool ,
+    print           .default:n   = true ,
+    ID              .tl_set:N    = \l__exsheets_questions_id_tl ,
+    class           .code:n      =
+      \bool_set_true:N \l__exsheets_questions_class_bool
+      \tl_set:Nn \l__exsheets_questions_class_tl { #1 } ,
+    topic           .code:n      =
+      \bool_set_true:N \l__exsheets_questions_topic_bool
+      \tl_set:Nn \l__exsheets_questions_topic_tl { #1 } ,
+    use             .choice: ,
+    use / true      .code:n      =
+      \bool_gset_true:N \g__exsheets_questions_use_bool
+      \bool_set_true:N  \l__exsheets_questions_use_bool ,
+    use / false     .code:n      =
+      \bool_gset_false:N \g__exsheets_questions_use_bool
+      \bool_set_false:N  \l__exsheets_questions_use_bool ,
+    use             .default:n   = true ,
+    skip-below      .dim_set:N   = \l__exsheets_questions_skip_below_dim
+  }
+
+% ----------------------------------------------------------------------------
+% using ``metadata'':
+\cs_new:Npn \__exsheets_declare_question_property:n #1
+  {
+    \prop_new:c { g__exsheets_question_property_#1_prop }
+    \keys_define:nn { question / meta }
+      { #1 .code:n = \__exsheets_question_set_property:nn { #1 } { ##1 } }
+  }
+
+\cs_new_eq:NN \exsheets_declare_question_property:n
+  \__exsheets_declare_question_property:n
+
+\NewDocumentCommand \DeclareQuestionProperty { m }
+  { \exsheets_declare_question_property:n { #1 } }
+\@onlypreamble\DeclareQuestionProperty
+
+\NewDocumentCommand \SetQuestionProperties { m }
+  { \exsheets_set_question_properties:n { #1 } }
+
+\cs_new:Npn \__exsheets_set_question_properties:n #1
+  {
+    \@bsphack
+      \bool_if:NTF \l__exsheets_inside_question_bool
+        { \keys_set:nn { question / meta } { #1 } }
+        {
+          \msg_error:nnn { exsheets } { only-inside-question }
+            { \SetQuestionProperties }
+        }
+    \@esphack
+  }
+
+\cs_new_eq:NN \exsheets_set_question_properties:n
+  \__exsheets_set_question_properties:n
+
+\cs_new:Npn \__exsheets_question_set_property:nn #1#2
+  {
+    \prop_gput:cVn { g__exsheets_question_property_#1_prop }
+      \g__exsheets_questions_current_id_tl { #2 }
+  }
+
+\NewDocumentCommand \GetQuestionProperty { mm }
+  { \exsheets_get_question_property:nn { #1 } { #2 } }
+
+\cs_new:Npn \exsheets_get_question_property:nn #1#2
+  {
+    \prop_if_in:cnT { g__exsheets_question_property_#1_prop } { #2 }
+      { \prop_get:cn { g__exsheets_question_property_#1_prop } { #2 } }
+  }
+
+% ----------------------------------------------------------------------------
+% debug-Info:
+\bool_new:N       \l__exsheets_questions_debug_bool
+\bool_set_false:N \l__exsheets_questions_debug_bool
+
+\colorlet { exsheetsdebugcolor } { yellow }
+
+\cs_new_nopar:Npn \exsheets_questions_debug:
+  {
+    \bool_if:nT { \l__exsheets_questions_debug_bool && \l__exsheets_inside_question_bool }
+      {
+        \colorbox { exsheetsdebugcolor }
+          {
+            \group_begin:
+              \normalfont\normalsize\normalcolor
+              ID:~
+              \tl_if_blank:VTF \l__exsheets_questions_id_tl
+                { \int_use:N \g__exsheets_questions_id_int }
+                { \tl_use:N \l__exsheets_questions_id_tl }
+              \bool_if:NT \l__exsheets_questions_class_bool
+                { ,~CLASS:~ \tl_use:N \l__exsheets_questions_class_tl }
+              \bool_if:NT \l__exsheets_questions_topic_bool
+                { ,~TOPIC:~ \tl_use:N \l__exsheets_questions_topic_tl }
+            \group_end:
+          }
+      }
+  }
+
+\NewDocumentCommand \DebugExSheets { G{true} }
+  { \use:c { bool_set_#1:N } \l__exsheets_questions_debug_bool }
+
+% ----------------------------------------------------------------------------
+% include random/selected questions from a file:
+\bool_new:N      \l__exsheets_select_questions_bool
+\bool_new:N      \l__exsheets_include_all_bool
+\bool_new:N      \l__exsheets_include_random_bool
+\bool_set_true:N \l__exsheets_include_all_bool
+\prop_new:N      \g__exsheets_selected_questions_prop
+\clist_new:N     \l__exsheets_include_id_clist
+\int_new:N       \l__exsheets_include_random_int
+\int_zero:N      \l__exsheets_include_random_int
+\tl_new:N        \l__exsheets_random_seed_tl
+\tl_set:Nn       \l__exsheets_random_seed_tl { -1 }
+\newcounter      {exsheets@include@random}
+
+\cs_new:Npn \file_input_if_exist:n #1
+  { \file_if_exist:nT { #1 } { \file_input:n { #1 } } }
+
+\cs_if_exist:NF \prop_length:N
+  {
+    \cs_new:Npn \prop_length:N #1
+      {
+        \prop_length:NN #1 \l__exsheets_tmpa_int
+        \int_use:N \l__exsheets_tmpa_int
+      }
+  }
+
+\cs_new:Npn \prop_length:NN #1#2
+  {
+    \int_zero:N #2
+    \prop_map_inline:Nn #1
+      { \int_incr:N #2 }
+  }
+
+\NewDocumentCommand \includequestions { om }
+  {
+    \group_begin:
+      \IfNoValueF { #1 }
+        { \keys_set:nn { exsheets / include } { #1 } }
+      \exsheets_include_questions:n { #2 }
+    \group_end:
+  }
+
+\cs_new:Npn \exsheets_include_questions:n #1
+  {
+    \seq_set_split:Nnn \l__exsheets_tmpa_seq { , } { #1 }
+    \seq_map_inline:Nn \l__exsheets_tmpa_seq
+      {
+        \bool_set_true:N \l__exsheets_questions_deactivate_bool
+        \file_input_if_exist:n { ##1 }
+        \bool_if:NT \l__exsheets_questions_debug_bool
+          {
+            \colorbox { exsheetsdebugcolor }
+              {
+                The~file~ ` \texttt { \tl_to_str:n { ##1 } } ' ~contains~
+                \prop_length:N \g__exsheets_selected_questions_prop \c_space_tl
+                questions.
+              }
+              \par
+          }
+        \bool_set_false:N \l__exsheets_questions_deactivate_bool
+        \__exsheets_select_question_random:n { ##1 }
+        \file_input_if_exist:n { ##1 }
+        \prop_gclear:N \g__exsheets_selected_questions_prop
+        \clist_clear:N \l__exsheets_include_id_clist
+      }
+  }
+
+% options:
+%  - IDs=<list of IDs>
+%  - all=true|false    % default when no option is given
+%  - random=<num>
+%  - seed=<num>        % set the seed for the random selection
+\keys_define:nn { exsheets / include }
+  {
+    all    .bool_set:N = \l__exsheets_include_all_bool ,
+    IDs    .code:n     =
+      \bool_set_false:N \l__exsheets_include_all_bool
+      \bool_set_false:N \l__exsheets_include_random_bool
+      \clist_set:Nn \l__exsheets_include_id_clist { #1 } ,
+    random .code:n     =
+      \bool_set_false:N \l__exsheets_include_all_bool
+      \bool_set_true:N  \l__exsheets_include_random_bool
+      \int_set:Nn \l__exsheets_include_random_int { #1 } ,
+    seed   .tl_set:N   = \l__exsheets_random_seed_tl
+  }
+
+\cs_new:Npn \__exsheets_select_question:n #1
+  {
+    \bool_if:NTF \l__exsheets_questions_deactivate_bool
+      {
+        \prop_gput:Nnn \g__exsheets_selected_questions_prop
+          { #1 } { \__exsheets_dummy: }
+      }
+      {
+        \bool_if:NF \l__exsheets_include_all_bool
+          { \__exsheets_select_question_by_id:n { #1 } }
+      }
+  }
+\cs_generate_variant:Nn \__exsheets_select_question:n { V }
+
+\cs_new:Npn \__exsheets_select_question_by_id:n #1
+  {
+%     \clist_show:N \l__exsheets_include_id_clist
+    \clist_if_in:NnTF
+      \l__exsheets_include_id_clist
+      { #1 }
+      { \bool_gset_true:N  \g__exsheets_questions_use_bool }
+      { \bool_gset_false:N \g__exsheets_questions_use_bool }
+  }
+
+\cs_new:Npn \__exsheets_select_question_random:n #1
+  {
+    \bool_if:NT \l__exsheets_include_random_bool
+      {
+        \prop_length:NN \g__exsheets_selected_questions_prop \l__exsheets_tmpa_int
+        \int_compare:nTF { \l__exsheets_include_random_int > \l__exsheets_tmpa_int }
+          {
+            \msg_warning:nnxxx { exsheets } { random }
+              { \int_use:N \l__exsheets_include_random_int }
+              { #1 }
+              { \int_use:N \l__exsheets_tmpa_int }
+            \bool_set_true:N \l__exsheets_include_all_bool
+          }
+          {
+            \group_begin:
+              \WarningsOff[lcg]
+              \tl_set:Nx \l__exsheets_tmpa_tl { \int_use:N \l__exsheets_tmpa_int }
+              \reinitrand
+                [
+                  first   = 1 ,
+                  last    = \l__exsheets_tmpa_tl ,
+                  counter = exsheets@include@random ,
+                  seed    = \l__exsheets_random_seed_tl ,
+                  quiet   = y
+                ]
+              \int_zero:N \l__exsheets_tmpa_int
+              \int_do_while:nNnn \l__exsheets_tmpa_int < \l__exsheets_include_random_int
+                {
+                  \rand
+                  \int_zero:N \l__exsheets_tmpb_int
+                  \prop_map_inline:Nn \g__exsheets_selected_questions_prop
+                    {
+                      \int_incr:N \l__exsheets_tmpb_int
+                      \int_compare:nT
+                        { \l__exsheets_tmpb_int = \value{exsheets@include@random} }
+                        {
+                          \tl_set_rescan:Nnn \l__exsheets_tmpa_tl {} { ##1 }
+                          \clist_if_in:NVTF \l__exsheets_include_id_clist \l__exsheets_tmpa_tl
+                            { \int_decr:N \l__exsheets_tmpb_int }
+                            {
+                              \clist_gput_right:NV \l__exsheets_include_id_clist
+                                \l__exsheets_tmpa_tl
+                              \prop_map_break:
+                            }
+                        }
+                    }
+                    \clist_remove_duplicates:N \l__exsheets_include_id_clist
+                    \int_set:Nn \l__exsheets_tmpa_int
+                      { \clist_count:N \l__exsheets_include_id_clist }
+                }
+              \WarningsOn[lcg]
+            \group_end:
+          }
+      }
+  }
+
+\NewDocumentCommand \PrintIfIncludeActiveTF { mm }
+  { \bool_if:NTF \l__exsheets_questions_deactivate_bool { #2 } { #1 } }
+
+\NewDocumentCommand \PrintIfIncludeActiveT { }
+  { \bool_if:NF \l__exsheets_questions_deactivate_bool }
+
+\NewDocumentCommand \PrintIfIncludeActiveF { }
+  { \bool_if:NT \l__exsheets_questions_deactivate_bool }
+
+% ----------------------------------------------------------------------------
+% die 'solution' Umgebung:
+\bool_new:N       \l__exsheets_solutions_print_bool
+\bool_set_false:N \l__exsheets_solutions_print_bool
+\bool_new:N       \l__exsheets_solutions_print_here_bool
+\bool_set_false:N \l__exsheets_solutions_print_here_bool
+\bool_new:N       \l__exsheets_solutions_print_section_bool
+\bool_set_false:N \l__exsheets_solutions_print_section_bool
+\bool_new:N       \l__exsheets_solutions_print_chapter_bool
+\bool_set_false:N \l__exsheets_solutions_print_chapter_bool
+\bool_new:N       \l__exsheets_solutions_print_all_bool
+\bool_set_false:N \l__exsheets_solutions_print_all_bool
+
+% \prop_new:N       \g__exsheets_question_number_prop
+\prop_new:N       \g__exsheets_solutions_content_prop
+\prop_new:N       \g__exsheets_solutions_questions_id_prop
+\prop_new:N       \g__exsheets_solutions_names_prop
+
+\tl_new:N         \l__exsheets_solutions_name_tl
+\tl_set:Nn        \l__exsheets_solutions_name_tl { Solution }
+
+\cs_new:Npn \__exsheets_save_solution:n #1
+  {
+    % save for later use
+    \prop_gput:Nff \g__exsheets_solutions_content_prop
+      { \int_use:N \g__exsheets_questions_id_int }
+      { #1 }
+    \prop_gput:Nff \g__exsheets_solutions_questions_id_prop
+      { \int_use:N \g__exsheets_questions_id_int }
+      { \tl_use:N \g__exsheets_questions_current_id_tl }
+    \prop_gput:Nff \g__exsheets_solutions_names_prop
+      { \int_use:N \g__exsheets_questions_id_int }
+      { \tl_use:N \l__exsheets_solutions_name_tl }
+    % print here
+    \bool_if:NT \l__exsheets_solutions_print_here_bool
+      {
+        \int_set:Nn \l__exsheets_counter_qu_int { \arabic{question} }
+        \__exsheets_solutions_name:VV
+          \l__exsheets_qu_counter_interpretation_tl
+          \l__exsheets_solutions_name_tl
+        \use:n { #1 } \par
+        \dim_compare:nNnT { \parskip } = { 0pt }
+          { \exsheets_glue:N \l__exsheets_solutions_skip_below_dim }
+      }
+  }
+\cs_generate_variant:Nn \prop_gput:Nnn { Nff,Nfx,Nfn,Nxx }
+\cs_generate_variant:Nn \__exsheets_save_solution:n { V }
+
+\NewEnviron { __exsheets_solution_int: }
+  {
+    \bool_if:nT { \g__exsheets_questions_use_bool && \l__exsheets_solutions_use_bool }
+      {
+        \cspreto { BODY } { \ifhmode \fi }% what's that good for?
+        \__exsheets_save_solution:V \BODY
+      }
+  }
+
+\bool_new:N       \l__exsheets_inside_solution_bool
+\bool_set_false:N \l__exsheets_inside_solution_bool
+
+\NewDocumentEnvironment { solution } { o }
+  {
+    \__exsheets_solutions_use_classes:
+    \__exsheets_solutions_use_topics:
+    \bool_if:NT \l__exsheets_questions_deactivate_bool
+      { \bool_set_false:N \l__exsheets_solutions_use_bool }
+    \bool_if:NT \l__exsheets_solutions_use_bool
+      {
+        \bool_set_true:N \l__exsheets_inside_solution_bool
+        \IfNoValueF { #1 } { \keys_set:nn { exsheets / solution } { #1 } }
+      }
+    \__exsheets_solution_int:
+  }
+  { \end__exsheets_solution_int: }
+
+\bool_new:N       \l__exsheets_solutions_runin_bool
+\bool_set_false:N \l__exsheets_solutions_runin_bool
+
+\cs_new_nopar:Npn \__exsheets_solutions_name:nn #1#2
+  {
+    \__exsheets_use_heading:Vnnnn
+      \l__exsheets_heading_instance_tl
+      { #2 } { #1 } { 0 } { 0 }
+  }
+\cs_generate_variant:Nn \__exsheets_solutions_name:nn { VV }
+
+\tl_new:N  \l__exsheets_solutions_name_style_tl
+\tl_set:Nn \l__exsheets_solutions_name_style_tl { \normalsize \bfseries }
+
+\cs_new:Npn \exsheets_solutions_name_style:n #1
+  { \l__exsheets_solutions_name_style_tl #1 }
+
+% ----------------------------------------------------------------------------
+% print solutions:
+% save section / chapter counter:
+\cs_new:Npn \__exsheets_exlabel:n #1
+  {
+    \@bsphack
+    \iow_now:Nx \@auxout
+      {
+        \token_to_str:N \newlabel { exse:#1 }
+          { { \arabic { section } } { \thepage } }
+      }
+    \cs_if_exist:NT \thechapter
+      {
+        \iow_now:Nx \@auxout
+          {
+            \token_to_str:N \newlabel { exch:#1 }
+              { { \arabic { chapter } } { \thepage } }
+          }
+      }
+    \@esphack
+  }
+
+% user command:
+\cs_new_eq:NN \exlabel \__exsheets_exlabel:n
+
+% adapt \label, maybe do this _after_ BeginDocument:
+\bool_if:NT \l__exsheets_solutions_by_ref_bool
+  {
+    \cs_new_eq:NN \__exsheets_saved_label:n \label
+    \cs_set:Npn \label #1
+      { \__exsheets_saved_label:n { #1 } \__exsheets_exlabel:n { #1 } }
+  }
+
+% this is like \ref from latex.ltx
+\cs_new:Npn \__exsheets_ref:n #1
+  {
+    \cs_if_exist:cTF { r@#1 }
+     { \__exsheets_ref_aux:n { #1 } }
+     {
+       \protect\G@refundefinedtrue
+       1
+       \@latex@warning{exlabel `#1' on page \thepage \space undefined}%
+     }
+  }
+
+\cs_new:Npn \__exsheets_ref_aux:n #1
+  { \exp_after:wN \exp_after:wN \exp_after:wN \use_i:nn \cs:w r@#1 \cs_end: }
+
+\cs_new_eq:NN \exref \__exsheets_ref:n
+
+% user command:
+\NewDocumentCommand \printsolutions { O{all} }
+  { \exsheets_print_solutions:n { #1 } }
+
+% internal command:
+\cs_new:Npn \exsheets_print_solutions:n #1
+  {
+    \group_begin:
+      \bool_set_true:N \l__exsheets_solutions_print_bool
+      \bool_set_true:N \l__exsheets_inside_solution_bool
+      \cs_set:Npn \S ##1 { \exref { exse:##1 } }
+      \cs_set:Npn \C ##1 { \exref { exch:##1 } }
+      \keys_set:nn { exsheets / exsheets_print_solutions } { #1 }
+    \group_end:
+  }
+
+\keys_define:nn { exsheets }
+  {
+    exsheets_print_solutions           .choice: ,
+    exsheets_print_solutions / section .code:n    =
+      { \exsheets_print_solutions_section:n { #1 } } ,
+    exsheets_print_solutions / chapter .code:n    =
+      { \exsheets_print_solutions_chapter:n { #1 } } ,
+    exsheets_print_solutions / all     .code:n    =
+      { \exsheets_print_solutions_all: } ,
+    exsheets_print_solutions / byID    .code:n    =
+      { \exsheets_print_solutions_byID:n { #1 } }
+  }
+
+\int_new:N \l__exsheets_counter_ch_int
+\int_new:N \l__exsheets_counter_sec_int
+\int_new:N \l__exsheets_counter_qu_int
+
+\cs_new:Npn \__exsheets_print_solution_if:nn #1#2
+  {
+    \exp_args:No \int_compare:nT { #2 }
+      {
+        \prop_get:NnN \g__exsheets_solutions_names_prop
+          { #1 } \l__exsheets_tmpa_tl
+        \prop_get:NnN \g__exsheets_solutions_content_prop
+          { #1 } \l__exsheets_tmpb_tl
+        \eSaveCounterPatternFrom [ exsheets ]
+          \l__exsheets_current_pattern_interpretation_tl
+          \l__exsheets_current_pattern_tl
+          \l__exsheets_qu_counter_pattern_tl
+        \exsheets_solutions_print_name:VV
+          \l__exsheets_current_pattern_tl
+          \l__exsheets_tmpa_tl
+        \tl_use:N \l__exsheets_tmpb_tl \par
+        \dim_compare:nNnT { \parskip } = { 0pt }
+          { \exsheets_glue:N \l__exsheets_solutions_skip_below_dim }
+      }
+  }
+
+% print by section:
+\cs_new:Npn \exsheets_print_solutions_section:n #1
+  {
+    \tl_if_blank:nTF { #1 }
+      {
+        \prop_map_inline:Nn \g__exsheets_question_number_prop
+          {
+            \prop_if_in:NnT \g__exsheets_solutions_names_prop { ##1 }
+              {
+                \__exsheets_print_solutions_section:nnn { ##1 } { ##2 }
+                  { \arabic{section} }
+              }
+          }
+      }
+      {
+        \clist_map_inline:nn { #1 }
+          { \__exsheets_print_solutions_by_section:w ##1-- \q_stop }
+      }
+  }
+
+\cs_new:Npn \__exsheets_print_solutions_by_section:w #1-#2-#3 \q_stop
+  {
+    % wenn #3=-, dann range-Input
+    \tl_if_eq:nnTF { #3 } { - }
+      {
+        \int_zero:N \l__exsheets_tmpa_int
+        \int_set_eq:NN \l__exsheets_tmpb_int \c_ten_thousand
+        \tl_if_blank:nF { #1 } { \int_set:Nn \l__exsheets_tmpa_int { #1 } }
+        \tl_if_blank:nF { #2 } { \int_set:Nn \l__exsheets_tmpb_int { #2 } }
+        \int_do_while:nn { \l__exsheets_tmpa_int <= \l__exsheets_tmpb_int }
+          {
+            \prop_map_inline:Nn \g__exsheets_question_number_prop
+              {
+                \prop_if_in:NnT \g__exsheets_solutions_names_prop { ##1 }
+                  {
+                    \__exsheets_print_solutions_section:nnn
+                      { ##1 } { ##2 } { \l__exsheets_tmpa_int }
+                  }
+              }
+            \int_incr:N \l__exsheets_tmpa_int
+          }
+      }
+      {
+        \prop_map_inline:Nn \g__exsheets_question_number_prop
+          {
+            \prop_if_in:NnT \g__exsheets_solutions_names_prop { ##1 }
+              { \__exsheets_print_solutions_section:nnn { ##1 } { ##2 } { #1 } }
+          }
+      }
+  }
+
+\cs_new:Npn \__exsheets_print_solutions_section:nnn #1#2#3
+  {
+    \__exsheets_read_number:w #2 \q_stop
+    \__exsheets_print_solution_if:nn { #1 }
+      { \l__exsheets_counter_sec_int = #3 }
+  }
+
+% print by chapter:
+\cs_new:Npn \exsheets_print_solutions_chapter:n #1
+  {
+    \tl_if_blank:nTF { #1 }
+      {
+        \prop_map_inline:Nn \g__exsheets_question_number_prop
+          {
+            \prop_if_in:NnT \g__exsheets_solutions_names_prop { ##1 }
+              {
+                \__exsheets_print_solutions_chapter:nnn { ##1 } { ##2 }
+                  { \arabic{chapter} }
+              }
+          }
+      }
+      {
+        \clist_map_inline:nn { #1 }
+          { \__exsheets_print_solutions_by_chapter:w ##1-- \q_stop }
+      }
+  }
+
+\cs_new:Npn \__exsheets_print_solutions_by_chapter:w #1-#2-#3 \q_stop
+  {
+    % wenn #3=-, dann range-Input
+    \tl_if_eq:nnTF { #3 } { - }
+      {
+        \int_zero:N \l__exsheets_tmpa_int
+        \int_set_eq:NN \l__exsheets_tmpb_int \c_ten_thousand
+        \tl_if_blank:nF { #1 } { \int_set:Nn \l__exsheets_tmpa_int { #1 } }
+        \tl_if_blank:nF { #2 } { \int_set:Nn \l__exsheets_tmpb_int { #2 } }
+        \int_do_while:nn { \l__exsheets_tmpa_int <= \l__exsheets_tmpb_int }
+          {
+            \prop_map_inline:Nn \g__exsheets_question_number_prop
+              {
+                \prop_if_in:NnT \g__exsheets_solutions_names_prop { ##1 }
+                  {
+                    \__exsheets_print_solutions_chapter:nnn
+                      { ##1 } { ##2 } { \l__exsheets_tmpa_int }
+                  }
+              }
+            \int_incr:N \l__exsheets_tmpa_int
+          }
+      }
+      {
+        \prop_map_inline:Nn \g__exsheets_question_number_prop
+          {
+            \prop_if_in:NnT \g__exsheets_solutions_names_prop { ##1 }
+              { \__exsheets_print_solutions_chapter:nnn { ##1 } { ##2 } { #1 } }
+          }
+      }
+  }
+
+\cs_new:Npn \__exsheets_print_solutions_chapter:nnn #1#2#3
+  {
+    \__exsheets_read_number:w #2 \q_stop
+    \__exsheets_print_solution_if:nn { #1 }
+      { \l__exsheets_counter_ch_int = #3 }
+  }
+
+% print all:
+\cs_new:Npn \exsheets_print_solutions_all:
+  {
+    \prop_map_function:NN \g__exsheets_question_number_prop
+      \__exsheets_print_solutions_all:nn
+  }
+
+\cs_new:Npn \__exsheets_print_solutions_all:nn #1#2
+  {
+    \__exsheets_read_number:w #2 \q_stop
+    \prop_get:NnNT \g__exsheets_solutions_names_prop
+      { #1 } \l__exsheets_tmpa_tl
+      {
+        \tl_set_eq:NN \l__exsheets_solutions_name_tl \l__exsheets_tmpa_tl
+        \prop_get:NnN \g__exsheets_solutions_content_prop
+          { #1 } \l__exsheets_tmpb_tl
+        \eSaveCounterPatternFrom [ exsheets ]
+          \l__exsheets_current_pattern_interpretation_tl
+          \l__exsheets_current_pattern_tl
+          \l__exsheets_qu_counter_pattern_tl
+        \exsheets_solutions_print_name:VV
+          \l__exsheets_current_pattern_tl
+          \l__exsheets_tmpa_tl
+        \tl_use:N \l__exsheets_tmpb_tl \par
+        \dim_compare:nNnT { \parskip } = { 0pt }
+          { \exsheets_glue:N \l__exsheets_solutions_skip_below_dim }
+      }
+  }
+
+% print by ID:
+\seq_new:N \l__exsheets_solutions_byID_seq
+\cs_new:Npn \exsheets_print_solutions_byID:n #1
+  {
+    \seq_set_split:Nnn \l__exsheets_solutions_byID_seq { , } { #1 }
+    \seq_clear:N \l__exsheets_tmpa_seq
+    \seq_map_inline:Nn \l__exsheets_solutions_byID_seq
+      {
+        \prop_get:NnN \g__exsheets_questions_id_prop
+          { ##1 } \l__exsheets_tmpa_tl
+        \seq_put_right:NV \l__exsheets_tmpa_seq \l__exsheets_tmpa_tl
+      }
+    \bool_if:NT \l__exsheets_print_byID_sorted_bool
+      {
+        \seq_sort:Nn \l__exsheets_tmpa_seq
+          {
+            \int_compare:nNnTF { ##1 } > { ##2 }
+              { \sort_reversed: }
+              { \sort_ordered: }
+          }
+      }
+    \seq_map_inline:Nn \l__exsheets_tmpa_seq
+      {
+        \group_begin:
+          \tl_if_eq:nnF { ##1 } { \q_no_value }
+            {
+              \prop_get:NnNT \g__exsheets_solutions_names_prop
+                { ##1 } \l__exsheets_tmpa_tl
+                {
+                  \prop_get:NnN \g__exsheets_solutions_content_prop
+                    { ##1 } \l__exsheets_tmpb_tl
+                  \__exsheets_restore_number_from_and_do:Nnn
+                    \g__exsheets_question_number_prop
+                    { ##1 }
+                    {
+                      \eSaveCounterPatternFrom [ exsheets ]
+                        \l__exsheets_current_pattern_interpretation_tl
+                        \l__exsheets_current_pattern_tl
+                        \l__exsheets_qu_counter_pattern_tl
+                      \exsheets_solutions_print_name:VV
+                        \l__exsheets_current_pattern_tl
+                        \l__exsheets_tmpa_tl
+                      \tl_use:N \l__exsheets_tmpb_tl \par
+                      \dim_compare:nNnT { \parskip } = { 0pt }
+                        { \exsheets_glue:N \l__exsheets_solutions_skip_below_dim }
+                    }
+                }
+            }
+        \group_end:
+      }
+  }
+
+\cs_new_nopar:Npn \__exsheets_read_number:w #1-#2-#3 \q_stop
+  {
+    \int_zero:N \l__exsheets_counter_ch_int
+    \int_zero:N \l__exsheets_counter_sec_int
+    \int_zero:N \l__exsheets_counter_qu_int
+    \tl_if_in:nnF { #1 } { @@@ }
+      {
+        \tl_if_blank:nF { #1 }
+          { \int_set:Nn \l__exsheets_counter_ch_int { #1 } }
+      }
+    \int_set:Nn \l__exsheets_counter_sec_int { #2 }
+    \int_set:Nn \l__exsheets_counter_qu_int { #3 }
+  }
+
+\cs_new_nopar:Npn \exsheets_solutions_print_name:nn #1#2
+  {
+    \tl_set_rescan:Nnn \l__exsheets_tmpa_tl
+      { \char_set_catcode_letter:N \@ } { #1 }
+    \tl_if_in:nnTF { #1 } { @@@ }
+      { \__exsheets_solutions_name:nn { } { #2 } }
+      { \__exsheets_solutions_name:nn { #1 } { #2  } }
+    \tex_penalty:D \c_ten_thousand
+  }
+\cs_generate_variant:Nn \exsheets_solutions_print_name:nn { VV }
+
+\cs_new:Npn \PrintSolutionsTF
+  { \bool_if:NTF \l__exsheets_solutions_print_bool }
+\cs_new:Npn \PrintSolutionsT
+  { \bool_if:NT \l__exsheets_solutions_print_bool }
+\cs_new:Npn \PrintSolutionsF
+  { \bool_if:NF \l__exsheets_solutions_print_bool }
+
+\bool_new:N      \l__exsheets_print_byID_sorted_bool
+\bool_set_true:N \l__exsheets_print_byID_sorted_bool
+
+\keys_define:nn { exsheets / solution }
+  {
+    print           .choice: ,
+    print / true    .code:n     =
+      {
+        \bool_set_true:N  \l__exsheets_solutions_print_bool
+        \bool_set_true:N  \l__exsheets_solutions_print_here_bool
+        \bool_set_false:N \l__exsheets_solutions_print_section_bool
+        \bool_set_false:N \l__exsheets_solutions_print_chapter_bool
+        \bool_set_false:N \l__exsheets_solutions_print_all_bool
+      } ,
+    print / false   .code:n     =
+      {
+        \bool_set_false:N \l__exsheets_solutions_print_bool
+      } ,
+    print           .default:n  = true ,
+    name            .tl_set:N   = \l__exsheets_solutions_name_tl ,
+    sorted          .bool_set:N = \l__exsheets_print_byID_sorted_bool ,
+    skip-below      .dim_set:N  = \l__exsheets_solutions_skip_below_dim
+  }
+
+% ----------------------------------------------------------------------------
+% the `tasks' list
+\input { exsheets_tasks.def }
+\bool_if:NT \l__exsheets_load_tasks_bool
+  {
+    \RequirePackage { amssymb }
+    \input { exsheets_tasks.cfg }
+  }
+
+% ----------------------------------------------------------------------------
+% the \blank{<words>} command
+\RequirePackage { ulem } \normalem
+\dim_new:N  \l__exsheets_blank_dim
+\box_new:N  \l__exsheets_blank_box
+\bool_new:N \l__exsheets_blank_width_bool
+
+\cs_new_nopar:Npn \exsheets_write_blank:n #1 { #1 }
+\cs_set_eq:NN \exsheets_write_blank:n \uline
+
+\keys_define:nn { exsheets / blank }
+  {
+    style          .choice: ,
+    style / line   .code:n =
+      { \cs_set_eq:NN \exsheets_write_blank:n \uline } ,
+    style / wave   .code:n =
+      { \cs_set_eq:NN \exsheets_write_blank:n \uwave } ,
+    style / dline  .code:n =
+      { \cs_set_eq:NN \exsheets_write_blank:n \uuline } ,
+    style / dotted .code:n =
+      { \cs_set_eq:NN \exsheets_write_blank:n \dotuline } ,
+    style / dashed .code:n =
+      { \cs_set_eq:NN \exsheets_write_blank:n \dashuline } ,
+    width          .code:n =
+      {
+        \bool_set_true:N \l__exsheets_blank_width_bool
+        \dim_set:Nn \l__exsheets_blank_dim { #1 }
+      }
+  }
+
+\NewDocumentCommand \blank { o m }
+  {
+    \group_begin:
+      \IfNoValueF { #1 } { \keys_set:nn { exsheets / blank } { #1 } }
+      \exsheets_blank:n { #2 }
+    \group_end:
+  }
+
+\cs_new:Npn \exsheets_blank:n #1
+  {
+    \box_clear:N \l__exsheets_blank_box
+    \hbox_set:Nn \l__exsheets_blank_box { #1 }
+    \bool_if:NTF \l__exsheets_inside_solution_bool
+      { \exsheets_write_blank:n { #1 } }
+      {
+        \bool_if:NTF \l__exsheets_blank_width_bool
+          { \__exsheets_blank_skip:N \l__exsheets_blank_dim }
+          { \__exsheets_blank_skip:n { \box_wd:N \l__exsheets_blank_box } }
+      }
+  }
+
+\cs_new:Npn \__exsheets_blank_skip:N #1
+  {
+    \dim_set:Nn \l__exsheets_tmpa_dim { #1 }
+    \dim_compare:nTF { \l__exsheets_tmpa_dim > 2em }
+      {
+        \exsheets_write_blank:n { \skip_horizontal:n { 1em } }
+        \dim_sub:Nn \l__exsheets_tmpa_dim { 2em }
+        \dim_do_while:nn { \l__exsheets_tmpa_dim > \c_zero_dim }
+          {
+            \tex_penalty:D \hyphenpenalty
+            \dim_compare:nTF { \l__exsheets_tmpa_dim < 1pt }
+              { \exsheets_write_blank:n { \skip_horizontal:N \l__exsheets_tmpa_dim } }
+              { \exsheets_write_blank:n { \skip_horizontal:n { 1pt } } }
+            \dim_sub:Nn \l__exsheets_tmpa_dim { 1pt }
+          }
+        \exsheets_write_blank:n { \skip_horizontal:n { 1em } }
+      }
+      { \exsheets_write_blank:n { \skip_horizontal:N \l__exsheets_tmpa_dim } }
+  }
+\cs_generate_variant:Nn \__exsheets_blank_skip:N { n }
+
+% the following code from Heiko Oberdieck in d.c.t.t served as inspiration
+% and basis for the \blank command:
+% 
+% \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
+
+% ----------------------------------------------------------------------------
+% SETUP
+\NewDocumentCommand \SetupExSheets { o m }
+  {
+    \IfNoValueTF { #1 }
+      { \keys_set:nn { exsheets } { #2 } }
+      { \keys_set:nn { exsheets / #1 } { #2 } }
+  }
+
+% ----------------------------------------------------------------------------
+% Sprachanpassungen
+\file_if_exist:nT { translations.sty }
+  {
+    \RequirePackage { translations }
+    % translation for the exercises
+    \DeclareTranslation { English  } { exsheets-exercise-name } { Exercise     }
+    \DeclareTranslation { British  } { exsheets-exercise-name } { Exercise     }
+    \DeclareTranslation { American } { exsheets-exercise-name } { Exercise     }
+    \DeclareTranslation { French   } { exsheets-exercise-name } { Exercise     }
+    \DeclareTranslation { German   } { exsheets-exercise-name } { \"Ubung      }
+    \DeclareTranslation { Italian  } { exsheets-exercise-name } { Esercizio    }
+    \DeclareTranslation { Spanish  } { exsheets-exercise-name } { Ejercicio    }
+    \DeclareTranslation { Catalan  } { exsheets-exercise-name } { Exercir      }
+    \DeclareTranslation { Turkish  } { exsheets-exercise-name } { Egzersiz     }
+    % translation for the question
+    \DeclareTranslation { English  } { exsheets-question-name } { Question     }
+    \DeclareTranslation { British  } { exsheets-question-name } { Question     }
+    \DeclareTranslation { American } { exsheets-question-name } { Question     }
+    \DeclareTranslation { French   } { exsheets-question-name } { Question     }
+    \DeclareTranslation { German   } { exsheets-question-name } { Aufgabe      }
+    \DeclareTranslation { Italian  } { exsheets-question-name } { Questione    }
+    \DeclareTranslation { Spanish  } { exsheets-question-name } { Pregunta     }
+    \DeclareTranslation { Catalan  } { exsheets-question-name } { Q\"uesti\'o  }
+    \DeclareTranslation { Turkish  } { exsheets-question-name } { Soru         }
+    % translation for the solutions
+    \DeclareTranslation { English  } { exsheets-solution-name } { Solution     }
+    \DeclareTranslation { British  } { exsheets-solution-name } { Solution     }
+    \DeclareTranslation { American } { exsheets-solution-name } { Solution     }
+    \DeclareTranslation { French   } { exsheets-solution-name } { Solution     }
+    \DeclareTranslation { German   } { exsheets-solution-name } { L\"osung     }
+    \DeclareTranslation { Italian  } { exsheets-solution-name } { Soluzione    }
+    \DeclareTranslation { Spanish  } { exsheets-solution-name } { Soluci\'on   }
+    \DeclareTranslation { Catalan  } { exsheets-solution-name } { Soluci\'o    }
+    \DeclareTranslation { Turkish  } { exsheets-solution-name } { \c C\"oz\"um }
+    % the actual translating
+    \tl_set:Nn \l__exsheets_exsheets_name_tl
+      { \GetTranslation { exsheets-exercise-name } }
+    \tl_set:Nn \l__exsheets_questions_name_tl
+      { \GetTranslation { exsheets-question-name } }
+    \tl_set:Nn \l__exsheets_solutions_name_tl
+      { \GetTranslation { exsheets-solution-name } }
+  }
+
+% ----------------------------------------------------------------------------
+% save total points in .aux file to make it available for \allpoints anywhere
+\AtEndDocument
+  {
+    \iow_now:Nx \@auxout
+      {
+        \exp_not:N \exsheets@sum@of@points
+          { \fp_eval:n { \g__exsheets_points_sum_fp } }
+        \exp_not:N \exsheets@sum@of@bonus
+          { \fp_eval:n { \g__exsheets_bonus_sum_fp } }
+      }
+  }
+
+% ----------------------------------------------------------------------------
+% load custom configuration
+\file_if_exist:nT { exsheets_configurations.cfg }
+  {
+    \AtBeginDocument
+      {
+        \msg_info:nn { exsheets } { loading-configurations }
+        \file_input:n { exsheets_configurations.cfg }
+      }
+  }
+
+\tex_endinput:D
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+HISTORY:
+2011/11/23 v0.1pre     - first upload to bitbucket and all changes until
+                         considered stable enough/ready to be called 0.1alpha.
+                         There'll be no further descriptions until then.
+2012/06/08 v0.1alpha   - first hopefully stable version
+2012/06/11 v0.1alpha-a - added headings instances, slightly rewritten
+                         `exercises-tasks' object and `tasks' environment
+2012/06/11 v0.1alpha-b - added `multiplechoice' instance and `load-tasks' option
+2012/06/12 v0.1alpha-c - renamed from `exercises' into `ExSheets'
+2012/06/15 v0.1alpha-d - added more flexible solution printing method
+2012/06/15 v0.1beta    - filled in some blanks in the documentation, now we need
+                         some testing!
+2012/09/07 v0.1beta-a  - adjustments to the updated l3kernel
+2012/09/08 v0.1beta-b  - sort solutions printed with the `byID' key
+2012/09/16 v0.1beta-c  - renamed option `questions-counter-format' into
+                         `counter-format'
+2012/09/19 v0.1beta-d  - added `topic' key, provide \includequestions with options
+                         `all' and `IDs'
+2012/09/24 v0.1beta-e  - added question properties and improved random question
+                         selection
+2012/09/27 v0.1        - added two headings instances, new option `headings-format'
+                       - small changes in the definition of the `exsheets-headings'
+                         object
+                       - preliminary version of totoc options. Unfortunatly
+                         \exsheets@recover@number is not expandable => no
+                         hyperref support
+2012/09/30 v0.2beta    - version numbering gone crazy! this will now stay 0.2beta
+                         until upload to CTAN (v0.2)
+                       - integrated packages `translations' and `cntformats':
+                         trnslt: provide expandable version of `translator's
+                           \translate
+                         cntfmts: outsourced previous counter formatting commands;
+                           should now be usable in other packages, too, and
+                           simplified definitions in `ExSheets'
+                       - thanks to `translations' and `cntformats' the `totoc'
+                         option now works with `hyperref'
+2012/10/05 v0.2        - removed \sumpoints and moved the functionality to
+                         \totalpoints*
+                       - changed meaning of \addpoints* and moved former
+                         functionality to \points
+                       - added bonus point functionality including \addbonus,
+                         \bonus, \bonussum, \pointssum, \currentpointssum,
+                         \currentbonussum
+                       - added grades distribution
+                       - `translations' got \LoadDictionary and \LoadDictionaryFor
+                         added and loads of languages defined.
+2012/10/05 v0.2a       - resolved bug in saving and recovering question number
+                         using \exsheets@save@number and \QuestionNumber
+2012/10/08 v0.2b       - improved the reference to chapter/solution numbers
+                         in \printsolutions
+                       - resolved bug in \printsolutions introduced in the last
+                         update
+                       - upload to CTAN
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% TODO:
+- points/decimal-marker, points/frac (?), points/format (?,im interface)
\ No newline at end of file
-- 
cgit v1.2.3

