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

auto- and subpoints (or \addpoints-extended) #2

Closed
maphy-psd opened this issue Apr 14, 2017 · 11 comments
Closed

auto- and subpoints (or \addpoints-extended) #2

maphy-psd opened this issue Apr 14, 2017 · 11 comments
Assignees
Labels
suggestion suggestions and feature requests

Comments

@maphy-psd
Copy link

maphy-psd commented Apr 14, 2017

I created thís issue to clean the discussion. So in #1 i mentioned the function of autopoints. I would specify a little bit.

  1. xsim sum the points (with addpoints) automatically
  2. xsim sum the subpoints of tasks (with the tasks env of the tasks package) automatically
  3. xsim can 1. and 3. in the solution env
  4. xsim can 1.,2. and 3. and prints the sumpoints in the exercises env.

So

 \begin{exercise}
	\begin{tasks}
		\task task1
		\task task2
	\end{tasks}
\end{exercise}
\begin{solution}
	\begin{tasks}
		\task solution if task1 \subpoints{3}
                \end{tasks}
		\begin{tasks}[resume]
		\task solution if task2 \subpoints{2}
	\end{tasks}
\end{solution}

would prints

Exercise 1  5points
a) task1 (3points)
b) task2 (2points)
@cgnieder cgnieder added the suggestion suggestions and feature requests label Apr 15, 2017
@maphy-psd maphy-psd mentioned this issue Apr 15, 2017
5 tasks
@cgnieder
Copy link
Owner

This is non-trivial. Definitely not as easy as it sounds (sum the points and print the sum). The first idea I had caused the points added in the environment to be added in each compilation run.

\begin{exercise}
  \addpoints{2}
\end{exercise}

had 6 points after three compilations…

@maphy-psd
Copy link
Author

maphy-psd commented Apr 16, 2017

That sounds bad. Maybe xsim creates his own aux file like *.xsim with the points distribution with the scheme id points

\begin{exercise}
  \addpoints{2}
\end{exercise}
\begin{exercise}
  \addpoints{3} text \addpoints{1}
\end{exercise}

Would produces the aux file

exercise-1 2
exercise-2 4

@cgnieder
Copy link
Owner

cgnieder commented Apr 16, 2017

A separate auxiliary file won't change the real problem. Every property is already written to the aux file. The current setup sets the property in the begin code of the environment before the layout template picks those properties up to be able to print them.

I probably need to delay the setting of the goal properties to the end code. And \xsim_addto_goal:nnnn maybe needs to add to a temporary variable which in the end of the environment is turned into the value of the corresponding property.

@cgnieder
Copy link
Owner

Implementing the setup I described is rather easy. The problem is making this work and

\begin{exercise}[points=2]

The latter directly sets the property. I can (and would need to) unset it until the end of the environment but then the layout template never sees the point property as being set and as a consequence never prints it.

@cgnieder
Copy link
Owner

After a few different approaches and tries I don't see how this can be added to the current implementation of xsim. I have to put this issue on hold.

@cgnieder cgnieder self-assigned this Jun 13, 2017
@cgnieder
Copy link
Owner

Idea (reminder for myself): maybe introduce some kind of “pseudo” goals for each existing goal (goal being the generic term for points). Commands like \addpoints would then record pseudo points and at end environment a check could be made if the pseudo points match the “real” points. Then the update would only be made in case they don't match? This needs testing…

@joneppie
Copy link
Contributor

joneppie commented Jun 3, 2018

In the schule package we have the following solution with points for "teilaufgaben":

\newcounter{teilpunkte}
\@ifclassloaded{beamer}{
	\newenvironment{teilaufgaben}{\begin{enumerate}[a)]
	}{\end{enumerate}}
}{
    \setcounter{teilpunkte}{0}
    \newlist{teilaufgaben}{enumerate}{1}
    \setlist[teilaufgaben]{
        label=\textbf{\alph{teilaufgabeni})},
        topsep=0.2em,
        itemsep=-0.1em,
    }
}

\xsimsetup{
	aufgabe/begin-hook={\setcounter{teilpunkte}{0}},
	aufgabe/end-hook={%
		\ifnum\theteilpunkte>0%
			\SetExpandedExerciseProperty{points}{\theteilpunkte}%
		\fi%
	}%
}

\newcommand{\Teilpunkte}{\arabic{teilpunkte}}

\makeatletter
\NewDocumentCommand{\teilaufgabe}{o}{
	\IfInsideSolutionTF{
		% In Lösungen
		\item%
	}{
		% In Aufgaben
		\item%
		\IfNoValueF{#1}{\addtocounter{teilpunkte}{#1}(#1)\xspace}
	}
}

@N-Coder
Copy link
Contributor

N-Coder commented Dec 11, 2019

I found a similar approach using an additional counter on stackexchange.
Unfortunately this won't fully work with subexercises (as defined here) as I currently see no way of accessing the "parent" exercise in which a subexercise is contained. If that was possible you could just append "+subpoints" to the parent's points property.

@N-Coder
Copy link
Contributor

N-Coder commented Dec 11, 2019

Even worse, the current exercise is set to be the subexercise once the first one is read, but the previous value is not restored after the subexercise is complete. This means that in the post-hook of an exercise that contains nested subexercises, the current exercise will be the last subexercise read, not the parent exercise of which the post-hook is run.

This can be seen in the following example:

\documentclass[a4paper]{article}

\usepackage{xsim}

\DeclareExerciseEnvironmentTemplate{exercise}{%
    \par{\GetExerciseName} \GetExerciseProperty{counter} (ID \GetExerciseProperty{id})
}{%
    (/ID \GetExerciseProperty{id})
}

\DeclareExerciseType{subexercise}{
    exercise-env = subexercise,
    solution-env = subsolution,
    exercise-name = subexercise,
    solution-name = subsolution,
    exercise-template = exercise,
    solution-template = exercise
}

\xsimsetup{
    exercise/template = exercise,
    subexercise/within = exercise,
    subexercise/the-counter = \arabic{exercise}.\roman{subexercise}
}

\begin{document}

\begin{exercise}
    Erste Aufgabe
    \begin{subexercise}
        Erste Unteraufgabe
    \end{subexercise}
    \begin{subexercise}
        Zweite Unteraufgabe
    \end{subexercise}
\end{exercise}

\end{document}

subexercise-bug

Accessing the number of the parent exercise works correctly when rendering the counter value of the subexercise in subexercise/the-counter = \arabic{exercise}.\roman{subexercise}. But, the very last (/ID 3) printed by the post-hook of the parent exercise actually has the current exercise set the the subexercise defined right beforehand.

This could maybe be solved by keeping track of separate "current exercise" values for different exercise types, which would at least allow nesting different types of exercises and easily accessing parent properties using something like \GetCurrentExerciseTypeProperty{exercise}{id}.
As an alternative, one could store the parent exercise as property of the child exercise once the child exercise is begun and restore the parent value as current exercise after the child is complete.
This would allow a generic tree-like structure of exercises, which could also be traversed after the exercises are parsed.

@N-Coder
Copy link
Contributor

N-Coder commented Feb 18, 2020

I found a fix for the above-mentioned bug and uploaded the code into this repository.
The test-nested.tex file is the same as given above, but if you uncomment the following lines, the output will be correct:

% Uncomment to fix the footer-template of outer exercise being executed with a wrong \ExerciseId
% \include{xsim-nested}
% \XSIMNestedSetup{exercise}
% \XSIMNestedSetup{subexercise}

image

The fix adds a pre- and post-hook for each exercise type. The pre-hook notes the parent of the current exercise by setting the container property of the currently started exercise using a global variable. Afterwards, it sets the global variable to point to the current exercise to allow for further levels of nesting. The post-hook reverts the changes made by the pre-hook, effectively popping one level of nesting off the stack. Additionally, it correctly reverts the XSIM internals from xsim_start_exercise so that footer-templates have the correct \ExerciseID. The fix is currently provided as a regular .tex file which needs to be \included, but I'd be happy to put it into a PR with a patch or maybe an XSIM module that can be loaded optionally - if I get some help with the technical details of that. @cgnieder what's you opinion on this?

Having the nesting now working correctly, I also wrote some code for accumulating the points of children exercises into the parent, effectively propagating the points up the tree. This could also work for the use-case initially described in this issue. You can find an example here.

cgnieder added a commit that referenced this issue Feb 20, 2020
@cgnieder
Copy link
Owner

I think I've got this sorted out. It will need thorough testing. This MWE

\documentclass{article}
\usepackage{xsim}

\begin{document}

\begin{exercise}[points=3]
  complete: 3~points
\end{exercise}
\begin{exercise}[points=3]
  \addpoints{2} \\
  complete: 5~points
\end{exercise}
\begin{exercise}
  \addpoints{1} \\
  complete: 1~point
\end{exercise}
\begin{exercise}
  no points
\end{exercise}

Total: \printtotalpoints

\end{document}

prints after two compilations:

image


I'll upload the next version to CTAN in the next few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
suggestion suggestions and feature requests
Projects
None yet
Development

No branches or pull requests

4 participants