Teil 2: Benutzerdefinierte Tags und Fragen im Prüfungsunterricht

Teil 2: Benutzerdefinierte Tags und Fragen im Prüfungsunterricht

Dies ist eine Erweiterung des von mir geposteten Problems, für das @John Kormylo eine Lösung bereitgestellt hat.

https://tex.stackexchange.com/questions/640726/create-custom-tags-for-questions-in-exam-class

Hier ist die ausgearbeitete Lösung von John.

\documentclass[addpoints]{exam}
\usepackage{tikz}% foreach and pgfmath

\newcommand{\tag}[1]{\expandafter\gdef\csname tagofq@\roman{question}\endcsname{#1}}

\makeatletter
\newcommand{\taglist}[1]{% #1 = comma delimmited list of tags (in order) for summary
\@ifundefined{exam@numquestions}{}{%
\bgroup% use local definitions
  \lineskip=0pt
  \noindent
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Tag}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Question}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Points}}\newline
  \foreach \x in {#1} {\count1=0
    \let\qlist=\empty
    \edef\pointsum{0}%
    \loop\ifnum\count1<\exam@numquestions\relax
      \advance\count1 by 1
      \@ifundefined{tagofq@\@roman\count1}{}{%
        \edef\thistag{\csname tagofq@\@roman\count1\endcsname}%
        \ifx\x\thistag\relax
          \ifx\empty\qlist\relax
            \edef\qlist{\the\count1}%
          \else
            \edef\qlist{\qlist, \the\count1}%
          \fi
          \edef\thispoints{\csname pointsofq@\@roman\count1\endcsname}%
          \pgfmathparse{int(\pointsum+\thispoints)}%
          \let\pointsum=\pgfmathresult
        \fi}%
    \repeat
    \vskip-\fboxrule\noindent
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\x}}\hspace{-\fboxrule}%
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\qlist}}\hspace{-\fboxrule}%
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\pointsum}}\newline}%
  \vskip-\fboxrule\noindent
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Total}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut\exam@numpoints}}
\egroup}}
\makeatother

\begin{document}
    
\begin{questions}
\question[1] \tag{Algebra}
This is Question 1. This is tagged against Algebra.

\question[2] \tag{Equations}
This is Question 2.This is tagged against Equations.

\question[2] \tag{Data}
This is Question 3.This is tagged against Data.

\question[1] \tag{Algebra}
This is Question 4. This is tagged against Algebra.

\question[2] \tag{Algebra}
This is Question 5.This is tagged against Algebra.

\question[2] \tag{Data}
This is Question 6.This is tagged against Data.

\end{questions}

\taglist{Algebra,Data,Equations}

\end{document}

Ich möchte Johns Code ändern, um ihn einzuschließen \parts.

Hier ist eine Beispieldatei im .tex-Format.

\documentclass[addpoints]{exam}
\begin{document}
    
\begin{questions}
\question[1] \tag{Algebra}
This is Question 1. This is tagged against Algebra.

\question[]
\begin{parts}
\part[1] \tag{Equations} This is Question 2a.This is tagged against Equations.
\part[1] \tag{Algebra} This is Question 2b.This is tagged against Algebra.
\end{parts}

\question[2] \tag{Data}
This is Question 3.This is tagged against Data.

\question[] 
\begin{parts}
\part[1] \tag{Equations} This is Question 4a.This is tagged against Equations.
\part[1] \tag{Data} This is Question 4b.This is tagged against Data.
\end{parts}

\question[2] \tag{Algebra}
This is Question 5.This is tagged against Algebra.

\question[2] \tag{Data}
This is Question 6.This is tagged against Data.

\end{questions}

\taglist{Algebra,Data,Equations}
\end{document}

Das gewünschte Ergebnis für den obigen Code ist unten.

Ergebnisse

Update 1: Zum Einbeziehen \subpartsund Unterdrücken \partsvon Punktwerten.

\documentclass[addpoints]{exam}
\usepackage{tikz}% foreach and pgfmath

\makeatletter
\let\normal@parts=\parts
\def\parts{\normal@parts
  \let\normal@part=\@doitem
  \let\@doitem=\my@part}
%
\newcommand{\my@part}[1][\@empty]{% store points by part
  \ifx\@empty#1
    \expandafter\normal@part
  \else
    \stepcounter{partno}%
    \immediate\write\@auxout{\string\gdef\string\pointsofp@\roman{question}@\roman{partno}{#1}}%
    \addtocounter{partno}{-1}%
    \expandafter\normal@part\expandafter[\expandafter#1\expandafter]%
  \fi}

\newcommand{\tag}[1]{\ifnum\@listdepth=1
    \expandafter\gdef\csname tagofq@\arabic{question}\endcsname{#1}%
  \else 
    \expandafter\gdef\csname tagofp@\arabic{question}@\arabic{partno}\endcsname{#1}%
  \fi}
\newcommand{\qlist}{}% reserve global name
\newcommand{\pointsum}{}

\newcommand{\addtoqlist}[1]{% #1 = \thequestion etc
  \ifx\empty\qlist\relax
    \xdef\qlist{#1}%
  \else
    \xdef\qlist{\qlist, #1}%
  \fi}
\newif{\ifpart}

\newcommand{\taglist}[1]{% #1 = comma delimmited list of tags (in order) for summary
\@ifundefined{exam@numquestions}{}{\par%
\bgroup% use local definitions
  \lineskip=0pt
  \noindent
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Tag}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Question}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Points}}\newline
  \foreach \x in {#1} {\setcounter{question}{0}% loop over tags
    \global\let\qlist=\empty
    \xdef\pointsum{0}%
    \loop\ifnum\value{question}<\exam@numquestions\relax% loop over questions
      \stepcounter{question}%
      \@ifundefined{tagofq@\arabic{question}}{% no tag on question
        \setcounter{partno}{0}\parttrue
        \bgroup\loop% llop over parts
          \stepcounter{partno}%
          \@ifundefined{r@part@\arabic{question}@\arabic{partno}}{\partfalse}{}%
        \ifpart
          \edef\thistag{\csname tagofp@\arabic{question}@\arabic{partno}\endcsname}%
          \ifx\x\thistag\relax
            \addtoqlist{\thequestion\thepartno}%
            \edef\thispoints{\csname pointsofp@\roman{question}@\roman{partno}\endcsname}%
            \pgfmathparse{int(\pointsum+\thispoints)}%
            \global\let\pointsum=\pgfmathresult
          \fi
        \repeat
        \egroup
      }{% tag on question
        \edef\thistag{\csname tagofq@\arabic{question}\endcsname}%
        \ifx\x\thistag\relax
          \addtoqlist{\thequestion}%
          \edef\thispoints{\csname pointsofq@\roman{question}\endcsname}%
          \pgfmathparse{int(\pointsum+\thispoints)}%
          \global\let\pointsum=\pgfmathresult
        \fi}%
    \repeat
    \vskip-\fboxrule\noindent
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\x}}\hspace{-\fboxrule}%
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\qlist}}\hspace{-\fboxrule}%
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\pointsum}}\newline}%
  \vskip-\fboxrule\noindent
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Total}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut\exam@numpoints}}
\egroup}}
\makeatother


\newcommand{\hidepoints}{%
    \pointsinmargin\pointformat{}
}

\newcommand{\showpoints}{%
    \nopointsinmargin\pointformat{(\thepoints)}
} 

\begin{document}
    
\begin{questions}
\question[1] \tag{Algebra}
This is Question 1. This is tagged against Algebra.

\question
\begin{parts}
\hidepoints
\part[2] \tag{Equations}  % I want to suppress and not include in total points this which is the sum of the subparts below.
\showpoints
\begin{subparts}
    \subpart[1]This is Question 2a (2ai).This is tagged against Equations.
    \subpart[1]This is Question 2a (2aii).This is tagged against Equations.
\end{subparts}
\part[1] \tag{Algebra} This is Question 2b.This is tagged against Algebra.
\end{parts}

\question[2] \tag{Data}
This is Question 3.This is tagged against Data.

\question
\begin{parts}
\part[1] \tag{Equations} This is Question 4a.This is tagged against Equations.
\part[1] \tag{Data} This is Question 4b.This is tagged against Data.
\end{parts}

\question[2] \tag{Algebra}
This is Question 5.This is tagged against Algebra.

\question[2] \tag{Data}
This is Question 6.This is tagged against Data.

\end{questions}

\taglist{Algebra,Data,Equations}
\end{document}

Beim Kompilieren der Notentabelle treten jedoch die folgenden Probleme auf.

Ergebnisse mit falscher Gesamtpunktzahl

Wie Sie sehen, entspricht die Summe nicht der Gesamtzahl der Tags.

Antwort1

Diese Version durchläuft auch Unterteile. Fragen usw. ohne Punkte sind nicht in enthalten \qlist. Fragen usw. ohne Tag erben den Tag ihres übergeordneten Elements. Ein \tagexternes Element questionserstellt einen Standardtag.

Wenn alle Unterteile dasselbe Tag haben, wird nur das Teil zur Fragenliste hinzugefügt.

\documentclass[addpoints]{exam}
\usepackage{tikz}% foreach and pgfmath
\usepackage{etoolbox}

\newif{\ifquestion}
\newif{\ifpart}
\newif{\ifsubpart}

\makeatletter
\def\@doitem{\@ifnextchar[{\@readpoints}%
                          {\def\@points{0}\item@points@pageinfo}%
}
\patchcmd{\item@points@pageinfo}{\item}{\item\savepoints}{}{FAILED}

\newcommand{\savepoints}{\ifcase\@listdepth
  \or \expandafter\xdef\csname qpoints@\arabic{question}\endcsname{\@points}% 1
  \or \expandafter\xdef\csname ppoints@\arabic{question}@\arabic{partno}\endcsname{\@points}% 2
  \or \expandafter\xdef\csname spoints@\arabic{question}@\arabic{partno}@\arabic{subpart}\endcsname{\@points}% 3
  \fi}

\newcommand{\tag}[1]{\ifcase\@listdepth \gdef\defaulttag{#1}% 0
  \or \expandafter\gdef\csname tagofq@\arabic{question}\endcsname{#1}% 1
  \or \expandafter\gdef\csname tagofp@\arabic{question}@\arabic{partno}\endcsname{#1}% 2
  \or \expandafter\gdef\csname tagofs@\arabic{question}@\arabic{partno}@\arabic{subpart}\endcsname{#1}% 3
  \fi}

\newcommand{\defaulttag}{}
\newcommand{\qlist}{}% reserve global names
\newcommand{\slist}{}
\newcommand{\pointsum}{}
\newcommand{\total@points}

\newcommand{\addtoqlist}[1]{% #1 = \thequestion etc
  \ifx\empty\qlist\relax
    \xdef\qlist{#1}%
  \else
    \xdef\qlist{\qlist, #1}%
  \fi}

\newcommand{\addtoslist}[1]{% #1 = \thequestion etc
  \ifx\empty\slist\relax
    \edef\slist{#1}%
  \else
    \edef\slist{\slist, #1}%
  \fi}

\newcommand{\loopoverquestions}{\setcounter{question}{0}%
  \questiontrue
  \loop
    \stepcounter{question}%
    \@ifundefined{r@question@\arabic{question}}{\questionfalse}%
      {\def\thisquestion{\ref{question@\arabic{question}}}}%
  \ifquestion
    \@ifundefined{qpoints@\arabic{question}}{\def\thispoints{0}}%
      {\def\thispoints{\csname qpoints@\arabic{question}\endcsname}}%
    \@ifundefined{tagofq@\arabic{question}}{\edef\qtag{\defaulttag}}%
      {\edef\qtag{\csname tagofq@\arabic{question}\endcsname}}%
    \ifnum\thispoints>0\relax
      \ifx\thetag\qtag\relax
        \addtoqlist{\thisquestion}%
        \pgfmathparse{int(\pointsum+\thispoints)}%
        \global\let\pointsum=\pgfmathresult
      \fi
    \fi
    \loopoverparts
  \repeat}
    
\newcommand{\loopoverparts}{\bgroup
  \setcounter{partno}{0}%
  \parttrue
  \loop
    \stepcounter{partno}%
    \@ifundefined{r@part@\arabic{question}@\arabic{partno}}{\partfalse}%
      {\def\thispartno{\ref{part@\arabic{question}@\arabic{partno}}}}%
  \ifpart
    \@ifundefined{ppoints@\arabic{question}@\arabic{partno}}{\def\thispoints{0}}%
      {\def\thispoints{\csname ppoints@\arabic{question}@\arabic{partno}\endcsname}}%
    \@ifundefined{tagofp@\arabic{question}@\arabic{partno}}{\edef\ptag{\qtag}}%
      {\edef\ptag{\csname tagofp@\arabic{question}@\arabic{partno}\endcsname}}%
    \ifnum\thispoints>0\relax
      \ifx\thetag\ptag\relax
        \addtoqlist{\thisquestion(\thispartno)}%
        \pgfmathparse{int(\pointsum+\thispoints)}%
        \global\let\pointsum=\pgfmathresult
      \fi
    \fi
    \loopoversubparts{\thispoints}%
  \repeat
\egroup}

\newcommand{\loopoversubparts}[1]% #1 = points for parent
{\bgroup
  \setcounter{subpart}{0}%
  \count1=0 %number of subparts
  \count2=0 %number of mathing tags
  \count3=#1\relax
  \let\slist=\empty
  \subparttrue
  \loop
    \stepcounter{subpart}%
    \@ifundefined{r@subpart@\arabic{question}@\arabic{partno}@\arabic{subpart}}{\subpartfalse}%
      {\def\thissubpart{\ref{subpart@\arabic{question}@\arabic{partno}@\arabic{subpart}}}}%
  \ifsubpart
    \advance\count1 by 1
    \@ifundefined{spoints@\arabic{question}@\arabic{partno}@\arabic{subpart}}{\def\thispoints{0}}%
      {\def\thispoints{\csname spoints@\arabic{question}@\arabic{partno}@\arabic{subpart}\endcsname}}%
    \@ifundefined{tagofs@\arabic{question}@\arabic{partno}@\arabic{subpart}}{\edef\stag{\ptag}}%
      {\edef\stag{\csname tagofs@\arabic{question}@\arabic{partno}@\arabic{subpart}\endcsname}}%
    \ifnum\thispoints>0\relax
      \ifx\thetag\stag\relax
        \advance\count2 by 1
        \addtoslist{\thisquestion(\thispartno)\thissubpart}%
        \pgfmathparse{int(\pointsum+\thispoints)}%
        \global\let\pointsum=\pgfmathresult
      \fi
    \fi
  \repeat
  \ifnum\count2>0
    \ifnum\count1=\count2
      \ifnum\count3=0
        \addtoqlist{\thisquestion(\thispartno)}%
      \fi
    \else
      \addtoqlist{\slist}%
    \fi
  \fi
\egroup}

\newcommand{\taglist}[1]{% #1 = comma delimmited list of tags (in order) for summary
\bgroup% use local definitions
  \par
  \lineskip=0pt
  \noindent
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Tag}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Question}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Points}}\newline
  \def\total@points{0}%
  \foreach \thetag in {#1} {% loop over tags
    \global\let\qlist=\empty
    \gdef\pointsum{0}%
    \loopoverquestions
    \vskip-\fboxrule\noindent
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\thetag}}\hspace{-\fboxrule}%
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\qlist}}\hspace{-\fboxrule}%
    \fbox{\parbox[t][1cm][t]{4cm}{\strut\pointsum}}\newline
    \pgfmathparse{int(\total@points+\pointsum)}%
    \global\let\total@points=\pgfmathresult}%
  \vskip-\fboxrule\noindent
  \fbox{\parbox[t][1cm][t]{4cm}{\strut Total}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut}}\hspace{-\fboxrule}%
  \fbox{\parbox[t][1cm][t]{4cm}{\strut\total@points}}
\egroup}
\makeatother

\begin{document}
    
\begin{questions}
\question[1] \tag{Algebra}
This is Question 1. This is tagged against Algebra.

\question
\begin{parts}
\part[1] \tag{Equations} This is Question 2a.This is tagged against Equations.
\part[1] \tag{Algebra} This is Question 2b.This is tagged against Algebra.
\end{parts}

\question[2] \tag{Data}
This is Question 3.This is tagged against Data.

\question
\begin{parts}
\part[1] \tag{Equations} This is Question 4a.This is tagged against Equations.
\part[1] \tag{Data} This is Question 4b.This is tagged against Data.
\part \tag{Algebra}
\begin{subparts}
\subpart[1]
\subpart[1]
\end{subparts}
\end{parts}

\question[2] \tag{Algebra}
This is Question 5.This is tagged against Algebra.

\question[2] \tag{Data}
This is Question 6.This is tagged against Data.

\end{questions}

\taglist{Algebra,Data,Equations}
\end{document}

verwandte Informationen