summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex')
-rw-r--r--Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex307
1 files changed, 307 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex b/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex
new file mode 100644
index 00000000000..3120c800bd8
--- /dev/null
+++ b/Master/texmf-dist/tex/latex/xsim/xsim.random.code.tex
@@ -0,0 +1,307 @@
+% ----------------------------------------------------------------------------
+% the XSIM package - random 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{random}{randomly select exercises from collections}
+
+\xsim_load_modules:n {collections}
+
+\tl_new:N \l_xsim_random_collection_tl
+\tl_new:N \l_xsim_random_exclude_list_tl
+\tl_new:N \l__xsim_print_random_choice_tl
+\tl_const:Nn \c__xsim_print_random_both_tl {both}
+\tl_const:Nn \c__xsim_print_random_exercise_tl {exercise}
+\tl_const:Nn \c__xsim_print_random_solution_tl {solution}
+\seq_new:N \g__xsim_random_list_seq
+\seq_new:N \l__xsim_allowed_exercise_ids_seq
+\int_new:N \g__xsim_random_list_id_int
+\bool_new:N \l__xsim_sort_random_bool
+
+% #1: random list id
+% #2: csv list of integers
+\xsim_new_aux_cs:cpn {random} #1#2
+ {
+ \xsim_random_list_if_exist:nF {#1}
+ { \xsim_new_random_list:n {#1} }
+ \xsim_set_random_list:nn {#1} {#2}
+ }
+
+\cs_new_protected:Npn \xsim_new_random_list:n #1
+ {
+ \xsim_verbose:n {Defining~ new~ random~ list~ `#1'}
+ \seq_new:c {g__xsim_random_#1 _seq}
+ }
+
+\cs_new_protected:Npn \xsim_set_random_list:nn #1#2
+ { \seq_gset_from_clist:cn {g__xsim_random_#1_seq} {#2} }
+
+\cs_new_protected:Npn \xsim_set_random_list_from_seq:nN #1#2
+ { \seq_gset_eq:cN {g__xsim_random_#1_seq} #2 }
+
+\cs_new:Npn \xsim_use_random_list:nn #1#2
+ { \seq_use:cn {g__xsim_random_#1_seq} {#2} }
+
+\cs_new_protected:Npn \xsim_map_random_list:nn #1#2
+ { \seq_map_inline:cn {g__xsim_random_#1_seq} {#2} }
+
+\prg_new_conditional:Npnn \xsim_random_list_if_exist:n #1 {p,T,F,TF}
+ {
+ \seq_if_exist:cTF {g__xsim_random_#1_seq}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+\prg_new_conditional:Npnn \xsim_random_list_if_empty:n #1 {p,T,F,TF}
+ {
+ \seq_if_empty:cTF {g__xsim_random_#1_seq}
+ { \prg_return_true: }
+ { \prg_return_false: }
+ }
+
+% #1: random list id
+% #2: sequence variable to set list from
+\cs_new_protected:Npn \xsim_save_random_list:nN #1#2
+ {
+ \xsim_random_list_if_exist:nF {#1}
+ { \xsim_new_random_list:n {#1} }
+ \xsim_random_list_if_empty:nT {#1}
+ { \xsim_set_random_list_from_seq:nN {#1} #2 }
+ \xsim_verbose:n {Saving~ random~ list~ `#1'}
+ \xsim_add_cs_to_aux:nn {random}
+ { {#1} { \xsim_use_random_list:nn {#1} {,} } }
+ }
+
+% #1: collection
+% #2: number of items
+% #3: csv list of excluded ids
+\cs_new_protected:Npn \xsim_print_random_list:nnn #1#2#3
+ {
+ \xsim_if_collection_exists:nTF {#1}
+ {
+ \int_gincr:N \g__xsim_random_list_id_int
+ \int_compare:nNnTF { \xsim_collection_count:n {#1} } = {0}
+ { \xsim_rerun: }
+ {
+ % generate seq of allowed ids from collection:
+ \xsim_foreach_exercise_id:n
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \xsim_get_type_for_property:nn {id} {##1} }
+ \xsim_if_in_collection:nVnT {#1} \l__xsim_tmpa_tl {##1}
+ {
+ \clist_if_in:nnF {#3} {##1}
+ { \seq_put_right:Nn \l__xsim_allowed_exercise_ids_seq {##1} }
+ }
+ }
+ \int_compare:nNnTF
+ {#2}
+ >
+ { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
+ {
+ \int_set:Nn \l__xsim_tmpa_int
+ { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
+ }
+ { \int_set:Nn \l__xsim_tmpa_int {#2} }
+ % generate random list:
+ \xsim_generate_random_list:nnnN
+ { \int_to_alph:n { \g__xsim_random_list_id_int } }
+ { \seq_count:N \l__xsim_allowed_exercise_ids_seq }
+ { \l__xsim_tmpa_int }
+ \g__xsim_random_list_seq
+ }
+ \xsim_save_random_list:nN
+ { \int_to_alph:n { \g__xsim_random_list_id_int } }
+ \g__xsim_random_list_seq
+ \xsim_verbose:x
+ {
+ Printing~ exercises~ of~ random~ list~
+ `\int_to_alph:n { \g__xsim_random_list_id_int }'~ of~
+ collection~ `#1'
+ }
+ \xsim_print_random_exercises:Nn
+ \l__xsim_allowed_exercise_ids_seq
+ { \int_to_alph:n { \g__xsim_random_list_id_int } }
+ }
+ { \msg_error:nnn {xsim} {unknown-collection} {#1} }
+ }
+\cs_generate_variant:Nn \xsim_print_random_list:nnn {VnV}
+
+% #1: random list id
+% #2: max number to choose from
+% #3: number of items
+% #4: seq variable
+\cs_new_protected:Npn \xsim_generate_random_list:nnnN #1#2#3#4
+ {
+ \bool_if:nT
+ {
+ !\xsim_random_list_if_exist_p:n {#1}
+ ||
+ \xsim_random_list_if_empty_p:n {#1}
+ }
+ {
+ \xsim_verbose:n
+ {Generating~ random~ list~ `#1'~ with~ #3~ out~ of~ #2~ items}
+ \seq_gclear:N #4
+ \int_do_until:nNnn { \seq_count:N #4 } = {#3}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \fp_eval:n { randint(#2) } }
+ \seq_if_in:NVF #4
+ \l__xsim_tmpa_tl
+ { \seq_gput_right:NV #4 \l__xsim_tmpa_tl }
+ }
+ \bool_if:NT \l__xsim_sort_random_bool
+ {
+ \seq_sort:Nn #4
+ {
+ \int_compare:nNnTF {##1} > {##2}
+ { \sort_return_swapped: }
+ { \sort_return_same: }
+ }
+ }
+ }
+ }
+
+% #1: seq variable of ids
+% #2: random list id
+\cs_new_protected:Npn \xsim_print_random_exercises:Nn #1#2
+ {
+ \bool_if:nT
+ {
+ \xsim_random_list_if_exist_p:n {#2}
+ &&
+ !\xsim_random_list_if_empty_p:n {#2}
+ }
+ {
+ \xsim_verbose:x
+ {
+ Printing~
+ \l__xsim_print_random_choice_tl \c_space_tl
+ \str_if_eq:onT { \l__xsim_print_random_choice_tl } {both}
+ { exercises~ and~ solutions~ }
+ of~ random~ list~ `#2'
+ }
+ \xsim_map_random_list:nn {#2}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \seq_item:Nn #1 {##1} }
+ \tl_set:Nx \l__xsim_tmpb_tl
+ { \xsim_get_type_for_property:nV {id} \l__xsim_tmpa_tl }
+ \bool_if:nT
+ {
+ \tl_if_eq_p:NN
+ \l__xsim_print_random_choice_tl
+ \c__xsim_print_random_both_tl
+ ||
+ \tl_if_eq_p:NN
+ \l__xsim_print_random_choice_tl
+ \c__xsim_print_random_exercise_tl
+ }
+ {
+ \xsim_if_exercise_exists:VVT
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {
+ \xsim_insert:VVnn
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {}
+ {exercise}
+ }
+ }
+ \bool_if:nT
+ {
+ \tl_if_eq_p:NN
+ \l__xsim_print_random_choice_tl
+ \c__xsim_print_random_both_tl
+ ||
+ \tl_if_eq_p:NN
+ \l__xsim_print_random_choice_tl
+ \c__xsim_print_random_solution_tl
+ }
+ {
+ \xsim_if_solution_exists:VVT
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {
+ \xsim_insert:VVnn
+ \l__xsim_tmpb_tl
+ \l__xsim_tmpa_tl
+ {}
+ {solution}
+ }
+ }
+ }
+ }
+ }
+
+\keys_define:nn {xsim/random}
+ {
+ sort .bool_set:N = \l__xsim_sort_random_bool ,
+ sort .initial:n = true ,
+ collection .tl_set:N = \l_xsim_random_collection_tl ,
+ collection .initial:n = all~exercises ,
+ exclude .code:n = \__xsim_exclude_ids:n {#1} ,
+ print .choice: ,
+ print/exercises .code:n =
+ \tl_set:Nn \l__xsim_print_random_choice_tl {exercise} ,
+ print/solutions .code:n =
+ \tl_set:Nn \l__xsim_print_random_choice_tl {solution} ,
+ print/both .code:n =
+ \tl_set:Nn \l__xsim_print_random_choice_tl {both} ,
+ print/unknown .code:n =
+ \msg_warning:nnn {xsim} {print-collection-choice} {#1}
+ \tl_set:Nn \l__xsim_print_random_choice_tl {exercise} ,
+ print .initial:n = exercises
+ }
+
+\cs_new_protected:Npn \__xsim_exclude_ids:n #1
+ {
+ \seq_clear:N \l__xsim_tmpa_seq
+ \clist_map_inline:nn {#1}
+ {
+ \tl_set:Nx \l__xsim_tmpa_tl
+ { \xsim_get_id_for_property:nn {ID} {##1} }
+ \tl_if_blank:NTF \l__xsim_tmpa_tl
+ { \seq_put_right:Nn \l__xsim_tmpa_seq {##1} }
+ {
+ \seq_put_right:Nx \l__xsim_tmpa_seq
+ { \xsim_get_id_for_property:nn {ID} {##1} }
+ }
+ }
+ \seq_remove_duplicates:N \l__xsim_tmpa_seq
+ \tl_set:Nx \l_xsim_random_exclude_list_tl
+ { \seq_use:Nn \l__xsim_tmpa_seq {,} }
+ }
+
+% use this in the exclude list:
+% \xsim_get_type_for_property:nn {id} {}
+% or a combination of:
+% \xsim_get_type_for_property:nn {ID} {}
+% \xsim_get_id_for_property:nn {ID} {}
+
+% ----------------------------------------------------------------------------
+\tex_endinput:D