%% %% This is file `problem.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% problem.dtx (with options: `package') %% \ProvidesExplPackage{problem}{2022/02/26}{3.0.1}{Semantic Markup for Problems} \RequirePackage{l3keys2e,stex} \keys_define:nn { problem / pkg }{ notes .default:n = { true }, notes .bool_set:N = \c__problems_notes_bool, gnotes .default:n = { true }, gnotes .bool_set:N = \c__problems_gnotes_bool, hints .default:n = { true }, hints .bool_set:N = \c__problems_hints_bool, solutions .default:n = { true }, solutions .bool_set:N = \c__problems_solutions_bool, pts .default:n = { true }, pts .bool_set:N = \c__problems_pts_bool, min .default:n = { true }, min .bool_set:N = \c__problems_min_bool, boxed .default:n = { true }, boxed .bool_set:N = \c__problems_boxed_bool, unknown .code:n = {} } \newif\ifsolutions \ProcessKeysOptions{ problem / pkg } \bool_if:NTF \c__problems_solutions_bool { \solutionstrue }{ \solutionsfalse } \RequirePackage{comment} \bool_if:NT \c__problems_boxed_bool { \RequirePackage{mdframed} } \def\prob@problem@kw{Problem} \def\prob@solution@kw{Solution} \def\prob@hint@kw{Hint} \def\prob@note@kw{Note} \def\prob@gnote@kw{Grading} \def\prob@pt@kw{pt} \def\prob@min@kw{min} \AddToHook{begindocument}{ \ltx@ifpackageloaded{babel}{ \makeatletter \clist_set:Nx \l_tmpa_clist {\bbl@loaded} \clist_if_in:NnT \l_tmpa_clist {ngerman}{ \input{problem-ngerman.ldf} } \clist_if_in:NnT \l_tmpa_clist {finnish}{ \input{problem-finnish.ldf} } \clist_if_in:NnT \l_tmpa_clist {french}{ \input{problem-french.ldf} } \clist_if_in:NnT \l_tmpa_clist {russian}{ \input{problem-russian.ldf} } \makeatother }{} } \keys_define:nn{ problem / problem }{ id .str_set_x:N = \l__problems_prob_id_str, pts .tl_set:N = \l__problems_prob_pts_tl, min .tl_set:N = \l__problems_prob_min_tl, title .tl_set:N = \l__problems_prob_title_tl, type .tl_set:N = \l__problems_prob_type_tl, refnum .int_set:N = \l__problems_prob_refnum_int } \cs_new_protected:Nn \__problems_prob_args:n { \str_clear:N \l__problems_prob_id_str \tl_clear:N \l__problems_prob_pts_tl \tl_clear:N \l__problems_prob_min_tl \tl_clear:N \l__problems_prob_title_tl \tl_clear:N \l__problems_prob_type_tl \int_zero_new:N \l__problems_prob_refnum_int \keys_set:nn { problem / problem }{ #1 } \int_compare:nNnT \l__problems_prob_refnum_int = 0 { \let\l__problems_prob_refnum_int\undefined } } \newcounter{problem} \newcommand\numberproblemsin[1]{\@addtoreset{problem}{#1}} \newcommand\prob@label[1]{#1} \newcommand\prob@number{ \int_if_exist:NTF \l__problems_inclprob_refnum_int { \prob@label{\int_use:N \l__problems_inclprob_refnum_int } }{ \int_if_exist:NTF \l__problems_prob_refnum_int { \prob@label{\int_use:N \l__problems_prob_refnum_int } }{ \prob@label\theproblem } } } \newcommand\prob@title[3]{% \tl_if_exist:NTF \l__problems_inclprob_title_tl { #2 \l__problems_inclprob_title_tl #3 }{ \tl_if_exist:NTF \l__problems_prob_title_tl { #2 \l__problems_prob_title_tl #3 }{ #1 } } } \def\prob@heading{ {\prob@problem@kw}\ \prob@number\prob@title{~}{~(}{)\strut} %\sref@label@id{\prob@problem@kw~\prob@number}{} } \newenvironment{sproblem}[1][]{ \__problems_prob_args:n{#1}%\sref@target% \@in@omtexttrue% we are in a statement (for inline definitions) \stepcounter{problem}\record@problem \def\current@section@level{\prob@problem@kw} \tl_if_exist:NTF \l__problems_inclprob_type_tl { \tl_set_eq:NN \sproblemtype \l__problems_inclprob_type_tl }{ \tl_set_eq:NN \sproblemtype \l__problems_prob_type_tl } \str_if_exist:NTF \l__problems_inclprob_id_str { \str_set_eq:NN \sproblemid \l__problems_inclprob_id_str }{ \str_set_eq:NN \sproblemid \l__problems_prob_id_str } \clist_set:No \l_tmpa_clist \sproblemtype \tl_clear:N \l_tmpa_tl \clist_map_inline:Nn \l_tmpa_clist { \tl_if_exist:cT {__problems_sproblem_##1_start:}{ \tl_set:Nn \l_tmpa_tl {\use:c{__problems_sproblem_##1_start:}} } } \tl_if_empty:NTF \l_tmpa_tl { \__problems_sproblem_start: }{ \l_tmpa_tl } \stex_ref_new_doc_target:n \sproblemid }{ \clist_set:No \l_tmpa_clist \sproblemtype \tl_clear:N \l_tmpa_tl \clist_map_inline:Nn \l_tmpa_clist { \tl_if_exist:cT {__problems_sproblem_##1_end:}{ \tl_set:Nn \l_tmpa_tl {\use:c{__problems_sproblem_##1_end:}} } } \tl_if_empty:NTF \l_tmpa_tl { \__problems_sproblem_end: }{ \l_tmpa_tl } \smallskip } \cs_new_protected:Nn \__problems_sproblem_start: { \par\noindent\textbf\prob@heading\show@pts\show@min\\\ignorespacesandpars } \cs_new_protected:Nn \__problems_sproblem_end: {\par\smallskip} \newcommand\stexpatchproblem[3][] { \str_set:Nx \l_tmpa_str{ #1 } \str_if_empty:NTF \l_tmpa_str { \tl_set:Nn \__problems_sproblem_start: { #2 } \tl_set:Nn \__problems_sproblem_end: { #3 } }{ \exp_after:wN \tl_set:Nn \csname __problems_sproblem_#1_start:\endcsname{ #2 } \exp_after:wN \tl_set:Nn \csname __problems_sproblem_#1_end:\endcsname{ #3 } } } \bool_if:NT \c__problems_boxed_bool { \surroundwithmdframed{problem} } \def\record@problem{ \protected@write\@auxout{} { \string\@problem{\prob@number} { \tl_if_exist:NTF \l__problems_inclprob_pts_tl { \l__problems_inclprob_pts_tl }{ \l__problems_prob_pts_tl } }% { \tl_if_exist:NTF \l__problems_inclprob_min_tl { \l__problems_inclprob_min_tl }{ \l__problems_prob_min_tl } } } } \def\@problem#1#2#3{} \keys_define:nn { problem / solution }{ id .str_set_x:N = \l__problems_solution_id_str , for .tl_set:N = \l__problems_solution_for_tl , height .dim_set:N = \l__problems_solution_height_dim , creators .clist_set:N = \l__problems_solution_creators_clist , contributors .clist_set:N = \l__problems_solution_contributors_clist , srccite .tl_set:N = \l__problems_solution_srccite_tl } \cs_new_protected:Nn \__problems_solution_args:n { \str_clear:N \l__problems_solution_id_str \tl_clear:N \l__problems_solution_for_tl \tl_clear:N \l__problems_solution_srccite_tl \clist_clear:N \l__problems_solution_creators_clist \clist_clear:N \l__problems_solution_contributors_clist \dim_zero:N \l__problems_solution_height_dim \keys_set:nn { problem / solution }{ #1 } } \newcommand\@startsolution[1][]{ \__problems_solution_args:n { #1 } \@in@omtexttrue% we are in a statement. \bool_if:NF \c__problems_boxed_bool { \hrule } \smallskip\noindent {\textbf\prob@solution@kw :\enspace} \begin{small} \def\current@section@level{\prob@solution@kw} \ignorespacesandpars } \newcommand\startsolutions{ \specialcomment{solution}{\@startsolution}{ \bool_if:NF \c__problems_boxed_bool { \hrule\medskip } \end{small}% } \bool_if:NT \c__problems_boxed_bool { \surroundwithmdframed{solution} } } \newcommand\stopsolutions{\excludecomment{solution}} \ifsolutions \startsolutions \else \stopsolutions \fi \bool_if:NTF \c__problems_notes_bool { \newenvironment{exnote}[1][]{ \par\smallskip\hrule\smallskip \noindent\textbf{\prob@note@kw : }\small }{ \smallskip\hrule } }{ \excludecomment{exnote} } \bool_if:NTF \c__problems_notes_bool { \newenvironment{hint}[1][]{ \par\smallskip\hrule\smallskip \noindent\textbf{\prob@hint@kw :~ }\small }{ \smallskip\hrule } \newenvironment{exhint}[1][]{ \par\smallskip\hrule\smallskip \noindent\textbf{\prob@hint@kw :~ }\small }{ \smallskip\hrule } }{ \excludecomment{hint} \excludecomment{exhint} } \bool_if:NTF \c__problems_notes_bool { \newenvironment{gnote}[1][]{ \par\smallskip\hrule\smallskip \noindent\textbf{\prob@gnote@kw : }\small }{ \smallskip\hrule } }{ \excludecomment{gnote} } \newenvironment{mcb}{ \begin{enumerate} }{ \end{enumerate} } \cs_new_protected:Nn \__problems_do_yes_param:Nn { \exp_args:Nx \str_if_eq:nnTF { \str_lowercase:n{ #2 } }{ yes }{ \bool_set_true:N #1 }{ \bool_set_false:N #1 } } \keys_define:nn { problem / mcc }{ id .str_set_x:N = \l__problems_mcc_id_str , feedback .tl_set:N = \l__problems_mcc_feedback_tl , T .default:n = { true } , T .bool_set:N = \l__problems_mcc_t_bool , F .default:n = { true } , F .bool_set:N = \l__problems_mcc_f_bool , Ttext .code:n = { \__problems_do_yes_param:Nn \l__problems_mcc_Ttext_bool { #1 } } , Ftext .code:n = { \__problems_do_yes_param:Nn \l__problems_mcc_Ftext_bool { #1 } } } \cs_new_protected:Nn \l__problems_mcc_args:n { \str_clear:N \l__problems_mcc_id_str \tl_clear:N \l__problems_mcc_feedback_tl \bool_set_true:N \l__problems_mcc_t_bool \bool_set_true:N \l__problems_mcc_f_bool \bool_set_true:N \l__problems_mcc_Ttext_bool \bool_set_false:N \l__problems_mcc_Ftext_bool \keys_set:nn { problem / mcc }{ #1 } } \newcommand\mcc[2][]{ \l__problems_mcc_args:n{ #1 } \item #2 \ifsolutions \\ \bool_if:NT \l__problems_mcc_t_bool { % TODO! % \ifcsstring{mcc@T}{T}{}{\mcc@Ttext}% } \bool_if:NT \l__problems_mcc_f_bool { % TODO! % \ifcsstring{mcc@F}{F}{}{\mcc@Ftext}% } \tl_if_empty:NTF \l__problems_mcc_feedback_tl { ! }{ \l__problems_mcc_feedback_tl } \fi } %solutions \keys_define:nn{ problem / inclproblem }{ id .str_set_x:N = \l__problems_inclprob_id_str, pts .tl_set:N = \l__problems_inclprob_pts_tl, min .tl_set:N = \l__problems_inclprob_min_tl, title .tl_set:N = \l__problems_inclprob_title_tl, refnum .int_set:N = \l__problems_inclprob_refnum_int, type .tl_set:N = \l__problems_inclprob_type_tl, mhrepos .str_set_x:N = \l__problems_inclprob_mhrepos_str } \cs_new_protected:Nn \__problems_inclprob_args:n { \str_clear:N \l__problems_prob_id_str \tl_clear:N \l__problems_inclprob_pts_tl \tl_clear:N \l__problems_inclprob_min_tl \tl_clear:N \l__problems_inclprob_title_tl \tl_clear:N \l__problems_inclprob_type_tl \int_zero_new:N \l__problems_inclprob_refnum_int \str_clear:N \l__problems_inclprob_mhrepos_str \keys_set:nn { problem / inclproblem }{ #1 } \tl_if_empty:NT \l__problems_inclprob_pts_tl { \let\l__problems_inclprob_pts_tl\undefined } \tl_if_empty:NT \l__problems_inclprob_min_tl { \let\l__problems_inclprob_min_tl\undefined } \tl_if_empty:NT \l__problems_inclprob_title_tl { \let\l__problems_inclprob_title_tl\undefined } \tl_if_empty:NT \l__problems_inclprob_type_tl { \let\l__problems_inclprob_type_tl\undefined } \int_compare:nNnT \l__problems_inclprob_refnum_int = 0 { \let\l__problems_inclprob_refnum_int\undefined } } \cs_new_protected:Nn \__problems_inclprob_clear: { \let\l__problems_inclprob_id_str\undefined \let\l__problems_inclprob_pts_tl\undefined \let\l__problems_inclprob_min_tl\undefined \let\l__problems_inclprob_title_tl\undefined \let\l__problems_inclprob_type_tl\undefined \let\l__problems_inclprob_refnum_int\undefined \let\l__problems_inclprob_mhrepos_str\undefined } \__problems_inclprob_clear: \newcommand\includeproblem[2][]{ \__problems_inclprob_args:n{ #1 } \str_if_empty:NTF \l__problems_inclprob_mhrepos_str { \input{#2} }{ \stex_in_repository:nn{\l__problems_inclprob_mhrepos_str}{ \input{\mhpath{\l__problems_inclprob_mhrepos_str}{#2}} } } \__problems_inclprob_clear: } \AddToHook{enddocument}{ \bool_if:NT \c__problems_pts_bool { \message{Total:~\arabic{pts}~points} } \bool_if:NT \c__problems_min_bool { \message{Total:~\arabic{min}~minutes} } } \def\pts#1{ \bool_if:NT \c__problems_pts_bool { \marginpar{#1~\prob@pt@kw} } } \def\min#1{ \bool_if:NT \c__problems_min_bool { \marginpar{#1~\prob@min@kw} } } \newcounter{pts} \def\show@pts{ \tl_if_exist:NTF \l__problems_inclprob_pts_tl { \bool_if:NT \c__problems_pts_bool { \marginpar{\l__problems_inclprob_pts_tl\ \prob@pt@kw\smallskip} \addtocounter{pts}{\l__problems_inclprob_pts_tl} } }{ \tl_if_exist:NT \l__problems_prob_pts_tl { \bool_if:NT \c__problems_pts_bool { \marginpar{\l__problems_prob_pts_tl\ \prob@pt@kw\smallskip} \addtocounter{pts}{\l__problems_prob_pts_tl} } } } } \newcounter{min} \def\show@min{ \tl_if_exist:NTF \l__problems_inclprob_min_tl { \bool_if:NT \c__problems_min_bool { \marginpar{\l__problems_inclprob_pts_tl\ min} \addtocounter{min}{\l__problems_inclprob_min_tl} } }{ \tl_if_exist:NT \l__problems_prob_min_tl { \bool_if:NT \c__problems_min_bool { \marginpar{\l__problems_prob_min_tl\ min} \addtocounter{min}{\l__problems_prob_min_tl} } } } } \endinput %% %% End of file `problem.sty'.