Filter exercises according to their difficulty

This is somehow a follow-up question after this question. I came across this problem when writing the answer, but I was wrong when I thought I would easily be able to get this to work later. Shame.

The problem is that while the filter works correctly for keys such as type, it doesn't for the key difficulty.

Here is a MWE :

\documentclass{article}

\usepackage{exercise}

\begin{document}

Here is a short exercise :

\ExerciseSelect[type={short}]

\begin{Exercise}[type={short}]
Prove that $1+1=2$.
\end{Exercise}

\begin{Exercise}[type={long}]
Prove that $P \neq NP$.
\end{Exercise}

\ExerciseStopSelect

\vspace{1cm}\hrule\vspace{1cm}

Now here is a hard exercise :
\ExerciseSelect[difficulty={2}]

\begin{Exercise}[difficulty=0]
Prove that $1+1=2$.
\end{Exercise}

\begin{Exercise}[difficulty=2]
Prove that $P \neq NP$.
\end{Exercise}

\ExerciseStopSelect

Or an easy one :

\ExerciseSelect[difficulty={0}]

\begin{Exercise}[difficulty={0}]
Prove that $1+1=2$.
\end{Exercise}

\begin{Exercise}[difficulty={2}]
Prove that $P \neq NP$.
\end{Exercise}

\ExerciseStopSelect

\end{document}


And its output :

As you can see, nothing is selected by the difficulty filters.

-
First your code isn't quite following the format outlined in the manual. But even when fixed, I still have the same difficulty. After looking around inside the package itself, I'm wondering whether it has to do with the way the key-value is being evaluated in exercise.sty. – A.Ellett Nov 26 '12 at 20:43
@A.Ellett : What parts of my code are different from the manual, exactly? In the \ExerciseSelect, or in the Exercise environment? – T. Verron Nov 26 '12 at 21:10
You left off some "{" and "}" that the manual seems to imply are necessary. Such as [difficulty={1}] – A.Ellett Nov 26 '12 at 21:18
I'm wondering about this portion of the code in the exercise.sty package: \define@key{PPExercise}{difficulty}% {\global\@ExeDifficultytrue\global\ExerciseDifficulty=\number#1} What's \number doing? – A.Ellett Nov 26 '12 at 21:19
@A.Ellett : you mean in \begin{Exercise}[difficulty=_1_]? It seems to me he does omit these braces in the manual as well... And anyway, that's why I added two examples, to show that adding of removing them doesn't change anything. – T. Verron Nov 26 '12 at 21:20

The solution is bit more involved than I initially thought. The package exercise relies too heavily on the counter for the level of difficulty for my first approach to be useful. I believe that, when testing the difficulty flag, it is its corresponding counter which is causing the flag not to be raised.

What I've done here is save portions of the code in exercise that I don't really think should be rewritten, but which do need to be augmented. I've also created a new flag call howdifficult. It's set the same way as difficult and I believe has the same desired effects. (I have not yet tested all possible cases, but that would require me to read the manual more thoroughly than I've already done.)

The code below seems to work. The difficulty key triggers several flags. I think this code triggers all the necessary flags. But for the time being, this does give an error-free patch.

\makeatletter
%% Adding new key to the "Exercise" environment
%% save old initialization code in a temporary command and then redefine.
\let\@tmp@InitExe\@InitExe
\def\@InitExe{\@tmp@InitExe%
\gdef\ExerciseHowDifficult{}%
\global\@ExeHowDifficultfalse%
}
%% For "Exercise" environment flags, set key-value="howdifficult" and
%% corresponding flags to true.  Also, set the counter for
%% key-value='difficult'. These additional settings for 'difficulty' may
%% not be necessary; I've put it here just to be on the safe side.
\newif\if@ExeHowDifficult \@ExeHowDifficultfalse
\define@key{PPExercise}{howdifficult}%
{\global\@ExeHowDifficulttrue\gdef\ExerciseHowDifficult{#1}%
\global\@ExeDifficultytrue%
\global\ExerciseDifficulty=\number#1}
%% set the Header       for key-value="howdifficult"
%% to be the header used by key-value="difficulty"
\let\@tmp@getExerciseInfo\@getExerciseInfo
\def\@getExerciseInfo{\@tmp@getExerciseInfo%
}
%% Adding new key to "Exercise Selection" routine to guarantee shipout
%% routine is properly carried out.
%% save old initialization code in a temporary command and then redefine.
\let\@tmp@selectExercise\@selectExercise
\def\@selectExercise{\@tmp@selectExercise%
\if@ExeSelectHowDifficult
\@for\@howdifficult:=\ExerciseSelectHowDifficult\do
{ \ifthenelse{\equal{\@howdifficult}{\ExerciseHowDifficult}}{
\global\@@ShipThisExercisetrue
}{}
}
\if@@ShipThisExercise\else\@ShipThisExercisefalse\fi
\global\@@ShipThisExercisefalse
\fi
}
%% Set appropriate difficulty flags for exercise selection.
\newif\if@ExeSelectHowDifficult          \@ExeSelectHowDifficultfalse
\define@key{PPExerciseSelect}{howdifficult}%
{\global\@ExeSelectHowDifficulttrue\gdef\ExerciseSelectHowDifficult{#1}}
%----------------------------------------------------------------------
%% It's not clear to me that the following code is at all necessary.  I
%% put it here so that the user of the package can completely dispense with
%% all uses of the key-value="difficulty".
%----------------------------------------------------------------------
%% translate infor from key-value="howdifficult" to "\QuestionDifficulty"
\define@key{PPQuestion}{howdifficult}{%
\global\@QuestionDifficultytrue\global\QuestionDifficulty=\number#1}
%% translate infor from key-value="howdifficult" to "\subQuestionDifficulty"
\define@key{PPsubQuestion}{howdifficult}{%
\global\@subQuestionDifficultytrue\global\subQuestionDifficulty=\number#1}
%% translate infor from key-value="howdifficult" to "\subsubQuestionDifficulty"
\define@key{PPsubsubQuestion}{howdifficult}{%
\global\@subsubQuestionDifficultytrue\global\subsubQuestionDifficulty=\number#1}
%% translate infor from key-value="howdifficult" to "\ExePartDifficulty"
\define@key{PPExePart}{howdifficult}{\global\@ExePartDifficultytrue%
\global\ExePartDifficulty=\number#1}
\makeatother


I should point out that using both key-values difficulty and howdifficult may result in uncertain results. So I have added code that, while not entirely necessary, allows the user of the package to forget the key difficulty and user howdifficult in all situations which may call for it.

-
Wow, great work, thanks! I am going to accept this for the time being, and it will probably help the package maintainer when he will try to debug this. To avoid confusing users, I suggest you delete your previous answer, or maybe include it in an edit to the "real" one, as a failed attempt, if you think it may be useful in other contexts. – T. Verron Nov 27 '12 at 21:36