Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested exercises as subexercises #67

Open
cgnieder opened this issue Mar 24, 2020 · 12 comments
Open

Nested exercises as subexercises #67

cgnieder opened this issue Mar 24, 2020 · 12 comments
Labels
discussion discussion about the development of xsim

Comments

@cgnieder
Copy link
Owner

What should be possible or what would be features when nested exercises are used as subexercises?

\documentclass{article}
\usepackage[no-files]{xsim}

\DeclareExerciseType{subquestion}{
  exercise-env = question ,
  solution-env = answer ,
  exercise-name = Question ,
  solution-name = Answer ,
  exercise-template = item ,
  solution-template = item
}

\DeclareExerciseEnvironmentTemplate{item}{\item}{}

\begin{document}

\begin{exercise}
  \ExerciseType:\ExerciseID
  \begin{enumerate}
    \begin{question}[ID=sub-a]
      \ExerciseType:\ExerciseID
    \end{question}
    \begin{answer}
      \ExerciseType:\ExerciseID
    \end{answer}
    \begin{question}[ID=sub-b]
      \ExerciseType:\ExerciseID
    \end{question}
    \begin{answer}
      \ExerciseType:\ExerciseID
    \end{answer}
    \begin{question}[ID=sub-c]
      \ExerciseType:\ExerciseID
    \end{question}
    \begin{answer}
      \ExerciseType:\ExerciseID
    \end{answer}
  \end{enumerate}
  \ExerciseType:\ExerciseID
\end{exercise}

\begin{solution}[print]
  \ExerciseType:\ExerciseID
  \begin{enumerate}
    \printsolution{subquestion}{sub-a}
    \printsolution{subquestion}{sub-b}
    \printsolution{subquestion}{sub-c}
  \end{enumerate}
  \ExerciseType:\ExerciseID
\end{solution}

\end{document}

I encourage users to give their thoughts here.

@cgnieder cgnieder added help wanted this is a tricky issue; any insights welcome discussion discussion about the development of xsim labels Mar 24, 2020
@jonascj
Copy link

jonascj commented Mar 24, 2020

@cgnieder Great idea to collect thoughts on the issue here.

The output of your snippet should be here as well

After 2 minutes of thinking I agree that being able to nest exercises seems very flexible and powerful. I am unsure if the \begin{question}\end{question} is a new suggestion or if it is already a part of xsim, but it looks fine, albeit a bit verbose.

I would be looking to nest once, like:

# Exercise 1
Two cars are traveling in opposite directions. 
They are 2.7km apart, driving 50km/h and 65km/h, respectively.
a) Write the equations of motion for the two cars.
b) Find the time t at which the two cars will meet.
c) Find the distance traveled by the cars when they meet.

I can't imagine I would want to nest any deeper. The following I would try to avoid:

#Exercise 1
a)
   1)
   2)
b)
   1)
   2)

@cgnieder
Copy link
Owner Author

cgnieder commented Apr 7, 2020

After 2 minutes of thinking I agree that being able to nest exercises seems very flexible and powerful. I am unsure if the \begin{question}\end{question} is a new suggestion or if it is already a part of xsim, but it looks fine, albeit a bit verbose.

The question environment was defined in my example in the OP.

As long as the no-files option is active (cf. #68 please) the environments can safely be put inside of custom commands. Customization like this and putting all the personal definitions in a separate style file is even very much encouraged by xsim, something I already had in mind when I started implementing it.

@joneppie
Copy link
Contributor

We have already included subexercises as teilaufgaben in the package schule (see https://gitlab.com/gi-fg-ibnw/schule/-/blob/master/latex/schule.mod.Aufgaben.code.tex#L96 ). It would be appreciated if this would work directly with xsim, respecting the following points: The points of the subexercises should be added to the score of the exercise. When outputting the solution of a exercise, the solutions of the subexercises must also be output. Properties of the subexercises must also be accessible. About it we realize the expectation horizon, which works so far only for the exercise completely (see https://gitlab.com/gi-fg-ibnw/schule/-/blob/master/latex/schule.mod.Bewertung.code.tex#L80 ).

@N-Coder
Copy link
Contributor

N-Coder commented Feb 15, 2021

Sorry for taking some time to comment here. Here's a summary of what I've been trying to do with the steps mentioned in issue #57.

  • I want to combine exercises with nested subexercises and flat exercises without any nesting in the same document. This also means that the former exercises should have the sum of the points of their subexercises as points, while the latter directly state the total number of points they have. See tasks 5 and 6 here for an example.

  • In the grading table on the front of the document, I only want the top-level exercises listed, together with their total number of points (no matter whether these come from sub-exercises or not).

  • In the header of the exercise, I'd like to indicate its total amount of points and how that is split across the different subtasks, e.g. something like [5+3+2 = 10 Points] for subtasks a, b and c being worth 5, 3 and 2 points respectively.

  • When using subexercises, I'd like to have the full flexibility of the xsim templating mechanism combined with the enumitem package. This includes the following:

    • define the item label format (i.e. a), A., 1., I,..., probably on the xsim and not the enumitem level)
    • include text before and after the enumeration of subexercises in the exercise
    • interrupt the enumeration, add some text at the top-level, and then let the enumeration continue afterwards (similar to using the resume option). For an example, see again task 6 here (note the indentation between subtasks i and j).
    • use a custom template for subexercises, e.g. not only starting the \item, but also printing its points before the content of the subexercise (or even better on the page margin with something like \marginpar)
  • I want the solution for a subexercise to directly following the definition of the subexercise - both in the source code and in the final (solution) document. Thus, I don't need the feature for collecting all sub-solutions and then printing them separately after the exercise - I want them inline directly following their respective subtasks (of course only when printing solutions), see here for an example. Both approaches could possibly exist in parallel by either setting subexercise/print=true or using a combination of subexercise/print=false and \printexercise{subexercise}{???} in the (template of the) solution for an exercise.

  • I currently don't see any reason while we should needlessly limit the nesting to one level - I actually had a case where having the second level was very useful. See task 6 on this other staatsexamen for another example.

With the changes I described here, all the above features are working.
Of course, it would be awesome if that would also work without the need for any monkey-patching, so I'd be happy to help in bringing this functionality to xsim.
I guess an unopinionated, generic approach would again be suited best for xsim, leaving more opinionated, use-case specific solutions to further dependent packages like schule (or what I've been using locally for my exams).

Two further features which would be nice to have in combination with subexercises (but which I couldn't get to work yet):

  • I have a macro for rendering various tick marks in the solution, indicating the relevant ideas that give a full/half/quarter point. Being able to add the respective amount of points to the current (sub-)exercise would also be very nice.

  • I sometimes need two versions of the same exam (e.g. for students of teaching aiming for different school types), where one also contains some additional, a little bit harder (variants of the) tasks. I currently use a command for conditionally enabling the respective sections, but this won't work when using individual files during the compilation of the exercises. Passing a variable for the value of use or print also doesn't seem to work, as the value is not expanded. Can tags be somehow used for this, e.g. printing all untagged exercises and only the ones tagged easy/hard depending on some external value?

@cgnieder
Copy link
Owner Author

Very much of this already is possible and it is possible without the need for nesting. Here is a quick example:

\documentclass[parskip=half]{scrartcl}
\usepackage{xsim}

\DeclareExerciseProperty{subpoints}
\newcommand*\thesubpoints{}

\newcounter{subexercise}[exercise]
\renewcommand\thesubexercise{\alph{subexercise})}
\NewDocumentCommand\question{O{}}{%
  \refstepcounter{subexercise}%
  \item[\thesubexercise]%
  \XSIMifblankF{#1}{%
    \xdef\thesubpoints{\thesubpoints\XSIMifblankF{\thesubpoints}{+}#1}%
    (\addpoints{#1})%
  }%
}

\DeclareExerciseEnvironmentTemplate{custom}{%
  \gdef\thesubpoints{}%
  \subsection*{\XSIMmixedcase{\GetExerciseName}~\GetExerciseProperty{counter}%
    \IfExercisePropertySetT{subtitle}
      { {\normalfont\itshape\GetExerciseProperty{subtitle}}}%
  }
  \GetExercisePropertyT{points}{%
    \begingroup
      \footnotesize\sffamily
      Points: \printgoal{\PropertyValue}%
      \IfExercisePropertySetT{subpoints}{ (\GetExerciseProperty{subpoints})}%
    \endgroup
    \par
  }
}{
  \XSIMifblankF{\thesubpoints}
    {\SetExpandedExerciseProperty{subpoints}{\thesubpoints}}%
  \par
}

\NewDocumentEnvironment{subexercise}{}
  {\begin{enumerate}}
  {\end{enumerate}}

\newcommand\answer[1]{\IfSolutionPrintT{\textbf{#1}}}

\xsimsetup{
  exercise/template=custom ,
  % solution/print
}

\begin{document}

\begin{exercise}[points=3, subtitle=Plain]
  Plain exercise. \answer{Plain answer}
\end{exercise}
\begin{exercise}[subtitle=With subexercises]
  \begin{subexercise}
    \question[2] One \answer{First answer}
    \question[3] Two \answer{Second answer}
  \end{subexercise}
  An exercise with subexercises.
  \begin{subexercise}
    \question[1] Three \answer{Third answer}
  \end{subexercise}
\end{exercise}

\end{document}

which gives

grafik

or

grafik

@cgnieder cgnieder removed the help wanted this is a tricky issue; any insights welcome label Feb 21, 2021
@N-Coder
Copy link
Contributor

N-Coder commented Feb 22, 2021

Very much of this already is possible and it is possible without the need for nesting. Here is a quick example:

Yes. This is actually not that different from what I did in my proof of concept here. But instead of defining custom "bare" LaTeX commands for the subexercises, I used a custom xsim exercise environment for the subexercises. Similar to what you did in your code, I used the hook system to collect the subpoints, sum them up, and then report the result to the parent exercise here. The seemingly complicated logic in the post hook is just to ensure that we don't add any dangling pluses when any of the concerned exercises doesn't have points assigned. If we don't care about these we could simply always use the True branch of the ifs and completely drop the False branch, making the total code size required for nested points in xsim roughly 100 lines (including all my comments, empty lines,...).

Thanks to your fix from 0f90bd6 and setting most variables locally, nesting is actually no big issue any more. The fixes for restoring the variables I included in previous versions of the POC are mostly no longer required. Now, I'm mostly setting nice-to-have properties related to nesting, i.e. a property for the ID of the parent exercise and its type and a full counter consisting of the concatenation of the parent's counter with the child's. The only thing that still needs to be restored after a nested subexercise is \g_xsim_exercise_id_tl (which is simply set to the ID of the parent), because that value needs to be global for a following solution to pick it up.

There is really nothing more required than what I just described here for nesting to work flawlessly. I did prefer using a solution via xsim environments instead of custom LaTeX commands because that seemed a lot cleaner, more flexible and extensible. If someone wants to have the subexercises listed individually in the grading table, this would be trivial thanks to the nested exercises. Same goes for using the property, template and hook infrastructure xsim already provides. Also, if xsim were to provide this functionality by default, the custom code a user would need for nesting to work would be minimal. Collecting all the subsolutions and only printing them after the whole body of the exercise would also be easy this way, e.g. by setting subsolutions/print=false, collecting all subsolutions encountered in the exercise body and then using \printsolution in the actual solution of the whole exercise.

Merging the code of my POC into xsim shouldn't be much work. The only thing that would need to be done is to throw out the monkey-patching via hooks and instead find the right places of the xsim code base to insert my additions. If I were to create and open this PR, would you be willing to consider it for merging?

@cgnieder
Copy link
Owner Author

I am inclined to add a subexercise mechanism to xsim that will not require nesting but will still be customizable through xsim's templates. I will present ideas here once they're ready to be tested.

I'm glad that the nested approach works for you but I am hesitating to officially support it. If I do I will always have to keep possible complications in mind whenever I try to add a new feature. That being said I'll still look at your code and will see if I can integrate it in a proper way.

@N-Coder
Copy link
Contributor

N-Coder commented Mar 1, 2021

I see, preventing regressions will probably become a bigger issue the more users and features xsim gets. Maybe it would make future releases easier to make and new features easier to incorporate if GitHub Actions or another Continuous Integration system would be used to check that, for every commit, the examples (or maybe also further test documents) still compile fine and continue to yield the same output. I'm already using CI to check that all the tex files my colleagues and me produce aren't broken by a certain commit and continue to compile fine (including automated e-mails reminding you about figures you forgot to check in, which is very useful), so the first half would be very easy to do. For the second half, checking that the output doesn't change, we could use some PDF diff tool (with an appropriate level of detail, e.g. only comparing word-by-word and not pixel-by-pixel) to compare the results with the PDFs of the examples already stored in the repo. If the results differ in an unintended way, there'll be an automated notification about that breaking change. If the results differ in an intended way, this would be a reminder to update the PDFs files in the repo. Should I try to set up an example configuration for this so that we can test this?

@N-Coder
Copy link
Contributor

N-Coder commented Mar 30, 2021

I encountered two further use-cases for nested subexercises:

  • I have a big collection of "short questions", which usually ask whether a statement is true or false and require a short justification of the answers. They usually appear in a "wrapper exercise" that explains this mode and gives a total sum of points achievable through these short questions. If I group my database of questions by topic, I could generate the respective tasks automatically using \printrandomexercises. Using multiple invocations of \printrandomexercises with different collections within the same exercise together with the random/exclude parameter for already used questions would also give me a nice exam question like this one.
  • I'd like to have a grading table that lists subexercises individually. If I just want the subexercises (and not their parent exercises), this works perfectly with using my nesting fix and the \gradingtable solution provided by xsim. I'm still working on a custom version of the table generation code that lists the exercises first followed by the subexercises they consist of, but that shouldn't be too hard either. An example of this usage can be found here.

@Jowi-Ammerbuch
Copy link

Hello, I find the discussion about exercises with subexercises very interesting, because in my teaching practice I need this all the time. For my learning objective checks I used the package exam by Philip Hirschhorn so far. However, XSIM seems to me potentially much more powerful, I especially appreciate the ability to have solutions output at the end, after the questions, this is very charming especially for practice sheets.
But on the subject of tasks with sub-tasks: Frankly, what I don't like about N-Coder's interesting approach is that it further extends XSIM's already sophisticated code. By the way, I also feel uncomfortable with the package Schule, they also have tasks with subtasks and a lush functionality, mostly great design, but as a non-LATEX expert you are quickly lost if something does not go through at first, too confusing are the interweavings of different code collections. Can't it be simpler? I had the feeling from the beginning that XSIM already has everything to achieve my goal, but I can't really handle this tool yet.
It should be possible to achieve with XSIM what exam by Philip Hirschorn can do, i.e. that subtasks have the functionalities as stand-alone tasks. That the evaluation points are displayed in the same way (I prefer on the right margin) and are added to one counter.

Translated with www.DeepL.com/Translator (free version) (Mein Englisch ist leider nicht sehr gut.)

@Jowi-Ammerbuch
Copy link

My feeling didn't deceive me, with this versatile XSIM package you can also realize nice exam tasks with subtasks, however it did take me some time. The code can certainly be optimized, I am not an expert and have read my eyes sore at the manual.
Attached is an example of an exam template, based on the document class scrartcl and adapted to LuaLaTex. I would be very grateful for any optimization suggestions!

``

KA-Vorlage-KOMA-Lua.pdf
XSIM-KA-Koma-Style.tex.txt
KA-Vorlage-KOMA-Lua .tex.txt

@projetmbc
Copy link

projetmbc commented Apr 4, 2023

This would be a great feature. I need for final exams to type problems divided in "parts" Part A, Part B, ... This could be implemented using the concept of sub-exercices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion discussion about the development of xsim
Projects
None yet
Development

No branches or pull requests

6 participants