第 2 部分:考试类中的自定义标签和问题

第 2 部分:考试类中的自定义标签和问题

这是我发布的问题的扩展,@John Kormylo 已为其提供了解决方案。

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

这是约翰提出的解决方案。

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

我想修改约翰的代码以包括\parts

这是一个示例 .tex 文件。

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

上述代码的预期结果如下。

结果

更新 1:包含\subparts和抑制\parts点值。

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

但是在编译 gradetable 时会遇到以下问题。

总分错误的结果

正如您所见,总数与标签总数不相等。

答案1

此版本也循环遍历子部分。没有分数的问题等不包含在内\qlist。没有标签的问题等将继承其父级的标签。\tag外部questions将创建默认标签。

如果所有子部分都有相同的标签,则只有该部分会被添加到问题列表中。

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

相关内容