% \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\bibfolder{../../lib/bib}
\input{../../doc/stex-docheader}
\RequirePackage[hints,solutions,notes]{problem}

\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
% \fi
% 
% \iffalse\CheckSum{318}\fi
%
% ^^A\changes{v0.9}{2006/09/18}{First Version with Documentation}
% 
% \GetFileInfo{problem.sty}
% 
% \MakeShortVerb{\|}
%
% \title{\texttt{problem.sty}: An Infrastructure for formatting Problems\thanks{Version {\fileversion} (last revised
%        {\filedate})}}
%    \author{Michael Kohlhase\\
%            FAU Erlangen-N\"urnberg\\
%            \url{http://kwarc.info/kohlhase}}
% \maketitle
%
%\ifinfulldoc\else
% This is the documentation for the \pkg{problem} package.
% For a more high-level introduction, 
%  see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the
% \href{\basedocurl/stex.pdf}{full \sTeX documentation}.
%
% \input{../../doc/packages/stex-problem}
% \fi
%
% \begin{documentation}
%   The |problem| package supplies an infrastructure that allows specify problems and to
%   reuse them efficiently in multiple environments.
%
%\section{Introduction}\label{sec:intro}
%
% The |problem| package supplies an infrastructure that allows specify problem.  Problems
% are text fragments that come with auxiliary functions: hints, notes, and
% solutions\footnote{for the moment multiple choice problems are not supported, but may
%   well be in a future version}. Furthermore, we can specify how long the solution to a
% given problem is estimated to take and how many points will be awarded for a perfect
% solution.
% 
% Finally, the |problem| package facilitates the management of problems in small files,
% so that problems can be re-used in multiple environment. 
% 
% \section{The User Interface}\label{sec:ui}
%
% \subsection{Package Options}
% The |problem| package takes the options \DescribeMacro{solutions}|solutions| (should
% solutions be output?), \DescribeMacro{notes}|notes| (should the problem notes be
% presented?), \DescribeMacro{hints}|hints| (do we give the hints?),
% \DescribeMacro{gnotes}|gnotes| (do we show grading notes?), \DescribeMacro{pts}|pts| (do
% we display the points awarded for solving the problem?), \DescribeMacro{min}|min| (do we
% display the estimated minutes for problem soling). If theses are specified, then the
% corresponding auxiliary parts of the problems are output, otherwise, they remain
% invisible.
% 
% The \DescribeMacro{boxed}|boxed| option specifies that problems should be formatted in
% framed boxes so that they are more visible in the text. Finally, the
% \DescribeMacro{test}|test| option signifies that we are in a test situation, so this
% option does not show the solutions (of course), but leaves space for the students to
% solve them.
%
% The \DescribeMacro{mh}|mh| option turns on MathHub support; see \cite{Kohlhase:mss}.
% 
% Finally, if the \DescribeMacro{showmeta}|showmeta| is set, then the metadata keys are
% shown (see~\cite{Kohlhase:metakeys} for details and customization options).
% 
% \subsection{Problems and Solutions}\label{sec:user:probsols}
%
% \DescribeEnv{problem} The main environment provided by the |problem| package is
% (surprise surprise) the |problem| environment. It is used to mark up problems and
% exercises. The environment takes an optional KeyVal argument with the keys
% \DescribeMacro{id}|id| as an identifier that can be reference later,
% \DescribeMacro{pts}|pts| for the points to be gained from this exercise in homework or
% quiz situations, \DescribeMacro{min}|min| for the estimated minutes needed to solve the
% problem, and finally \DescribeMacro{title}|title| for an informative title of the
% problem. For an example of a marked up problem see Figure~\ref{fig:problem} and the
% resulting markup see Figure~\ref{fig:result}. 
%
%\begin{exfig}
% \begin{verbatim}
% \usepackage[solutions,hints,pts,min]{problem}
% \begin{document}
%   \begin{sproblem}[id=elefants,pts=10,min=2,title=Fitting Elefants]
%     How many Elefants can you fit into a Volkswagen beetle?
% \begin{hint}
%   Think positively, this is simple!
% \end{hint}
% \begin{exnote}
%   Justify your answer
% \end{exnote}
% \begin{solution}[for=elefants,height=3cm]
%   Four, two in the front seats, and two in the back.
% \begin{gnote}
%   if they do not give the justification deduct 5 pts
% \end{gnote}
% \end{solution}
%   \end{sproblem}
% \end{document}
% \end{verbatim}
% \caption{A marked up Problem}\label{fig:problem}
% \end{exfig}
%
% \DescribeEnv{solution} The |solution| environment can be to specify a solution to a
% problem. If the \DescribeMacro{solutions}|solutions| option is set or |\solutionstrue|
% is set in the text, then the solution will be presented in the output. The |solution|
% environment takes an optional KeyVal argument with the keys \DescribeMacro{id}|id| for
% an identifier that can be reference \DescribeMacro{for}|for| to specify which problem
% this is a solution for, and \DescribeMacro{height}|height| that allows to specify the
% amount of space to be left in test situations (i.e. if the \DescribeMacro{test}|test|
% option is set in the |\usepackage| statement).
%
%\begin{exfig}
% \begin{minipage}{.9\linewidth}
% \begin{sproblem}[id=elefants.prob,title=Fitting Elefants]
%   How many Elefants can you fit into a Volkswagen beetle?
% \begin{hint}
%   Think positively, this is simple!
% \end{hint}
% \begin{exnote}
%   Justify your answer
% \end{exnote}
% \smallskip\noindent\hrule\textbf{Solution:}
%   Four, two in the front seats, and two in the back.
% \hrule
% \end{sproblem}
% \end{minipage}
% \caption{The Formatted Problem from Figure~\ref{fig:problem}}\label{fig:result}
% \end{exfig}
% 
% \DescribeEnv{hint}\DescribeEnv{exnote} The |hint| and |exnote| environments can be used
% in a |problem| environment to give hints and to make notes that elaborate certain
% aspects of the problem.
%
% \DescribeEnv{gnote} The |gnote| (grading notes) environment can be used to document
% situtations that may arise in grading. 
%
% Sometimes we would like to locally override the |solutions| option we have given to the
% package. To turn on solutions we use the
% \DescribeMacro{\startsolutions}|\startsolutions|, to turn them off,
% \DescribeMacro{\stopsolutions}|\stopsolutions|. These two can be used at any point in
% the documents.
%
% Also, sometimes, we want content (e.g. in an exam with master solutions) conditional on
% whether solutions are shown. This can be done with the
% \DescribeMacro{\ifsolutions}|\ifsolutions| conditional.
%
% \subsection{Multiple Choice Blocks}\label{sec:user:mcq}
% 
% Multiple choice blocks can be formatted using the \DescribeMacro{mcb}|mcb| environment,
% in which single choices are marked up with
% \DescribeMacro{\mcc}|\mcc[|\meta{keyvals}|]{|\meta{text}|}| macro, which takes an
% optional key/value argument \meta{keyvals} for choice metadata and a required argument
% \meta{text} for the proposed answer text. The following keys are supported
% \begin{itemize}
% \item \DescribeMacro{T}|T| for true answers, \DescribeMacro{F}|F| for false ones,
% \item \DescribeMacro{Ttext}|Ttext| the verdict for true answers,
%   \DescribeMacro{Ftext}|Ftext| for false ones, and
% \item \DescribeMacro{feedback}|feedback| for a short feedback text given to the student.
% \end{itemize}
% See Figure~\ref{fig: mcq} for an example
%\begin{exfig}
% \begin{verbatim}
% \begin{sproblem}[title=Functions]
%   What is the keyword to introduce a function definition in python?
%   \begin{mcb}
%     \mcc[T]{def}
%     \mcc[F,feedback=that is for C and C++]{function}
%     \mcc[F,feedback=that is for Standard ML]{fun}
%     \mcc[F,Ftext=Nooooooooo,feedback=that is for Java]{public static void}
%   \end{mcb}
% \end{sproblem}
% \end{verbatim}
%  \solutionsfalse\hrule
% \begin{sproblem}[title=Functions]
%   What is the keyword to introduce a function definition in python?
%   \begin{mcb}
%     \mcc[T]{def}
%     \mcc[F,feedback=that is for C and C++]{function}
%     \mcc[F,feedback=that is for Standard ML]{fun}
%     \mcc[F,Ftext=Nooooooooo,feedback=that is for Java]{public static void}
%   \end{mcb}
% \end{sproblem}
% \solutionstrue\hrule
% \begin{sproblem}[title=Functions]
%   What is the keyword to introduce a function definition in python?
%   \begin{mcb}
%     \mcc[T]{def}
%     \mcc[F,feedback=that is for C and C++]{function}
%     \mcc[F,feedback=that is for Standard ML]{fun}
%     \mcc[F,Ftext=Nooooooooo,feedback=that is for Java]{public static void}
%   \end{mcb}
% \end{sproblem}
% \caption{A Problem with a multiple choice block}\label{fig:mcq}
% \end{exfig}
% 
% \subsection{Including Problems}\label{sec:user:includeproblem}
% 
% The \DescribeMacro{\includeproblem}|\includeproblem| macro can be used to include a
% problem from another file. It takes an optional KeyVal argument and a second argument
% which is a path to the file containing the problem (the macro assumes that there is only
% one problem in the include file). The keys \DescribeMacro{title}|title|,
% \DescribeMacro{min}|min|, and \DescribeMacro{pts}|pts| specify the problem title, the
% estimated minutes for solving the problem and the points to be gained, and their values
% (if given) overwrite the ones specified in the |problem| environment in the included
% file.
% 
% \subsection{Reporting Metadata}\label{sec:user:reporting}
% 
% The sum of the points and estimated minutes (that we specified in the |pts| and |min|
% keys to the |problem| environment or the |\includeproblem| macro) to the log file and
% the screen after each run. This is useful in preparing exams, where we want to make sure
% that the students can indeed solve the problems in an allotted time period.
% 
% The |\min| and |\pts| macros allow to specify (i.e. to print to the margin) the
% distribution of time and reward to parts of a problem, if the |pts| and |pts| package
% options are set. This allows to give students hints about the estimated time and the
% points to be awarded.
%
% \section{Limitations}\label{sec:limitations}
% 
% In this section we document known limitations. If you want to help alleviate them,
% please feel free to contact the package author. Some of them are currently discussed in
% the \sTeX GitHub repository~\cite{sTeX:github:on}. 
% \begin{enumerate}
% \item none reported yet
% \end{enumerate}
% 
% \end{documentation}
% \begin{implementation}
%
% \section{The Implementation}\label{sec:implementation}
% 
% \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}{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_@@_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,
  unknown   .code:n       = {}
}
\newif\ifsolutions

\ProcessKeysOptions{ problem / pkg }
\bool_if:NTF \c_@@_solutions_bool {
  \solutionstrue
}{
  \solutionsfalse
}
%    \end{macrocode}
%
% Then we make sure that the necessary packages are loaded (in the right versions).
%    \begin{macrocode}
\RequirePackage{comment}
%    \end{macrocode}
%
% The next package relies on the \LaTeX3 kernel, which \latexml only partially
% supports. As it is purely presentational, we only load it when the |boxed| option is
% given and we run {\latexml}.
%
%    \begin{macrocode}
\bool_if:NT \c_@@_boxed_bool { \RequirePackage{mdframed} }
%    \end{macrocode}
%
% \begin{macro}{\prob@*@kw}
%   For multilinguality, we define internal macros for keywords that can be specialized in
%   |*.ldf| files. 
%    \begin{macrocode}
\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}
%    \end{macrocode}
% \end{macro}
% 
% For the other languages, we set up triggers
%    \begin{macrocode}
\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
  }{}
}
%    \end{macrocode}
%
% \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}
\keys_define:nn{ problem / problem }{
  id      .str_set_x:N  = \l_@@_prob_id_str,
  pts     .tl_set:N     = \l_@@_prob_pts_tl,
  min     .tl_set:N     = \l_@@_prob_min_tl,
  title   .tl_set:N     = \l_@@_prob_title_tl,
  type    .tl_set:N     = \l_@@_prob_type_tl,
  refnum  .int_set:N    = \l_@@_prob_refnum_int
}
\cs_new_protected:Nn \_@@_prob_args:n {
  \str_clear:N \l_@@_prob_id_str
  \tl_clear:N \l_@@_prob_pts_tl
  \tl_clear:N \l_@@_prob_min_tl
  \tl_clear:N \l_@@_prob_title_tl
  \tl_clear:N \l_@@_prob_type_tl
  \int_zero_new:N \l_@@_prob_refnum_int
  \keys_set:nn { problem / problem }{ #1 }
  \int_compare:nNnT \l_@@_prob_refnum_int = 0 {
    \let\l_@@_prob_refnum_int\undefined
  }
}
%    \end{macrocode}
%
% Then we set up a counter for problems.
% \begin{macro}{\numberproblemsin}
%    \begin{macrocode}
\newcounter{problem}
\newcommand\numberproblemsin[1]{\@addtoreset{problem}{#1}}
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\prob@label}
%   We provide the macro |\prob@label| to redefine later to get context involved. 
%    \begin{macrocode}
\newcommand\prob@label[1]{#1} 
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\prob@number}
%   We consolidate the problem number into a reusable internal macro
%    \begin{macrocode}
\newcommand\prob@number{
  \int_if_exist:NTF \l_@@_inclprob_refnum_int {
    \prob@label{\int_use:N \l_@@_inclprob_refnum_int }
  }{
    \int_if_exist:NTF \l_@@_prob_refnum_int {
      \prob@label{\int_use:N \l_@@_prob_refnum_int }
    }{
        \prob@label\theproblem
    }
  }
}
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\prob@title}
%   We consolidate the problem title into a reusable internal macro as well. |\prob@title|
%   takes three arguments the first is the fallback when no title is given at all, the
%   second and third go around the title, if one is given.
%    \begin{macrocode}
\newcommand\prob@title[3]{%
  \tl_if_exist:NTF \l_@@_inclprob_title_tl {
    #2 \l_@@_inclprob_title_tl #3
  }{
    \tl_if_exist:NTF \l_@@_prob_title_tl {
      #2 \l_@@_prob_title_tl #3
    }{
      #1
    }
  }
}
%    \end{macrocode}
% \end{macro}
% 
% With these the problem header is a one-liner
%
% \begin{macro}{\prob@heading}
%   We consolidate the problem header line into a separate internal macro that can be
%   reused in various settings. 
%    \begin{macrocode}
\def\prob@heading{
  {\prob@problem@kw}\ \prob@number\prob@title{~}{~(}{)\strut}
  %\sref@label@id{\prob@problem@kw~\prob@number}{}
}
%    \end{macrocode}
% \end{macro}
% 
% With this in place, we can now define the |problem| environment. It comes in two shapes,
% depending on whether we are in boxed mode or not. In both cases we increment the problem
% number and output the points and minutes (depending) on whether the respective options
% are set.
% \begin{environment}{sproblem}
%    \begin{macrocode}
\newenvironment{sproblem}[1][]{
  \_@@_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_@@_inclprob_type_tl {
    \tl_set_eq:NN \sproblemtype \l_@@_inclprob_type_tl
  }{
    \tl_set_eq:NN \sproblemtype \l_@@_prob_type_tl
  }
  \str_if_exist:NTF \l_@@_inclprob_id_str {
    \str_set_eq:NN \sproblemid \l_@@_inclprob_id_str
  }{
    \str_set_eq:NN \sproblemid \l_@@_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 {_@@_sproblem_##1_start:}{
      \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sproblem_##1_start:}}
    }
  }
  \tl_if_empty:NTF \l_tmpa_tl {
    \_@@_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 {_@@_sproblem_##1_end:}{
      \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sproblem_##1_end:}}
    }
  }
  \tl_if_empty:NTF \l_tmpa_tl {
    \_@@_sproblem_end:
  }{
    \l_tmpa_tl
  }


  \smallskip
}


\cs_new_protected:Nn \_@@_sproblem_start: {
  \par\noindent\textbf\prob@heading\show@pts\show@min\\\ignorespacesandpars
}
\cs_new_protected:Nn \_@@_sproblem_end: {\par\smallskip}

\newcommand\stexpatchproblem[3][] {
    \str_set:Nx \l_tmpa_str{ #1 }
    \str_if_empty:NTF \l_tmpa_str {
      \tl_set:Nn \_@@_sproblem_start: { #2 }
      \tl_set:Nn \_@@_sproblem_end: { #3 }
    }{
      \exp_after:wN \tl_set:Nn \csname _@@_sproblem_#1_start:\endcsname{ #2 }
      \exp_after:wN \tl_set:Nn \csname _@@_sproblem_#1_end:\endcsname{ #3 }
    }
}


\bool_if:NT \c_@@_boxed_bool {
  \surroundwithmdframed{problem}
}
%    \end{macrocode}
% \end{environment}
% 
% \begin{macro}{\record@problem}
%   This macro records information about the problems in the |*.aux| file. 
%    \begin{macrocode}
\def\record@problem{
  \protected@write\@auxout{}
  {
    \string\@problem{\prob@number}
    {
      \tl_if_exist:NTF \l_@@_inclprob_pts_tl {
        \l_@@_inclprob_pts_tl
      }{
        \l_@@_prob_pts_tl
      }
    }%
    {
      \tl_if_exist:NTF \l_@@_inclprob_min_tl {
        \l_@@_inclprob_min_tl
      }{
        \l_@@_prob_min_tl
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@problem}
%   This macro acts on a problem's record in the |*.aux| file. It does not have any
%   functionality here, but can be redefined elsewhere (e.g. in the |assignment|
%   package). 
%    \begin{macrocode}
\def\@problem#1#2#3{}
%    \end{macrocode}
% \end{macro}
% 
% The \DescribeEnv{solution}|solution| environment is similar to the |problem|
% environment, only that it is independent of the boxed mode. It also has it's own keys
% that we need to define first.
% 
%    \begin{macrocode}
\keys_define:nn { problem / solution }{
  id            .str_set_x:N  = \l_@@_solution_id_str ,
  for           .tl_set:N     = \l_@@_solution_for_tl ,
  height        .dim_set:N    = \l_@@_solution_height_dim ,
  creators      .clist_set:N  = \l_@@_solution_creators_clist ,
  contributors  .clist_set:N  = \l_@@_solution_contributors_clist ,
  srccite       .tl_set:N     = \l_@@_solution_srccite_tl
}
\cs_new_protected:Nn \_@@_solution_args:n {
  \str_clear:N \l_@@_solution_id_str
  \tl_clear:N \l_@@_solution_for_tl
  \tl_clear:N \l_@@_solution_srccite_tl
  \clist_clear:N \l_@@_solution_creators_clist
  \clist_clear:N \l_@@_solution_contributors_clist
  \dim_zero:N \l_@@_solution_height_dim
  \keys_set:nn { problem / solution }{ #1 }
}
%    \end{macrocode}
% the next step is to define a helper macro that does what is needed to start a solution. 
%    \begin{macrocode}
\newcommand\@startsolution[1][]{
  \_@@_solution_args:n { #1 }
  \@in@omtexttrue% we are in a statement.
  \bool_if:NF \c_@@_boxed_bool { \hrule }
  \smallskip\noindent
  {\textbf\prob@solution@kw :\enspace}
  \begin{small}
  \def\current@section@level{\prob@solution@kw}
  \ignorespacesandpars
}
%    \end{macrocode}
%
% \begin{macro}{\startsolutions}
% for the |\startsolutions| macro we use the |\specialcomment| macro from the |comment|
% package. Note that we use the |\@startsolution| macro in the start codes, that parses
% the optional argument. 
%    \begin{macrocode}
\newcommand\startsolutions{
  \specialcomment{solution}{\@startsolution}{
    \bool_if:NF \c_@@_boxed_bool {
      \hrule\medskip
    }
    \end{small}%
  }
  \bool_if:NT \c_@@_boxed_bool {
    \surroundwithmdframed{solution}
  }
}
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\stopsolutions}
%    \begin{macrocode}
\newcommand\stopsolutions{\excludecomment{solution}}
%    \end{macrocode}
% \end{macro}
% 
% so it only remains to start/stop solutions depending on what option was specified.
%
%    \begin{macrocode}
\ifsolutions
  \startsolutions
\else
  \stopsolutions
\fi
%    \end{macrocode}
%
% \begin{environment}{exnote}
%    \begin{macrocode}
\bool_if:NTF \c_@@_notes_bool {
  \newenvironment{exnote}[1][]{
    \par\smallskip\hrule\smallskip
    \noindent\textbf{\prob@note@kw : }\small
  }{
    \smallskip\hrule
  }
}{
  \excludecomment{exnote}
}
%    \end{macrocode}
% \end{environment}
% 
% \begin{environment}{hint}
%    \begin{macrocode}
\bool_if:NTF \c_@@_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}
}
%    \end{macrocode}
% \end{environment}
% 
% \begin{environment}{gnote}
%    \begin{macrocode}
\bool_if:NTF \c_@@_notes_bool {
  \newenvironment{gnote}[1][]{
    \par\smallskip\hrule\smallskip
    \noindent\textbf{\prob@gnote@kw : }\small
  }{
    \smallskip\hrule
  }
}{
  \excludecomment{gnote}
}
%    \end{macrocode}
% \end{environment}
% 
% \subsection{Multiple Choice Blocks}\label{sec:impl:mcq}
%
% \begin{environment}{mcb}
%   \ednote{MK: maybe import something better here from a dedicated MC package}
%    \begin{macrocode}
\newenvironment{mcb}{
  \begin{enumerate}
}{
  \end{enumerate}
}
%    \end{macrocode}
% \end{environment}
% 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
  }
}
\keys_define:nn { problem / mcc }{
  id        .str_set_x:N  = \l_@@_mcc_id_str ,
  feedback  .tl_set:N     = \l_@@_mcc_feedback_tl ,
  T         .default:n    = { true } ,
  T         .bool_set:N   = \l_@@_mcc_t_bool ,
  F         .default:n    = { true } ,
  F         .bool_set:N   = \l_@@_mcc_f_bool ,
  Ttext     .code:n       = {
    \_@@_do_yes_param:Nn \l_@@_mcc_Ttext_bool { #1 }
  } ,
  Ftext     .code:n       = {
    \_@@_do_yes_param:Nn \l_@@_mcc_Ftext_bool { #1 }
  }
}
\cs_new_protected:Nn \l_@@_mcc_args:n {
  \str_clear:N \l_@@_mcc_id_str
  \tl_clear:N \l_@@_mcc_feedback_tl
  \bool_set_true:N \l_@@_mcc_t_bool
  \bool_set_true:N \l_@@_mcc_f_bool
  \bool_set_true:N \l_@@_mcc_Ttext_bool
  \bool_set_false:N \l_@@_mcc_Ftext_bool
  \keys_set:nn { problem / mcc }{ #1 }
}
%    \end{macrocode}
%
% \begin{macro}{\mcc}
%    \begin{macrocode}
\newcommand\mcc[2][]{
  \l_@@_mcc_args:n{ #1 }
  \item #2
  \ifsolutions
    \\
    \bool_if:NT \l_@@_mcc_t_bool {
      % TODO!
      % \ifcsstring{mcc@T}{T}{}{\mcc@Ttext}%
    }
    \bool_if:NT \l_@@_mcc_f_bool {
      % TODO!
      % \ifcsstring{mcc@F}{F}{}{\mcc@Ftext}%
    }
    \tl_if_empty:NTF \l_@@_mcc_feedback_tl {
      !
    }{
      \l_@@_mcc_feedback_tl
    }
  \fi
} %solutions
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Including Problems}\label{sec:impl:includeproblem}
%
% \begin{macro}{\includeproblem}
%   The |\includeproblem| command is essentially a glorified |\input| statement, it sets
%   some internal macros first that overwrite the local points. Importantly, it resets the
%   |inclprob| keys after the input. 
%    \begin{macrocode}

\keys_define:nn{ problem / inclproblem }{
  id      .str_set_x:N  = \l_@@_inclprob_id_str,
  pts     .tl_set:N     = \l_@@_inclprob_pts_tl,
  min     .tl_set:N     = \l_@@_inclprob_min_tl,
  title   .tl_set:N     = \l_@@_inclprob_title_tl,
  refnum  .int_set:N    = \l_@@_inclprob_refnum_int,
  type    .tl_set:N     = \l_@@_inclprob_type_tl,
  mhrepos .str_set_x:N  = \l_@@_inclprob_mhrepos_str
}
\cs_new_protected:Nn \_@@_inclprob_args:n {
  \str_clear:N \l_@@_prob_id_str
  \tl_clear:N \l_@@_inclprob_pts_tl
  \tl_clear:N \l_@@_inclprob_min_tl
  \tl_clear:N \l_@@_inclprob_title_tl
  \tl_clear:N \l_@@_inclprob_type_tl
  \int_zero_new:N \l_@@_inclprob_refnum_int
  \str_clear:N \l_@@_inclprob_mhrepos_str
  \keys_set:nn { problem / inclproblem }{ #1 }
  \tl_if_empty:NT \l_@@_inclprob_pts_tl {
    \let\l_@@_inclprob_pts_tl\undefined
  }
  \tl_if_empty:NT \l_@@_inclprob_min_tl {
    \let\l_@@_inclprob_min_tl\undefined
  }
  \tl_if_empty:NT \l_@@_inclprob_title_tl {
    \let\l_@@_inclprob_title_tl\undefined
  }
  \tl_if_empty:NT \l_@@_inclprob_type_tl {
    \let\l_@@_inclprob_type_tl\undefined
  }
  \int_compare:nNnT \l_@@_inclprob_refnum_int = 0 {
    \let\l_@@_inclprob_refnum_int\undefined
  }
}

\cs_new_protected:Nn \_@@_inclprob_clear: {
  \let\l_@@_inclprob_id_str\undefined
  \let\l_@@_inclprob_pts_tl\undefined
  \let\l_@@_inclprob_min_tl\undefined
  \let\l_@@_inclprob_title_tl\undefined
  \let\l_@@_inclprob_type_tl\undefined
  \let\l_@@_inclprob_refnum_int\undefined
  \let\l_@@_inclprob_mhrepos_str\undefined
}
\_@@_inclprob_clear:

\newcommand\includeproblem[2][]{
  \_@@_inclprob_args:n{ #1 }
  \str_if_empty:NTF \l_@@_inclprob_mhrepos_str {
    \input{#2}
  }{
    \stex_in_repository:nn{\l_@@_inclprob_mhrepos_str}{
      \input{\mhpath{\l_@@_inclprob_mhrepos_str}{#2}}
    }
  }
  \_@@_inclprob_clear:
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Reporting Metadata}
%
% For messages it is OK to have them in English as the whole documentation is, and we can
% therefore assume authors can deal with it. 
%
%    \begin{macrocode}
\AddToHook{enddocument}{
  \bool_if:NT \c_@@_pts_bool {
    \message{Total:~\arabic{pts}~points}
  }
  \bool_if:NT \c_@@_min_bool {
    \message{Total:~\arabic{min}~minutes}
  }
}
%    \end{macrocode}
%
% The margin pars are reader-visible, so we need to translate
% 
%    \begin{macrocode}
\def\pts#1{
  \bool_if:NT \c_@@_pts_bool {
    \marginpar{#1~\prob@pt@kw}
  }
}
\def\min#1{
  \bool_if:NT \c_@@_min_bool {
    \marginpar{#1~\prob@min@kw}
  }
}
%    \end{macrocode}
%
% \begin{macro}{\show@pts}
%   The |\show@pts| shows the points: if no points are given from the outside and also no
%   points are given locally do nothing, else show and add. If there are outside points
%   then we show them in the margin.
%    \begin{macrocode}
\newcounter{pts}
\def\show@pts{
  \tl_if_exist:NTF \l_@@_inclprob_pts_tl {
    \bool_if:NT \c_@@_pts_bool {
      \marginpar{\l_@@_inclprob_pts_tl\ \prob@pt@kw\smallskip}
      \addtocounter{pts}{\l_@@_inclprob_pts_tl}
    }
  }{
    \tl_if_exist:NT \l_@@_prob_pts_tl {
      \bool_if:NT \c_@@_pts_bool {
        \marginpar{\l_@@_prob_pts_tl\ \prob@pt@kw\smallskip}
        \addtocounter{pts}{\l_@@_prob_pts_tl}
      }
    }
  }
}
%    \end{macrocode}
% \end{macro}
% and now the same for the minutes
% \begin{macro}{\show@min}
%    \begin{macrocode}
\newcounter{min}
\def\show@min{
  \tl_if_exist:NTF \l_@@_inclprob_min_tl {
    \bool_if:NT \c_@@_min_bool {
      \marginpar{\l_@@_inclprob_pts_tl\ min}
      \addtocounter{min}{\l_@@_inclprob_min_tl}
    }
  }{
    \tl_if_exist:NT \l_@@_prob_min_tl {
      \bool_if:NT \c_@@_min_bool {
        \marginpar{\l_@@_prob_min_tl\ min}
        \addtocounter{min}{\l_@@_prob_min_tl}
      }
    }
  }
}
%</package>
%    \end{macrocode}
% \end{macro}
% \end{implementation}
\endinput
% LocalWords:  GPL structuresharing STR dtx pts keyval xcomment CPERL DefKeyVal iffalse
%%% Local Variables: 
%%% mode: doctex
%%% TeX-master: t
%%% End: 
% \fi
% 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

