파트 2: 시험 수업의 사용자 정의 태그 및 질문

파트 2: 시험 수업의 사용자 정의 태그 및 질문

이것은 @John Kormylo가 솔루션을 제공한 제가 게시한 문제의 확장입니다.

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

다음은 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}

.\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. 태그가 없는 질문 등은 상위 태그를 상속받습니다. 외부 \tagquestions기본 태그를 생성합니다.

모든 하위 파트에 동일한 태그가 있는 경우 해당 파트만 질문 목록에 추가됩니다.

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

관련 정보