![第 2 部分:考试类中的自定义标签和问题](https://linux22.com/image/448639/%E7%AC%AC%202%20%E9%83%A8%E5%88%86%EF%BC%9A%E8%80%83%E8%AF%95%E7%B1%BB%E4%B8%AD%E7%9A%84%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%87%E7%AD%BE%E5%92%8C%E9%97%AE%E9%A2%98.png)
这是我发布的问题的扩展,@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}