感谢@AlexG 和@Marcel Kruger,可以使用下面不同的链接来详细说明 MCQ。
(2)ocgx2、xparse、expl3:拆分逗号分隔的 OCMD/OCGs 参数列表以实现引用自动化
这给出了实际上下文,但问题在于拆分参数列表,以便自动执行上述第三个链接的 ID 和引用。对于前两个链接,它工作正常。
从下面的 MWE 来看,“手动”方法(必须输入所有 ID(\mcqcheck
宏和Check
按钮))按预期工作,而“自动”方法(\mcqverify
)失败。
我不理解这种行为,因为参数的拆分和重建在\mcqverify
命令内部是有效的。我犯了什么错误?
\documentclass{article}
\usepackage[tikz]{ocgx2}
\usepackage{media9} % \mediabutton
\usepackage{animate}
\usepackage{fontawesome5}
\usepackage{wasysym} % \Circle, \CIRCLE
\usepackage{calc} % \widthof{...}
\newcounter{quiz}%
\newcounter{quizquestion}[quiz]
\newcounter{mcqproposal}[quizquestion]% Proposal IDs counter to choose within a quiz question
\newcounter{mcqquiztotal}[quizquestion]% Total proposals counter within a quiz question
\newlength{\quizcheckboxwidth}
% quiz statement
\NewDocumentCommand{\mcqproposal}{m}{%
% Syntax − #1 = proposal/statement text
\stepcounter{mcqproposal}
\stepcounter{mcqquiztotal}%
% action on click: toggle myself (choice layer), hide verifcation layer
\setlength{\quizcheckboxwidth}{\widthof{\faIcon[regular]{square}}}%
\makebox[\quizcheckboxwidth][c]{%
\actionsocg{mcqproposalref.\thequiz.\thequizquestion.\themcqproposal}%
{}{verify.\thequiz.\thequizquestion}{\faIcon[regular]{square}}%
}%
\begin{ocg}{mcqproposalref.\thequiz.\thequizquestion.\themcqproposal}%
{mcqproposalref.\thequiz.\thequizquestion.\themcqproposal}{off}% choice layer
\hspace*{-\quizcheckboxwidth}%
\makebox[\quizcheckboxwidth][c]{\textcolor{green!60!black}{\faCheckSquare}}%
\end{ocg}%
\parbox[t]{\linewidth}{\hspace*{6pt}#1}%
}
% reset button
\NewDocumentCommand{\mcqreset}{}{%
\def\ocglistreset{}%
\xdef\ocglistreset{%
\ocglistreset\space verify.\thequiz.\thequizquestion}%
\foreach \X in {1,...,\value{mcqquiztotal}} {%
\xdef\ocglistreset{\ocglistreset\space mcqproposalref.\thequiz.\thequizquestion.\X}%
}%
%\ocglistreset
\hideocg{\ocglistreset}{\fbox{\strut Reset}}%
}
\ExplSyntaxOn
\NewDocumentCommand{\askreplymcqArgsIds}{m}{%
% Syntax − #1: proposal/statement number within a question
mcqproposalref.\thequiz.\thequizquestion.#1%
}
\NewDocumentCommand{\mcqverify}{ m m }{%
% Syntax − #1: list of OCG ids of correct/required answer(s), comma separated
% #2: list of OCG ids of wrong answer(s), comma separated
\askreplymcq_process_list:Nn \l_correct_seq { #1 }% Save OCMD IDs as LaTeX3 seq variable
\askreplymcq_process_list:Nn \l_wrong_seq { #2 }% Save OCMD IDs as LaTeX3 seq variable
\askreplymcq__verify:ff { \seq_use:Nn \l_correct_seq {,} } { \seq_use:Nn \l_wrong_seq {,} }
}
\cs_new_protected:Npn \askreplymcq_process_list:Nn #1 #2
{
% clear the sequence
\seq_clear:N #1
% cycle through the arguments, storing "\askreplymcqArgsIds{<arg>}" in the sequence
\clist_map_inline:nn { #2 }
{
% Here :Nx instead of :Nn ensures that \askreplymcqArgsIds
% is actually evaluated instead of passed as-is
\seq_put_right:Nx #1 { \askreplymcqArgsIds{##1} }
}
}
\seq_new:N \l_correct_seq
\seq_new:N \l_wrong_seq
\cs_new_protected:Npn \askreplymcq__verify:nn #1 #2
{%
\mediabutton[jsaction={%
var ocgs=this.getOCGs(this.pageNum);%
for(var i=0;i<ocgs.length;i++){%
if(ocgs[i].name=="verify.\thequiz.\thequizquestion"%
&&ocgs[i].state==false%
&&anim["verify.\thequiz.\thequizquestion"].frameNum<3){%
ocgs[i].state=true;%
anim["verify.\thequiz.\thequizquestion"].frameNum++;%
}%
}%
}]{\fbox{\strut Verify}}\space%
\begin{animateinline}[label=verify.\thequiz.\thequizquestion,nomouse,step]{1}
\strut\Circle\ \Circle\ \Circle
\newframe
\strut\CIRCLE\ \Circle\ \Circle
\newframe
\strut\CIRCLE\ \CIRCLE\ \Circle
\newframe
\strut\CIRCLE\ \CIRCLE\ \CIRCLE
\end{animateinline}\quad%
\begin{ocg}{verify.\thequiz.\thequizquestion}%
{verify.\thequiz.\thequizquestion}{off}% verification layer
\makebox[0pt][l]{%
\begin{ocmd}{\Not{\And{#1,\Not{\Or{#2}}}}}% "wrong" layer (OCMD)
Wrong%
\end{ocmd}%
}%
\begin{ocmd}{\And{#1,\Not{\Or{#2}}}}% "correct" layer (OCMD)
Correct%
\end{ocmd}%
\end{ocg}%
}
\cs_generate_variant:Nn \askreplymcq__verify:nn {ff}
\ExplSyntaxOff
\NewDocumentCommand{\mcqcheck}{m m}{%
% Syntax − #1: list of OCG ids of correct answer(s), comma separated
% #2: list of OCG ids of wrong answer(s), comma separated
\mediabutton[jsaction={%
var ocgs=this.getOCGs(this.pageNum);%
for(var i=0;i<ocgs.length;i++){%
if(ocgs[i].name=="verify.\thequiz.\thequizquestion"
&&ocgs[i].state==false
&&anim["verify.\thequiz.\thequizquestion"].frameNum<3){%
ocgs[i].state=true;%
anim["verify.\thequiz.\thequizquestion"].frameNum++;%
}%
}%
}]{%
\fbox{\strut Check}}\space%
\begin{animateinline}[label=verify.\thequiz.\thequizquestion,nomouse,step]{1}
\strut\Circle\ \Circle\ \Circle
\newframe
\strut\CIRCLE\ \Circle\ \Circle
\newframe
\strut\CIRCLE\ \CIRCLE\ \Circle
\newframe
\strut\CIRCLE\ \CIRCLE\ \CIRCLE
\end{animateinline}\quad%
\begin{ocg}{verify.\thequiz.\thequizquestion}%
{verify.\thequiz.\thequizquestion}{off}% verification layer
\makebox[0pt][l]{%
\begin{ocmd}{\Not{\And{#1,\Not{\Or{#2}}}}}% "wrong" layer (OCMD)
Wrong.
\end{ocmd}%
}%
\begin{ocmd}{\And{#1,\Not{\Or{#2}}}}% "correct" layer (OCMD)
Correct.
\end{ocmd}%
\end{ocg}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\parindent=0pt
\begin{document}
\stepcounter{quiz}
\stepcounter{quizquestion}
Which are the colour components of an RGB image? Multiple required assertions.\\[8pt]
\mcqproposal{Magenta.}
\mcqproposal{Green.}
\mcqproposal{Cyan.}
\mcqproposal{Blue.}
\mcqproposal{Red.}
\mcqproposal{Black.}
\mcqproposal{Yellow.}\\[8pt]
\mcqcheck{mcqproposalref.\thequiz.\thequizquestion.2,mcqproposalref.\thequiz.\thequizquestion.4,mcqproposalref.\thequiz.\thequizquestion.5}{mcqproposalref.\thequiz.\thequizquestion.1,mcqproposalref.\thequiz.\thequizquestion.3,mcqproposalref.\thequiz.\thequizquestion.6,mcqproposalref.\thequiz.\thequizquestion.7}%
%
\mcqverify{2,4,5}{1,3,6,7}
\hspace{0.1\linewidth}
\mcqreset
\end{document}