diff options
author | Karl Berry <karl@freefriends.org> | 2017-05-19 21:12:44 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2017-05-19 21:12:44 +0000 |
commit | b6a9d061f27e2822b7de379c66c030d9ea0e8fb3 (patch) | |
tree | 7a9b6e488d40920bb153db1f0e7be10f8df3935a /Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex | |
parent | 910f589664407d620dc2a30c7b1de1a10e715df1 (diff) |
xsim (19may17)
git-svn-id: svn://tug.org/texlive/trunk@44430 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex | 515 |
1 files changed, 515 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex b/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex new file mode 100644 index 00000000000..59434ec3071 --- /dev/null +++ b/Master/texmf-dist/tex/latex/xsim/xsim.exercises.code.tex @@ -0,0 +1,515 @@ +% ---------------------------------------------------------------------------- +% the XSIM package - exercises module +% +% eXercise Sheets IMproved +% +% ---------------------------------------------------------------------------- +% Clemens Niederberger +% Web: https://github.com/cgnieder/xsim +% E-Mail: contact@mychemistry.eu +% ---------------------------------------------------------------------------- +% Copyright 2017 Clemens Niederberger +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is Clemens Niederberger. +% ---------------------------------------------------------------------------- +% If you have any ideas, questions, suggestions or bugs to report, please +% feel free to contact me. +% ---------------------------------------------------------------------------- +\XSIMmodule{exercises}{main exercises definitions} + +\xsim_load_modules:n + { + base, properties, environments, templates, solutions, tags, goals, + collections + } + +\seq_new:N \l__xsim_parameters_seq +\seq_new:N \l__xsim_fixed_parameters_seq +\seq_new:N \l__xsim_mandatory_parameters_seq +\prop_new:N \g__xsim_exercises_prop +\int_gzero_new:N \g_xsim_id_int +\int_gzero_new:N \g_xsim_max_id_int +\tl_new:N \l_xsim_current_id_tl +\tl_new:N \g_xsim_exercise_id_tl +\tl_new:N \ExerciseID +\bool_new:N \l____xsim_print_bool + +% ---------------------------------------------------------------------------- + +\msg_new:nnn {xsim} {parameter-fixed} + { + You~ tried~ to~ set~ parameter~ `#2'~ for~ type~ `#1'~ \msg_line_context: + . ~ However,~ parameter~ `#2'~ is~ a~ fixed~ parameter~ that~ already~ + has~ been~ set~ for~ type~ `#1'.~ Its~ value~ can't~ be~ changed! + } + +\msg_new:nnn {xsim} {type-exists} + { + You~ try~ to~ define~ exercise~ type~ `#1'~ \msg_line_context: .~ + However,~ the~ exercise~ type~ `#1'~ already~ exists. + } + +\msg_new:nnn {xsim} {mandatory-parameter} + { + You~ forget~ to~ set~ the~ mandatory~ parameter~ `#1'~ when~ defining~ + exercise~ type~ `#2'. + } + +% ---------------------------------------------------------------------------- + +\xsim_new_list:n {types} + +% #1: true|false (fixed parameter) +% #2: true|false (mandatory parameter) +% #3: parameter name +\cs_new_protected:Npn \xsim_declare_parameter:nnn #1#2#3 + { + \xsim_verbose:n { Declaring~ parameter~ `#3'. } + \xsim_if_parameter_exist:nF {#3} + { + \seq_put_right:Nn \l__xsim_parameters_seq {#3} + \bool_if:cT {c_#1_bool} + { \seq_put_right:Nn \l__xsim_fixed_parameters_seq {#3} } + \bool_if:cT {c_#2_bool} + { \seq_put_right:Nn \l__xsim_mandatory_parameters_seq {#3} } + } + } + +\cs_new_protected:Npn \xsim_remove_parameter:n #1 + { + \xsim_verbose:n { Removing~ parameter~ `#1'. } + \xsim_if_parameter_exist:nT {#1} + { \seq_remove_all:Nn \l__xsim_parameters_seq {#1} } + } + +\prg_new_conditional:Npnn \xsim_if_parameter_exist:n #1 {p,T,F,TF} + { + \seq_if_in:NnTF \l__xsim_parameters_seq {#1} + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \xsim_if_parameter_exist:nT {x} + +\prg_new_conditional:Npnn \xsim_if_parameter_fixed:n #1 {p,T,F,TF} + { + \seq_if_in:NnTF \l__xsim_fixed_parameters_seq {#1} + { \prg_return_true: } + { \prg_return_false: } + } + +% #1: type +% #2: csv list of parameters +\cs_new_protected:Npn \xsim_set_parameters:nn #1#2 + { + \clist_map_inline:nn {#2} + { + \seq_set_split:Nnx \l__xsim_tmpa_seq {=} { \tl_trim_spaces:n {##1} } + \xsim_set_parameter:nxx {#1} + { \seq_item:Nn \l__xsim_tmpa_seq {1} } + { \seq_item:Nn \l__xsim_tmpa_seq {2} } + } + } +\cs_generate_variant:Nn \xsim_set_parameters:nn {nx} + +% #1: type +\cs_new_protected:Npn \xsim_check_mandatory_parameters:n #1 + { + \seq_map_inline:Nn \l__xsim_mandatory_parameters_seq + { + \xsim_if_parameter:nnF {#1} {##1} + { \msg_error:nnnn {xsim} {mandatory-parameter} {##1} {#1} } + } + } + +% #1: type +\prg_new_conditional:Npnn \xsim_if_type:n #1 {p,T,F,TF} + { + \prop_if_exist:cTF {l__xsim_#1_type_parameters_prop} + { \prg_return_true: } + { \prg_return_false: } + } + +% #1: type +% #2: parameter +% #3: value +\cs_new_protected:Npn \xsim_set_parameter:nnn #1#2#3 + { + \xsim_if_parameter_exist:nT {#2} + { + \xsim_if_parameter_fixed:nTF {#1} + { + \xsim_if_parameter:nnTF {#1} {#2} + { + \msg_warning:nnnn {xsim} {parameter-fixed} {#1} {#2} + \xsim_verbose:n + { + Not~ setting~ already~ set~ and~ fixed~ parameter~ `#2'~ + for~ type~ `#1'. + } + } + { + \xsim_verbose:n + { Setting~ parameter~ `#2'~ for~ type~ `#1'~ to~ `#3'. } + \prop_put:cnn {l__xsim_#1_type_parameters_prop} {#2} {#3} + } + } + { + \xsim_verbose:n + { Setting~ parameter~ `#2'~ for~ type~ `#1'~ to~ `#3'. } + \prop_put:cnn {l__xsim_#1_type_parameters_prop} {#2} {#3} + } + } + } +\cs_generate_variant:Nn \xsim_set_parameter:nnn {nnx,nxx} + +% #1: type +% #2: parameter +\cs_new:Npn \xsim_get_parameter:nn #1#2 + { \prop_item:cn {l__xsim_#1_type_parameters_prop} {#2} } +\cs_generate_variant:Nn \xsim_get_parameter:nn {o} + +\prg_new_conditional:Npnn \xsim_if_parameter:nn #1#2 {p,T,F,TF} + { + \prop_if_in:cnTF {l__xsim_#1_type_parameters_prop} {#2} + { \prg_return_true: } + { \prg_return_false: } + } + +% ---------------------------------------------------------------------------- +% inside the argument `#1' refers to the type +\cs_new_protected:Npn \xsim_foreach_exercise_type:n #1 + { \xsim_foreach_new_list_entry:nn {types} {#1} } + +\cs_new_protected:Npn \xsim_foreach_exercise_id:n #1 + { \int_step_inline:nnnn {1} {1} { \g_xsim_max_id_int } {#1} } + +\cs_new:Npn \__xsim_loop_item:nnnnnn #1#2#3#4#5#6 {} +\cs_generate_variant:Nn \__xsim_loop_item:nnnnnn {VVxxxx} + +% #1: type +% #2: id +% #3: boolean property +\cs_new:Npn \__xsim_deliver_exercise_details:nnn #1#2#3 + { + \xsim_if_in_list:nnT {#3} {#1-#2=={true}} + { + \tl_set_rescan:Nnx \l__xsim_tmpa_tl {} {#1} + \tl_set_rescan:Nnx \l__xsim_tmpb_tl {} {#2} + \__xsim_loop_item:VVxxxx + \l__xsim_tmpa_tl % #1 + \l__xsim_tmpb_tl % #2 + { \xsim_get_property:nnn {#1} {#2} {counter} } % #3 + { \xsim_get_property:nnn {#1} {#2} {subtitle} } % #4 + { \xsim_get_property:nnn {#1} {#2} {points} } % #5 + { \xsim_get_property:nnn {#1} {#2} {bonus-points} } % #6 + } + } + +% #1: boolean property +% #2: loop code +\xsim_define_loop_macro:Nnn \xsim_foreach_exercise_type_id:nn + {nnnnnn} + { + \xsim_foreach_exercise_type:n + { + \xsim_foreach_exercise_id:n + { \__xsim_deliver_exercise_details:nnn {##1} {####1} {#1} } + } + } + +\xsim_define_loop_macro:Nnn \xsim_foreach_exercise_id_type:nn + {nnnnnn} + { + \xsim_foreach_exercise_id:n + { + \xsim_foreach_exercise_type:n + { \__xsim_deliver_exercise_details:nnn {####1} {##1} {#1} } + } + } + +\cs_new_protected:Npn \xsim_define_exercise_type_variables:n #1 + { + \prop_new:c {l__xsim_#1_type_parameters_prop} + \bool_new:c {l__xsim_#1_solution_print_bool} + \bool_new:c {l__xsim_#1_exercise_print_bool} + \bool_new:c {l__xsim_#1_exercise_use_bool} + } + +\cs_new_protected:Npn \xsim_define_counters:n #1 + { + \xsim_verbose:n { Defining~ counters~ for~ new~ exercise~ type~ `#1' } + \cs_if_exist:cF { c@ \xsim_get_parameter:nn {#1} {counter} } + { \newcounter { \xsim_get_parameter:nn {#1} {counter} } } + \cs_if_exist:cF { c@ \xsim_get_parameter:nn {#1} {solution-counter} } + { \newcounter { \xsim_get_parameter:nn {#1} {solution-counter} } } + \cs_if_exist:cF { c@ number of \xsim_get_parameter:nn {#1} {exercise-env} s } + { \newcounter { number of \xsim_get_parameter:nn {#1} {exercise-env} s } } + } + +% #1: type +% #2: id +\cs_new_protected:Npn \xsim_step_exercise_counter:nn #1#2 + { + \refstepcounter { \xsim_get_parameter:nn {#1} {counter} } + \xsim_set_properties:nnx {#1} {#2} + { + counter = \use:c { the \xsim_get_parameter:nn {#1} {counter} } , + counter-value = \arabic { \xsim_get_parameter:nn {#1} {counter} } + } + } +\cs_generate_variant:Nn \xsim_step_exercise_counter:nn {nV} + +% #1: type +\cs_new_protected:Npn \xsim_declare_exercise_type:nn #1#2 + { + \xsim_if_type:nTF {#1} + { \msg_error:nnn {xsim} {type-exists} {#1} } + { + \xsim_verbose:n { Declaring~ new~ exercise~ type~ `#1'. } + \xsim_define_exercise_type_variables:n {#1} + \xsim_add_to_list:nn {types} {#1} + \xsim_set_parameters:nn {#1} {#2} + \xsim_set_parameter:nnx {#1} {number} + { number of \xsim_get_parameter:nn {#1} {exercise-env} s } + \xsim_check_mandatory_parameters:n {#1} + \xsim_if_parameter:nnF {#1} {counter} + { + \xsim_set_parameters:nx {#1} + { counter = \xsim_get_parameter:nn {#1} {exercise-env} } + } + \xsim_if_parameter:nnF {#1} {solution-counter} + { + \xsim_set_parameters:nx {#1} + { solution-counter = \xsim_get_parameter:nn {#1} {solution-env} } + } + \xsim_define_counters:n {#1} + \xsim_verbose:n { Defining~ options~ for~ new~ exercise~ type~ `#1' } + \keys_define:nx {xsim} + { + \xsim_get_parameter:nn {#1} {solution-env} / print + .bool_set:N = \exp_not:c {l__xsim_#1_solution_print_bool} , + \xsim_get_parameter:nn {#1} {solution-env} / print + .initial:n = false , + \xsim_get_parameter:nn {#1} {exercise-env} / print + .bool_set:N = \exp_not:c {l__xsim_#1_exercise_print_bool} , + \xsim_get_parameter:nn {#1} {exercise-env} / print + .initial:n = true , + \xsim_get_parameter:nn {#1} {exercise-env} / use + .bool_set:N = \exp_not:c {l__xsim_#1_exercise_use_bool} , + \xsim_get_parameter:nn {#1} {exercise-env} / use + .initial:n = true , + \xsim_get_parameter:nn {#1} {exercise-env} / within .code:n = + \exp_not:N \@addtoreset { \xsim_get_parameter:nn {#1} {counter} } {####1}, + \xsim_get_parameter:nn {#1} {exercise-env} / the-counter .code:n = + \cs_set:cpn {the \xsim_get_parameter:nn {#1} {counter} } {####1} , + \xsim_get_parameter:nn {#1} {exercise-env} / template + .code:n = \xsim_set_parameter:nnn {#1} {exercise-template} {####1} , + \xsim_get_parameter:nn {#1} {solution-env} / template + .code:n = \xsim_set_parameter:nnn {#1} {solution-template} {####1} , + \xsim_get_parameter:nn {#1} {exercise-env} / name + .code:n = \xsim_set_parameter:nnn {#1} {exercise-name} {####1} , + \xsim_get_parameter:nn {#1} {solution-env} / name + .code:n = \xsim_set_parameter:nnn {#1} {solution-name} {####1} + } + \xsim_new_environment:nn {#1} {exercise} + \xsim_new_environment:nn {#1} {solution} + } + } + +% #1: type +% #2: id +\prg_new_conditional:Npnn \xsim_if_exercise_exists:nn #1#2 {T,F,TF} + { + \__xsim_set_file_signature:nnn {#1} {#2} {exercise} + \file_if_exist:VTF \l__xsim_file_path_and_name_tl + { \prg_return_true: } + { \prg_return_false: } + } +\cs_generate_variant:Nn \xsim_if_exercise_exists:nnT {VV} + +% #1: type +% #2: options +\cs_new_protected:Npn \xsim_start_exercise:nn #1#2 + { + \xsim_if_insert_mode:F + { + \int_gincr:N \g_xsim_id_int + \int_compare:nF { \g_xsim_max_id_int > \g_xsim_id_int } + { \int_gset_eq:NN \g_xsim_max_id_int \g_xsim_id_int } + \xsim_set_properties:nxx {#1} { \int_use:N \g_xsim_id_int } + { + print = true , + use = true , + \exp_not:n {#2} , + id = \int_use:N \g_xsim_id_int , + section-value = \arabic{section} , + section = \thesection , + page-value = \arabic{page} , + page = \thepage , + used = false + } + \xsim_if_property_exist:nT {chapter} + { + \xsim_set_properties:nxx {#1} { \int_use:N \g_xsim_id_int } + { + chapter-value = \arabic{chapter} , + chapter = \thechapter + } + } + \tl_gclear:N \g_xsim_exercise_id_tl + \xsim_gsave_property:nxnN {#1} { \int_use:N \g_xsim_id_int } {id} + \g_xsim_exercise_id_tl + \tl_gset_eq:NN \ExerciseID \g_xsim_exercise_id_tl + \tl_gset:Nn \ExerciseType {#1} + \xsim_verbose:x + { + Starting~ exercise~ type~ `#1' with~ id~ + ` \g_xsim_exercise_id_tl '. + } + \xsim_exercise_if_use:nVTF {#1} \g_xsim_exercise_id_tl + { + \stepcounter { \xsim_get_parameter:nn {#1} {number} } + % don't step if in active collection: + \xsim_if_collections_active:TF + { + \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl + {print} + {false} + } + { + \xsim_step_exercise_counter:nV {#1} \g_xsim_exercise_id_tl + \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl + {used} + {true} + } + \xsim_set_property:nVnn {#1} \g_xsim_exercise_id_tl + {use} + {true} + \xsim_update_goals:nV {#1} \g_xsim_exercise_id_tl + } + { + \xsim_set_properties:nVn {#1} \g_xsim_exercise_id_tl + { use = false , print = false } + } + \xsim_update_collections:nV {#1} \g_xsim_exercise_id_tl + } + } + +\cs_new_protected:Npn \xsim_stop_exercise:n #1 {} + +% ---------------------------------------------------------------------------- +% #1: type +% #2: id +\prg_new_protected_conditional:Npnn \xsim_exercise_if_print:nn #1#2 {T,F,TF} + { + \xsim_if_boolean_property:nnnTF {#1} {#2} {print!} + { \prg_return_true: } + { + \bool_set_true:N \l____xsim_print_bool + \bool_if:cF {l__xsim_#1_exercise_print_bool} + { \bool_set_false:N \l____xsim_print_bool } + \xsim_if_tagged:nnF {#1} {#2} + { \bool_set_false:N \l____xsim_print_bool } + \xsim_if_boolean_property:nnnF {#1} {#2} {print} + { \bool_set_false:N \l____xsim_print_bool } + \bool_if:NTF \l____xsim_print_bool + { \prg_return_true: } + { \prg_return_false: } + } + } +\cs_generate_variant:Nn \xsim_exercise_if_print:nnT {nV} +\cs_generate_variant:Nn \xsim_exercise_if_print:nnTF {nV} + +% #1: type +% #2: id +\prg_new_protected_conditional:Npnn \xsim_exercise_if_use:nn #1#2 {T,F,TF} + { + \xsim_if_boolean_property:nnnTF {#1} {#2} {use!} + { \prg_return_true: } + { + \xsim_exercise_if_print:nnTF {#1} {#2} + { \prg_return_true: } + { + \bool_if:cTF {l__xsim_#1_exercise_use_bool} + { + \xsim_if_boolean_property:nnnTF {#1} {#2} {use} + { + \xsim_if_tagged:nnTF {#1} {#2} + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } + { \prg_return_false: } + } + + } + } +\cs_generate_variant:Nn \xsim_exercise_if_use:nnT {nV} +\cs_generate_variant:Nn \xsim_exercise_if_use:nnTF {nV} + +% #1: type +% #2: id +% #3: exercise|solution +\prg_new_protected_conditional:Npnn \xsim_if_print:nnn #1#2#3 {T,F,TF} + { + \use:c {xsim_#3_if_print:nnTF} {#1} {#2} + { \prg_return_true: } + { \prg_return_false: } + } + +% ---------------------------------------------------------------------------- + +\xsim_new_aux_cs:cpn {total-number} #1 + { \int_gset:Nn \g_xsim_max_id_int {#1} } + +\RequirePackage {etoolbox} + +\AtEndPreamble + { + \xsim_foreach_exercise_type:n + { + \tl_new:c { number of #1 s } + \tl_set:cn { number of #1 s } {0} + \xsim_new_aux_cs:cpn {#1} ##1 + { \tl_gset:cn { number of #1 s } {##1} } + } + } + +\AtBeginDocument + { + \xsim_foreach_exercise_type:n + { + \xsim_write_to_aux:x + { \token_to_str:N \providecommand \token_to_str:N \numberof #1 s {} } + } + } + +\AtEndDocument + { + \xsim_if_clear_aux:T + { + \int_compare:nNnF { \g_xsim_max_id_int } = { \g_xsim_id_int } + { \xsim_empty_lists: } + } + \xsim_add_cs_to_aux:nn {total-number} { { \int_use:N \g_xsim_id_int } } + \xsim_foreach_exercise_type:n + { + \xsim_add_cs_to_aux:nn {#1} + { { \arabic { \xsim_get_parameter:nn {#1} {number} } } } + } + \xsim_update_list:n {types} + } + +% ---------------------------------------------------------------------------- +\tex_endinput:D |