% \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/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}
%</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