Parte 2: Etiquetas personalizadas y preguntas en la clase de examen

Parte 2: Etiquetas personalizadas y preguntas en la clase de examen

Esta es una ampliación del problema que publiqué, para el cual @John Kormylo proporcionó una solución.

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

Aquí está la solución trabajada de 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}

Me gustaría modificar el código de John para incluir \parts.

Aquí hay un archivo .tex de muestra.

\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}

El resultado deseado para el código anterior se encuentra a continuación.

Resultados

Actualización 1: incluir \subpartsy suprimir \partsvalores de puntos.

\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}

Pero esto presenta los siguientes problemas al compilar la tabla de calificaciones.

Resultados con puntos totales falsos

Como puede ver, el total no suma las etiquetas totales.

Respuesta1

Esta versión también recorre las subpartes. Las preguntas, etc. sin puntos no están incluidas \qlist. Las preguntas, etc. sin etiqueta heredan la etiqueta de su padre. Un \tagexterior questionscreará una etiqueta predeterminada.

Si todas las subpartes tienen la misma etiqueta, solo la parte se agregará a la lista de preguntas.

\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}

información relacionada