From d2e50e76ef7e64efa460c918c4c751262c063476 Mon Sep 17 00:00:00 2001 From: Norbert Preining 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= +% - all=true|false % default when no option is given +% - random= +% - seed= % 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{} 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