我已在如何删除 \NewEnviron 定义的环境的 \BODY 宏中的命令ex
关于我尝试将我的环境转换为multi
moodle 包的环境时出现的问题。
我从上周末开始尝试解决我的问题,现在,我几乎解决了所有问题。它运行良好,并输出正确的 .pdf 文件和 .xml 文件。
但是,显示数学模式$$...$$
和环境会出现错误。\[...\]
\begin{center}...\end{center}
这是我的代码
\documentclass[12pt,a4paper]{article}
\usepackage[tikz]{moodle}
\usepackage{ifthen}
\usepackage{etoolbox}
\usepackage{environ}
\usepackage{xstring}
\usepackage{amsmath,amssymb,yhmath,mathrsfs,fontawesome}
\usepackage{fancyhdr,enumerate,tkz-euclide,tikz-3dplot,tikz,tkz-tab}
\moodleregisternewcommands
\makeatletter
\newcounter{c@ex}%
\setcounter{c@ex}{0}
\newcounter{ans@wer}%
\newcounter{correct@answer}%
\newcommand{\True}{}%
\newcommand\exname{MC}
%% Define the command to hide the text body of the environment.
\newlength{\trashlength}%
\def\hide@text#1{%
\settowidth{\trashlength}{#1}
}
%% Define the command to find the correct answer.
\def\begin@ans{\@ifnextchar\True
{\setcounter{correct@answer}{\theans@wer}}{\stepcounter{ans@wer}}%
}
\environbodyname\@body
\htmlregister\@body
\htmlregister\final@result
\htmlregister\ans@one
\htmlregister\ans@two
\htmlregister\ans@three
\htmlregister\ans@four
\htmlregister\feed@back
\htmlregister\envbody
\newcommand{\choice}[4]{
\gdef\ans@one{#1}
\gdef\ans@two{#2}
\gdef\ans@three{#3}
\gdef\ans@four{#4}
\gdef\del@choice{\choice
{#1}
{#2}
{#3}
{#4}
}%
}%
\newcommand{\loigiai}[1]{
\gdef\feed@back{#1}
\gdef\del@feedback{\loigiai{#1}}
}%
\NewEnviron{ex}{%
}%
\AtEndEnvironment{ex}{%
\stepcounter{c@ex}
\hide@text{\@body}
%% Delete the macro \choice and \loigiai in the body of environment
\hide@text{
\global\let\@result\@body
\expandarg
\StrDel{\@result}{\del@choice}[\re@sult]
\StrDel{\re@sult}{\del@feedback}[\re@@sult]
\global\let\final@result\re@@sult
}
% \let\envbody\noexpand{\funal@result}
%% Finding the correct answer
\setcounter{ans@wer}{1}
\hide@text{\expandafter\begin@ans\ans@one}
\hide@text{\expandafter\begin@ans\ans@two}
\hide@text{\expandafter\begin@ans\ans@three}
\hide@text{\expandafter\begin@ans\ans@four}
%% Write the data in `milti' environment
\def\ex@name{\exname\thec@ex}
\ifnum\the\value{correct@answer}=1%
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\ex@name}
\final@result
\item* \ans@one%
\item \ans@two%
\item \ans@three%
\item \ans@four%
\end{multi}
\else
\ifnum\the\value{correct@answer}=2%
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\exname\thec@ex}
\final@result
\item \ans@one%
\item* \ans@two%
\item \ans@three%
\item \ans@four%
\end{multi}
\else
\ifnum\the\value{correct@answer}=3
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\exname\thec@ex}
\final@result
\item \ans@one%
\item \ans@two%
\item* \ans@three%
\item \ans@four%
\end{multi}
\else
\ifnum\the\value{correct@answer}=4
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\exname\thec@ex}
\final@result
\item \ans@one%
\item \ans@two%
\item \ans@three%
\item* \ans@four%
\end{multi}
\else
\relax
\fi
\fi
\fi
\fi
}%
\makeatother
\begin{document}
\begin{quiz}{My first test}
\begin{ex}
This is my question. $\dfrac{a}{b}$
\choice
{\True Answer one}
{Answer two}
{Answer three}
{Answer four}
\loigiai{This is a detail answer.}
\end{ex}
\end{quiz}
\end{document}
我不知道哪里错了,当我在问题主体中使用显示数学模式时出现错误(当然它使用了正确的语法)
! Missing $ inserted.
<inserted text>
$
此外,当我使用 \begin{center}...\end{center} 时,出现错误
! LaTeX Error: Something's wrong--perhaps a missing \item.
请帮我修复它们!
答案1
你可以将示例简化为
\documentclass{article}
\begin{document}
\mbox{$ \times $}
\mbox{$$ \times $$}
\mbox{\begin{center} x \end{center}}
\end{document}
你没有得到任何错误$
但$$
产生了
! Missing $ inserted.
<inserted text>
$
l.7 \mbox{$$ \times $$}
?
因为在 hbox 中$$
类似于$ $
并创建一个空的数学列表所以\times
它不处于数学模式,它位于两个空的数学列表之间的文本中。
并center
产生
! LaTeX Error: Something's wrong--perhaps a missing \item.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.9 \mbox{\begin{center} x \end{center}}
?
因为你不能在水平框中构建垂直显示结构。
所以你肯定不想
%% Define the command to hide the text body of the environment.
\newlength{\trashlength}%
\def\hide@text#1{%
\settowidth{\trashlength}{#1}
}
它的作用类似于错误,\mbox
并且是错误的原因,您可能也不想要\StrDel
。您没有在任何地方说明您希望此代码执行什么操作,我猜不到,因此这个答案仅限于解释为什么会出现错误,我无法建议替代代码。
答案2
正如我在评论中指出的那样,在这种情况下避免使用\[..\]
(和),而应使用。使用而不是环境。因此,将给出一个居中方程(如果需要限制居中范围,可以使用括号)。$$...$$
$...$
\centering
center
\centering $...$
{\centering $...$\par}
\displaystyle
如果您希望进一步模拟所提供的显示样式外观,您可能会或可能不会希望在等式开头添加材料\[...\]
。
\documentclass[12pt,a4paper]{article}
\usepackage[tikz]{moodle}
\usepackage{ifthen}
\usepackage{etoolbox}
\usepackage{environ}
\usepackage{xstring}
\usepackage{amsmath,amssymb,yhmath,mathrsfs,fontawesome}
\usepackage{fancyhdr,enumerate,tkz-euclide,tikz-3dplot,tikz,tkz-tab}
\moodleregisternewcommands
\makeatletter
\newcounter{c@ex}%
\setcounter{c@ex}{0}
\newcounter{ans@wer}%
\newcounter{correct@answer}%
\newcommand{\True}{}%
\newcommand\exname{MC}
%% Define the command to hide the text body of the environment.
\newlength{\trashlength}%
\def\hide@text#1{%
\settowidth{\trashlength}{#1}
}
%% Define the command to find the correct answer.
\def\begin@ans{\@ifnextchar\True
{\setcounter{correct@answer}{\theans@wer}}{\stepcounter{ans@wer}}%
}
\environbodyname\@body
\htmlregister\@body
\htmlregister\final@result
\htmlregister\ans@one
\htmlregister\ans@two
\htmlregister\ans@three
\htmlregister\ans@four
\htmlregister\feed@back
\htmlregister\envbody
\newcommand{\choice}[4]{
\gdef\ans@one{#1}
\gdef\ans@two{#2}
\gdef\ans@three{#3}
\gdef\ans@four{#4}
\gdef\del@choice{\choice
{#1}
{#2}
{#3}
{#4}
}%
}%
\newcommand{\loigiai}[1]{
\gdef\feed@back{#1}
\gdef\del@feedback{\loigiai{#1}}
}%
\NewEnviron{ex}{%
}%
\AtEndEnvironment{ex}{%
\stepcounter{c@ex}
\hide@text{\@body}
%% Delete the macro \choice and \loigiai in the body of environment
\hide@text{
\global\let\@result\@body
\expandarg
\StrDel{\@result}{\del@choice}[\re@sult]
\StrDel{\re@sult}{\del@feedback}[\re@@sult]
\global\let\final@result\re@@sult
}
% \let\envbody\noexpand{\funal@result}
%% Finding the correct answer
\setcounter{ans@wer}{1}
\hide@text{\expandafter\begin@ans\ans@one}
\hide@text{\expandafter\begin@ans\ans@two}
\hide@text{\expandafter\begin@ans\ans@three}
\hide@text{\expandafter\begin@ans\ans@four}
%% Write the data in `milti' environment
\def\ex@name{\exname\thec@ex}
\ifnum\the\value{correct@answer}=1%
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\ex@name}
\final@result
\item* \ans@one%
\item \ans@two%
\item \ans@three%
\item \ans@four%
\end{multi}
\else
\ifnum\the\value{correct@answer}=2%
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\exname\thec@ex}
\final@result
\item \ans@one%
\item* \ans@two%
\item \ans@three%
\item \ans@four%
\end{multi}
\else
\ifnum\the\value{correct@answer}=3
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\exname\thec@ex}
\final@result
\item \ans@one%
\item \ans@two%
\item* \ans@three%
\item \ans@four%
\end{multi}
\else
\ifnum\the\value{correct@answer}=4
\begin{multi}[numbering=ABCD,penalty=0,feedback={\feed@back}]{\exname\thec@ex}
\final@result
\item \ans@one%
\item \ans@two%
\item \ans@three%
\item* \ans@four%
\end{multi}
\else
\relax
\fi
\fi
\fi
\fi
}%
\makeatother
\begin{document}
\begin{quiz}{My first test}
\begin{ex}
\centering This is my question. $\dfrac{a}{b}$
$\dfrac{c}{d}$
\choice
{\True Answer one}
{Answer two}
{Answer three}
{Answer four}
\loigiai{This is a detail answer.}
\end{ex}
\end{quiz}
\end{document}
答案3
实际上,您需要做的就是将输入结构转换为moodle
期望的输入结构。这里我假设你的输入数据总是具有以下结构
\begin{ex}
Question text
\choice{...}{...}{...}{...}
\loigiai{...}
\end{ex}
(特别是,\choice
总是出现在“问题文本”之后,并且\loigiai
总是出现在最后,并且每个问题都有一个\loigiai
命令(反馈不是可选的)。)
在这种情况下,如果你ex
使用 进行定义\NewEnviron
,则可以\BODY
用以下形式的分隔宏进行解析
\long\def\@transformBody#1\choice#2#3#4#5\loigiai#6{...}
其中#1
成为问题文本,#2...#5
是选项,#6
是反馈。人们可以尝试执行适当的转换并将内容塞入\begin{multi}...\end{multi}
,但由于后者也是从 构建的\NewEnviron
,我们也可以省去中间人,只需复制 的定义并multi
放入适当的内容即可。
然而还有最后一个问题:你原来的格式用 标记了正确答案,\True
moodle 使用*
。在这里我做了另一个假设:你总是把\True
答案放在开头。基本上,我希望能够扩展\True
为*
而不影响其余的选择文本;对于列表中的第一个标记来说,这很容易做到。
备注:可能还有其他我没考虑到的因素,但至少对于基本测试用例,以下方法有效。以下方法包含一些解释
\documentclass{article}
\usepackage[tikz]{moodle}
\usepackage{amsmath}
\usepackage{ifthen}
\usepackage{etoolbox}
\usepackage{environ}
\newcommand\True{*} %% Makes \True expand to *
\makeatletter
%%%%
\long\def\@transformBody#1\choice#2#3#4#5\loigiai#6{%
%% The purpose of the next four lines are to expand the first token
%% of the answer choices, so that \True -> *
\ExpandArgs{Nf}\def\my@choice@A{#2}
\ExpandArgs{Nf}\def\my@choice@B{#3}
\ExpandArgs{Nf}\def\my@choice@C{#4}
\ExpandArgs{Nf}\def\my@choice@D{#5}
%% The next command creates the processed body text to pass on for
%% processing by Moodle's internal commands. The complicated
%% string of \expandafter's are all because of the \True -> * replacement
\long\edef\ex@NewBody{\unexpanded{#1}
\noexpand\item\expandafter\unexpanded\expandafter{\my@choice@A}
\noexpand\item\expandafter\unexpanded\expandafter{\my@choice@B}
\noexpand\item\expandafter\unexpanded\expandafter{\my@choice@C}
\noexpand\item\expandafter\unexpanded\expandafter{\my@choice@D}}%
%% This stashes the feedback somewhere
\def\ex@feedback{#6}%
}
\newcounter{mymulti}
\NewEnviron{ex}{%
\refstepcounter{mymulti}
\expandafter\@transformBody\BODY %Process the \BODY
\bgroup
\setkeys{moodle}{numbering=ABCD,penalty=0,feedback={\ex@feedback},questionname={MC\themymulti}}% Sets most of the Moodle parameters for the MC question
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\expandafter\gatheritems\xa{\ex@NewBody}% Feed the Moodle Processor the transformed body text
%% everything below is copied straight from the definition of the
%% multi environment in moodle.sty
\let\moodle@questionheader=\gatheredheader
%First, the LaTeX processing
\item \moodle@begin@samepage \textbf{\moodle@questionname}
\ifmoodle@handout
\moodle@makelatextag@qtype{multi}
\else
\moodle@latex@writetags
\par
\noindent
\moodle@makelatextag@qtype{multi}%
\moodle@makelatextag@value{default grade}{marked out of}
\moodle@makelatextag@value{penalty}{penalty}%
\fi
\moodle@makelatextag@multi\par
\noindent
\moodle@questionheader
\edef\moodle@generalfeedback{\expandonce\moodle@feedback}
\csname moodle@multi@latexprocessing\endcsname
\moodle@end@samepage
%Now, writing information to XML
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\moodle@questionheader}% Save the question text.
\csname writemultiquestion\endcsname
\bgroup
\gdef\moodle@answers@xml{}%
\setkeys{moodle}{feedback={}}%
\xa\loopthroughitemswithcommand\xa{\csname savemultianswer\endcsname}%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
\moodle@writeanswers%
\moodle@writetags%
\writetomoodle{</question>}%
}{}%
\egroup
}%
%%%%
\makeatother
\moodleregisternewcommands
\begin{document}
\begin{quiz}{A}
\begin{ex}
This is my question. $\dfrac{a}{b}$
\choice
{\True Answer one}
{$15$ Answer two}
{Answer three}
{Answer four}
\loigiai{This is a detail answer.}
\end{ex}
\end{quiz}
\end{document}