% \iffalse meta-comment % An Infrastructure for Problems % Copyright (c) 2019 Michael Kohlhase, all rights reserved % this file is released under the % LaTeX Project Public License (LPPL) % The original of this file is in the public repository at % http://github.com/sLaTeX/sTeX/ % \fi % % \iffalse % %<*driver> \def\stexdocpath{../doc} \input{\stexdocpath/stex-docheader} \stextoptitle{The \texttt{problem} Package}{problem} \docmodule % % \fi % % \begin{stexmanual} % \begin{sfragment}{Problem Manual} % \input{\stexdocpath/packages/stex-problem} % \end{sfragment} % \end{stexmanual} % % \begin{documentation} % \begin{sfragment}{Problem Documentation} % TODO % \end{sfragment} % \end{documentation} % % \begin{implementation} % % \section{Implementation: The problem Package} % % \subsection{Package Options}\label{sec:impl:options} % % The first step is to declare (a few) package options that handle whether certain % information is printed or not. They all come with their own conditionals that are set by % the options. % % \begin{macrocode} %<*package> %<@@=problems> \ProvidesExplPackage{problem}{2023/10/13}{3.4.0}{Semantic Markup for Problems} \RequirePackage{l3keys2e} \keys_define:nn { problem / pkg }{ notes .default:n = { true }, notes .bool_set:N = \c_@@_notes_bool, gnotes .default:n = { true }, gnotes .bool_set:N = \c_@@_gnotes_bool, hints .default:n = { true }, hints .bool_set:N = \c_@@_hints_bool, solutions .default:n = { true }, solutions .bool_set:N = \c_@@_solutions_bool, pts .default:n = { true }, pts .bool_set:N = \c_@@_pts_bool, min .default:n = { true }, min .bool_set:N = \c_@@_min_bool, %boxed .default:n = { true }, %boxed .bool_set:N = \c_@@_boxed_bool, test .default:n = { true }, test .bool_set:N = \c_@@_test_bool, unknown .code:n = { \PassOptionsToPackage{\CurrentOption}{stex} } } \newif\ifsolutions \ProcessKeysOptions{ problem / pkg } \bool_if:NTF \c_@@_solutions_bool { \solutionstrue }{ \solutionsfalse } \newif\ifintest \bool_if:NTF \c_@@_test_bool { \intesttrue }{ \intestfalse } \RequirePackage{stex} % \end{macrocode} % % \begin{macro}{\problem@kw@*} % For multilinguality, we define internal macros for keywords that can be specialized in % |*.ldf| files. % \begin{macrocode} \AddToHook{begindocument}{ \ExplSyntaxOn\makeatletter \input{problem-english.ldf} \ltx@ifpackageloaded{babel}{ \clist_set:Nx \l_tmpa_clist {\exp_args:No \tl_to_str:n \bbl@loaded} \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\detokenize{ngerman}}{ \input{problem-ngerman.ldf} } \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\detokenize{finnish}}{ \input{problem-finnish.ldf} } \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\detokenize{french}}{ \input{problem-french.ldf} } \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\detokenize{russian}}{ \input{problem-russian.ldf} } }{} \makeatother\ExplSyntaxOff } % \end{macrocode} % \end{macro} % % \subsection{Problems and Solutions}\label{sec:impl:probsols} % % We now prepare the KeyVal support for problems. The key macros just set appropriate % internal macros. % % \begin{macrocode} \bool_new:N \l_stex_key_autogradable_bool \stex_keys_define:nnnn{ problem }{ \tl_set:Nn \l_stex_key_pts_tl 0 \tl_set:Nn \l_stex_key_min_tl 0 \str_clear:N \l_stex_key_name_str \str_clear:N \l_stex_key_mhrepos_str \bool_set_false:N \l_stex_key_autogradable_bool }{ pts .tl_set:N = \l_stex_key_pts_tl, min .tl_set:N = \l_stex_key_min_tl, name .str_set:N = \l_stex_key_name_str, autogradable .bool_set:N = \l_stex_key_autogradable_bool, archive .code:n = {}, %archive .str_set:N = \l_stex_key_mhrepos_str, creators .code:n = {} %imports .tl_set:N = \l_@@_prob_imports_tl, %refnum .int_set:N = \l_@@_prob_refnum_int, }{id,title,style,uses} % \end{macrocode} % % Then we set up a counter for problems. % \begin{macro}{\numberproblemsin} % \begin{macrocode} \newcounter{sproblem}[section] \newcommand\numberproblemsin[1]{ \@addtoreset{sproblem}{#1} \def\thesproblem{\arabic{#1}.\arabic{sproblem}} } \numberproblemsin{section} %\def\theplainsproblem{\arabic{sproblem}} %\def\thesproblem{\thesection.\theplainsproblem} % \end{macrocode} % \end{macro} % % \begin{environment}{sproblem} % \begin{macrocode} \cs_new:Nn \_@@_activate_macros: { \stex_reactivate_macro:N \solution \stex_reactivate_macro:N \mcb \stex_reactivate_macro:N \scb \stex_reactivate_macro:N \fillinsol \stex_reactivate_macro:N \hint \stex_reactivate_macro:N \exnote \stex_reactivate_macro:N \gnote } \newcounter{pts} \newcounter{min} \bool_new:N \l_@@_in_problem_bool \bool_new:N \l_@@_has_pts_bool \bool_new:N \l_@@_has_min_bool \bool_set_false:N \l_@@_in_problem_bool \stex_new_stylable_env:nnnnnnn {problem} {O{}}{ \bool_if:NT \l_@@_in_problem_bool { \msg_error:nn{stex}{error/nestedproblem} } \cs_if_exist:NTF \l_problem_inputproblem_keys_tl { \tl_put_left:Nn \l_problem_inputproblem_keys_tl {#1,} \exp_args:Nno \stex_keys_set:nn{problem}{ \l_problem_inputproblem_keys_tl } }{ \stex_keys_set:nn{problem}{#1} } \refstepcounter{sproblem} \stex_if_do_html:T { \str_if_empty:NT \l_stex_key_name_str { \stex_file_split_off_lang:NN \l_@@_path_seq \g_stex_current_file \seq_get_right:NN \l_@@_path_seq \l_stex_key_name_str } \exp_args:Nne \begin{stex_annotate_env} { shtml:problem={\l_stex_key_name_str}, shtml:language={ \l_stex_current_language_str}, shtml:autogradable={\bool_if:NTF \l_stex_key_autogradable_bool {true}{false}} } \tl_if_empty:NF \l_stex_key_title_tl { \exp_args:No \stexdoctitle \l_stex_key_title_tl } \stex_annotate_invisible:nn{ shtml:problempoints={\l_stex_key_pts_tl} }{ \l_stex_key_pts_tl } } \tl_set_eq:NN \thistitle \l_stex_key_title_tl \bool_set_true:N \l_@@_in_problem_bool \tl_set_eq:NN \l_@@_pts_tl \l_stex_key_pts_tl \tl_set_eq:NN \l_@@_min_tl \l_stex_key_min_tl \tl_if_eq:NnTF \l_@@_pts_tl {0} {\bool_set_false:N \l_@@_has_pts_bool} {\bool_set_true:N \l_@@_has_pts_bool} \tl_if_eq:NnTF \l_@@_min_tl {0} {\bool_set_false:N \l_@@_has_min_bool} {\bool_set_true:N \l_@@_has_min_bool} \int_gzero:N \g_@@_subproblem_int \stex_style_apply: \_stex_do_id: \_@@_activate_macros: }{ \addtocounter{pts}{\l_@@_pts_tl} \addtocounter{min}{\l_@@_min_tl} \_@@_record_problem: \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{ \par\noindent\problemheader \bool_if:NT \c_@@_pts_bool { \tl_if_eq:NnF \l_@@_pts_tl {0}{ \marginpar{\l_@@_pts_tl{}~\problem@kw@pts\smallskip} } } \bool_if:NT \c_@@_min_bool { \tl_if_eq:NnF \l_@@_min_tl {0} { \marginpar{\l_@@_min_tl{}~\problem@kw@minutes\smallskip} } } \par \stex_ignore_spaces_and_pars: }{ \par\bigskip % \bool_if:NT \c_@@_test_bool \pagebreak }{s} \tl_set:Nn \problemheader { \textbf{\sproblemautorefname{~}\thesproblem \tl_if_empty:NF \thistitle { {~}(\thistitle) } } } \cs_new_protected:Nn \_@@_record_problem: { \exp_args:NNe \iow_now:Nn \@auxout { \problem@restore {\thesproblem}{\l_@@_pts_tl}{\l_@@_min_tl} } } \cs_new_protected:Npn \problem@restore #1 #2 #3 {} % \end{macrocode} % \end{environment} % % \begin{environment}{subproblem} % \begin{macrocode} \int_new:N \g_@@_subproblem_int \stex_new_stylable_env:nnnnnnn {subproblem} {O{}}{ \stex_keys_set:nn{problem}{#1} \bool_if:NF \l_@@_in_problem_bool{ \ifstexhtml\else \par{\bfseries WARNING~subproblem~to~be~used~in~some~problem}\par \fi \_@@_activate_macros: \bool_set_true:N \l_@@_in_problem_bool \tl_set:Nn \l_@@_pts_tl{0} \tl_set:Nn \l_@@_min_tl{0} } \str_if_empty:NT \l_stex_key_name_str { \stex_file_split_off_lang:NN \l_@@_path_seq \g_stex_current_file \seq_get_right:NN \l_@@_path_seq \l_stex_key_name_str } \stex_if_do_html:T { \str_if_empty:NT \l_stex_key_name_str { \stex_file_split_off_lang:NN \l_@@_path_seq \g_stex_current_file \seq_get_right:NN \l_@@_path_seq \l_stex_key_name_str } \exp_args:Nne \begin{stex_annotate_env} { shtml:subproblem={\l_stex_key_name_str}, shtml:language={ \l_stex_current_language_str}, shtml:autogradable={\bool_if:NTF \l_stex_key_autogradable_bool {true}{false}} } \stex_annotate_invisible:n{} \tl_if_empty:NF \l_stex_key_title_tl { \exp_args:No \stexdoctitle \l_stex_key_title_tl } } \int_gincr:N \g_@@_subproblem_int \bool_if:NF \l_@@_has_pts_bool { \tl_gset:Nx \l_@@_pts_tl {\int_eval:n {\l_@@_pts_tl + \l_stex_key_pts_tl}} } \bool_if:NF \l_@@_has_min_bool { \tl_gset:Nx \l_@@_min_tl {\int_eval:n {\l_@@_min_tl + \l_stex_key_min_tl}} } \stex_if_smsmode:F \stex_style_apply: }{ \stex_if_smsmode:F \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{ \begin{list}{}{ \setlength\topsep{0pt} \setlength\parsep{0pt} \setlength\rightmargin{0pt} }\item[\int_use:N \g_@@_subproblem_int .] \bool_if:NT \c_@@_pts_bool { \bool_if:NF \l_@@_has_pts_bool { \marginpar{\smallskip\l_stex_key_pts_tl{}~\problem@kw@pts} } } \bool_if:NT \c_@@_min_bool { \bool_if:NF \l_@@_has_min_bool{ \marginpar{\smallskip\l_stex_key_min_tl{}~\problem@kw@minutes} } } }{ \end{list} }{} % \end{macrocode} % \end{environment} % % \begin{macro}{\includeproblem} % \begin{macrocode} \stex_keys_define:nnnn{ includeproblem }{ \str_clear:N \l_stex_key_mhrepos_str }{ archive .str_set:N = \l_stex_key_mhrepos_str, unknown .code:n = {} }{} \NewDocumentCommand\includeproblem{O{} m}{ \group_begin: \tl_set:Nn \l_problem_inputproblem_keys_tl {#1} \stex_keys_set:nn{includeproblem}{#1} \exp_args:Nno \use:nn{\inputref[}\l_stex_key_mhrepos_str]{#2} \group_end: } % \end{macrocode} % \end{macro} % % \begin{environment}{solution} % \begin{macrocode} \int_new:N \g_problem_id_counter \dim_new:N \l_stex_key_testspace_dim \stex_keys_define:nnnn{ solution }{ \str_clear:N \l_stex_key_answerclass_str \dim_zero:N \l_stex_key_testspace_dim }{ testspace .dim_set:N = \l_stex_key_testspace_dim, answerclass .str_set:N = \l_stex_key_answerclass_str }{id,title,style} \cs_new_protected:Nn \_@@_solution_start:n { \stex_keys_set:nn{ solution }{#1} \str_if_empty:NT \l_stex_key_id_str { \int_gincr:N \g_problem_id_counter \str_set:Nx \l_stex_key_id_str { SOLUTION_\int_use:N \g_problem_id_counter } } \stex_if_do_html:T{ \begin{stex_annotate_env}{ shtml:solution=\l_stex_key_id_str, shtml:answerclass={\l_stex_key_answerclass_str} } } \stex_style_apply: } \stex_new_stylable_env:nnnnnnn { solution }{ O{} }{ \stex_if_do_html:TF{ \_@@_solution_start:n{#1} }{ \ifsolutions \_@@_solution_start:n{#1} \else \stex_keys_set:nn{ solution }{#1} \testspace{\l_stex_key_testspace_dim} \setbox\l_tmpa_box\vbox\bgroup \fi } }{ \stex_if_do_html:TF{ \stex_style_apply: \end{stex_annotate_env} }{ \ifsolutions \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } \else \egroup \fi } }{ \par\smallskip\rule[.3em]{\linewidth}{0.4pt}\newline\smallskip \noindent\emph{\problem@kw@solution\tl_if_empty:NF \l_stex_key_title_tl{ {~}\l_stex_key_title_tl \str_if_empty:NF \l_stex_key_answerclass_str { (Answer Class: \l_stex_key_answerclass_str) } } :~} }{ \par\rule[.3em]{\linewidth}{0.4pt}\newline }{} \stex_deactivate_macro:Nn \solution {sproblem~environments} % \end{macrocode} % \end{environment} % % \begin{macro}{\startsolutions,\stopsolutions} % \begin{macrocode} \cs_new_protected:Npn \startsolutions{ \global\solutionstrue } \cs_new_protected:Npn \stopsolutions{ \global\solutionsfalse } % \end{macrocode} % \end{macro} % % \begin{environment}{hint} % \begin{macrocode} \stex_keys_define:nnnn{ problemenv }{}{}{id,title,style} \cs_new_protected:Nn \_@@_hint_start:n { \stex_keys_set:nn{ problemenv }{#1} \str_if_empty:NT \l_stex_key_id_str { \int_gincr:N \g_problem_id_counter \str_set:Nx \l_stex_key_id_str { HINT_\int_use:N \g_problem_id_counter } } \stex_if_do_html:T{ \begin{stex_annotate_env}{ shtml:problemhint=\l_stex_key_id_str } } \stex_style_apply: } \stex_new_stylable_env:nnnnnnn { hint }{ O{} }{ \stex_if_do_html:TF{ \_@@_hint_start:n{#1} }{ \bool_if:NTF \c_@@_hints_bool { \_@@_hint_start:n{#1} }{ \setbox\l_tmpa_box\vbox\bgroup } } }{ \stex_if_do_html:TF{ \stex_style_apply: \end{stex_annotate_env} }{ \bool_if:NTF \c_@@_hints_bool { \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{ \egroup } } }{ \par\smallskip\rule[.3em]{\linewidth}{0.4pt}\newline\smallskip \noindent\emph{\problem@kw@hint\tl_if_empty:NF \l_stex_key_title_tl{ {~}\l_stex_key_title_tl } :~} }{ \par\rule[.3em]{\linewidth}{0.4pt}\newline }{} \stex_deactivate_macro:Nn \hint {sproblem~environments} % \end{macrocode} % \end{environment} % % \begin{environment}{exnote} % \begin{macrocode} \cs_new_protected:Nn \_@@_exnote_start:n { \stex_keys_set:nn{ problemenv }{#1} \str_if_empty:NT \l_stex_key_id_str { \int_gincr:N \g_problem_id_counter \str_set:Nx \l_stex_key_id_str { EXNOTE_\int_use:N \g_problem_id_counter } } \stex_if_do_html:T{ \begin{stex_annotate_env}{ shtml:problemnote=\l_stex_key_id_str } } \stex_style_apply: } \stex_new_stylable_env:nnnnnnn { exnote }{ O{} }{ \stex_if_do_html:TF{ \_@@_exnote_start:n{#1} }{ \bool_if:NTF \c_@@_notes_bool { \_@@_exnote_start:n{#1} }{ \setbox\l_tmpa_box\vbox\bgroup } } }{ \stex_if_do_html:TF{ \stex_style_apply: \end{stex_annotate_env} }{ \bool_if:NTF \c_@@_notes_bool { \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{ \egroup } } }{ \par\smallskip\rule[.3em]{\linewidth}{0.4pt}\newline\smallskip \noindent\emph{\problem@kw@note\tl_if_empty:NF \l_stex_key_title_tl{ {~}\l_stex_key_title_tl } :~} }{ \par\rule[.3em]{\linewidth}{0.4pt}\newline }{} \stex_deactivate_macro:Nn \exnote {sproblem~environments} % \end{macrocode} % \end{environment} %% \begin{environment}{gnote} % \begin{macrocode} \int_new:N \l_@@_anscls_int \cs_new_protected:Nn \_@@_gnote_start:n { \stex_keys_set:nn{ problemenv }{#1} \str_if_empty:NT \l_stex_key_id_str { \int_gincr:N \g_problem_id_counter \str_set:Nx \l_stex_key_id_str { GNOTE_\int_use:N \g_problem_id_counter } } \stex_if_do_html:T{ \begin{stex_annotate_env}{ shtml:problemgnote=\l_stex_key_id_str } } \stex_style_apply: } \stex_new_stylable_env:nnnnnnn { gnote }{ O{} }{ \stex_if_do_html:TF{ \_@@_gnote_start:n{#1} }{ \bool_if:NTF \c_@@_gnotes_bool { \_@@_gnote_start:n{#1} }{ \setbox\l_tmpa_box\vbox\bgroup } } \stex_reactivate_macro:N \anscls }{ \stex_if_do_html:TF{ \stex_style_apply: \end{stex_annotate_env} }{ \bool_if:NTF \c_@@_gnotes_bool { \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{ \egroup } } }{ \par\smallskip\rule[.3em]{\linewidth}{0.4pt}\newline\smallskip \noindent\emph{\problem@kw@grading\str_if_empty:NF \l_stex_key_title_tl{ {~}\l_stex_key_title_tl } :~} }{ \par\rule[.3em]{\linewidth}{0.4pt}\newline }{} \stex_deactivate_macro:Nn \gnote {sproblem~environments} \stex_keys_define:nnnn{ anscls }{ \str_clear:N \l_stex_key_pts_str \tl_clear:N \l_stex_key_feedback_tl }{ pts .str_set:N = \l_stex_key_pts_str, feedback .tl_set:N = \l_stex_key_feedback_str, update .code:n = {} }{id} \newcommand \anscls [2][] { \stex_keys_set:nn{ anscls }{#1} \str_if_empty:NT \l_stex_key_id_str { \int_incr:N \l_@@_anscls_int \str_set:Nx \l_stex_key_id_str { AC\int_use:N \l_@@_anscls_int } } \begin{list}{}{ \setlength\topsep{0pt} \setlength\parsep{0pt} \setlength\rightmargin{0pt} }\item[\l_stex_key_id_str] \stex_if_do_html:TF{ \stex_annotate:nn{ shtml:answerclass={\l_stex_key_id_str} \str_if_empty:NF \l_stex_key_pts_str{ ,shtml:answerclass-pts={\l_stex_key_pts_str} } \str_if_empty:NF \l_stex_key_feedback_str{ ,shtml:answerclass-feedback={\l_stex_key_feedback_str} } }{ #2 } }{#2} \str_if_empty:NF \l_stex_key_pts_str {\par ~ \problem@kw@points:~\l_stex_key_pts_str } \str_if_empty:NF \l_stex_key_feedback_str {\par ~ \problem@kw@feedback :~\l_stex_key_feedback_str } \end{list} } \stex_deactivate_macro:Nn \anscls {gnote~environments} % \end{macrocode} % \end{environment} % % The margin pars are reader-visible, so we need to translate % % \begin{macrocode} \def\pts#1{ \bool_if:NT \c_@@_pts_bool { \stex_annotate:nn{shtml:problempoints={#1}}{\marginpar{#1~\problem@kw@pts}} }\hbox_unpack:N\c_empty_box } \def\min#1{ \bool_if:NT \c_@@_min_bool { \stex_annotate:nn{shtml:problemminutes={}}{\marginpar{#1~\problem@kw@minutes}} }\hbox_unpack:N\c_empty_box } % \end{macrocode} % % \begin{environment}{mcb} % % \begin{macrocode} \stex_new_stylable_env:nnnnnnn{mcb}{O{}}{ \stex_keys_set:nn{style}{#1} \stex_if_do_html:T{ \tl_set:Nn\problem_mcc_box_tl{} \exp_args:Nne \begin{stex_annotate_env}{ shtml:multiple-choice-block={} \clist_if_empty:NF \l_stex_key_style_clist {, shtml:styles={\l_stex_key_style_clist} } } } \stex_deactivate_macro:Nn \mcb {sproblem~environments} \stex_deactivate_macro:Nn \scb {sproblem~environments} \stex_deactivate_macro:Nn \solution {sproblem~environments} \stex_deactivate_macro:Nn \hint {sproblem~environments} \stex_deactivate_macro:Nn \exnote {sproblem~environments} \stex_deactivate_macro:Nn \gnote {sproblem~environments} \stex_reactivate_macro:N \mcc \cs_set:Nn \_@@_mccline:n{ \begin{list}{}{ \setlength\topsep{0pt} \setlength\parsep{0pt} \setlength\rightmargin{0pt} }\item[\problem_mcc_box_tl] ##1 \end{list} } \stex_style_apply: }{ \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{\par}{}{} \stexstylemcb[inline]{ \cs_set:Nn \_@@_mccline:n{\problem_mcc_box_tl{~} #1} }{} \stex_deactivate_macro:Nn \mcb {sproblem~environments} % \end{macrocode} % % we define the keys for the |mcc| macro % % \begin{macrocode} \cs_new_protected:Nn \_@@_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 } } \stex_keys_define:nnnn{mcc}{ \tl_clear:N \l_stex_key_feedback_tl \bool_set_false:N \l_stex_key_T_bool \tl_clear:N \l_stex_key_Ttext_tl \tl_clear:N \l_stex_key_Ftext_tl }{ feedback .tl_set:N = \l_stex_key_feedback_tl , T .code:n = {\bool_set_true:N \l_stex_key_T_bool} , F .code:n = {\bool_set_false:N \l_stex_key_T_bool} , Ttext .tl_set:N = \l_stex_key_Ttext_tl , Ftext .tl_set:N = \l_stex_key_Ftext_tl , }{id} % \end{macrocode} % % \begin{macro}{\mcc} % \begin{macrocode} \tl_set:Nn \problem_mcc_box_tl { \ltx@ifpackageloaded{amssymb}{$\square$}{ \hbox{\vrule\vbox{\hrule width 6 pt\vskip 6pt\hrule}\vrule} } } \newcommand\mcc[2][]{ \stex_keys_set:nn{mcc}{#1} \tl_set:Nn \l_tmpa_tl{ \bool_if:NTF \l_stex_key_T_bool { \tl_if_empty:NTF \l_stex_key_Ttext_tl \problem@kw@correct \l_stex_key_Ttext_tl }{ \tl_if_empty:NTF \l_stex_key_Ftext_tl \problem@kw@wrong \l_stex_key_Ftext_tl } \tl_if_empty:NF \l_stex_key_feedback_tl { \\\emph{\l_stex_key_feedback_tl} } } \_@@_mccline:n{ \stex_if_do_html:TF{ \stex_annotate:nn{shtml:mcc={ \bool_if:NTF \l_stex_key_T_bool {true}{false} }}{ #2\stex_annotate:nn{shtml:mcc-solution={}}{\l_tmpa_tl} } }{ #2\ifsolutions\footnote{\l_tmpa_tl}\fi } } } \stex_deactivate_macro:Nn \mcc {mcb~environments} % \end{macrocode} % \end{macro} % \end{environment} % % \begin{environment}{scb} % % \begin{macrocode} \tl_set:Nn\problem_scc_box_tl{$\bigcirc$} \stex_new_stylable_env:nnnnnnn{scb}{O{}}{ \stex_keys_set:nn{style}{#1} \stex_if_do_html:T{ \exp_args:Nne\begin{stex_annotate_env}{ shtml:single-choice-block={} \clist_if_empty:NF \l_stex_key_style_clist {, shtml:styles={\l_stex_key_style_clist} } } \tl_set:Nn\problem_scc_box_tl{} } \stex_deactivate_macro:Nn \mcb {sproblem~environments} \stex_deactivate_macro:Nn \scb {sproblem~environments} \stex_deactivate_macro:Nn \solution {sproblem~environments} \stex_deactivate_macro:Nn \hint {sproblem~environments} \stex_deactivate_macro:Nn \exnote {sproblem~environments} \stex_deactivate_macro:Nn \gnote {sproblem~environments} \stex_reactivate_macro:N \scc \cs_set:Nn \_@@_sccline:n{ \begin{list}{}{ \setlength\topsep{0pt} \setlength\parsep{0pt} \setlength\rightmargin{0pt} }\item[\problem_scc_box_tl] ##1 \end{list} } \stex_style_apply: }{ \stex_style_apply: \stex_if_do_html:T{ \end{stex_annotate_env} } }{\par}{}{} \stexstylescb[inline]{ \cs_set:Nn \_@@_sccline:n{\problem_scc_box_tl{~} #1} }{} \stex_deactivate_macro:Nn \scb {sproblem~environments} % \end{macrocode} % % \begin{macro}{\scc} % \begin{macrocode} \newcommand\scc[2][]{ \stex_keys_set:nn{mcc}{#1} \tl_set:Nn \l_tmpa_tl{ \bool_if:NTF \l_stex_key_T_bool { \tl_if_empty:NTF \l_stex_key_Ttext_tl \problem@kw@correct \l_stex_key_Ttext_tl }{ \tl_if_empty:NTF \l_stex_key_Ftext_tl \problem@kw@wrong \l_stex_key_Ftext_tl } \tl_if_empty:NF \l_stex_key_feedback_tl { \\\emph{\l_stex_key_feedback_tl} } } \_@@_sccline:n{ \stex_if_do_html:TF{ \stex_annotate:nn{shtml:scc={ \bool_if:NTF \l_stex_key_T_bool {true}{false} }}{ #2\stex_annotate:nn{shtml:scc-solution={}}{\l_tmpa_tl} } }{ #2\ifsolutions\footnote{\l_tmpa_tl}\fi } } } \stex_deactivate_macro:Nn \scc {scb~environments} \newcommand\yesTnoF{ \begin{scb}[style=inline] \scc[T]{yes}~\scc[F]{no} \end{scb} } \newcommand\yesFnoT{ \begin{scb}[style=inline] \scc[F]{yes}~\scc[T]{no} \end{scb} } \newcommand\trueTfalseF{ \begin{scb}[style=inline] \scc[T]{true}~\scc[F]{false} \end{scb} } \newcommand\trueFfalseT{ \begin{scb}[style=inline] \scc[F]{true}~\scc[T]{false} \end{scb} } % \end{macrocode} % \end{macro} % \end{environment} % % \begin{macro}{\fillinsol} % \begin{macrocode} \stex_keys_define:nnnn{fillinsol}{ \tl_clear:N \l_@@_fillin_solution_tl \dim_zero:N \l_stex_key_testspace_dim }{ testspace .dim_set:N = \l_stex_key_testspace_dim, exact .code:n = {\_@@_parse_fillin_arg:nnnn{exact}#1 }, numrange .code:n = {\_@@_parse_fillin_arg:nnnn{numrange}#1 }, regex .code:n = {\_@@_parse_fillin_arg:nnnn{regex}#1 } }{} \cs_new:Nn \_@@_parse_fillin_arg:nnnn { \stex_if_do_html:TF{ \tl_set:Nn \l_tmpa_tl{#3} \tl_set:Nn \l_tmpb_tl{T} \stex_annotate_invisible:nn{ shtml:fillin-case={#1}, shtml:fillin-case-value={#2}, shtml:fillin-case-verdict={ \tl_if_eq:NNTF\l_tmpa_tl\l_tmpb_tl{true}{false} }, }{#4} }{ \tl_put_right:Nn \l_@@_fillin_solution_tl { #1{~} & #2{~} & #3{~} & #4{~} \\ } } } \newcommand\fillinsol[2][]{ \quad \mode_if_math:TF{ \hbox{\_@@_fillinsol:nn{#1}{$#2$}} }{ \_@@_fillinsol:nn{#1}{#2} } \quad } \cs_new_protected:Nn \_@@_fillinsol:nn { \stex_keys_set:nn{fillinsol}{#1} \stex_if_do_html:TF{ \stex_annotate:nn{shtml:fillinsol={}}{ \_stex_annotate_force_break:n{ #2 \l_@@_fillin_solution_tl } } }{ \ifsolutions \textcolor{red}{\fbox{#2}} \tl_if_empty:NF \l_@@_fillin_solution_tl { \footnote{ \halign{ ##\hfil & ##\hfil &##\hfil&##\hfil \cr \textbf{type }&\textbf{case }&\textbf{verdict }&\textbf{feedback }\cr \l_@@_fillin_solution_tl } } } \else \fbox{\dim_compare:nNnTF\l_stex_key_testspace_dim={0pt}{ \phantom{\huge{#2}} }{ \hspace{\l_stex_key_testspace_dim} }} \fi } } \stex_deactivate_macro:Nn \fillinsol {sproblem~environments} % \end{macrocode} % \end{macro} % % % \begin{macro}{\testemptypage} % \begin{macrocode} \newcommand\testemptypage[1][]{% \bool_if:NT \c_@@_test_bool {\ \vfill\begin{center}\hwexam@kw@testemptypage\end{center}\eject} } % \end{macrocode} % \end{macro} % % \begin{macro}{\testspace} % \begin{macrocode} \newcommand\testspace[1]{\bool_if:NT \c_@@_test_bool {\vspace*{#1}}} \newcommand\testsmallspace{\testspace{1cm}} \newcommand\testmedspace{\testspace{2cm}} \newcommand\testbigspace{\testspace{3cm}} % \end{macrocode} % \end{macro} % % \begin{macro}{\testnewpage} % \begin{macrocode} \newcommand\testnewpage{\bool_if:NT \c_@@_test_bool {\newpage}} % \end{macrocode} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % \end{implementation} % ^^A \ifinfulldoc\else\printbibliography\fi \endinput %%% Local Variables: %%% mode: doctex %%% TeX-master: t %%% End: % \fi % LocalWords: GPL structuresharing STR dtx pts keyval xcomment CPERL DefKeyVal iffalse % LocalWords: RequirePackage Semiverbatim DefEnvironment OptionalKeyVals soln texttt baz % LocalWords: exnote DefConstructor inclprob NeedsTeXFormat omd.sty textbackslash exfig % LocalWords: stopsolution fileversion filedate maketitle setcounter tocdepth newpage % LocalWords: tableofcontents showmeta showmeta solutionstrue usepackage minipage hrule % LocalWords: linewidth elefants.prob Elefants smallskip noindent textbf startsolutions % LocalWords: startsolutions stopsolutions stopsolutions includeproblem includeproblem % LocalWords: textsf HorIacJuc cscpnrr11 includemhproblem includemhproblem importmodule % LocalWords: importmhmodule foobar ldots latexml mhcurrentrepos mh-variants mh-variant % LocalWords: compactenum langle rangle langle rangle ltxml metakeys newif ifexnotes rm % LocalWords: exnotesfalse exnotestrue ifhints hintsfalse hintstrue ifsolutions ifpts % LocalWords: solutionsfalse ptsfalse ptstrue ifmin minfalse mintrue ifboxed boxedfalse % LocalWords: boxedtrue sref mdframed marginpar prob srefaddidkey addmetakey refnum kv % LocalWords: newcounter ifx thesection theproblem hfill newenvironment metasetkeys ltx % LocalWords: stepcounter currentsectionlevel xspace ignorespaces surroundwithmdframed % LocalWords: omdoc autoopen autoclose solvedinminutes kvi qw vals newcommand exhint % LocalWords: specialcomment excludecomment mhrepos xref marginpar addtocounter doctex % LocalWords: mh@currentrepos endinput