diff options
author | Norbert Preining <norbert@preining.info> | 2023-03-22 03:01:52 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-03-22 03:01:52 +0000 |
commit | cbbc6dbdbf08b70a7e7d8d184ca51c57c835415a (patch) | |
tree | 97ded8ca7095c54f6ff9b661be6b93f80bf792c4 /macros/latex/contrib/stex/source/problem.dtx | |
parent | de9a0afa47c2ee09e1d4704821cad2b231d36b3f (diff) |
CTAN sync 202303220301
Diffstat (limited to 'macros/latex/contrib/stex/source/problem.dtx')
-rw-r--r-- | macros/latex/contrib/stex/source/problem.dtx | 638 |
1 files changed, 638 insertions, 0 deletions
diff --git a/macros/latex/contrib/stex/source/problem.dtx b/macros/latex/contrib/stex/source/problem.dtx new file mode 100644 index 0000000000..c62a9242ba --- /dev/null +++ b/macros/latex/contrib/stex/source/problem.dtx @@ -0,0 +1,638 @@ +% \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 +%</driver> +% \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/03/19}{3.3.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 +} +\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 {\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} +\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 +}{ + 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, + 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} +\newcounter{pts} +\newcounter{min} +\stex_new_stylable_env:nnnnnnn {problem} {O{}}{ + \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} + \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:No \stex_module_setup:n \l_stex_key_name_str + + \stex_if_do_html:T { + \exp_args:Nne \begin{stex_annotate_env} { + shtml:problem={\l_stex_current_module_str}, + shtml:language={ \l_stex_current_language_str}, + shtml:signature={\l_stex_key_sig_str} + \tl_if_empty:NF \l_stex_metatheory_uri {, + shtml:metatheory={\stex_uri_use:N \l_stex_metatheory_uri} + } + } + \stex_annotate_invisible:n{} + \tl_if_empty:NF \l_stex_key_title_tl { + \exp_args:No \stexdoctitle \l_stex_key_title_tl + } + } + \stex_if_smsmode:F { + \str_set_eq:NN \thismoduleuri \l_stex_current_module_str + \tl_set_eq:NN \thismodulename \l_stex_key_name_str + \tl_set_eq:NN \thistitle \l_stex_key_title_tl + \stex_style_apply: + \addtocounter{pts}{\l_stex_key_pts_tl} + \addtocounter{min}{\l_stex_key_min_tl} + \_stex_do_id: + \_@@_record_problem: + } + \stex_reactivate_macro:N \solution + \stex_reactivate_macro:N \mcb + \stex_reactivate_macro:N \fillinsol + \stex_smsmode_do: +}{ + \stex_close_module: + \stex_if_smsmode:F \stex_style_apply: + \stex_if_do_html:T{ \end{stex_annotate_env} } +}{ + \par\noindent\problemheader + \bool_if:NT \c_@@_pts_bool { + \marginpar{\l_stex_key_pts_tl{}~\problem@kw@points\smallskip} + } + \bool_if:NT \c_@@_min_bool { + \marginpar{\l_stex_key_min_tl{}~\problem@kw@minutes\smallskip} + } + \\ + \stex_ignore_spaces_and_pars: +}{ + \par\bigskip +% \bool_if:NT \c_@@_test_bool \pagebreak +}{s} +\stex_sms_allow_env:n{sproblem} + +\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_stex_key_pts_tl}{\l_stex_key_min_tl} + } +} + +\cs_new_protected:Npn \problem@restore #1 #2 #3 {} +% \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 + +\cs_new_protected:Nn \_@@_solution_start:n { + \str_set:Nn \l_stex_key_title_tl {#1} + \str_set:Nn \l_stex_key_id_str {#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 + } + } + \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 + \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\hrule\smallskip + \noindent\emph{Solution\str_if_empty:NF \l_stex_key_title_tl{ + {~}\l_stex_key_title_tl + } :~} +}{ + \par\smallskip\hrule +}{} + +\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} +\cs_new_protected:Nn \_@@_hint_start:n { + \str_set:Nn \l_stex_key_title_tl {#1} + \str_set:Nn \l_stex_key_id_str {#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\hrule\smallskip + \noindent\emph{Hint\str_if_empty:NF \l_stex_key_title_tl{ + {~}\l_stex_key_title_tl + } :~} +}{ + \par\smallskip\hrule +}{} +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{exnote} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_exnote_start:n { + \str_set:Nn \l_stex_key_title_tl {#1} + \str_set:Nn \l_stex_key_id_str {#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\hrule\smallskip + \noindent\emph{Note\str_if_empty:NF \l_stex_key_title_tl{ + {~}\l_stex_key_title_tl + } :~} +}{ + \par\smallskip\hrule +}{} +% \end{macrocode} +% \end{environment} +%% \begin{environment}{gnote} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_gnote_start:n { + \str_set:Nn \l_stex_key_title_tl {#1} + \str_set:Nn \l_stex_key_id_str {#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_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\hrule\smallskip + \noindent\emph{Grading\str_if_empty:NF \l_stex_key_title_tl{ + {~}\l_stex_key_title_tl + } :~} +}{ + \par\smallskip\hrule +}{} +% \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 { + \marginpar{#1~\problem@kw@points} + } +} +\def\min#1{ + \bool_if:NT \c_@@_min_bool { + \marginpar{#1~\problem@kw@minutes} + } +} +% \end{macrocode} +% +% \begin{environment}{mcb} +% +% \begin{macrocode} +\newenvironment{mcb}{\par + \stex_if_do_html:T{ + \begin{stex_annotate_env}{shtml:multiple-choice-block={}} + } + \stex_deactivate_macro:Nn \mcb {sproblem~environments} + \stex_deactivate_macro:Nn \solution {sproblem~environments} + \stex_reactivate_macro:N \mcc + \begin{enumerate} +}{ + \end{enumerate} + \stex_if_do_html:T{ + \end{stex_annotate_env} + } +} +\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 .default:n = { false } , + T .bool_set:N = \l_stex_key_T_bool , + F .default:n = { false } , + 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}\par + \tl_set:Nn \l_tmpb_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} + } + } + \tl_set:Nn \l_tmpa_tl { + #2 + \stex_if_do_html:TF{ + \stex_annotate:nn{shtml:mcc-solution={}}{\l_tmpb_tl} + }{ + \ifsolutions\l_tmpb_tl\fi + } + } + \item[\problem_mcc_box_tl]{}~ + \stex_if_do_html:TF{ + \stex_annotate:nn{shtml:mcc={ + \bool_if:NTF \l_stex_key_T_bool {true}{false} + }}{\l_tmpa_tl} + }{\l_tmpa_tl} +} +\stex_deactivate_macro:Nn \mcc {mcb~environments} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\fillinsol} +% \begin{macrocode} +\newcommand\fillinsol[2][]{ + \quad + \stex_if_do_html:TF{ + \stex_annotate:nn{shtml:fillinsol={}}{ \_stex_annotate_force_break:n{#2} } + }{ + \ifsolutions + \textcolor{red}{\fbox{#2}} + \else + \fbox{ + \tl_if_empty:nTF{#1}{ + \phantom{\huge{#2}} + }{ + \hspace{#1} + } + } + \fi + } + \quad +} +\stex_deactivate_macro:Nn \fillinsol {sproblem~environments} +% \end{macrocode} +% \end{macro} +% +% \end{environment} +% +% +% \begin{macrocode} +%</package> +% \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 + |