% \iffalse meta-comment
%
% moodle.dtx
% Copyright 2016 by Anders O.F. Hendrickson (anders.o.f.hendrickson AT gmail.com)
% and 2019-2021 by Matthieu Guerquin-Kern (guerquin-kern AT crans.org).
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
% http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is Matthieu Guerquin-Kern.
%
% This work consists of the files moodle.dtx and moodle.ins
% and the derived file moodle.sty.
%
% \fi
%
% \iffalse
%<*driver>
\ProvidesFile{moodle.dtx}
%
%\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%\ProvidesPackage{moodle}
%<*package>
[2021/02/07 v0.9 Moodle quiz XML generation]
%
%
%<*driver>
\documentclass[a4paper]{ltxdoc}
\usepackage{iftex}
\ifPDFTeX
\usepackage[utf8]{inputenc} % necessary
\usepackage[T1]{fontenc} % necessary
\usepackage[protrusion=true,expansion]{microtype}
\usepackage[ttscale=.875]{libertine}
\else % assuming LuaLaTeX or XeLaTeX
\usepackage{fontspec}
\setmainfont[Mapping=tex-text]{Linux Libertine O}
\fi
%\usepackage{moodle}[2020/07/09]
\usepackage{amssymb,metalogo,multirow,threeparttable,booktabs}
\usepackage{hyperref,tikz,minted,changelog}
\usetikzlibrary{arrows,positioning,decorations.text}
%\usemintedstyle{Wombat}
\EnableCrossrefs
\CodelineIndex
\OnlyDescription
\RecordChanges
\begin{document}
\DocInput{moodle.dtx}
%\PrintChanges
\end{document}
%
% \fi
%
% \CheckSum{7729} ^^A Comment \OnlyDescription above to adjust
%
% \CharacterTable
% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
% Digits \0\1\2\3\4\5\6\7\8\9
% Exclamation \! Double quote \" Hash (number) \#
% Dollar \$ Percent \% Ampersand \&
% Acute accent \' Left paren \( Right paren \)
% Asterisk \* Plus \+ Comma \,
% Minus \- Point \. Solidus \/
% Colon \: Semicolon \; Less than \<
% Equals \= Greater than \> Question mark \?
% Commercial at \@ Left bracket \[ Backslash \\
% Right bracket \] Circumflex \^ Underscore \_
% Grave accent \` Left brace \{ Vertical bar \|
% Right brace \} Tilde \~}
%
%
% \GetFileInfo{\jobname.dtx}
%
% \DoNotIndex{\newcommand,\newenvironment,\def}
%
%
% \title{The \textsf{moodle} package: \\
% generating Moodle quizzes via \LaTeX%
% \thanks{This document
% corresponds to \textsf{moodle.sty}~\fileversion, dated \filedate.}}
% \author{Anders Hendrickson\footnote{original author of the package (\texttt{v0.5}), inactive.}\\
% \texttt{anders.o.f.hendrickson AT gmail.com} \and
% Matthieu Guerquin-Kern\footnote{current maintainer, author of the updates (\texttt{v0.6}
% to \texttt{v0.9}), partially funded in 2019 by \href{https://www.ensea.fr/en/}{ENSEA Graduate School}, France.}\\
% \href{mailto:guerquin-kern AT crans.org}{guerquin-kern AT crans.org}}
% \date{February 7, 2021}
%
% \maketitle
%
% \providecommand\TikZ{Ti\emph{k}Z}
%
% \section{Motivation}
%
% The acronym Moodle stands for ``Modular Object-Oriented Dynamic Learning Environment.''
% It is an open source learning management system (LMS) employed by many universities,
% colleges, and high schools to provide digital access to course materials, such as
% notes, video lectures, forums, and the like; see
% \url{https://moodle.com/moodle-lms/} for more information.
% One of the many useful
% features of Moodle is that mathematical and scientific notation can be entered in
% \LaTeX\ or \TeX\ code, which will be typeset either through a built-in \TeX\ filter
% or by invoking MathJax.
%
% For instructors who want to give students frequent feedback,
% but lack the time to do so, a particularly valuable module in Moodle
% is the \emph{quiz}. A Moodle quiz can consist of several different types of
% questions---not only multiple choice or true/false questions, but also
% questions requiring a short phrase or numerical answer, and even essay
% questions. All but the essay questions are automatically graded by the
% system, and the instructor has full control over how often the quiz may be
% attempted, its duration, and so forth. Feedback can be tailored to specific
% mistakes the student makes.
%
% All these features make Moodle quizzes very useful tools for instructors
% who have access to them.
% Unfortunately, the primary way to create or edit a Moodle quiz
% is through a web-based interface that can be slow to operate.
% To users of \LaTeX, accustomed to the speed of typing source code on
% a keyboard alone, the agonizing slowness of switching between mouse and keyboard
% to navigate a web form with its myriad dropdown boxes, radio buttons,
% compounded with a perceptible time lag as one's Moodle server responds to requests,
% can produce a very frustrating experience. Moreover, editing is entirely
% impossible without network access.
%
% Once the quiz is written, there is no easy way to view and proofread all the
% information of which it is made. Each question is edited on a separate webpage,
% which is so full of options that it cannot be viewed on a single screen.
% An instructor has to spend much time checking over the newly created quiz in
% order to be confident there are no errors.
%
% Added to all this is the frustration of managing graphics.
% If a question requires an image---say, asking a calculus student to interpret
% the graph of a function---the image must first be produced as a standalone file
% (e.g., in JPG or PNG format), uploaded to Moodle, and then chosen in a web-based
% HTML editor. Great is the vexation of the instructor who decided to alter a
% question, as there are more and more possibilities of error whenever multiple
% files must be kept synchronized.
%
% Users of \LaTeX\ are also accustomed to the speed and flexibility that
% comes from defining their own macros, which may be as brief as writing
% |\R| instead of |\mathbb{R}|
% or as complex as macros that generate entire paragraphs of text.
% The Moodle editor, by contrast, requires you to type |\mathbb{R}|
% every single time you want $\mathbb{R}$.
%
% Finally, there is the question of archiving and reusing one's work.
% Much, much work goes into creating Moodle quizzes, which then reside
% on a Moodle server somewhere in the cloud in a format neither easily browsable
% nor easily modifiable.
%
% \LaTeX\ itself has the power to solve all these difficulties:
% it is swift to edit and swifter to compile a \LaTeX\ document,
% and the PDF may be previewed onscreen or printed out for ease of proofreading.
% Mathematical graphics can be integrated within the main file through \TikZ,
% and of course \LaTeX\ macros can be customized.
% Using the present \textsf{moodle} package,
% a quiz author can type a quiz using familiar \LaTeX\ syntax and document
% structure. Upon compilation, \LaTeX\ will generate both a well-organized
% PDF that is easy to proofread and an XML file that can be uploaded directly
% to Moodle. The entire process is far faster than using Moodle's own
% web-based editor, makes it easier to catch one's mistakes,
% and the ultimate source code of one's work is a human-readable |.tex| file
% that can be archived, versioned, browsed, and edited offline.
%
% Strictly speaking, the \textsf{moodle} package does not generate quizzes:
% it generates question banks that can be imported in the LMS. The teacher
% still needs to compose manually a quiz from the question banks. Hopefully,
% two Moodle features supported by the package make this task easier:
% categories and tags.
%
% In this documentation the LMS is referred to as Moodle (uppercase M and
% roman font) while the \LaTeX\ package that is documented here is referred
% to as \textsf{moodle} (all lower case and sans serif font).
%
% \section{Workflow}
% The process of creating a quiz in Moodle using this package is depicted in
% Figure~\ref{fig:workflow}. It follows a few steps:
% \begin{enumerate}
% \item Write a \LaTeX\ document using |\usepackage{moodle}| as described
% below.
% \item Compile the document to PDF using pdf\LaTeX\, \XeLaTeX\ or \LuaLaTeX.
% This will also produce the file \meta{jobname}|-moodle.xml|.
% \item Open Moodle, navigate to the desired course,
% and under ``Question bank'' select ``Import.''
% \item Select ``Moodle XML format,'' choose the XML file to upload, and press ``Import.''
% \item After Moodle verifies that the questions have been imported correctly,
% you may add them to your quizzes.
% \end{enumerate}
% \begin{figure}[tbp]
% \centering
% \begin{tikzpicture}[node distance=1,auto,bend
% angle=45,box/.style={rectangle,draw=blue!50,rounded corners=3,top
% color=white,bottom color=black!20,thick,align=center,text
% width=2.5cm},elmt/.style={font=\itshape,align=left},
% cmnt/.style={font=\footnotesize,align=center},
% bigcmnt/.style={font=\normalsize,align=center},pre/.style={<-,>=stealth',thick},
% post/.style={->,>=stealth',thick}, prepost/.style={<->,>=stealth',thick}]
% \draw[white,fill=orange!20,rounded corners=10]
% (-1.5,-.7)--++(0,1.4)--++(10.3,0)--++(0,-3.3)--++(-6.7,0)--++(-.25,1.725)--cycle;
% \node[orange!80!black,above] (dev) at (7.5,-2.6) {\textit{Developpement}};
% \fill[green,fill opacity=.2,rounded corners=10]
% (-1.5,.7)--++(3,0)--++(0.5,-3.4)--++(6.8,0)--++(0,-2)--++(-10.3,0)--cycle;
% \node[green!80!black,below] (dev) at (7.5,-2.7) {\textit{Publishing}};
% \node[box,text width=2cm] (tex) {\texttt{.tex} source file};
% \node[rectangle,fill=white,draw,align=center,text
% width=1.5cm,below=of tex] (compfinal) {\LaTeX{}\\ engine};
% \node[rectangle,fill=white,draw,align=center,text width=1.5cm,right=of tex,xshift=4.5cm]
% (compdraft) {\LaTeX{}\\ engine};
% \node[box,right=of compfinal,xshift=.5cm] (pdf) {\texttt{.pdf} file for proofreading};
% \node[rectangle,fill=white,draw,align=center,text width=2cm,below=of compfinal] (extern)
% {Picture\\processing};
% \draw (pdf|-extern) node[box,anchor=center] (xml) {\texttt{.xml} file\\\footnotesize(pictures embedded)};
% \draw (compdraft|-xml)
% node[rectangle,fill=white,draw,align=center,text width=1.5cm,anchor=center] (moodle)
% {Moodle\\Server};
% \draw (tex) edge [post,bend right=10] node[cmnt,pos=.5,left] {\texttt{final}} (compfinal);
% \draw (tex) edge [post,bend left=10] node[cmnt,pos=.5,below] {\texttt{draft}} (compdraft);
% \draw (compdraft) edge [post,bend left=10] (pdf);
% \draw (compfinal) edge [post] (pdf);
% \draw (compfinal) edge [post,bend left=10] (xml);
% \draw (compfinal) edge [post,bend right=30] node[cmnt,black!40,pos=.5,text width=1cm,left]
% {\texttt{tikz}, \texttt{.png}, \texttt{.jpg}} (extern);
% \draw (extern) edge [post,green,bend right=30] node[cmnt,black!40,pos=.5,below,right]
% {\texttt{base64}} (compfinal);
% \draw (pdf) edge [post,red,bend right=15] node[sloped,cmnt,pos=.5,above] {improve} (tex);
% \draw (xml) edge [post,red] node[cmnt,pos=.5,below] {import} (moodle);
% \end{tikzpicture}
% \caption{Block diagram describing a typical workflow using the \textsf{moodle} package.}
% \label{fig:workflow}
% \end{figure}
%
% \section{Usage}\label{sect:usage}
% The following pages presume the reader already has some familiarity with creating
% and editing Moodle quizzes through the web interface.
% Users that are not familiar with Moodle quizzes can learn more in the Moodle
% documentation. For instance, \url{https://docs.moodle.org/310/en/Question_types}.
%
% The |xkeyval| package is used to provide a key-value interface.
%
% \subsection{Example Document}
%
% Here is a simple example document:
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \documentclass[12pt]{article}
% \usepackage[section]{moodle}
% \moodleregisternewcommands
% \newcommand\monomial[1]{x^{#1}}
% \newcommand\sillyanswer{What!?}
% \begin{document}
% \begin{quiz}{My first quiz}
% \begin{numerical}[points=2]{Basic addition}
% What is $8+3$?
% \item 11
% \end{numerical}
% \begin{shortanswer}[usecase]{Newton's name}
% What was Newton's first name?
% \item Isaac
% \item[fraction=0, feedback={\sillyanswer}] Fig
% \item[fraction=0] Sir
% \end{shortanswer}
% \begin{multi}[points=3]{A first derivative}
% What is the first derivative of $\monomial{3}$?
% \item $\frac{1}{4}\monomial{4}+C$
% \item[feedback={yes!}]* $3\monomial{2}$
% \item[feedback={\sillyanswer}] $51$
% \end{multi}
% \end{quiz}
% \end{document}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
% Key features to note in this first example are that a |quiz| environment
% contains several question environments.
% Each question takes a name as a mandatory argument,
% and it may also take optional key-value arguments within brackets.
% The question environments resemble list environments
% such as |itemize| or |enumerate|, in that answers are set off by
% |\item|'s, but the question itself is the text that occurs before
% the first |\item|.
%
%^^A \DescribeMacro{\moodleregisternewcommands}\DescribeMacro{\htmlregister}
%^^A Calling |\moodleregisternewcommands| tells the package to treat
%^^A specifically the macros defined subsequently.
%^^A This way, the macros that Moodle's \LaTeX\ renderer does not know
%^^A about can be properly expanded in the XML file.
%^^A This mechanism applies only to the macros defined using |\newcommand|
%^^A and \emph{without} optional argument.
%^^A Using |\htmlregister|\marg{macroname}, lets you declare a specific
%^^A macro for expansion. This mechanism, instead, also applies to the
%^^A macros defined using \TeX's primitive |\def|.
%
% \subsection{Package Options}
% \DescribeMacro{draft}
% \DescribeMacro{final}
% If the package option |draft| is invoked, by calling
% |\usepackage[draft]{moodle}| or |\documentclass[draft]{...}|, then no
% XML file will be generated. This is especially useful while editing a
% quiz containing graphics, so as to avoid the time spent converting
% image files. The package option |final| might be useful if one wants
% to avoid the option |draft| to be inherited from the |documentclass|.
%
% \DescribeMacro{handout}
% If the package option |handout| is invoked (|\usepackage[handout]{moodle}|),
% the PDF file is generated clean from teacher-only information (answers,
% points, penalty, feedback, tags) and, hence, can be given to students for
% classroom work. In particular, as would Moodle do, answers in
% \texttt{matching} questions are shuffled and the option \texttt{shuffle}
% triggers the shuffling of choices offered (\texttt{multi} and
% \texttt{matching}). This is achieved thanks to the package
% \texttt{randomlist}, loaded if the option is invoked.
% The XML file is generated as usual.
%
% \DescribeMacro{nostamp}
% By default, the package will output a stamp as a comment in the XML
% file. This stamp contains information gathered about the TeX engine,
% the operating system used and the package version. For instance:
% \begin{quote}\small
% ||\\
% ||
% \end{quote}
% The package option
% |nostamp| prevents this stamp to be written in the XML file.
%
% \DescribeMacro{section}
% \DescribeMacro{section*}
% \DescribeMacro{subsection}
% \DescribeMacro{subsection*}
% If the package option |section| is invoked (|\usepackage[section]{moodle}|),
% then each quiz is represented by a different \LaTeX\ section. Starred
% variants correspond to unnumbered sections or subsections. To preserve
% compatibility with Version 0.5 of this package, the default is |subsection*|.
% Consequently, |\usepackage{moodle}| is equivalent to
% |\usepackage[subsection*]{moodle}|.
%
% \DescribeMacro{tikz} The package option \texttt{tikz} is described in section
% \ref{subsec:tikz}.
%
% \DescribeMacro{svg} The package option \texttt{svg} is described in section
% \ref{subsec:svg}.
%
% \subsection{Quiz and Question Environments}
%
% \DescribeMacro{quiz}
% A |.tex| document to generate Moodle quizzes contains one or more
% |quiz| environments, within which various question environments are nested.
% The required argument to the |quiz| environment names a category for Moodles
% ``question bank'': after import, the questions defined in this environment
% will be gathered in this category.
% \begin{center}
% |\begin{quiz}|\oarg{options}\marg{category name}%
% \end{center}
% There are no |quiz|-specific options,
% but any \meta{options} set with |\begin{quiz}|
% will be inherited by all questions contained within that |quiz| environment.
%
% \DescribeMacro{\moodleset}
% Options may also be set outside question environments with
% |\moodleset|\marg{options}; these changes are local to \TeX-groups.
%
% \DescribeMacro{\setcategory}\DescribeMacro{\setsubcategory}
% Although the |quiz| environment defines a category by its own, one can change
% the current category inside the quiz environment and in between questions,
% using the macro |\setcategory|\marg{category name}. A subcategory can also be
% defined with |\setsubcategory|\marg{subcategory name}. The categories and
% subcategories are reflected in the PDF file as sections, subsections, or
% subsubsections, in accordance to the package setting |section|, |section*|,
% |subsection|, or |subsection*|.
%
% The syntax for each question environment is
% \begin{quote}
% |\begin|\marg{question type}\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item|\oarg{item options} \meta{item} \\
% \rule{2em}{0pt}\quad$\vdots$ \\
% \rule{2em}{0pt}|\item|\oarg{item options} \meta{item} \\
% |\end|\marg{question type}
% \end{quote}
% The meaning of the \meta{item}s varies depending on the question type,
% but they usually are answers to the question.
% Details will be given below.
%
% The following key-value options may be set for all questions:
%
% \DescribeMacro{points}\DescribeMacro{default grade}
% By default, each question is worth 1 point on the quiz.
% This may be changed with the |points| key or its synonym, |default grade|;
% for example, |points=2| makes that question worth two points.
%
% \DescribeMacro{penalty}
% The |penalty| is the fraction of points that is taken off for each wrong attempt;
% it may be set to any value between 0 and 1.
% The default is |penalty=0.10|.
%
% \DescribeMacro{fraction}
% In most question types, it is possible to designate some answers as being
% worth partial credit---that is, some fraction of a completely correct answer.
% The |fraction| key may be set to any of the values given in Table~\ref{tab:fraction},
% from |0| (entirely wrong) to |100| (entirely correct).
%
% \begin{table}[tbp]
% \centering
% \caption{\href{https://github.com/moodle/moodle/blob/MOODLE\_310\_STABLE/question/engine/bank.php\#L339}{Valid positive options} for the \texttt{fraction} key: $100\cdot(p/q)$.}
% \label{tab:fraction}
% \footnotesize
% \begin{tabular}{l*{10}{l}}
% \toprule
% Denominator $q$ & \multicolumn{10}{c}{Numerator $p$}\\
% \cmidrule{2-11}
% & 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9\\
% \cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}\cmidrule(lr){4-4}
% \cmidrule(lr){5-5}\cmidrule(lr){6-6}\cmidrule(lr){7-7}\cmidrule(lr){8-8}
% \cmidrule(lr){9-9}\cmidrule(lr){10-10}\cmidrule(lr){11-11}
% 20 & 0&5&&&&&&&&\\\cmidrule(lr){1-1}
% 10 & &10&20&30&40&50&60&70&80&90\\\cmidrule(lr){1-1}
% 9 & &11.11111&&&&&&&&100\\\cmidrule(lr){1-1}
% 8 & &12.5&&&&&&&100&\\\cmidrule(lr){1-1}
% 7 & &14.28571&&&&&&100&&\\\cmidrule(lr){1-1}
% 6 & &16.66667&&&&83.33333&100&&&\\\cmidrule(lr){1-1}
% 5 & &20&&&80&100&&&&\\\cmidrule(lr){1-1}
% 4 & &25&&75&100&&&&&\\\cmidrule(lr){1-1}
% 3 & &33.33333&66.66667&100&&&&&&\\\cmidrule(lr){1-1}
% 2 & &50&100&&&&&&&\\\cmidrule(lr){1-1}
% 1 & 0&100&&&&&&&&\\\cmidrule(lr){1-1}
% \bottomrule
% \end{tabular}
% \end{table}
% In questions where several choices can be selected (see |multi| with the option
% |multiple|), positive fractions must sum up to exactly 100. It is also possible to set
% negative fractions (from -100 to 0) for wrong choices, in order to prevent the
% selection of all choices from leading to a good grade.
% In this case, the value ranging from -100 to 0 must be the opposite of one of the
% values listed in Table~\ref{tab:fraction}.
%
% \DescribeMacro{fractiontol}
% The package tries to match the |fraction| key to one of the admissible values.
% To this end, the tolerance is controlled by the |fractiontol| key. It defaults
% to |0.01| but may be changed. When no admissible fraction value is matched, the
% package throws an error.
%
% \DescribeMacro{feedback}
% The |feedback| key sets text that will appear to the student after completing the quiz.
% For example, one might set
% \begin{center}
% |feedback={This question might show up in the final exam.}|
% \end{center}
% The desired feedback should be included in braces.
%
% Two kinds of feedback can be given. If the |feedback| key is set for a
% question, then that feedback will appear to each student regardless of the student's answer.
% Answer-specific feedback (perhaps explaining a common mistake)
% may also be given by setting the |feedback| key \emph{at the individual answer}.
%
% \DescribeMacro{tags}
% The |tags| key sets a list of keywords for the question that will be taken into account
% by Moodle for filtering purposes or classification of questions inside the question bank.
% It is possible for instance to build a quiz with questions cherry-picked among the set of
% questions holding a particular tag.
% For example, one might set
% \begin{center}
% |tags={easy}|
% \end{center}
% The desired tag should be specified in between braces. Multiple tags can be set as a
% comma-separated list:
% \begin{center}
% |tags={tag1,tag2,{ leading whitespace},{including, comma}}|
% \end{center}
%
% Tags can be assigned at two levels. If the |tags| key is set at the quiz level,
% then that tag list will serve as a default for each question of the quiz.
% Question-specific tags can be assigned by setting the |tags| key \emph{at the question level}.
% The question-level |tags| key overrides eventual quiz-level tags.
%
% Users willing to specify a same tag for all questions of the quiz could
% also rely on Moodle's category mechanism.
%
% \subsection{\href{https://docs.moodle.org/en/Question_types}{Question Types}}
%
% We next discuss the various question types supported by \textsf{moodle}
% and the options that may be set.
%
%\subsubsection{\href{https://docs.moodle.org/en/True/False_question_type}{True/False}}
%
% \DescribeMacro{truefalse}
% The syntax for a True/False question is as follows:
% \begin{quote}
% |\begin{truefalse}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item*| \meta{feedback when ``true" is chosen} \\
% \rule{2em}{0pt}|\item| \meta{feedback when ``false" is chosen} \\
% |\end{truefalse}|
% \end{quote}
% The correct answer is designated by the asterisk |*| after the |\item|;
% it need not appear first in the list.
%
% Answer-specific feedback can also be defined as an item option, similarly to
% other types.
% \begin{quote}
% |\begin{truefalse}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item[feedback={|\meta{When ``true" is chosen}|}]*| \\
% |\end{truefalse}|
% \end{quote}
% Note that, in this example, no feedback is defined for the incorrect answer
% ``False": the corresponding item can be omitted.
%
% With the True/False question type, the |penalty| key has no effect.
%
% \subsubsection{\href{https://docs.moodle.org/310/Multiple_Choice_question_type}{Multiple Choice}}
%
% \DescribeMacro{multi}
% The syntax for a classic multiple choice question,
% with only one correct answer, is as follows:
% \begin{quote}
% |\begin{multi}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item*| \meta{correct answer} \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{wrong answer} \\
% \rule{2em}{0pt}\quad$\vdots$ \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{wrong answer} \\
% |\end{multi}|
% \end{quote}
% The correct answer is designated by the asterisk |*| after the |\item|;
% it need not appear first in the list.
%
%
% \DescribeMacro{shuffle}
% The boolean key |shuffle| determines whether Moodle will
% rearrange the possible answers in a random order.
% Setting |shuffle=false| will guarantee that the answer appear
% in the order they were typed; the default is |shuffle=true|.
%
% \DescribeMacro{numbering}
% Moodle offers different options for numbering the possible answers.
% You may set the |numbering| key to any of the following values,
% which mirror the usual \LaTeX\ syntax:
% |alph|, |Alph|, |arabic|, |roman|, |Roman|, and |none|.
% Calling |numbering=none| produces an unnumbered list of answers.
% The Moodle syntax of |abc|, |ABCD|, |123|, |iii|, and |IIII| is also
% acceptable,
% but note that it requires \emph{four} capital letters to obtain
% upper-case Roman or alphabetic numerals this way.
%
% \DescribeMacro{fraction}
% The |fraction| key can be used to designate some wrong answers
% as being worth partial credit. For example, a question might read thus:
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{multi}{my question}
% Compute $\int 4x^3\,dx$.
% \item* $x^4+C$
% \item[fraction=50] $x^4$
% \item $12x^2$
% \end{multi}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
% Thus the asterisk |*| is shorthand for |fraction=100|,
% whereas a bare |\item| sets |fraction=0|.
%
% \DescribeMacro{single}
% By default, the |multi| environment produces
% a multiple choice question with only one correct answer;
% this is called |single| mode, and on Moodle it appears with radio buttons.
%
% \DescribeMacro{multiple}
% It is also possible to write questions with possibly more than one correct answer,
% asking the user to check all correct answers. To do this, use the key |multiple|
% or |single=false|.
% The worth of each correct answers in |multiple| mode may be set by |fraction|,
% but Moodle asks that all the fractions add up to \emph{exactly} 100.
% If you simply designate each correct answer with |\item*|, then \textsf{moodle}
% will divide equally among those answers the points lefts for a sum of 100\%.
% Items that are not given a |fraction| are considered incorrect and selecting them
% results in negative points such that the sum of all incorrect answers is -100\%.
% For example, the following two examples are equivalent:
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{multi}[multiple]{my question}
% Which numbers are prime?
% \item[fraction=20] 2
% \item* 5
% \item* 7
% \item[fraction=-10] 1
% \item 6
% \item 8
% \end{multi}
%
% \begin{multi}[multiple]{my question}
% Which numbers are prime?
% \item[fraction=20] 2
% \item[fraction=40] 5
% \item[fraction=40] 7
% \item[fraction=-10] 1
% \item[fraction=-45] 6
% \item[fraction=-45] 8
% \end{multi}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
% Note that, in this example, negative fractions are set for wrong choices. This
% prevents students selecting all options to obtain a good grade with no merit.
%
% \DescribeMacro{allornothing}
% There also exists a \href{https://moodle.org/plugins/qtype_multichoiceset}
% {``All-or-Nothing Multiple Choice''} plugin for Moodle that introduces a
% question type similar to a multiple choice with multiple correct answers,
% with the specificity that the points are given if and only if the student
% selects all correct answers. This kind of question is set up using the
% |allornothing| key.
% The recommended way for designating correct answers is with |\item*|. If instead
% the |fraction| is used, \textsf{moodle} moodle will consider that non-negative
% fractions ($>0$) designate correct answers and negative fractions ($\leq 0$)
% designate incorrect choices.
% The option |allornothing| supersedes the options |multiple| and |single|.
% To the best of our knowledge, Moodle does not offer the all-or-nothing behavior
% for multiple choice questions embedded inside a cloze question.
%
% \subsubsection{\href{https://docs.moodle.org/en/Numerical_question_type}{Numerical}}
%
% A numerical question in Moodle requires the student
% to input a real number in decimal form.
% Its typical format is
% \begin{quote}
% |\begin{numerical}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{correct answer} \\
% |\end{numerical}|
% \end{quote}
% If there is more than one correct answer, additional |\item|'s may be included.
% Because this is not a multiple choice question, there is no need to provide
% incorrect answers. There may nevertheless be reasons to include incorrect answers.
% For example, partially correct answers may be specified by setting the |fraction| key.
% Feedback for a common mistake may be given by including the incorrect answer like this:
% \begin{quote}\footnotesize
% |\item[fraction=0,feedback={You forgot to antidifferentiate!}]| \meta{incorrect answer}
% \end{quote}
%
% \DescribeMacro{tolerance}
% The |tolerance| key can be used to specify the validity of answers within some margin.
% This key can be set at different levels: quiz, question, item.
% For example, with the question
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{numerical}[tolerance=0.01]{my question}
% Approximate value of $\sqrt{2}$?
% \item[tolerance={1e-1}] 1.4142
% \item[fraction=20,feedback={twice this!}] 7.0711e-1
% \item[fraction=0,feedback={Wrong!}] *
% \end{numerical}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
% In this example,
% \begin{itemize}
% \item any answer in the range $[1.4042,1.4242]$ will be validated,
% \item any answer in the range $[0.69711,0.71711]$ will get the specific feedback
% \emph{twice this!} and 20\% of points,
% \item any other answer is incorrect and will get the specific feedback
% \emph{Wrong!}.
% \end{itemize}
%
% When feedback is to be given for any non-specified answer, one can add a \emph{last} answer
% item containing the wilcard character |*| only. In this case, the |tolerance| key is irrelevant.
%
% Both answers and tolerance can be specified with the comma (|,|) as a decimal separator.
% Exponent notation is accepted. After import, Moodle will recognize indifferently |0.000165|,
% |0,000165|, |1.65E-4|, |1.65e-4|, |1,65E-4|, and |1,65e-4|.
%
% If the \textsf{siunitx} package is loaded, \textsf{moodle} will detect it and
% numbers will be rendered nicely in the PDF output.
%
% Units, unit-handling and multipliers are currently unsupported.
%
% \subsubsection{\href{https://docs.moodle.org/en/Short-Answer_question_type}{Short Answer}}
% A short answer question resembles a numerical question: the student is to fill
% in a text box with a missing word or phrase.
% \begin{quote}
% |\begin{shortanswer}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{correct answer} \\
% \rule{2em}{0pt}\quad$\vdots$ \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{correct answer} \\
% |\end{shortanswer}|
% \end{quote}
% You can make the text box appear as part of the question with the
% control sequence |\blank|. For example,
% your question might read
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{shortanswer}{Leibniz}
% Newton's rival was Gottfried Wilhelm \blank.
% \item Leibniz
% \item Leibniz.
% \end{shortanswer}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
% Note that as the blank occurred at the end of a sentence,
% we included two answers,
% lest students get the question wrong merely by
% including or omitting a period.
%
% \DescribeMacro{case sensitive}\DescribeMacro{usecase}
% The default setting when creating a Short Answer question in Moodle
% is to ignore the distinction between upper- and lower-case letters
% when grading a short answer question. This default is preserved by
% \textsf{moodle}.
% You can make a question case-sensitive with the key |case sensitive|
% or its shorter synonym |usecase|.
%
% The wildcard character |*| can used to grab answers that match
% a specific pattern. For instance:
% \begin{itemize}
% \item ``\emph{Sir Isaac Newton}'', ``\emph{Isaac Newton}'' and
% ``\emph{Newton}'' will match the pattern |*Newton|,
% \item ``\emph{Gaston}'' and ``\emph{Wellington}'' will match the
% pattern |*ton|,
% \item ``\emph{Isaac}'' and ``\emph{Isaac Newton}'' will match the
% pattern |Isaac*|,
% \item any non empty answer will match the pattern |*| (wildcard alone).
% \end{itemize}
%
% \subsubsection{\href{https://docs.moodle.org/en/Essay_question_type}{Essay}}\label{subsubsect:essay}
% Instructors may ask essay questions on a Moodle quiz,
% although Moodle's software is not up to the task of grading them!
% Instead each essay question answer must be graded manually by the
% instructor or a teaching assistant.
% \begin{quote}
% |\begin{essay}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{notes for grader} \\
% \rule{2em}{0pt}\quad$\vdots$ \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{notes for grader} \\
% |\end{essay}|
% \end{quote}
% Instead of containing answers, the |\item| tags for the |essay| question
% contain notes that will appear to whoever is grading the question manually.
%
% \DescribeMacro{response required}
% Although Moodle cannot grade the content of an essay question,
% it can at least determine whether the question has been left blank.
% If the |response required| key is set, Moodle will insist that the student
% enter something in the blank before accepting the quiz as completed.
%
% \DescribeMacro{response format}
% Moodle offers five different ways for students to enter and/or upload their
% answers to an essay question. You may choose one of these five options:
% \begin{description}
% \item[{\ttfamily html}] An editor with the ability to format HTML responses
% including markup for italics, boldface, etc. This is the default.
% \item[{\ttfamily file}] A file picker allowing the student to upload a
% file, such as a PDF or DOC file, containing the essay.
% \item[{\ttfamily html+file}] The same HTML editor as above, but with the
% ability to upload files as well. This permits some students to type
% answers directly into the web form, and others to compose their
% essays in another program first.
% \item[{\ttfamily text}] This editor allows only for entering plain text
% without any markup.
% \item[{\ttfamily monospaced}] This yields a plain text editor, without any
% markup, and with a fixed-width font. This could be useful for
% entering code snippets, for example.
% \end{description}
%
% \DescribeMacro{response field lines}
% The key |response field lines| controls the height of the input box.
% For Moodle, the admissible values are: 5, 10, 15, 20, 25, 30, 35, and 40.
% If the value set is not admissible, \textsf{moodle} will approximate the value:
% \begin{itemize}
% \item with either 5 or 40 if the value set was out of range, or
% \item with the next multiple of 5 otherwise.
% \end{itemize}
% The default is |response field lines=15|.
%
% \DescribeMacro{attachments allowed}
% The |attachments allowed| key controls \emph{how many} attachments a student is
% allowed to upload. Permissible values are |0|, |1|, |2|, |3|, or |unlimited|.
%
% \DescribeMacro{attachments required}
% You may also require the student to upload a certain number of attachments
% by setting |attachments required| to |0|, |1|, |2|, or |3|.
%
% \DescribeMacro{template}
% Finally, you may preload the essay question with a template that the student
% will edit and/or type over, with the key |template=|\marg{template}.
% The \meta{template} should be enclosed in braces.
%
% \subsubsection{\href{https://docs.moodle.org/en/Matching_question_type}{Matching}}
%
% A matching question offers a series of subquestions
% and a set of possible answers from which to choose.
% If there are $m$ questions and $n\geq m$ possible answers,
% a matching question will look like this:
%
% \begin{quote}
% |\begin{matching}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{question 1} |\answer| \meta{answer 1}\\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{question 2} |\answer| \meta{answer 2}\\
% \rule{2em}{0pt}\quad$\vdots$ \\
% \rule{2em}{0pt}|\item|\oarg{options} \meta{question $m$} |\answer| \meta{answer $m$}\\
% \rule{2em}{0pt}|\item|\oarg{options} |\answer| \meta{answer $m+1$}\\
% \rule{2em}{0pt}\quad$\vdots$ \\
% \rule{2em}{0pt}|\item|\oarg{options} |\answer| \meta{answer $n$}\\
% |\end{matching}|
% \end{quote}
% Answers $1$ through $m$ correspond to questions $1$ through $m$;
% answers $m+1$ through $n$ are ``decoy'' answers.
% If multiple questions should have the same answer,
% be sure your typed answer match exactly, so that Moodle will not
% create duplicate copies of the same answer!
%
% \DescribeMacro{shuffle}
% The |matching| question accepts the option of |shuffle| to randomly
% permute the questions and answers; by default |shuffle=true|.
%
% \DescribeMacro{drag and drop}\DescribeMacro{dd}
% The standard matching question offered by Moodle corresponds to
% a dropdown box for choosing the answer to each question.
% There also exists a \href{https://docs.moodle.org/310/en/Drag_and_drop_matching_question_type}
% {``drag and drop matching''} plugin for Moodle that
% shows all questions in one column,
% all answers in a second column, and allows students to drag the correct
% answer to the question using a mouse.
% In this package, to enable drag-and-drop matching, use the key
% `|drag and drop|' or `|dd|' for short. The default is |dd=false|.
% If you choose the standard format, then due to the limitations of
% dropdown boxes, no \LaTeX\ or HTML code can be used in the answers.
%
% \subsubsection{\href{https://docs.moodle.org/en/Embedded_Answers_(Cloze)_question_type}
% {Cloze Questions and Subquestions}}
%
% A ``cloze question'' has one or more subquestions embedded within a passage of text.
% For example, you might ask students to fill in several missing words within
% a sentence, or calculate several coefficients of a polynomial.
% To encode cloze questions in \LaTeX\ using this package is easy:
% you simply nest one or more |multi|, |shortanswer|, or |numerical| environments
% within a |cloze| environment, as in the following example:
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{cloze}{my cloze question}
% Thanks to calculus, invented by Isaac
% \begin{shortanswer}[usecase]
% \item Newton
% \end{shortanswer},
% we know that the derivative of $x^2$ is
% \begin{multi}[horizontal]
% \item $2x$
% \item* $\frac{1}{3} x^3 + C$
% \item $0$
% \end{multi}
% and that $\int_0^2 x^2\,dx$ equals
% \begin{numerical}
% \item[tolerance={4e-4}] 2.667
% \end{numerical}.
% Thanks, Isaac!
% \end{cloze}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
% Note that when used as a subquestion within a cloze question,
% |\begin{multi}| is \emph{not} followed by name in braces;
% the same is true for the |shortanswer| and |numerical|
% environments.
%
% \DescribeMacro{single=true}\DescribeMacro{single=false}\DescribeMacro{multiple}
% Before Moodle version 3.5, within a cloze question, a multiple choice question
% was necessarily of type |single|, i.e. with a single good answer. If you intend
% to export your quiz to Moodle 3.5+, the option |multiple| can be used, when
% multiple good answers are to be found.
%
% \DescribeMacro{vertical}\DescribeMacro{horizontal}\DescribeMacro{inline}
% Within a cloze question, by default, a multiple choice question is implemented
% as an |inline| dropdown box. This is visually compact, but it also prevents
% the use of mathematical or HTML formatting.
% Adding the option |vertical| displays the subquestion as a vertical column
% of radio buttons instead; likewise the option |horizontal| creates a horizontal
% row of radio buttons.
% The option |inline| is incompatible with |multiple| or |single=false|
% (dropdown boxes don't let you pick up several answers!).
%
% \DescribeMacro{shuffle}
% Starting from Moodle version 3.0, within a cloze question, the items of a
% multiple choice question can be shuffled. Setting |shuffle=false| will
% guarantee that the answer appear in the order they were typed; the
% default is |shuffle=true|.
%
% \DescribeMacro{case sensitive}\DescribeMacro{usecase}
% Within a cloze question, the short answer question can be made case sensitive.
% This option, disabled by default, is selected with |case sensitive| or |usecase|.
%
%\subsubsection{\href{https://docs.moodle.org/en/Description_question_type}{Description}}
%
% The Moodle description type is not really a question. It is more like a label.
% One can set a |feedback| that the student gets when reviewing the submission.
% Tags can be set as well.
%
% For descriptions, \textsf{moodle} redefines the existing |description| environment.
%
% The syntax for a Description question is as follows:
% \begin{quote}
% |\begin{description}|\oarg{question options}\marg{question name} \\
% \rule{2em}{0pt}\meta{question text} \\
% |\end{description}|
% \end{quote}
%
% \subsection{Summary of the Key Options}
%
% Table~\ref{tab:key-options} summarizes the key options available at the question
% and answer levels depending on the question type. For the essay questions,
% please refer to section~\ref{subsubsect:essay}.
%
% \begin{table}[tbp]
% \centering
% \caption{Options offered at the question and answer levels for each question type.}
% \label{tab:key-options}
% \small
% \begin{tabular}{*{15}{l}}
% \toprule
% & \multicolumn{11}{l}{Question} & \multicolumn{3}{l}{Answer}\\
% \cmidrule(lr){2-12}\cmidrule(lr){13-15}
% Question type & \rotatebox{90}{points} &
% \rotatebox{90}{penalty} & \rotatebox{90}{feedback} & \rotatebox{90}{tags} &
% \rotatebox{90}{shuffle} & \rotatebox{90}{numbering} & \rotatebox{90}{multiple} &
% \rotatebox{90}{allornothing} &\rotatebox{90}{usecase} & \rotatebox{90}{tolerance} &
% \rotatebox{90}{dd} & \rotatebox{90}{fraction} & \rotatebox{90}{feedback} &
% \rotatebox{90}{tolerance}\\\cmidrule(lr){1-1}\cmidrule(lr){2-2}\cmidrule(lr){3-3}
% \cmidrule(lr){4-4}\cmidrule(lr){5-5}\cmidrule(lr){6-6}\cmidrule(lr){7-7}
% \cmidrule(lr){8-8}\cmidrule(lr){9-9}\cmidrule(lr){10-10}\cmidrule(lr){11-11}
% \cmidrule(lr){12-12}\cmidrule(lr){13-13}\cmidrule(lr){14-14}\cmidrule(lr){15-15}
% \href{https://docs.moodle.org/35/en/Multiple_Choice_question_type}
% {Multichoice} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ &
% $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & & & & $\bullet$ & $\bullet$ \\
% \href{https://docs.moodle.org/35/en/Numerical_question_type}{Numerical}
% & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & & & &
% & & $\bullet$ & & $\bullet$ & $\bullet$ & $\bullet$ \\
% \href{https://docs.moodle.org/35/en/Short-Answer_question_type}{Short
% Answer} & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & & & &
% & $\bullet$ & & & $\bullet$ & $\bullet$ \\
% \href{https://docs.moodle.org/35/en/Matching_question_type}{Matching}
% & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ & & &
% & & & $\bullet$ & $\bullet$ & \\
% \href{https://docs.moodle.org/35/en/True/False_question_type}
% {True/False} & $\bullet$ & & $\bullet$ & $\bullet$ & & & &
% & & & & & $\bullet$ \\
% \href{https://docs.moodle.org/35/en/Description_question_type}
% {Description} & & & $\bullet$ & $\bullet$ & & & &
% & & & & & \\
% ^^A\href{https://docs.moodle.org/35/en/Essay_question_type}{Essay} & \\\hline%
% \href{https://docs.moodle.org/35/en/Embedded_Answers_(Cloze)_question_type}{Cloze}
% & & $\bullet$ & $\bullet$ & $\bullet$ & & & &
% & & & & & \\\cmidrule(lr){1-1}
% \hspace{1em}Numerical & $\bullet$ & & & & & & &
% & &$\bullet$ & & $\bullet$ & $\bullet$ & $\bullet$ \\
% \hspace{1em}Short Answer & $\bullet$ & & & & & & &
% & $\bullet$ & & & $\bullet$ & $\bullet$ \\
% \hspace{1em}Multi (inline) & $\bullet$ & & & & $\bullet$ & & &
% & & & & $\bullet$ & $\bullet$ \\
% \hspace{1em}Multi (horizontal)& $\bullet$ & & & & $\bullet$ & & $\bullet$
% & & & & & $\bullet$ & $\bullet$ \\
% \hspace{1em}Multi (vertical)& $\bullet$ & & & & $\bullet$ & & $\bullet$
% & & & & & $\bullet$ & $\bullet$ \\
% \bottomrule
% \end{tabular}
% \end{table}
%
% \section{Conversion to HTML}
%
% Questions should be typed as usual for \LaTeX,
% including |\$| to obtain dollar signs, |$|'s or |\(|...|\)| for math shifts,
% |$$|'s or |\[|...|\]| for display math, et cetera.
% The package \textsf{moodle.sty} automatically converts
% this \LaTeX\ code into HTML for web display.
%
% Table~\ref{tab:html} lists \LaTeX\ macros, commands, and environments that
% are specifically converted to HTML.
% \begin{table}[tbp]
% \centering
% \caption{Conversion of \LaTeX\ material to HTML.}
% \label{tab:html}
% \begin{tabular}{llll}
% \toprule
% \multicolumn{2}{l}{Macros} & Commands & Environnments \\
% \cmidrule(lr){1-2}\cmidrule(lr){3-3}\cmidrule(lr){4-4}
% |\%| & |\#| &|\emph{}| & |\begin{center}|\\
% |\$| & |\&| &|\textbf{}| & |\begin{enumerate}|\\
% |\\| & |\par| &|\textit{}| & |\begin{itemize}|\\
% |\&| & |\S| & |\texttt{}| & |\begin{tikzpicture}|\\
% |\{| & |\}| & |\textsc{}| & \\
% |\|\textvisiblespace & |\relax| & |\underline{}| &\\
% |\,| & |\thinspace| & |\textsuperscript{}| & \\
% |\dots| & |\ldots| & |\up{}| & \\
% |\euro| & |\texteuro| & |\fup{}| & \\
% |\TeX| & |\LaTeX|& |\textsubscript{}| & \\
% |\_| & |\textbackslash| & |\url{}| & \\
% |~| & & |\href{}{}| & \\
% & & |\tikz[]{}| & \\
% & & |\includegraphics[]{}| & \\
% & & |\verbatiminput{}| & \\
% & & |\VerbatimInput[]{}| & \\
% & & |\LVerbatimInput[]{}| & \\
% & & |\BVerbatimInput[]{}| & \\
% & & |\inputminted[]{}{}| & \\
% \bottomrule
% \end{tabular}
% \end{table}
% Single and double quotation marks (with german variants), french quotation marks,
% inverted exclamation and question marks, and the diacritical
% commands |\^|, |\'|, |\`|, |\"|, |\~|, |\c|, |\H|, |\k|, |\u| and |\v| are
% also handled, as are the characters |\aa|, |\ae|, |\l|, |\oe|,
% |\o|, |\ss|, and their capitalizations. See Tables~\ref{tab:diacritical},
% \ref{tab:ligatures}, and \ref{tab:other} for more details.
%
% In addition, |<| and |>| will be converted to |<| and |>| \emph{within math mode only}.
% If they should be typed outside of math mode, they will be passed as typed to
% the HTML, and probably interpreted by students' browsers as HTML tags
% or other unpredicated results.
% A doubled dash will be converted to en-dash |–| \emph{outside math mode}.
%
% Be aware that \emph{\textsf{moodle} does not know how to convert any
% other \TeX\ or \LaTeX\ commands to HTML.}
% If other sequences are used, they may be passed verbatim to the XML file
% or may cause unpredicted results.
%
% \DescribeMacro{\htmlonly}The |\htmlonly|\oarg{Content for traditional output}
% \marg{HTML content} command is to be used inside question environments (text,
% answers, or feedback). It lets you pass directly code to the XML file while being
% ignored for the traditional output (PDF). The HTML content passed as an argument
% is subject to no particular processing and users should not expect to be able to
% pass dangerous characters like |\|, |%|, or |#|. An optional argument allows to
% pass contents to be processed for the traditional output. This argument is
% ignored for the XML output.
% For instance, one can write code like this in a question environment
% \begin{quote}
% |\htmlonly[\fbox{PDF contents}]{|\\
% |
|\\
% \rule{10em}{0pt}|HTML contents
|\\
% |}|
% \end{quote}
%
% \DescribeMacro{\htmlregister}The |\htmlregister| command lets you specify
% the macros that must be expanded in the XML file. It works only when no
% optional argument is used.
%
% \DescribeMacro{\moodleregisternewcommands}
% When the list of macros is long, it becomes cumbersome to record them
% individually for expansion.
% Calling |\moodleregisternewcommands| triggers the automatic
% expansion of macros defined subsequently using |\newcommand|,
% |\renewcommand|, |\providecommand|, or their starred variants.
% Again, this works only if the macros are defined \emph{without} optional
% argument.
%
% If you think of another \LaTeX\ command that should be changed to an HTML
% equivalent, please have a look at Section~\ref{sec:dev}.
%
% \section{Graphics}
% The \textsf{moodle} package can handle two kinds of graphics seamlessly.
% External graphics files may be included with the |\includegraphics| command
% from the |graphicx| package, and graphics may be generated internally using \TikZ.
% In either case, the graphics will be embedded in base-64 encoding directly within
% the Moodle~XML produced. This prevents the hassle of managing separate
% graphics files on the Moodle server, as Moodle will store the picture
% within the question in the question bank.
%
% \subsection{Default \texttt{includegraphics}}
% \DescribeMacro{\includegraphics}\DescribeMacro{height}\DescribeMacro{width}
% When using |\includegraphics|, the only options currently supported
% are |height| and |width|. Attempts to use other |\includegraphics| options,
% such as |scale| or |angle|, will affect the PDF but not the XML output.
% The dimensions set by |height| and |width| are \TeX\ dimensions such as \texttt{4\,in}
% or \texttt{2.3\,cm}.
% In order to prepare the image for web viewing, this package converts those
% dimensions to pixels using a default of
% 103 pixels per inch.\footnote{This
% number was selected because an image with
% || showed up as almost exactly 1 inch
% tall and 1 inch wide on several of this author's devices and browsers
% as of January 2016.}
% \DescribeMacro{ppi}
% That value may be changed by setting the |ppi| key (e.g., |ppi=72|);
% this is probably best done for the entire document with a |\moodleset| command,
% rather than image-by-image.
% \DescribeMacro{\graphicspath}
% You can use |\graphicspath{{|\emph{path}|}}| to specify a directory where the
% pictures to be included are located.
%
% A special rule was added for the inclusion of GIF pictures (|.gif| extension).
% These files are passed as-is to the XML, preserving potential animations.
% However, as pdf\TeX\ engines do not support the GIF format, the picture is
% passed to the PDF output after a conversion to the PNG format. When the GIF
% file is animated, only its first frame is passed to the PDF.
%
%^^A \DescribeMacro{\DeclareGraphicsAlien} Users may declare other graphic
%^^A formats with the command |\DeclareGraphicsAlien|\marg{alien extension}
%^^A \marg{native extension}\marg{command line for conversion}.
%
% \subsection{\TikZ\ Pictures}
% \TikZ\ is a user-friendly syntax layer for PGF, the macro \LaTeX\ package for creating
% graphics. Users that are not familiar with TikZ\ can learn more here:
% \url{https://ctan.org/pkg/pgf}.
%
% When \TikZ\ is loaded and used to define pictures, \textsf{moodle} invokes
% the |external| \TikZ\ library, so that each |tikzpicture| environment is compiled
% to a freestanding PDF file.
%
% \subsection{Package Option \texttt{tikz}}\label{subsec:tikz}
% \DescribeMacro{tikz}
% The \textsf{moodle} package admits a \texttt{tikz} option which has the following effects:
% \begin{itemize}
% \item the package \texttt{tikz} is loaded.
% \item \texttt{includegraphics} is embedded in a \TikZ\ picture. Consequences are that
% \begin{itemize}
% \item the pictures encoded in the XML file are resampled. This prevents encoding
% images at a higher resolution than rendered by Moodle.
% \item the full set of \texttt{includegraphics} options is accessible,
% e.g.~|scale=.5|, |angle=90|, or |width=.2\textwidth|.
% \end{itemize}
% \item \DescribeMacro{\embedaspict} a macro |\embedaspict{...}| is provided for the
% inclusion of inline \LaTeX\ material as images. This can serve as a workaround to
% overcome limitations of this package---like the conversion of tabulars to HTML---
% or limitations of Moodle itself.
% For the definition of this macro, the package \texttt{varwidth} is loaded.
% \item optimizations of the \TikZ-external library are disabled. Compilation might get
% sensibly slower.
% \end{itemize}
%
% \subsection{External Tools}
% The mechanisms used for handling graphics are somewhat fragile and rely upon
% three free external programs.
% \begin{enumerate}
% \item GhostScript (\url{www.ghostscript.com}) is used to convert the PDF output
% from \TikZ\ into a PNG raster graphics file.
% The default command line is presumed to be |gswin64c.exe|
% (if |\ifwindows| from the |ifplatform| package returns true)
% or |gs| (if |\ifwindows| returns false).
% If your system requires a different command line to invoke Ghostscript,
% \DescribeMacro{\ghostscriptcommand}
% you may change it by invoking:
% \begin{quote}
% |\ghostscriptcommand|\marg{executable filename}
% \end{quote}
% \item When external graphics files such as PDF are included,
% the open-source ImageMagick software (\url{www.imagemagick.org})
% converts each file to PNG format.
% The command line for ImageMagick is the nondescript word |convert|,
% \DescribeMacro{\imagemagickcommand}
% but may be changed by invoking |\imagemagickcommand|\marg{executable filename}.
% \item OptiPNG (\url{http://optipng.sourceforge.net/}) is used to optimize the PNG images.
% The command line is presumed to be |optipng|, but can be changed with
% \DescribeMacro{\optipngcommand} |\optipngcommand|\marg{executable filename}.
% \end{enumerate}
%
% Please note the following vital points to make the graphics handling work:
% \begin{itemize}
% \item As of now, graphics are only supported when compiling directly to a PDF
% with |pdflatex|. Including PS graphics or using \TikZ\ with the DVI$\to$PS workflow is not
% yet supported.
%^^A \item Filenames should not contains spaces or, under windows, special characters like |_| or |\|.
% \item You must have Ghostscript and ImageMagick installed on your system
% to fully use the graphics-handling capabilities of \textsf{moodle}.
% \item If OptiPNG is not installed, the corresponding system calls will fail with otherwise no
% impact on the compilation process: PNG files are passed unoptimized to the XML output.
% \item \LaTeX\ must be able to call system commands; that is, |\write18| must be enabled.
% For Mik\TeX, this means adding |--enable-write18| to the command line of |pdflatex|;
% for \TeX Live, this means adding |--shell-escape=true|.
% \item Due to security issues with old versions of Ghostcript, some systems default to a
% policy that prevents the conversion of PDF and PS to PNG. Assuming that, as a user of
% \textsf{moodle} which requires shell escape capabilities, you either use a sandboxed
% environment or trust the files handled at the system-level, you may want to disable this
% over-zelous security policy. For example,
% \href{https://stackoverflow.com/a/52661288/14608059}{see this}.
% \item Users of the |circuitikz| package (\url{https://www.ctan.org/pkg/circuitikz}) must
% enclose their circuits' \TikZ\ code in the |tikzpicture| environment instead of
% the historical |circuitikz| environment. That is required, as of \TikZ\ 2.1,
% by the |external| library.
% \end{itemize}
%
% \subsection{Package Option \texttt{svg}}\label{subsec:svg}
%
% \paragraph{Important Notice} \emph{The \texttt{svg} option is an experimental feature
% introduced in \textsf{moodle} v0.8. It has been tested exclusively under Linux, with
% TeXLive 2020, Inkscape v1.0.1 and Scour 0.38.2.}
%
% \DescribeMacro{svg} The \textsf{moodle} package admits an experimental \texttt{svg}
% option which has the following effects:
% \begin{itemize}
% \item |\includegraphics| can be used to import SVG graphic files directly
% (extension |.svg| or |.SVG|). In this case, the SVG file is passed as-is to the
% XML output and is converted using \href{https://inkscape.org/}
% {Inkscape} (must be installed) for inclusion in the PDF output.
% \item the graphic files in PDF format are converted to the SVG format using
% \href{https://inkscape.org/}{Inkscape} (must be installed), rather than beeing
% rasterized. Before inclusion to the XML output, the SVG file is optimized using
% the \href{https://github.com/scour-project/scour}{Scour} utility. This
% optimization step is optional in the sense that, if the Scour call fails,
% the unoptimized SVG file will be passed to the XML output.
% Two processes benefit from this PDF$\to$SVG conversion:
% \begin{itemize}
% \item inclusion of PDF graphics with |\includegraphics|, and
% \item Tikz pictures that are externalized.
% \end{itemize}
% \end{itemize}
%
% \DescribeMacro{\PDFtoSVGcommand}\DescribeMacro{\SVGtoPDFcommand}
% \DescribeMacro{\optiSVGcommand} The call of external tools can be changed using
% the macros |\PDFtoSVGcommand| \marg{\dots}, |\SVGtoPDFcommand|\marg{\dots} and
% |\optiSVGcommand|\marg{\dots}.
%
% \section{Verbatim Code}
% Because, for HTML translation, \textsf{moodle} parses the body of questions, the use of
% verbatim code results in compilation errors. This is why the use of |\verb|,
% |\begin{verbatim}| and other standard utilities is not supported.
%
% However, using the following three utilities, verbatim code can be imported from an external file:
% \begin{enumerate}
% \item \DescribeMacro{\verbatiminput}|\verbatiminput|\marg{filename} from the \textsf{verbatim}
% package inserts verbatim code in both the PDF and the XML for moodle, without fancy additions.
% \item \DescribeMacro{\VerbatimInput}The macro |\VerbatimInput|\marg{options}\marg{filename} from
% \textsf{fancyvrb} or \textsf{fvextra} does more, with several options and settings offered
% (see below).
% The variants \DescribeMacro{\BVerbatimInput}|\VBerbatimInput| and
% \DescribeMacro{\LVerbatimInput}|\LVerbatimInput| are also supported, with identical
% effect on the XML output.
% The variants with a star are unsupported and result in errors when used.
% \item \DescribeMacro{\inputminted}On top of that |\inputminted|\oarg{options}\marg{lang}
% \marg{filename}from the \textsf{minted} package offers syntaxic highlighting tailored to the
% specified language.
% \end{enumerate}
% The \textsf{moodle} package handles these three commands to pass the code in the output XML.
% With |\inputminted|, an external Python tool, \textsc{pygmentize}, performs syntax analysis and
% its HTML formatter is used to populate the XML. With the other commands, the contents of the
% file is passed as-is to the XML. A drawback of this approach, is that characters |<|, |>|,
% |&|, |'|, and |"| are likely to mislead the web browser rendering the question on Moodle.
%
% With |\VerbatimInput| and |\inputminted|, the options that are taken care of for XML
% generation are listed in Table~\ref{tab:verbatim-options}. Using |\fvset|\marg{key=value,...},
% options can be set globally. Equivalently, with \textsf{minted},
% |\setminted|\oarg{lang}\marg{key=value,...} is available.
%
% \begin{table}[tbp]
% \centering
% \begin{threeparttable}[b]
% \caption{Options and corresponding values considered for XML generation of verbatim material
% with \texttt{VerbatimInput} and \texttt{inputminted}.}
% \label{tab:verbatim-options}
% \begin{tabular}{ll}
% \toprule
% Option keys & Possible values\\\cmidrule(lr){1-1}\cmidrule(lr){2-2}
% ^^A\texttt{commentchar} & \meta{character}\\
% \texttt{gobble} & \meta{integer}\\
% \texttt{autogobble}\tnote{1} & \texttt{true} or \texttt{false}\\
% \texttt{tabsize} & \meta{integer}\\
% \texttt{numbers} & \texttt{none}, \texttt{left}, \texttt{right}, or \texttt{both}\tnote{2}\\
% \texttt{firstnumber} & \texttt{auto}, \texttt{last}, or \meta{integer}\\
% \texttt{firstline} & \meta{integer}\\
% \texttt{lastline} & \meta{integer}\\
% \texttt{numberblanklines} & \texttt{true} or \texttt{false}\\
% \texttt{highlightlines}\tnote{2} & \marg{coma-separated list of integers or ranges}\\
% \texttt{style}\tnote{1} & \meta{string}\\
% \bottomrule
% \end{tabular}
%\begin{tablenotes}
%\item[1] \texttt{autogobble}, \texttt{numbers=both}, and \texttt{style} are offered only by \textsf{minted}.
%\item[2] line highlighting is offered only with \textsf{fvextra} or \textsf{minted} loaded.
%\end{tablenotes}
%\end{threeparttable}
%\end{table}
%
% In order to define the verbatim code from the \LaTeX\ document itself, it is still possible
% to use, outside the scope of the \textsf{moodle} questions, the environments |filecontents*| (from the
% \textsf{filecontents} package or \LaTeX\ kernel itself since 2019) or |VerbatimOut|
% (from the \textsf{fancyvrb} and \textsf{fvextra} packages).
%
% Here is an example:
% \begin{VerbatimOut}[gobble=2]{minted.doc.out}
% \documentclass[12pt,a4paper]{article}
% \usepackage[section]{moodle}
% \usepackage{minted}
% \begin{document}
% \begin{quiz}[tags={minted}]{LaTeX Quiz}
% \begin{filecontents*}{excerpt.tex}
% % !TeX encoding = UTF-8
% % !TeX spellcheck = en_US
% % !TEX TS-program = lualatex
% \documentclass{article}
% \usepackage[nostamp]{moodle}
% \ifPDFTeX % FOR LATEX and PDFLATEX
% \usepackage[utf8]{inputenc} % necessary
% \usepackage[T1]{fontenc} % necessary
% \else % assuming XELATEX or LUALATEX
% \usepackage{fontspec}
% \fi
% \end{filecontents*}
% \begin{numerical}[tolerance=0]{Loading a Class}
% Consider the following \LaTeX\ code excerpt.\\
% \inputminted[numbers=left]{latex}{excerpt.tex}
% On which line is the class loaded?
% \item[feedback={
% yes! \inputminted[highlightlines={4}]{latex}{excerpt.tex}
% } ] 4
% \item[feedback={No. On line 3, there is only a comment.},
% fraction=0] 3
% \item[feedback={No. On line 5, the package \texttt{moodle} is loaded.},
% fraction=0] 5
% \end{numerical}
% \begin{multi}[single]{IDE}
% Consider the following \LaTeX\ code excerpt.\\
% \inputminted[numbers=left]{latex}{excerpt.tex}
% Which \TeX\ engine will be used by the IDE for compilation.
% \item[feedback={Have a closer look at line 3}] \texttt{tex}
% \item[feedback={Have a closer look at line 3}] \texttt{latex}
% \item[feedback={Have a closer look at line 3}] \texttt{pdflatex}
% \item[feedback={Have a closer look at line 3}] \texttt{xelatex}
% \item* \texttt{lualatex}
% \end{multi}
% \end{quiz}
% \end{document}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=lines]{latex}{minted.doc.out}
%
% When code decorated with left-side line numbers is placed in question items, the output PDF could
% show a collision between numbers of the item and the first line. To avoid this, |\LVerbatimInput| or
% |\BVerbatimInput| can be used. Instead, when \textsf{minted} is used, the ``left-right'' mode can be
% enforced with the \LaTeX\ command:
% \begin{quote}
% |\RecustomVerbatimEnvironment{Verbatim}{LVerbatim}{}|
% \end{quote}
%
% When using utilities from \textsf{fancyvrb}, \textsf{fvextra}, or \textsf{minted}, \textsf{moodle}
% sets framing options for the display of code in the output PDF:
% \begin{quote}
% |\fvset{frame=lines,label={[Beginning of code]End of code},|\\
% | framesep=3mm,numbersep=9pt}|
% \end{quote}
% These settings can be overidden using |\fvset| after the preamble.
%
% \section{Calculated Questions}
% Moodle's calculated questions are not supported by this package.
%
% However, as \href{https://github.com/avohns/python-latex-moodle-quiz}{demonstrated by A.
% Vohns}, an advanced scripting language may be used to generate a series of questions sharing
% the same prototype.
%
% We suggest to apply a specific tag to these questions. After import in Moodle, when creating
% a quizz, this tag can be selected to narrow down a random selection of questions.
% This would mimic the behavior of calculated questions while bringing the flexibility of your
% favorite scripting language.
%
% Here are two examples inspired from the work of A. Vohns. The first one relies on the
% native Lua capabilities of \LuaLaTeX.
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{quiz}[tags={calculated}]{Example Quiz}
% \directlua{
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=topline]{latex}{minted.doc.out}
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% function clozenum_print(pair,op,result)
% tex.print("\\begin{numerical}$"..pair[1].." "..op.." "..pair[2].."
% =$".."\\item ",result,"\\end{numerical}")
% end
% function cloze_print(pair,points)
% tex.print("\\begin{cloze}[points="..points.."]{Arithmetic Quiz
% ("..pair[1]..", "..pair[2]..")}Solve the following tasks!\\\\")
% clozenum_print(pair,"+",pair[1]+pair[2])
% clozenum_print(pair,"-",pair[1]-pair[2])
% clozenum_print(pair,"*",pair[1]*pair[2])
% if pair[1]/pair[2]==math.floor(pair[1]/pair[2]) then
% clozenum_print(pair,":",math.floor(pair[1]/pair[2]))
% end
% tex.print("\\end{cloze}")
% end
% for x = 2,4 do
% for y = 2,4 do
% if x>y then
% if x/y==math.floor(x/y) then points=4 else points=3 end
% cloze_print({x,y},points)
% end
% end
% end
% \end{VerbatimOut}
% \inputminted[]{lua}{minted.doc.out}
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% }
% \end{quiz}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=bottomline]{latex}{minted.doc.out}
% The second example makes use of the \textsf{python} package (|\usepackage{python}|).
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \begin{quiz}[tags={calculated}]{Example Quiz}
% \begin{python}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=topline]{latex}{minted.doc.out}
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% def clozenum_print(pair,op,result):
% print(rf"""\begin{{numerical}}
% ${pair[0]} {op} {pair[1]} =$\item {result}
% \end{{numerical}}""")
% def cloze_print(pair,points):
% print(rf"""\begin{{cloze}}[points={points}]{{Arithmetic Quiz
% {(pair[0],pair[1])}}}Solve the following tasks!\\""")
% clozenum_print([x,y],"+",x+y)
% clozenum_print([x,y],"-",x-y)
% clozenum_print([x,y],"*",x*y)
% if pair[0]/pair[1] == pair[0]//pair[1]:
% clozenum_print([x,y],":",x//y)
% print("\end{cloze}")
% for x in range(2,5):
% for y in range(2,5):
% if x > y:
% if x/y == x//y:
% points=4
% else:
% points=3
% cloze_print([x,y],points)
% \end{VerbatimOut}
% \inputminted[]{python}{minted.doc.out}
% \begin{VerbatimOut}[gobble=1]{minted.doc.out}
% \end{python}
% \end{quiz}
% \end{VerbatimOut}
% \inputminted[gobble=2,frame=bottomline]{latex}{minted.doc.out}
% These two codes yield the same XML content.
%
% \section{Known Limitations and Call for Bug Reports}
% Table~\ref{tab:support-limitations} lists some features supported, limitations, and
% bugs.
%\begin{table}[tbp]
%\centering
%\begin{threeparttable}[b]
%\caption{Content enrichment (pictures, equations) support after XML import in Moodle v3.5.7,
% depending on the question type.}
%\label{tab:support-limitations}
%\begin{tabular}{lccc}
% \toprule
% & \multicolumn{3}{l}{XML rendering in\dots}\\\cmidrule(lr){2-4}
%Question type & Question & Answer & Feedback\\\cmidrule(lr){1-1}\cmidrule(lr){2-2}
%\cmidrule(lr){3-3}\cmidrule(lr){4-4}
% \href{https://docs.moodle.org/35/en/Multiple_Choice_question_type}{Multichoice}
%& yes & yes & yes \\
% \href{https://docs.moodle.org/35/en/Numerical_question_type}{Numerical}
%& yes & no\tnote{1} & yes \\
% \href{https://docs.moodle.org/35/en/Short-Answer_question_type}{Short Answer}
% & yes & no\tnote{1} & yes \\
% Matching (\href{https://docs.moodle.org/35/en/Matching_question_type}{std})
%& yes & no\tnote{2} & no\tnote{3} \\
% Matching (\href{https://docs.moodle.org/35/en/Drag_and_drop_matching_question_type}{dd})
% & yes & yes\tnote{4} & no\tnote{3} \\
% \href{https://docs.moodle.org/35/en/Essay_question_type}{Essay}
%& yes & yes\tnote{5,6} & yes\tnote{5} \\
% \href{https://docs.moodle.org/35/en/True/False_question_type}{True/False}
%& yes & no & yes \\
% \href{https://docs.moodle.org/35/en/Description_question_type}{Description}
%& yes & $\varnothing$ & yes \\
%\href{https://docs.moodle.org/35/en/Embedded_Answers_(Cloze)_question_type}{Cloze} &
%yes & $\varnothing$& $\varnothing$ \\\cmidrule(lr){1-1}
%\hspace{1em}Numerical & yes & no\tnote{1} & yes \\
%\hspace{1em}Short Answer & yes & no\tnote{1} & yes\tnote{7} \\
%\hspace{1em}Multi (inline) & yes & no\tnote{2} & yes\tnote{7} \\
%\hspace{1em}Multi (horizontal) & yes & yes & yes \\
%\hspace{1em}Multi (vertical) & yes & yes & yes \\\bottomrule
%\end{tabular}
%\begin{tablenotes}
%\item[1] Moodle prompts the student for an answer and then compares it to the
%solutions provided. This is text-only.
%\item[2] Moodle uses a dropdown list to let one choose among the possible
%answers. This forbids either picture inclusion and \LaTeX\ rendering.
%\item[3] Not supported by Moodle (in this context, answer-specific feedback
%represents lots of possible combinations).
%\item[4] The drag-and-drop-matching plugin seems broken before version 1.6
%20190409. Moodle's XML import fails with a \textsf{dmlwriteexception} when
%the field content exceeds few hundreds characters. This prevents the inclusion
%of most base64 images and maybe some complicated equations.
%\item[5] For this question type and in the context of XML generation, the
%Answer column represents the ``template" while the Feedback column represents
%the ``notes for the grader". Obviously, the grading process is not automatic
%and there is no answer-specific feedback.
%\item[6] Picture and \LaTeX\ rendering could be done, but only after
%submission and only if the keyval ``response format" is set to ``html".
%\item[7] Moodle only reveals the feedback when hovering the checkmark or X
%mark with the mouse.
%\end{tablenotes}
%\end{threeparttable}
%\end{table}
% Tables~\ref{tab:diacritical}, \ref{tab:ligatures}, and \ref{tab:other} describe the current
% state of support special characters, accents and other diacritical marks.
%\begin{table}[tbp]
% \centering
% \caption{Support for diacritical marks
% in a UTF8-coded \TeX~document compiled with (pdf)\LaTeX\ (packages
% \texttt{inputenc} with option \texttt{utf8} and \texttt{fontenc} with option \texttt{T1}),
% \LuaLaTeX\ or \XeLaTeX\ (package \texttt{fontspec}).}
% \label{tab:diacritical}
% \begin{threeparttable}[t]
% \begin{tabular}{*{6}{l}}
% \toprule
% \multicolumn{4}{l}{Input type} & \multicolumn{2}{l}{Engine support}\\
% \cmidrule(lr){1-4}\cmidrule(lr){5-6}
% \multicolumn{2}{l}{Unicode} & \multicolumn{2}{l}{\LaTeX} & \XeLaTeX\ or \LuaLaTeX & (pdf)\LaTeX \\
% \cmidrule(lr){1-2}\cmidrule(lr){3-4}\cmidrule(lr){5-5}\cmidrule(lr){6-6}
% \aa & \AA & \verb|\aa| & \verb|\AA| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \`a & \`A & \verb|\`a| & \verb|\`A| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \^a & \^A & \verb|\^a| & \verb|\^A| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \~a & \~A & \verb|\~a| & \verb|\~A| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \'e & \'E & \verb|\'e| & \verb|\'E| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \`e & \`E & \verb|\`e| & \verb|\`E| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \"e & \"E & \verb|\"e| & \verb|\"E| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \^e & \^E & \verb|\^e| & \verb|\^E| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \^i & \^I & \verb|\^i| & \verb|\^I| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \"i & \"I & \verb|\"i| & \verb|\"I| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \~n & \~N & \verb|\~n| & \verb|\~N| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \~o & \~O & \verb|\~o| & \verb|\~O| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \"o & \"O & \verb|\"o| & \verb|\"O| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \^o & \^O & \verb|\^o| & \verb|\^O| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \`u & \`U & \verb|\`u| & \verb|\`U| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \"u & \"U & \verb|\"u| & \verb|\"U| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \^u & \^U & \verb|\^u| & \verb|\^U| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \c{c} & \c{C} & \verb|\c{c}| & \verb|\c{C}| & Unicode and \LaTeX & Unicode and \LaTeX \\
% \c{s} & \c{S} & \verb|\c{s}| & \verb|\c{S}| & Unicode and \LaTeX & \LaTeX\ only\\
% \c{t} & \c{T} & \verb|\c{t}| & \verb|\c{T}| & Unicode and \LaTeX & \LaTeX\ only\\
% \H{o} & \H{O} & \verb|\H{o}| & \verb|\H{O}| & Unicode and \LaTeX & \LaTeX\ only\\
% \H{u} & \H{U} & \verb|\H{u}| & \verb|\H{U}| & Unicode and \LaTeX & \LaTeX\ only\\
% \"y & \"Y & \verb|\"y| & \verb|\"Y| & Unicode and \LaTeX & \LaTeX only\\
% \k{a} & \k{A} & \verb|\k{a}| & \verb|\k{A}| & Unicode and \LaTeX & \LaTeX\ only\\
% \k{e} & \k{E} & \verb|\k{e}| & \verb|\k{E}| & Unicode and \LaTeX & \LaTeX\ only\\
% \k{i} & \k{I} & \verb|\k{i}| & \verb|\k{I}| & Unicode and \LaTeX & \LaTeX\ only\\
% \k{o} & \k{O} & \verb|\k{o}| & \verb|\k{O}| & Unicode and \LaTeX & \LaTeX\ only\\
% \k{u} & \k{U} & \verb|\k{u}| & \verb|\k{U}| & Unicode and \LaTeX & \LaTeX\ only\\
% \u{a} & \u{A} & \verb|\u{a}| & \verb|\u{A}| & Unicode and \LaTeX & \LaTeX\ only\\
% \u{e} & \u{E} & \verb|\u{e}| & \verb|\u{E}| & Unicode and \LaTeX & \LaTeX\ only\\
% \u{g} & \u{G} & \verb|\u{g}| & \verb|\u{G}| & Unicode and \LaTeX & \LaTeX\ only\\
% \u{\i} & \u{I} & \verb|\u{\i}| & \verb|\u{I}| & Unicode and \LaTeX & \LaTeX\ only\tnote{1}\\
% \u{o} & \u{O} & \verb|\u{o}| & \verb|\u{O}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{c} & \v{C} & \verb|\v{c}| & \verb|\v{C}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{d} & \v{D} & \verb|\v{d}| & \verb|\v{D}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{e} & \v{E} & \verb|\v{e}| & \verb|\v{E}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{l} & \v{L} & \verb|\v{l}| & \verb|\v{L}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{n} & \v{N} & \verb|\v{n}| & \verb|\v{N}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{r} & \v{R} & \verb|\v{r}| & \verb|\v{R}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{s} & \v{S} & \verb|\v{s}| & \verb|\v{S}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{t} & \v{T} & \verb|\v{t}| & \verb|\v{T}| & Unicode and \LaTeX & \LaTeX\ only\\
% \v{z} & \v{Z} & \verb|\v{z}| & \verb|\v{Z}| & Unicode and \LaTeX & \LaTeX\ only\\
% \bottomrule
% \end{tabular}
% \begin{tablenotes}
% \item[1] The rendering of |\u{i}| is flawed in (pdf)\LaTeX's traditional output.
% ^^A \XeLaTeX\ renders correctly |\u{i}|, that is, without a superscript dot.
% ^^A Instead, with (pdf)\LaTeX\ the rendering of |\u{i}| is flawed by the
% ^^A superposition of the superscript dot and the breve diacritical mark.
% ^^A Both engines render |\u{\i}| as expected.
% \end{tablenotes}
% \end{threeparttable}
% \end{table}
%
%\begin{table}[tbp]
% \centering
% \begin{threeparttable}[t]
% \caption{Support for ligatures in a UTF8-coded \TeX~document compiled with (pdf)\LaTeX\ (packages
% \texttt{inputenc} with option \texttt{utf8}, \texttt{fontenc} with option \texttt{T1}),
% \LuaLaTeX\ or \XeLaTeX\ (package \texttt{fontspec}).}
% \label{tab:ligatures}
% \begin{tabular}{llllll}
% \toprule
% \multicolumn{4}{l}{Input type} & \multicolumn{2}{l}{Engine support}\\
% \cmidrule(lr){1-4}\cmidrule(lr){5-6}
% \multicolumn{2}{l}{Unicode} & \multicolumn{2}{l}{\LaTeX} & \XeLaTeX \ or \LuaLaTeX& (pdf)\LaTeX \\
% \cmidrule(lr){1-2}\cmidrule(lr){3-4}\cmidrule(lr){5-6}\cmidrule(lr){6-6}
% \ae & \AE & \verb|\ae| & \verb|\AE| & Unicode and \LaTeX & \LaTeX\ only\\
% \oe & \OE & \verb|\oe| & \verb|\OE| & Unicode and \LaTeX & \LaTeX\ only\\
% \ss & \SS & \verb|\ss| & \verb|\SS| & Unicode and \LaTeX\tnote{1} & \LaTeX\ only\tnote{2}\\
% \bottomrule
% \end{tabular}
% \begin{tablenotes}[b]
% \item[1] the Libertine font, used in this documentation and available for instance via the
% package |libertine|, defines the glyph \SS. Most fonts do not define this glyph.
% \item[2] \LaTeX\ defines the \verb|\SS| macro but (pdf)\LaTeX\ renders it as a doubled capital S.
% \end{tablenotes}
% \end{threeparttable}
% \end{table}
%
%\begin{table}[tbp]
% \centering
% \begin{threeparttable}[b]
% \caption{Support for other glyphs and punctuation marks in a UTF8-coded \TeX~document compiled
% with (pdf)\LaTeX\ (packages \texttt{inputenc} with option \texttt{utf8}, \texttt{fontenc} with
% option \texttt{T1}), \LuaLaTeX\ or \XeLaTeX\ (package \texttt{fontspec}).}
% \label{tab:other}
% \begin{tabular}{llllll}
% \toprule
% \multicolumn{4}{l}{Input type} & \multicolumn{2}{l}{Engine support}\\
% \cmidrule(lr){1-4}\cmidrule(lr){5-6}
% \multicolumn{2}{l}{Unicode} & \multicolumn{2}{l}{\LaTeX} & \XeLaTeX\ or \LuaLaTeX & (pdf)\LaTeX \\
% \cmidrule(lr){1-2}\cmidrule(lr){3-4}\cmidrule(lr){5-5}\cmidrule(lr){6-6}
% \l & \L & \verb|\l| & \verb|\L| & Unicode and \LaTeX & \LaTeX\ only\\
% \o & \O & \verb|\o| & \verb|\O| & Unicode and \LaTeX & \LaTeX\ only\\
% « & & \verb|\guillemotleft|\tnote{1} & & Unicode and \LaTeX & \LaTeX\ only\\
% » & & \verb|\guillemotright|\tnote{1} & & Unicode and \LaTeX & \LaTeX\ only\\
% ¿ & & \verb|\textquestiondown| & & Unicode and \LaTeX & \LaTeX\ only\\
% ¡ & & \verb|\textexclamdown| & & Unicode and \LaTeX & \LaTeX\ only\\
% \bottomrule
% \end{tabular}
% \begin{tablenotes}
% \item[1] for the same symbols the package |babel| defines |\flqq| and |\frqq|, and
% if loaded with option |french| defines |\og| and |\fg|. These commands
% are also supported by \textsf{moodle}.
% \end{tablenotes}
% \end{threeparttable}
% \end{table}
%
% Some features of Moodle quizzes have not yet been implemented in \textsf{moodle}.
% Here is a non-exhaustive list.
% \begin{itemize}
% \item Moodle's feature of designating feedback for correct,
% partially correct, and incorrect answers.
%^^A \item Calculated questions; that is, automatically generated numerical questions
%^^A using randomly chosen numbers.
% \item Hints
% \item Units handling in numerical questions
% \end{itemize}
% The authors have used this package together with a limited number of colleagues
% for a few semesters of teaching. If other users adopt this package, we fully expect them
% to find bugs. If you run into a problem, please have a look at Section~\ref{sec:dev}.
%
% \section{Compatibility}
% This package has been originally written for and tested with the implementation of
% Moodle 2.9 run by Moodlerooms for St.~Norbert College in January 2016.
% Since then, it has been successfully combined with Moodle 3.5.
% Future versions of this package might include some support for
% specifying your version of Moodle in the |.tex| file to help ensure compatibility.
%
% As the ultimate purpose of this package is the generation of XML files,
% future versions of \textsf{moodle} will attempt to maintain backwards
% compatibility with earlier versions regarding the XML output, apart from
% bug fixes.
% Backwards compatibility of the PDF output is not yet guaranteed, however,
% in case the author or users discover better ways for the PDF to display
% the underlying XML data to be proofread.
%
% In other words, compiling your current |.tex| file with a future version
% of \textsf{moodle} should produce the same XML file it does now
% (apart from bug fixes),
% but it might produce a more informative, and hence different,
% PDF output.
%
%
% \section{Unrelated Tip: Quality of Moodle \TeX\ Images}
% This has nothing to do with \textsf{moodle}, but is a Frequently Asked Question
% in is own right.
% On some servers, at least, Moodle's default ``\TeX\ Filter'' for
% displaying mathematical notation is of abysmally poor quality, rending mathematics
% as low-resolution PNG's. One solution that has worked for me is to go
% to ``Course Administration $\to$ Filters,'' turn ``\TeX\ Notation'' \emph{off},
% but turn ``MathJax'' \emph{on}. This forces \TeX\ code to be rendered by MathJax
% instead of Moodle, producing much higher-quality results.
%
% \clearpage
% \section{Package Development}\label{sec:dev}
% This package is developed as a collaborative project, currently hosted
% on the Gitlab server instance \url{https://framagit.org/mattgk/moodle}.
% The project's activity can be monitored there: reported issues, last
% modifications, \dots
%
% Contributions, either bug reports or fixes, are welcome. Users willing to
% help can either sign-in with an existing \textsf{GitHub}, \textsf{Gitlab.com}, or
% \textsf{Bitbucket} account or register a new account.
%
% Of course, getting in touch with the package maintainer by
% \href{mailto:guerquin-kernATcrans.org}{email} works as well.
%
% When experiencing a problem and before reporting it, please check whether
% or not something similar has already been filed as an issue
% \href{https://framagit.org/mattgk/moodle/-/issues?scope=all&state=all}{here}.
% If the problem appears to be new, please report it by following these steps:
% \begin{enumerate}
% \item Prepare a \emph{minimal} working example, i.e. a |.tex| file shunk down
% to the strict minimum (loaded packages, code, \dots) while still showing the
% faulty behavior upon compilation.
% \item Gather and send the |*.tex|, |*.log| and |*-moodle.xml| files together
% with an explanation about
% \begin{itemize}
% \item your working environment (\TeX\ engine and distribution, operating
% system, \dots),
% \item the faulty behavior, and
% \item what you expected instead.
% \end{itemize}
% \end{enumerate}
%
% ^^A\clearpage
% \changes{v0.5}{2016/01/05}{Initial version}
% \changes{v0.6}{2019/02/18}{Bux-fixing release}
% \changes{v0.7}{2020/07/09}{Feature extensions}
% \changes{v0.8}{2021/01/04}{Bug fixes and feature extensions}
% \changes{v0.9}{2021/02/07}{Bug fixes and feature extensions}
% \begin{changelog}[title={Version History},author={Matthieu Guerquin-Kern}]
% \begin{version}[version=0.9,date=2021-02-07]
% \added
% \item Support for \href{https://docs.moodle.org/310/en/All_or_nothing_multiple_choice_question_type}
% {all-or-nothing multiple choice} questions.
% \item Support for the ogonek diacritical mark via |\k|\marg{\dots}.
% \item Warn user of the \texttt{babel} package set for a German-related language
% that using the character |"| will not play well with \textsf{moodle}.
% \item Support for \textsf{babel} commands related to German quotes.
% \item Support for en-dash (--) outside of math mode.
% \item Support for |\%| in conversion to HTML.
% \item Command |\htmlonly[]{}| to pass HTML contents directly to the XML file.
% \changed
% \item An error is issued when a graphics conversion step fails.
% \item Irrelevant points are no longer written at the cloze question level in PDF and XML.
% \item The total number of marks is shown in the PDF at the end of each quiz.
% \item The |tags| key can now be used to specify a comma-separated list of tags.
% \fixed
% \item Answer text of shortanswer questions is converted to HTML.
% \item Paragraph breaks in multi and essay items no longer break compilation.
% \item Question text in Essays was not shown in PDF file.
% \item Commands |\textsc|, |\underline|, |\url|, and |\href| yielded HTML code with
% inadequate double quotation marks.
% \item Broken base64-encoding pipeline for images under Windows (thanks to Andreas Vohns).
% \item Repeated single right quotation marks no longer merged in math mode
% (thanks to Alberto Albano).
% \end{version}
% \begin{version}[version=0.8,date=2021-01-04]
% \added
% \item Support for inclusion of GIF pictures.
% \item Added package option |svg| to avoid the rasterization of vector graphics.
% \item New macro |\setsubcategory| to define subcategories, reflected in PDF and XML.
% \item Package option |handout| for sharing PDF with students.
% \item Extensions can be omitted when including pictures.
% \item Description question type.
% \item \LuaLaTeX\ is now supported (and recommended for UTF8-coded sources).
% \item Examples of ways to reproduce the behavior of calculated questions.
% \item Command to trigger the automatic recording of new commands.
% \item Mechanism to match |fraction| key to values accepted by Moodle.
% \item A |fractiontol| key to control the tolerance in this mechanism.
% \item Support for inverted punctuation marks |¿| and |¡|.
% \item Support for |\_| and |\textbackslash|.
% \item Support for the wildcard character as an answer in numerical questions.
% \changed
% \item Template of Essay questions is now shown in PDF.
% \item The macro |\setcategory| is reflected by a new section in PDF.
% \item In matching questions, warnings are raised if the number of items is insufficient.
% \item Improved display of matching questions in PDF.
% \item The package \textsf{iftex} is now required.
% \item An error is thrown when |fraction| is set to an invalid value.
% \item In numerical questions, the tolerance can be set in exponent form.
% \item Nicer PDF rendering of numbers in numerical questions if \textsf{siunitx} is loaded.
% \item Included PNG and JPEG files are now directly converted to base64.
% \fixed
% \item TeX's inline math (|$...$|) can now contain escaped dollar signs (|\$|).
% \item Closing braces escaped in cloze subquestions outside math environment.
% \item The scope of the |tolerance| key is now respected.
% \end{version}
% \begin{version}[version=0.7,date=2020-09-06]
% \added
% \item Support for inclusion of verbatim code.
% \item Package option \texttt{tikz}.
% \item Support for |\"Y| and |\"y|.
% \item New commands converted to XML.
% \item Adding a stamp comment in XML, package option offered to disable
% this behavior.
% \item Support for the |\tikz| command.
% \item A different directory can be specified for picture inclusion.
% \item Warn user of the \texttt{babel} package set for french that autospacing
% must be deactivated.
% \item Square bracket math delimiters are recognized and converted properly.
% \item Support of breve and caron diacritical marks.
% \changed
% \item In multi with multiple answers allowed, choosing all options no longer
% results in a good grade. An automatic penalty mechanism is introduced.
% Can be overridden by manually setting fractions.
% \removed
% \item Irrelevant \texttt{penalty} tag in cloze subquestions.
% \fixed
% \item Non-integer fractions can now be specified in cloze subquestions.
% \item Significantly squeeze PNG images size by skipping ancillary data.
% \item Enumerate or itemize environment can now be nested in question items.
% \item Several pictures can be included in a question without being mixed
% in the XML file.
% \item Management and rendering of fraction in questions.
% \item Correctly handling a \LaTeX\ command starting the last item of a question.
% \item Closing braces escaped in cloze subquestions. This allows \LaTeX\
% equations or images to be included.
% \item Image inclusion with macOS.
% \end{version}
% \begin{version}[version=0.6b,date=2019-11-27]
% \added
% \item New package options to set section or subsection at the quiz level.
% \item True/False question type is now supported.
% \item Moodle tags can now be specified for questions (and rendered in PDF
% as well).
% \item In cloze questions, the \texttt{multiresponse} subquestion type is
% now supported.
% \removed
% \item External dependency on \texttt{OpenSSL}.
% \item Irrelevant tags were written in XML for matching questions.
% \fixed
% \item \TikZ\ externalization now works when using \XeLaTeX.
% \item It is now possible to set points manually among several correct
% answers in multichoice questions.
% \item General feedbacks can now contain backslashes.
% \item Several quizzes can now be defined in a single source file, each
% specifying a category for Moodle's question bank.
% \item Correct encoding information is now written in XML depending on
% the \LaTeX\ compiler used.
% \end{version}
% \begin{version}[version=0.6a,date=2019-06-21]
% \added
% \item \XeLaTeX\ is now recommended when using UTF8-encoded sources (support
% of accents).
% \item Feedbacks are now displayed in the PDF file produced.
% \item The \texttt{optipng} utility is used to reduce the size
% of images embedded in the XML file.
% \item Question options and settings are now displayed in the PDF file
% \item Supporting more \LaTeX\ macros for symbols and accents (mostly
% diacritical marks and ligatures).
% \item Introduce shuffle options in cloze-multi subquestions.
% \item Package option \texttt{final}.
% \changed
% \item In draft mode, \TikZ\ externalization is no longer triggered.
% \fixed
% \item In the different question types, the feedback fields are now converted
% for HTML allowing \LaTeX\ equation and images.
% \item Documentation improvements (limitations and previously undocumented
% features).
% \end{version}
% \shortversion{version=0.5,date=2016-01-05,simple,changes=Initial version,author={Anders O.F. Hendrickson}}
% \end{changelog}
%
% \StopEventually{}
%
% \section{Implementation}
% \subsection{Packages, Options, and Utilities}
% \begin{macrocode}
\newif\ifmoodle@draftmode
\newif\ifmoodle@handout
\newif\ifmoodle@stampmode
\newif\ifmoodle@tikz
\newif\ifmoodle@tikzloaded
\newif\ifmoodle@svg
\newif\ifmoodle@section
\newif\ifmoodle@subsection
\newif\ifmoodle@numbered
%%DECLARATION OF OPTIONS
\DeclareOption{draft}{\moodle@draftmodetrue}
\DeclareOption{handout}{\moodle@handouttrue}
\DeclareOption{final}{\moodle@draftmodefalse}
\DeclareOption{nostamp}{\moodle@stampmodefalse}
\DeclareOption{tikz}{\moodle@tikztrue}
\DeclareOption{svg}{\moodle@svgtrue}
\DeclareOption{section}{\moodle@sectiontrue\moodle@numberedtrue}
\DeclareOption{section*}{\moodle@sectiontrue\moodle@numberedfalse}
\DeclareOption{subsection}{\moodle@sectionfalse\moodle@numberedtrue}
\DeclareOption{subsection*}{\moodle@sectionfalse\moodle@numberedfalse}
\moodle@draftmodefalse
\moodle@handoutfalse
\moodle@stampmodetrue
\moodle@tikzfalse
\moodle@tikzloadedfalse
\moodle@svgfalse
\moodle@subsectiontrue
\moodle@numberedfalse
\ProcessOptions
\RequirePackage{environ} %To be able to take environment body as a macro argument
\RequirePackage{xkeyval} %For key-handling
\RequirePackage{amssymb} %For \checkmark symbol
%\RequirePackage{trimspaces} %To remove extra spaces from strings (loaded by environ)
\@ifpackageloaded{iftex}{}{\RequirePackage{iftex}}
% iftex already required by recent versions of ifplatform. Needed to know:
% 1) whether we can convert output from PDF to PNG (ifpdf),
% 2) when output pdf is latin1-encoded (ifpdf)
% 3) when output xml is utf8-encoded (if?tex)
\@ifundefined{ifeTeX}{% version of 'iftex' prior to November 2019.
\RequirePackage{etex}{}
}{
\ifeTeX\else
\RequirePackage{etex}{} % Recent (2015+) TeX engines should be e-TeX.
%This is needed for expansion control, detokenization, etc.
\fi
}
\RequirePackage{etoolbox}%List management
\RequirePackage{xpatch} %To patch commands easily in HTML mode
\RequirePackage{array} %For formatting tables in the LaTeX mode of Clozes
\RequirePackage{ifplatform} % To choose Ghostscript commands
\@ifundefined{ifpdf}{\RequirePackage{ifpdf}}{}% old iftex would not define the conditional
\RequirePackage{shellesc} %Luatex-compatible way of getting system access
\RequirePackage{fancybox} %For fancy LaTeX tags
\RequirePackage{getitems} %To gather the header and items
\ifmoodle@handout
\RequirePackage[seed=42]{randomlist} %To randomize answers in matching questions
\fi
\ifmoodle@svg
\RequirePackage{graphicx} %To include graphics
\fi
\let\xa=\expandafter
\def\@star{*}%
\def\@hundred{100}%
\def\@fifty{50}%
\def\@moodle@empty{}%
\def\@relax{\relax}%
\def\@moodle@par{\par}%
% Taken from https://tex.stackexchange.com/questions/47576/combining-ifxetex-and-ifluatex-with-the-logical-or-operation
\@ifundefined{ifTUTeX}{
\newif\ifTUTeX % a new conditional starts as false
\ifnum 0\ifXeTeX 1\fi\ifLuaTeX 1\fi>0%
\TUTeXtrue
\fi
}{}%
\newif\ifpdfoutput % a new conditional starts as false
\ifnum 0\ifTUTeX 1\fi\ifPDFTeX\ifpdf 1\fi\fi>0%
\pdfoutputtrue
\fi
% \end{macrocode}
% As the package involves a fair bit of file processing,
% we automate the naming of auxiliary files.
% \begin{macrocode}
\def\jobnamewithsuffixtomacro#1#2{%
\filenamewithsuffixtomacro{#1}{\jobname}{#2}%
}
\def\@jn@quote{"}%
\def\filenamewithsuffixtomacro#1#2#3{%
% #1 = macro to create
% #2 = filename to add suffix to
% #3 = suffix to add
\edef\jn@suffix{#3}%
\def\jn@macro{#1}%
\xa\testforquote#2\@jn@rdelim
}
\def\testforquote#1#2\@jn@rdelim{%
\def\jn@test@i{#1}%
\ifx\jn@test@i\@jn@quote
% Involves quotes
\edef\jn@next{"\jn@stripquotes#1#2\jn@suffix"}%
\else
\edef\jn@next{#1#2\jn@suffix}%
\fi
\xa\xdef\jn@macro{\jn@next}%
}
\def\jn@stripquotes"#1"{#1}%
\jobnamewithsuffixtomacro{\outputfilename}{-moodle.xml}
% \end{macrocode}
% Next, we create macros to open and close the Moodle XML file
% we will be writing.
% \begin{macrocode}
\newwrite\moodle@outfile
\def\openmoodleout{%
\immediate\openout\moodle@outfile=\outputfilename\relax
\ifPDFTeX % latin1-based engines (pdflatex or latex)
\writetomoodle{}%
\else
\ifTUTeX % UTF8-based engines (XeTeX or LuaTeX)
\writetomoodle{}%
\else % what shall we do?
\writetomoodle{}%
%\stop
\fi
\fi
\ifmoodle@stampmode
\def\moodle@stamp{This file was generated on \the\year-\two@digits\month-\two@digits\day}
\ifPDFTeX % pdflatex or latex
\ifpdf % pdflatex
\g@addto@macro{\moodle@stamp}{ by pdfLaTeX }%
\else % latex
\g@addto@macro{\moodle@stamp}{ by LaTeX }%
\fi
\else
\ifXeTeX % xetex
\g@addto@macro{\moodle@stamp}{ by XeLaTeX }%
\else
\ifLuaTeX % luatex
\g@addto@macro{\moodle@stamp}{ by LuaLaTeX }%
\else
\g@addto@macro{\moodle@stamp}{ a TeX engine }%
\fi
\fi
\fi
\writetomoodle{}%
\def\moodle@stamp{running on \platformname}%
\g@addto@macro{\moodle@stamp}{ with the package moodle v0.9 }%
\writetomoodle{}%
\fi
\immediate\write\moodle@outfile{}%
\writetomoodle{}%
}%
\def\closemoodleout{%
\writetomoodle{ }%
\writetomoodle{}%
\immediate\closeout\moodle@outfile
}%
% \end{macrocode}
%
% To both make this |.sty| file and the XML output more readable,
% we create a mechanism for writing to the output file with indents.
% The macro |\calculateindent|\marg{$n$} globally defines
% |\moodle@indent| to be a string of \meta{$n$} |\otherspace|'s.
% \begin{macrocode}
\def\calculateindent#1{%
\bgroup
\count0=\number#1\relax
\gdef\moodle@indent{}%
\calculateindent@int
\egroup
}%
\def\calculateindent@int{%
\ifnum\count0>0\relax
\g@addto@macro{\moodle@indent}{\otherspace}%
\advance\count0 by -1\relax
\expandafter
\calculateindent@int
\fi
}%
% \end{macrocode}
% Now the command |\writetomoodle|\oarg{n}\marg{stuff} adds the line
% ``\meta{stuff}'' to the XML file
% preceded by an indent of \meta{n} spaces.
% Note that this command |\edef|'s its second argument.
% \begin{macrocode}
\newcommand\writetomoodle[2][0]{%
\edef\test@ii{#2}%
\ifnum#1=0\relax
\immediate\write\moodle@outfile{\test@ii}%
\else
\calculateindent{#1}%
\immediate\write\moodle@outfile{\moodle@indent\trim@pre@space{\test@ii}}%
\fi
}%
% \end{macrocode}
% We now create the main |quiz| environment that will contain
% the questions we write. It outputs to XML as a || tag.
% \begin{macrocode}
{\catcode`\$=12\catcode`\ =12% in this context we cannot indent with spaces...
\gdef\moodle@write@category@xml#1{%
\@moodle@ifgeneratexml{%
\writetomoodle{ }%
\writetomoodle{}%
\writetomoodle{ }%
\writetomoodle{ $course$/top/#1}%
\writetomoodle{ }%
\writetomoodle{}%
\writetomoodle{ }%
}{}%
}}%
\newcommand*\@enumeratename{enumerate}%
\newdimen\moodle@totalmarks \moodle@totalmarks=0pt%
\newenvironment{quiz}[2][]{%
\setkeys{moodle}{#1}%
\gdef\setcategory##1{%
% At first call (end of \begin{quiz}) enumerate is not started yet
\ifx\@currenvir\@enumeratename
% In case no question is defined between two calls of \setcategory
\def\@noitemerr{}%\@latex@warning{Empty question list}
\end{enumerate}%
\fi
\gdef\moodle@currentcategory{##1}%
\moodle@write@category@xml{##1}%
\ifmoodle@section
\ifmoodle@numbered
\section{##1}%
\else
\section*{##1}%
\fi
\else
\ifmoodle@numbered
\subsection{##1}%
\else
\subsection*{##1}%
\fi
\fi
\begin{enumerate}%
}%
\gdef\setsubcategory##1{%
\def\@noitemerr{}%\@latex@warning{Empty question list}
\end{enumerate}%
\moodle@write@category@xml{\moodle@currentcategory/##1}%
\ifmoodle@section
\ifmoodle@numbered
\subsection{##1}%
\else
\subsection*{##1}%
\fi
\else
\ifmoodle@numbered
\subsubsection{##1}%
\else
\subsubsection*{##1}%
\fi
\fi
\begin{enumerate}%
}%
\setcategory{#2}%
}{%
\end{enumerate}%
\emph{Total of marks: \strip@pt\moodle@totalmarks}%
\let\setcategory\relax
\let\setsubcategory\relax
}%
% \end{macrocode}
% The next utility takes a single macro control sequence |#1|,
% and allows that macro's current value to persist
% after the next |\egroup|, |}|, or |\endgroup|.
% \begin{macrocode}
\def\passvalueaftergroup#1{%
\xa\xa\xa\gdef\xa\xa\csname moodle@remember@\string#1\endcsname\xa{\xa\def\xa#1\xa{#1}}%
\xa\aftergroup\csname moodle@remember@\string#1\endcsname
}
% \end{macrocode}
%
% \subsubsection{Main Switch: to create XML or not}
%
% \begin{macrocode}
\long\def\@moodle@ifgeneratexml#1#2{%
% If we are generating XML, do #1; otherwise do #2.
\tikzifexternalizing{%
% This run of LaTeX is currently ONLY generating a Tikz image
% to be saved in an external file. We do NOT want to waste time
% generating XML, and moreover trying to do so would cause errors
% because of file dependencies.
#2%
}{%
\ifmoodle@draftmode
#2%
\else
#1%
\fi
}%
}
% \end{macrocode}
% Now the macros |openmoodleout| and |closemoodleout| are triggered at Begin and End Document, respectively
% \begin{macrocode}
\AfterEndPreamble{
\@moodle@ifgeneratexml{%
\openmoodleout%
}{}%
}
\AtEndDocument{
\@moodle@ifgeneratexml{%
\closemoodleout%
}{}%
}
% \end{macrocode}
%
% \subsection{Key-Value Pairs for Quiz Questions}
%
% The various options are set using key-value syntax of |xkeyval|.
% \begin{macrocode}
\def\moodleset#1{\setkeys{moodle}{#1}}%
% \end{macrocode}
% We first define some macros that will help us write other macros.
% Calling |\generate@moodle@write@code|\marg{name}|<|\meta{HTML tag}|>|\marg{text to write}
% creates a macro |\moodle@write|\meta{name}, taking no parameters,
% which writes the code |<|\meta{HTML tag}|>...|\meta{HTML tag}|>|
% to the output XML file.
%
% The ordinary version |\generate@moodle@write@code| passes its output text |#3|
% through the HTMLizer, producing HTML code, while the starred variant
% |\generate@moodle@write@code*| passes |#3| verbatim as text.
%
% For example,
% |\generate@moodle@write@code{excuse}{\theexcuse}|
% would expand to
% \begin{Verbatim}[gobble=4,frame=single]
% \gdef\moodle@writeexcuse{%
% \xa\def\xa\test@iii\xa{\theexcuse}%
% \ifx\test@iii\@moodle@empty
% \writetomoodle[2]{ }%
% \else
% \xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{\theexcuse}%
% \writetomoodle[2]{ }%
% \writetomoodle[4]{ \moodle@htmltowrite
]]>}%
% \writetomoodle[2]{ }%
% \fi
% }%
% \end{Verbatim}
% but
% |\generate@moodle@write@code*{excuse}{\theexcuse}|
% would expand only to
% \begin{Verbatim}[gobble=4,frame=single]
% \gdef\moodle@writeexcuse{%
% \writetomoodle[2]{ \theexcuse}%
% }
% \end{Verbatim}
% \begin{macrocode}
\def\generate@moodle@write@code{%
\@ifnextchar*\generate@moodle@write@data\generate@moodle@write@html
}%
\def\generate@moodle@write@html#1<#2>#3{%
% #1 = NAME for \moodle@writeNAME
% #2 = HTML tag
% #3 = what, exactly, to write
\xa\gdef\csname moodle@write#1\endcsname{%
\xa\def\xa\test@iii\xa{#3}%
\ifx\test@iii\@moodle@empty
\writetomoodle[2]{ <#2 format="html">#2>}%
\else
\xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{#3}%
\writetomoodle[2]{ <#2 format="html">}%
\writetomoodle[4]{ \moodle@htmltowrite]]>}%
\writetomoodle[2]{ #2>}%
\fi
}%
}%
\def\generate@moodle@write@html@noptag#1<#2>#3{%
% No
..
introduced
% #1 = NAME for \moodle@writeNAME
% #2 = HTML tag
% #3 = what, exactly, to write
\xa\gdef\csname moodle@write#1\endcsname{%
\xa\def\xa\test@iii\xa{#3}%
\ifx\test@iii\@moodle@empty
\writetomoodle[2]{ <#2 format="html">#2>}%
\else
\xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{#3}%
\writetomoodle[2]{ <#2 format="html">}%
\writetomoodle[4]{ }%
\writetomoodle[2]{ #2>}%
\fi
}%
}%
\def\generate@moodle@write@data*#1<#2>#3{%
% #1 = NAME for \moodle@writeNAME
% #2 = HTML tag
% #3 = what, exactly, to write
\xa\gdef\csname moodle@write#1\endcsname{%
\writetomoodle[2]{ <#2>#3#2>}%
}%
}%
\def\moodle@writetags{%
\xa\xdef\xa\test@iii\xa{\moodle@tags}%
\ifx\test@iii\@moodle@empty\relax\else
\writetomoodle[2]{ }%
\renewcommand*{\do}[1]{%
\def\moodle@tagtext{##1}%
\xa\converttohtmlmacro\xa\moodle@htmltowrite\xa{\moodle@tagtext}%
\writetomoodle[4]{ }%
}
\xa\docsvlist\xa{\moodle@tags}%
\writetomoodle[2]{ }%
\fi
}%
\newif\ifmoodle@firsttag
\moodle@firsttagtrue
\def\moodle@latex@writetags{%
\xa\xdef\xa\test@iii\xa{\moodle@tags}%
\ifx\test@iii\@moodle@empty\relax\else
\hfill tags: %
\renewcommand*{\do}[1]{\ifmoodle@firsttag\moodle@firsttagfalse\else, \fi\texttt{##1}}%
\xa\docsvlist\xa{\test@iii}%
\fi
}%
% \end{macrocode}
% \subsubsection{Keys for all question types}
% \begin{macrocode}
%% QUESTIONNAME
\define@cmdkey{moodle}[moodle@]{questionname}{}%
% \gdef\moodle@writequestionname{%
% \writetomoodle[2]{}%
% \writetomoodle[4]{ \moodle@questionname}%
% \writetomoodle[2]{}%
% }%
%\generate@moodle@write@code{questionname}{\moodle@questionname}%
\generate@moodle@write@html@noptag{questionname}{\moodle@questionname}%
%% QUESTIONTEXT
%I tried to use questiontext as a key, but it doesn't seem to work.
%The trouble is that xkeyval has trouble parsing a key with a \par token followed by a comma within brackets,
%like \setkeys{moodle}{questiontext={ABC\par [D,E]}}
%It's not worth trying to fix.
\long\def\questiontext#1{%
%\converttohtmlmacro\myoutput{#1}%
%\let\moodle@questiontext=\myoutput%
\def\moodle@questiontext{#1}%
}%
\generate@moodle@write@code{questiontext}{\moodle@questiontext}%{%
%% PENALTY FOR WRONG ATTEMPT
\define@cmdkey{moodle}[moodle@]{penalty}[0.10]{}%
\generate@moodle@write@code*{penalty}{\moodle@penalty}%
\moodleset{penalty=0.10}%
%% FEEDBACK
% Moodle allows for feedback tailored to each question,
% and feedback tailored to each right or wrong answer.
% We shall use the key 'feedback' to record both kinds of feedback,
% relying on TeX's grouping mechanism to keep them apart.
% When it comes time to write them to XML,
% \moodle@writegeneralfeedback uses the HTML tag
% whereas \moodle@writefeedback uses the tag .
% Note that the general feedback is NOT inherited by each answer!
\define@cmdkey{moodle}[moodle@]{feedback}[]{}%
\generate@moodle@write@code{generalfeedback}{\moodle@feedback}%
\generate@moodle@write@code{feedback}{\moodle@feedback}%
\moodleset{feedback={}}%
%% DEFAULT GRADE
%The next line creates \moodle@defaultgrade,
%which is how many points the quiz question is worth.
%Key calls like [default grade=7] set \moodle@defaultgrade.
\define@cmdkey{moodle}[moodle@]{default grade}[1.0]{}%
%Next, makes 'points' a synonym for 'default grade'
\define@key{moodle}{points}[1.0]{\xa\def\csname moodle@default grade\endcsname{#1}}
\generate@moodle@write@code*{defaultgrade}{\csname moodle@default grade\endcsname}%
\moodleset{default grade=1.0} %This sets the default.
%% HIDDEN
\define@boolkey{moodle}[moodle@]{hidden}[true]{}%
\generate@moodle@write@code*{hidden}{\ifmoodle@hidden 1\else 0\fi}%
\moodleset{hidden=false}%
\def\moodle@writecommondata{%
\moodle@writequestionname%
\moodle@writequestiontext%
\moodle@writedefaultgrade%
\moodle@writegeneralfeedback%
\moodle@writepenalty%
\moodle@writehidden%
}%
%% TAGS
%The next line creates \moodle@tags,
%which defines a "tag" (i.e., keyword) for the question.
%Key calls like [tags={random}] set \moodle@tags.
\define@cmdkey{moodle}[moodle@]{tags}[]{}%
\moodleset{tags={}}%
% \end{macrocode}
% \subsubsection{Keys for all answers}
% \begin{macrocode}
%% FRACTION -- how much this answer is worth out of 100 percent
\define@cmdkey{moodle}[moodle@]{fraction}[100]{}%
%We do not create \moodle@writefraction, because the fraction occurs in
%the XML within the answer tag, like .
\moodleset{fraction=100} %This sets the default.
% \end{macrocode}
% \begin{macrocode}
%% FRACTIONTOL -- the tolerance for fractions with respect to valid values
\define@cmdkey{moodle}[moodle@]{fractiontol}[0.1]{}%
\moodleset{fractiontol=0.1} %This sets the default.
% \end{macrocode}
% \subsubsection{Keys for multiple choice questions}
% \begin{macrocode}
%% SINGLE and MULTIPLE -- for multichoice, is there 1 right answer or more than 1?
\define@boolkey{moodle}[moodle@]{single}[true]{}%
\generate@moodle@write@code*{single}{\ifmoodle@single true\else false\fi}%
\moodleset{single=true}%
%The key 'multiple' is an antonym to 'single'.
\define@boolkey{moodle}[moodle@]{multiple}[true]{\ifmoodle@multiple\moodle@singlefalse\else\moodle@singletrue\fi}%
%% SHUFFLE ANSWERS
\define@boolkey{moodle}[moodle@]{shuffle}[true]{}%
\generate@moodle@write@code*{shuffle}{\ifmoodle@shuffle 1\else 0\fi}%
\moodleset{shuffle=true}%
%% ALLORNOTHING -- for multichoice with multiple answers where all the points are given
% if and only if all the correct answers are selected.
\define@boolkey{moodle}[moodle@]{allornothing}[true]{}%
\moodleset{allornothing=false}%
%% TODO: CORRECTFEEDBACK
%% TODO: PARTIALLYCORRECTFEEDBACK
%% TODO: INCORRECTFEEDBACK
%% TODO: NUMCORRECT key
%% NUMBERING -- for numbering of multichoice questions
\define@choicekey{moodle}{numbering}%
{alpha,alph,Alpha,Alph,arabic,roman,Roman,%
abc,ABCD,123,iii,IIII,none}[abc]{%
\def\moodle@numbering{#1}%
\def\test@@i{#1}%
\ifx\test@@i\@moodle@alpha
\def\moodle@numbering{abc}\fi
\ifx\test@@i\@moodle@alph
\def\moodle@numbering{abc}\fi
\ifx\test@@i\@moodle@Alpha
\def\moodle@numbering{ABCD}\fi
\ifx\test@@i\@moodle@Alph
\def\moodle@numbering{ABCD}\fi
\ifx\test@@i\@moodle@arabic
\def\moodle@numbering{123}\fi
\ifx\test@@i\@moodle@roman
\def\moodle@numbering{iii}\fi
\ifx\test@@i\@moodle@Roman
\def\moodle@numbering{IIII}\fi
}%
%'answer numbering' will be a synonym to 'numbering'
\define@key{moodle}{answer numbering}[abc]{\setkeys{moodle}{numbering={#1}}}%
\generate@moodle@write@code*{answernumbering}{\moodle@numbering}%
%N.B. if we did not set the default here, then \moodle@numbering would be undefined, causing problems.
\moodleset{answer numbering=abc}%
\def\@moodle@alpha{alpha}%
\def\@moodle@Alpha{Alpha}%
\def\@moodle@alph{alph}%
\def\@moodle@Alph{Alph}%
\def\@moodle@arabic{arabic}%
\def\@moodle@roman{roman}%
\def\@moodle@Roman{Roman}%
\def\@moodle@abc{abc}%
\def\@moodle@ABCD{ABCD}%
\def\@moodle@arabicnumbers{123}%
\def\@moodle@iii{iii}%
\def\@moodle@IIII{IIII}%
\def\@moodle@none{none}%
\def\moodle@obeynumberingstyle{%
\ifx\moodle@numbering\@moodle@abc
\renewcommand\theenumii{\alph{enumii}}%
\fi
\ifx\moodle@numbering\@moodle@ABCD
\renewcommand\theenumii{\Alph{enumii}}%
\fi
\ifx\moodle@numbering\@moodle@arabicnumbers
\renewcommand\theenumii{\arabic{enumii}}%
\fi
\ifx\moodle@numbering\@moodle@iii
\renewcommand\theenumii{\roman{enumii}}%
\fi
\ifx\moodle@numbering\@moodle@IIII
\renewcommand\theenumii{\Roman{enumii}}%
\fi
\ifx\moodle@numbering\@moodle@none
\renewcommand\labelenumii{$\bullet$~}%
\fi
}
%TODO: * In the PDF, how should 'none' in a multi look different from
% short answer or numerical options?
% * Instead of \theenumi and \labelenumi,
% use \@enumdepth to automatically set the correct depth.
%% DISPLAY MODE -- affects Cloze multiple choice questions only.
% 0 = inline, 1 = vertical, 2 = horizontal
\def\moodle@multi@mode{0}%
\define@key{moodle}{inline}[]{\def\moodle@multi@mode{0}}%
\define@key{moodle}{vertical}[]{\def\moodle@multi@mode{1}}%
\define@key{moodle}{horizontal}[]{\def\moodle@multi@mode{2}}%
% \end{macrocode}
% \subsubsection{Keys for numerical questions}
% \begin{macrocode}
%% TOLERANCE
\define@cmdkey{moodle}[moodle@]{tolerance}[0]{}%
\moodleset{tolerance=0}%
%There is no \moodle@writetolerance, because in the XML the
%tolerance is given within the answer tag,
%like .
% TODO: implement unit-handling for numerical questions!
% \end{macrocode}
% \subsubsection{Keys for short answer questions}
% \begin{macrocode}
%% CASE SENSITIVE
\define@boolkey{moodle}[moodle@]{case sensitive}[true]{}%
\generate@moodle@write@code*{usecase}{\csname ifmoodle@case sensitive\endcsname 1\else 0\fi}%
% We make 'usecase' a synonym for 'case sensitive'.
\define@boolkey{moodle}[moodle@]{usecase}[true]{\ifmoodle@usecase\csname moodle@case sensitivetrue\endcsname\else\csname moodle@case sensitivefalse\endcsname\fi}%
\moodleset{case sensitive=false}%
% \end{macrocode}
% \subsubsection{Keys for matching questions}
% \begin{macrocode}
%% DRAG-AND-DROP FORMAT
\define@boolkey{moodle}[moodle@]{draganddrop}[true]{}%
% We make 'dd' and 'dragdrop' and 'drag and drop' synonyms for 'draganddrop'.
\define@boolkey{moodle}[moodle@]{dd}[true]{\ifmoodle@dd\moodle@draganddroptrue\else\moodle@draganddropfalse\fi}%
\define@boolkey{moodle}[moodle@]{drag and drop}[true]{\moodle@ddsynonym}%
\def\moodle@ddsynonym{%
\csname ifmoodle@drag and drop\endcsname
\moodle@draganddroptrue
\else
\moodle@draganddropfalse
\fi
}
\moodleset{draganddrop=false}%
% \end{macrocode}
% \subsubsection{Keys for essay questions}
% \begin{macrocode}
%% EDITOR
\def\@moodle@html{html}%
\def\@moodle@htmlfile{html+file}%
\def\@moodle@text{text}%
\def\@moodle@plain{plain}%
\def\@moodle@monospaced{monospaced}%
\def\@moodle@file{file}%
\def\@moodle@noinline{noinline}%
\define@choicekey{moodle}{response format}%
{html,html+file,text,monospaced,file}[html]%
{\def\test@i{#1}%
\ifx\test@i\@moodle@html
% HTML Editor
\def\moodle@responseformat{editor}%
\fi
\ifx\test@i\@moodle@htmlfile
% HTML Editor with File Picker
\def\moodle@responseformat{editorfilepicker}%
\fi
\ifx\test@i\@moodle@text
% Plain text
\def\moodle@responseformat{plain}%
\fi
\ifx\test@i\@moodle@plain
% Plain text
\def\moodle@responseformat{plain}%
\fi
\ifx\test@i\@moodle@monospaced
% Plain text, monospaced font
\def\moodle@responseformat{monospaced}%
\fi
\ifx\test@i\@moodle@file
% No inline text (i.e., attachments only)
\def\moodle@responseformat{noinline}%
\fi
\ifx\test@i\@moodle@noinline
% No inline text (i.e., attachments only)
\def\moodle@responseformat{noinline}%
\fi
}%
\generate@moodle@write@code*{responseformat}{\moodle@responseformat}%
\moodleset{response format=html}%
%N.B. if we did not set a default, then \moodle@responseformat would be undefined, causing problems.
%% RESPONSE REQUIRED
\define@boolkey{moodle}[moodle@]{response required}[true]{}%
% TODO: Make synonym 'required'
\generate@moodle@write@code*{responserequired}{\csname ifmoodle@response required\endcsname 1\else 0\fi}%
\moodleset{response required=false}%
%% RESPONSEFIELDLINES
\define@cmdkey{moodle}[moodle@]{response field lines}[15]{}%
\generate@moodle@write@code*{responsefieldlines}{\csname moodle@response field lines\endcsname}%
%Make synonyms 'input box size' or 'height' or 'lines'?
\moodleset{response field lines=15}% N.B. if we do not set a default, then \moodle@responseformat will be undefined, causing problems.
%% ATTACHMENTS ALLOWED
\def\@moodle@unlimited{unlimited}%
\define@choicekey{moodle}{attachments allowed}{0,1,2,3,unlimited}[1]{%
\def\test@i{#1}%
\ifx\test@i\@moodle@unlimited
\def\moodle@attachmentsallowed{-1}%
\else
\def\moodle@attachmentsallowed{#1}%
\fi
}
\generate@moodle@write@code*{attachmentsallowed}{\moodle@attachmentsallowed}
\moodleset{attachments allowed=0}%
%% ATTACHMENTS REQUIRED
\define@choicekey{moodle}{attachments required}{0,1,2,3}[1]{\def\moodle@attachmentsrequired{#1}}%
\generate@moodle@write@code*{attachmentsrequired}{\moodle@attachmentsrequired}
\moodleset{attachments required=0}%
%% RESPONSE TEMPLATE
\define@key{moodle}{template}{\long\def\moodle@responsetemplate{#1}}%
\generate@moodle@write@html@noptag{responsetemplate}{\moodle@responsetemplate}
\moodleset{template={}}%
% \end{macrocode}
% \subsubsection{Hint tags}
% The following are not yet fully implemented.
% \begin{macrocode}
%% SHOWNUMCORRECT
\define@boolkey{moodle}[moodle@]{shownumcorrect}[true]{}%
\gdef\moodle@writeshownumcorrect{%
\if\moodle@shownumcorrect
\writetomoodle[4]{ }%
\fi
}%
\moodleset{shownumcorrect=false}%
%% CLEARWRONG
\define@boolkey{moodle}[moodle@]{clearwrong}[true]{}%
\gdef\moodle@writeclearwrong{%
\if\moodle@clearwrong
\writetomoodle[4]{ }%
\fi
}%
\moodleset{clearwrong=false}%
% TODO: Implement hints
% \end{macrocode}
%
% \subsection{Answer handling}
%
% \begin{macrocode}
%The Answers XML depends heavily on the question type.
%Each type of question defines how it obtains answers from the LaTeX input,
%how it typesets those in a PDF or DVI, and how it writes them as XML code.
%It will write that XML to the macro \moodle@answers@xml,
%which them gets written to the file when \moodle@writeanswers
%is invoked.
\def\moodle@answers@xml{}%
\gdef\moodle@writeanswers{%
\writetomoodle{\moodle@answers@xml}%
}%
\newcommand\addto@xml[3][0]{%
% #1 = spaces to indent (default=0)
% #2 = macro containing XML code (possibly empty)
% #3 = XML text to be appended to that macro (will be \edef'd)
\calculateindent{#1}%
\edef\xml@to@add{\moodle@indent\trim@pre@space{#3}}%
\ifx#2\@moodle@empty
\edef\newxml{\noexpand#2\xml@to@add}%
\else
\edef\newxml{\noexpand#2^^J\xml@to@add}%
\fi
\xa\xa\xa\def\xa\xa\xa#2\xa\xa\xa{\newxml}%
}%
% \end{macrocode}
%
% \subsubsection{Not yet implemented}
%
% \begin{macrocode}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% CALCULATED %%%%%%%%%%%%%%%%%%%%%%%%%%
% TODO: I don't think I really want to handle this. Not now.
% \end{macrocode}
% \subsection{Front Ends}
% This section creates the user interface for the various question types.
% First, we define a generic command to create
% a front-end environment for a Moodle question type.
% In order to function, the following macros must be hard-coded:
% \begin{itemize}
% \item |\moodle@|\meta{type}|@latexprocessing|:
% Loops through the saved |\item|'s to typeset them in LaTeX,
% usually inside an itemize or enumerate environment.
% \item |\save|\meta{type}|answer#1|:
% Processes the text of a single |\item| to save the information to memory,
% usually inside |\moodle@answers@xml|.
% \item |\write|\meta{type}|question|:
% Writes the information, hitherto saved only in macros,
% into the XML file.
% \end{itemize}
% For example, to create the `shortanswer' question type,
% we shall call
% \begin{Verbatim}[gobble=5,frame=single]
% \moodle@makefrontend{shortanswer}
% \def\moodle@shortanswer@latexprocessing{...}
% \def\saveshortansweranswer#1{...}
% \def\writeshortanswerquestion{...}
% \end{Verbatim}
%
% \begin{macrocode}
\def\moodle@makelatextagbox#1{%
% \ifmoodle@tikzloaded
% \tikzset{external/export next=false}
% \tikz[baseline]{\node[draw,minimum height=1.2em,rounded corners,fill=black!20] {\tiny #1};}
% % Fancy but interferes with the tikzexternalize counter
% \else
\Ovalbox{\tiny #1}
%\ovalbox{\tiny #1}
%\shadowbox{\tiny #1}
% \fi
}%
\def\moodle@makelatextag@qtype#1{%
\doublebox{\tiny \textsc{#1}}
}%
\def\moodle@makelatextag@value#1#2{%
\moodle@makelatextagbox{\csname moodle@#1\endcsname~#2}
}%
\def\moodle@makelatextag@key#1{%
\moodle@makelatextagbox{\csname moodle@#1\endcsname}
}%
\def\moodle@marks#1{point\ifdim#1pt=1pt \else s\fi}
\def\moodle@makefrontend#1#2{%
\NewEnviron{#1}[2][]{%
\bgroup
\setkeys{moodle}{##1,questionname={##2}}%
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\expandafter\gatheritems\xa{\BODY}%
\let\moodle@questionheader=\gatheredheader
%First, the LaTeX processing
\item \textbf{\moodle@questionname}
\ifmoodle@handout
\moodle@makelatextag@qtype{#1}
\else
\moodle@latex@writetags
\par
\noindent
\moodle@makelatextag@qtype{#1}
\moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
\moodle@makelatextag@value{penalty}{penalty}
\fi
#2\par
\noindent
\moodle@questionheader
\edef\moodle@generalfeedback{\expandonce\moodle@feedback}
\csname moodle@#1@latexprocessing\endcsname
%Now, writing information to XML
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\moodle@questionheader}% Save the question text.
\csname write#1question\endcsname
\bgroup
\gdef\moodle@answers@xml{}%
\setkeys{moodle}{feedback={}}%
\xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
\moodle@writeanswers%
\moodle@writetags%
\writetomoodle{}%
}{}%
\egroup
}%
}
% \end{macrocode}
%
% \subsubsection{Description Question Front-End}
% Description and essay questions are the only question types whose front end
% is not yet created by |\moodle@makefrontend|.
% This is because of what need to be done with their contents.
%
% Description blocks can be empty. In this case, nothing is done.
%
% \begin{macrocode}
\AfterEndPreamble{% in case something like \usepackage[french]{babel} is loaded
\let\description\relax% remove the meaning of existing \description and \enddescription
\let\enddescription\relax
\NewEnviron{description}[2][]{%
\bgroup
\setkeys{moodle}{#1,questionname={#2}}%
\let\moodle@questiontext=\BODY
\trim@spaces@in\moodle@questiontext
\ifx\moodle@questiontext\@empty\relax\else%
%First, the LaTeX processing.
\item \textbf{\moodle@questionname}
\ifmoodle@handout\else
\moodle@latex@writetags
\par
\noindent
\fi
\moodle@makelatextag@qtype{description}\par
\noindent
\moodle@questiontext\par
\ifmoodle@handout\else
\ifx\moodle@feedback\@empty\relax\else
\fbox{\parbox{\linewidth}{\emph{\moodle@feedback}}}%
\fi
\fi
%Now, writing information to memory.
\@moodle@ifgeneratexml{%
\writetomoodle{}%
\moodle@writecommondata
\moodle@writetags%
\writetomoodle{}%
}{}%
\fi
\egroup
}%
}%
% \end{macrocode}
%
% \subsubsection{Essay Question Front-End}
% The front end is not yet created by |\moodle@makefrontend| because of
% what must must be done with the |\item|'s.
%
% \begin{macrocode}
\def\moodle@essay@latexprocessing{%
% Moodle cannot automatically grade an essay,
% but if the user puts \item's in, we can list them in an itemize as notes.
\par\noindent \emph{Notes for grader:}
\ifnum\c@numgathereditems>0\relax
\begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
\loopthroughitemswithcommand{\moodle@print@essay@answer}%
\end{itemize}%
\fi
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
}
\NewEnviron{essay}[2][]{%
\bgroup
\setkeys{moodle}{#1,questionname={#2}}%
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\moodle@checkresponsefieldlines
\expandafter\gatheritems\expandafter{\BODY}%
\let\moodle@questionheader=\gatheredheader
%First, the LaTeX processing.
\item \textbf{\moodle@questionname}
\ifmoodle@handout
\moodle@makelatextag@qtype{essay}
\else
\moodle@latex@writetags
\par
\noindent
\moodle@makelatextag@qtype{essay}
\moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
\moodle@makelatextag@value{penalty}{penalty}
\moodle@makelatextag@key{responseformat}
\fi
\par
\noindent
\moodle@questionheader
\long\def\@lempty{}%
\ifx\moodle@responsetemplate\@lempty\else
\par\noindent \emph{Template:}
\par\fbox{\parbox{\linewidth}{\moodle@responsetemplate}}\par
\fi
\edef\moodle@generalfeedback{\expandonce\moodle@feedback}
\ifmoodle@handout\else
\csname moodle@essay@latexprocessing\endcsname
\fi
%Now, writing information to memory.
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\moodle@questionheader}% Save the question text.
\writeessayquestion
\bgroup
\gdef\moodle@answers@xml{}%
%
\ifnum\c@numgathereditems=0\relax
\addto@xml[2]\moodle@answers@xml{}%
\else
\addto@xml[2]\moodle@answers@xml{1\relax
\addto@xml[4]\moodle@answers@xml{
}%
\fi
\addto@xml[2]\moodle@answers@xml{]]>}%
\fi
%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
\moodle@writeanswers% The 'answers' XML really contains the grader info.
\moodle@writeresponsetemplate%
\moodle@writetags%
\writetomoodle{}%
}{}%
\egroup
}%
\def\moodle@checkresponsefieldlines{%
\newcount\a\a=\number\csname moodle@response field lines\endcsname
\newcount\b\b=5%
\ifnum\the\a>40% if the value was more than 40
\a=40%
\fi
\ifnum\the\a<5% if the value was less than 5
\a=5%
\fi
\divide\a by\b% integer division by 5
\multiply\a by\b% multiply by 5
\ifnum\a=\csname moodle@response field lines\endcsname% equality holds if we had 5, 10, 15, 20, 25, 30, or 40
\else
\ifnum\csname moodle@response field lines\endcsname>5%
\ifnum\csname moodle@response field lines\endcsname<40%
\advance\a by\b% approximate with the next multiple of 5
\fi
\fi
\PackageWarning{moodle}{"response field lines" admits only multiples of 5 between 5 and 40
(You tried to set \csname moodle@response field lines\endcsname). The value
\the\a\space will be used.}%
\setkeys{moodle}{response field lines=\the\a}%
\fi
}%
%%%% TODO
%%%% To make essay work will be tough.
%%%% Every line from \ifnum\c@numgathereditems=0\relax through its \else and \fi,
%%%% with the exception of
%%%% \xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
%%%% , does not exist in our current \moodle@makefrontend code.
%%%% How can we cope?
%%%%
%%%% Idea: change \moodle@makefrontend so that
%%%% 1. if \c@numgathereditems=0, we don't do anything.
%%%% 2. it calls a preamble and postamble around the \loopthroughitemswithcommand.
%%%% Like this:
%%%%
%%%% \@moodle@ifgeneratexml{%
%%%% \xa\questiontext\xa{\moodle@questionheader}% Save the question text.
%%%% \bgroup
%%%% \gdef\moodle@answers@xml{}%
%%%% \setkeys{moodle}{feedback={}}%
%%%% \@ifundefined{moodle@#1@answers@preamble}{}{}%
%%%% \csname moodle@#1@answers@preamble\endcsname
%%%% \ifnum\c@numgathereditems=0\relax
%%%% \relax
%%%% \else
%%%% \xa\loopthroughitemswithcommand\xa{\csname save#1answer\endcsname}%
%%%% \fi
%%%% \@ifundefined{moodle@#1@answers@postamble}{}{}%
%%%% \csname moodle@#1@answers@postamble\endcsname
%%%% \passvalueaftergroup{\moodle@answers@xml}%
%%%% \egroup
%%%% \csname write#1question\endcsname
%%%% }{}%
%%%% The \@ifundefined lines should automatically define the
%%%% \...@preamble \...@postamble macros to be \relax if they don't exist already.
\gdef\writeessayquestion{%
\writetomoodle{}%
\moodle@writecommondata%
\moodle@writeresponserequired%
\moodle@writeresponseformat%
\moodle@writeresponsefieldlines%
\moodle@writeattachmentsallowed%
\moodle@writeattachmentsrequired%
}%
\long\def\moodle@print@essay@answer#1{%
\item #1%
}%
\long\def\moodle@savegraderinfo#1{%
%\def\ds{#1}\show\ds
\bgroup
\moodle@savegraderinfo@int#1\moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\moodle@savegraderinfo@int[1][]{%
\setkeys{moodle}{fraction=0,#1}%
\moodle@savegraderinfo@int@int%
}%
\long\def\moodle@savegraderinfo@int@int#1\moodle@answer@rdelim{%
\def\moodle@answertext{#1}
\xa\converttohtmlmacro\xa\moodle@answertext@html\xa{\moodle@answertext}%
%\trim@spaces@in\moodle@answertext
\ifnum\c@numgathereditems>1\relax
\addto@xml[6]{\moodle@answers@xml}{
\moodle@answertext@html
}%
\else
\addto@xml[4]{\moodle@answers@xml}{\moodle@answertext@html}%
\fi
}%
% \end{macrocode}
%
% \subsubsection{Short Answer Question Front-End}
%
% \begin{macrocode}
\def\blank{\rule{1in}{0.5pt}}%
% TODO: Make an optional argument for width? This wouldn't affect Moodle,
% only the appearance in the PDF. It doesn't seem worth it.
%\NewEnviron{shortanswer}[2][]{%
% \bgroup
% \setkeys{moodle}{#1,questionname={#2}}%
% \expandafter\gatheritems\xa{\BODY}%
% \let\moodle@questionheader=\gatheredheader
% %First, the LaTeX processing.
% \item \textbf{\moodle@questionname}
% \csname ifmoodle@case sensitive\endcsname
% \framebox{\tiny Case-Sensitive}\relax
% \fi
% \framebox{\tiny\csname moodle@default grade\endcsname~points}
% \framebox{\tiny\csname moodle@penalty\endcsname~penalty}\par
% \noindent
% \moodle@questionheader
% \csname moodle@shortanswer@latexprocessing\endcsname
% %Now, writing information to memory.
% \@moodle@ifgeneratexml{%
% \xa\questiontext\xa{\moodle@questionheader}% Save the question text.
% \bgroup
% \gdef\moodle@answers@xml{}%
% \setkeys{moodle}{feedback={}}%
% \xa\loopthroughitemswithcommand\xa{\csname
% saveshortansweranswer\endcsname}%
% \passvalueaftergroup{\moodle@answers@xml}%
% \egroup
% \csname writeshortanswerquestion\endcsname
% }{}%
% \egroup
% }%
\moodle@makefrontend{shortanswer}{\moodle@makelatextag@shortanswer}%
% LATEX PROCESSING
\def\moodle@makelatextag@shortanswer{%
\csname ifmoodle@case sensitive\endcsname
\moodle@makelatextagbox{Case-Sensitive}\relax
\else
\moodle@makelatextagbox{Case-Insensitive}\relax
\fi
}
\ifmoodle@handout
\let\moodle@shortanswer@latexprocessing\relax
\else
\def\moodle@shortanswer@latexprocessing{%
\begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
\loopthroughitemswithcommand{\moodle@print@shortanswer@answer}%
\end{itemize}%
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
}
\fi
\def\moodle@print@shortanswer@answer#1{%
\let\moodle@feedback=\@empty
\moodle@print@shortanswer@answer@int#1\@rdelim
}%
\newcommand\moodle@print@shortanswer@answer@int[1][]{%
\setkeys{moodle}{#1}%
\moodle@print@shortanswer@answer@int@int%
}%
\def\moodle@print@shortanswer@answer@int@int#1\@rdelim{%
\ifx\moodle@fraction\@hundred
\item #1$~\checkmark$%
\else
\moodle@checkfraction
\item #1$~(\moodle@fraction\%)$%
\fi
\ifx\moodle@feedback\@empty\relax\else
\hfill \emph{$\rightarrow$ \moodle@feedback}
\fi
}%
% SAVING ANSWERS TO MEMORY
\def\saveshortansweranswer#1{%
\bgroup
\saveshortansweranswer@int#1\moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\saveshortansweranswer@int[1][]{%
\setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
\saveshortansweranswer@int@int%
}%
\def\saveshortansweranswer@int@int#1\moodle@answer@rdelim{%
\def\moodle@answertext{#1}%
\trim@spaces@in\moodle@answertext
\moodle@checkfraction
\addto@xml[2]{\moodle@answers@xml}{}%
\xa\converttohtmlmacro\xa\moodle@answertext@html\xa{\moodle@answertext}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@answertext@html}%
\ifx\moodle@feedback\@empty\relax\else
\trim@spaces@in\moodle@feedback
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{}%
}%
% WRITING QUESTION TO XML FILE
\gdef\writeshortanswerquestion{%
\writetomoodle{}%
\moodle@writecommondata%
\moodle@writeusecase%
}%
% \end{macrocode}
%
% \subsubsection{Numerical Question Front-End}
%
% \begin{macrocode}
\moodle@makefrontend{numerical}{\moodle@makelatextag@numerical}%
% LATEX PROCESSING
\def\moodle@makelatextag@numerical{}
\AtEndPreamble{
\@ifpackageloaded{siunitx}{\def\moodle@printnum{\num[omit-uncertainty,copy-decimal-marker]}}{\let\moodle@printnum\trim@spaces}%
}
\ifmoodle@handout
\let\moodle@numerical@latexprocessing\relax
\else
\def\moodle@numerical@latexprocessing{%
\begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
\loopthroughitemswithcommand{\moodle@print@numerical@answer}%
\end{itemize}%
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
}
\fi
\def\moodle@print@numerical@answer#1{%
\let\moodle@feedback=\@empty
\bgroup
\moodle@print@numerical@answer@int#1\@rdelim
\egroup
}%
\newcommand\moodle@print@numerical@answer@int[1][]{%
\setkeys{moodle}{#1}%
\moodle@print@numerical@answer@int@int%
}%
\def\moodle@print@numerical@answer@int@int#1\@rdelim{%
\xdef\test@i{\trim@spaces{#1}}%
\ifx\test@i\@star
\item \test@i
\else
\item \moodle@printnum{#1}%
\ifnum\z@=\moodle@tolerance\else
$\,\pm\,$\moodle@printnum{\moodle@tolerance}%
\fi
\fi
\ifx\moodle@fraction\@hundred
$~\checkmark$%
\else
\moodle@checkfraction
$~(\moodle@fraction\%)$%
\fi
\ifx\moodle@feedback\@empty\relax\else
\hfill \emph{$\rightarrow$ \moodle@feedback}%
\fi
}%
% SAVING ANSWERS TO MEMORY
\def\savenumericalanswer#1{%
\bgroup
\savenumericalanswer@int#1\moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\savenumericalanswer@int[1][]{%
\setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
\savenumericalanswer@int@int%
}%
\def\savenumericalanswer@int@int#1\moodle@answer@rdelim{%
\def\moodle@answertext{#1}%
\trim@spaces@in\moodle@answertext
\moodle@checkfraction
\addto@xml[2]{\moodle@answers@xml}{}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@answertext}%
\ifx\moodle@answertext\@star\else
\addto@xml[4]{\moodle@answers@xml}{ \moodle@tolerance}%
\fi
\ifx\moodle@feedback\@empty\relax\else
\trim@spaces@in\moodle@feedback
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{}%
}%
% WRITING QUESTION TO XML FILE
\gdef\writenumericalquestion{%
\writetomoodle{}%
\moodle@writecommondata%
}%
% \end{macrocode}
%
% \subsubsection{Multiple Choice Question Front-End}
%
% \begin{macrocode}
%Multiple choice has the structure
% \begin{multi}[options]{name}%
% What is 5+7?
% \item 13
% \item* 12
% \item 11
% \end{multi}%
\moodle@makefrontend{multi}{\moodle@makelatextag@multi}%
% LATEX PROCESSING
\def\moodle@makelatextag@multi{%
\ifmoodle@allornothing
\ifx\endmulti\endclozemulti
\PackageError{moodle}{Unsupported option "allornothing" for a multichoice subquestion}
{Please set "allornothing=false"}%
\else
\moodle@makelatextagbox{All-or-nothing}%
\fi
\else
\ifmoodle@multiple
\moodle@makelatextagbox{Multiple}%
\else
\moodle@makelatextagbox{Single}%
\fi
\fi
\ifmoodle@handout\else
\ifmoodle@shuffle
\moodle@makelatextagbox{Shuffle}\relax%
\fi
\fi
}
\def\moodle@multi@latexprocessing{%
\ifmoodle@allornothing
\moodle@singletrue
\fi
\moodle@countcorrectanswers%
\ifmoodle@handout\NewList{answerlist}\fi
\begin{enumerate}\moodle@obeynumberingstyle%
%\renewcommand{\theenumi}{\alph{enumi}}%
\setlength\itemsep{0pt}\setlength\parskip{0pt}%
\loopthroughitemswithcommand{\moodle@print@multichoice@answer}%
\ifmoodle@handout
\ifmoodle@shuffle
\let\moodle@multi@loop=\ForEachRandomItem
\else
\let\moodle@multi@loop=\ForEachFirstItem
\fi
\moodle@multi@loop{answerlist}{Answer}{\Answer}%
\fi
\end{enumerate}%
\ifmoodle@handout\else
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
\fi
}
\long\def\moodle@print@multichoice@answer#1{%
\let\moodle@feedback=\@empty%
\moodle@print@multichoice@answer@int#1 \@rdelim%
}%
\newcommand\moodle@print@multichoice@answer@int[1][]{%
\let\moodle@fraction\@empty%
\setkeys{moodle}{#1}%
\moodle@print@multichoice@answer@int@int%
}%
\long\def\moodle@print@multichoice@answer@int@int#1#2\@rdelim{%
\def\test@i{#1}%
\def\test@ii{#2}%
\def\moodle@answertext{\item }%
\ifx\test@i\@star%
\g@addto@macro\moodle@answertext{#2}%
\ifmoodle@single%
\setkeys{moodle}{fraction=100}%
\else
\setkeys{moodle}{fraction=\moodle@autopoints}%
\fi
\else
\g@addto@macro\moodle@answertext{#1#2}%
\fi
\trim@spaces@in\moodle@answertext%
\trim@spaces@in\moodle@answertext%
\ifmoodle@handout\else
\ifmoodle@single%
\ifx\moodle@fraction\@empty\relax%
\setkeys{moodle}{fraction=0}%
\fi
\moodle@checkfraction
\ifx\moodle@fraction\@hundred%
\trim@spaces@in\moodle@answertext%
\g@addto@macro\moodle@answertext{$~\checkmark$}%
\else
\ifdim0pt=\moodle@fraction pt\relax\else%
\g@addto@macro\moodle@answertext{$~(\moodle@fraction\%)$}%
\fi
\fi
\else% multiple
\ifx\moodle@fraction\@empty\relax%
\setkeys{moodle}{fraction=\moodle@autosanctions}%
\fi
\moodle@checkfraction
\g@addto@macro\moodle@answertext{$~(\moodle@fraction\%)$}%
\fi
\fi
\ifmoodle@handout
\def\temp{\InsertLastItem{answerlist}}%
\xa\temp\xa{\moodle@answertext}%
\else
\ifx\moodle@feedback\@empty\relax\else%
\g@addto@macro\moodle@answertext{\hfill \emph{$\rightarrow$ \moodle@feedback}}%
\fi
\moodle@answertext
\fi
}%
% COMMON UTILITY: COUNTING CORRECT ANSWERS (AND A BIT MORE...)
\newcounter{moodle@numcorrectanswers}% count the stars
\newcounter{moodle@numincorrectanswers}% count the items without fraction key indicated
\newlength{\moodle@pointspercorrect}%
\newlength{\moodle@pointsperincorrect}%
\newlength{\moodle@sumofpositivefractions}% sums user-set positive fractions
\newlength{\moodle@sumofnegativefractions}% sums user-set negative fractions
\def\moodle@countcorrectanswers{%
\setcounter{moodle@numcorrectanswers}{0}%
\setcounter{moodle@numincorrectanswers}{0}%
\global\setlength{\moodle@pointspercorrect}{100pt}%
\global\setlength{\moodle@pointsperincorrect}{-100pt}%
\global\setlength{\moodle@sumofpositivefractions}{0pt}%
\global\setlength{\moodle@sumofnegativefractions}{0pt}%
\loopthroughitemswithcommand{\moodle@countcorrectanswers@a}%
\global\advance\moodle@pointspercorrect by-\moodle@sumofpositivefractions\relax%
\def\ds{\strip@pt\moodle@sumofpositivefractions}%
\ifnum0=\c@moodle@numcorrectanswers\relax%
% autopoints will never be used but we check if the sum of positive fractions is 100%
\ifdim\moodle@pointspercorrect<-\moodle@fractiontol pt\relax%
\PackageWarning{moodle}{Positive fractions sum up to more than 100 (here: \ds)}%
\else
\ifdim\moodle@pointspercorrect>\moodle@fractiontol pt\relax%
\PackageError{moodle}{Positive fractions sum up to less than 100 (here: \ds)}%
\fi
\fi
\else
\ifdim0pt<\moodle@pointspercorrect\relax\else%
% we have starred items so the sum of user-set positive fractions must be less than 100%
% otherwise, starred items would lead to penalties
\PackageError{moodle}{Positive fractions sum up to 100 or more (here: \ds):
there is no positive points left to be given to starred items.}%
\fi
\global\divide\moodle@pointspercorrect by \c@moodle@numcorrectanswers\relax%
\fi
\gdef\moodle@autopoints{\strip@pt\moodle@pointspercorrect}%
\global\advance\moodle@pointsperincorrect by-\moodle@sumofnegativefractions\relax%
\def\ds{\strip@pt\moodle@sumofnegativefractions}%
\ifnum0=\c@moodle@numincorrectanswers\relax%
% autosanctions will never be used and
% we do not care about the sum of negative fractions (might be less than -100)
\else
\ifdim0pt<\moodle@pointsperincorrect\relax%
% we have items without fractions set: to prevent auto sanctions from becoming bonuses,
% such items are neutralized.
\PackageWarning{moodle}{Negative fractions sum up to -100 or less (here: \ds):
items with no fraction key set will be considered as neutral.}%
\global\setlength{\moodle@pointsperincorrect}{0pt}%
\fi
\global\divide\moodle@pointsperincorrect by \c@moodle@numincorrectanswers\relax%
\fi
\gdef\moodle@autosanctions{\strip@pt\moodle@pointsperincorrect}%
}
\long\def\moodle@countcorrectanswers@a#1{%
%The grouping is to keep key answer-specific key changes local.
\bgroup
\moodle@countcorrectanswers@b#1\moodle@answer@rdelim
\egroup
}%
\newcommand\moodle@countcorrectanswers@b[1][]{%
%\ifx&%
\let\moodle@fraction\@empty%
\setkeys{moodle}{#1}%
\moodle@countcorrectanswers@c%
%\fi
}%
\long\def\moodle@countcorrectanswers@c#1#2\moodle@answer@rdelim{%
\def\test@i{#1}%
\ifx\test@i\@star
\stepcounter{moodle@numcorrectanswers}%
\else
\ifx\moodle@fraction\@empty\relax%
\stepcounter{moodle@numincorrectanswers}%
\else
\ifdim0pt<\moodle@fraction pt\relax%
\global\addtolength{\moodle@sumofpositivefractions}{\moodle@fraction pt}%
\else
\global\addtolength{\moodle@sumofnegativefractions}{\moodle@fraction pt}%
\fi
\fi
\fi
}%
\newlength{\test@fraction}%
\newlength{\test@lower}%
\newlength{\test@upper}%
\def\moodle@fractionerror{%
\def\ds{\moodle@fraction}%
\PackageError{moodle}{the current fraction is not a valid value (here: \ds)}%
}
{\catcode`|=3\relax
\gdef\moodle@validfractionlist{0|5|10|11.11111|12.5|14.28571|16.66667|20|25|30|33.33333|40|50|60|66.66667|70|75|80|83.33333|90|100}}%
\def\moodle@isfractionnear#1{%
\setlength{\test@lower}{#1 pt}%
\addtolength{\test@lower}{-\moodle@fractiontol pt}%
\setlength{\test@upper}{#1 pt}%
\addtolength{\test@upper}{\moodle@fractiontol pt}%
\ifdim\test@upper>\test@fraction\relax
\ifdim\test@lower<\test@fraction\relax
\gdef\test@fractionmatched{#1}%
\fi
\fi
}
\def\moodle@checkfraction{%
\ifmoodle@allornothing
\ifnum\moodle@fraction>0%
\setkeys{moodle}{fraction=100}%
\fi
\ifnum\moodle@fraction<0%
\setkeys{moodle}{fraction=0}%
\fi
\else
%\def\test@i{#1}%
\setlength{\test@fraction}{\moodle@fraction pt}%
% take the absolute value
\ifdim0pt>\test@fraction\relax%
\setlength{\test@fraction}{-\moodle@fraction pt}%
\fi
% test if the fraction is an admissible value
\let\test@fractionmatched\@empty
\forlistloop{\moodle@isfractionnear}{\moodle@validfractionlist}%
\ifx\test@fractionmatched\@empty\relax
\moodle@fractionerror%
\fi
\ifdim\moodle@fraction pt<-\moodle@fractiontol pt\relax%
\setkeys{moodle}{fraction=-\test@fractionmatched}%
\else
\setkeys{moodle}{fraction=\test@fractionmatched}%
\fi
\fi
}
% TODO: Put these macros in same order as other sections'.
% SAVING ANSWERS TO MEMORY
\long\def\savemultianswer#1{%
\bgroup
\savemultianswer@int#1 \moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\savemultianswer@int[1][]{%
\let\moodle@fraction\@empty%
\setkeys{moodle}{#1}%
\ifmoodle@allornothing
\moodle@singletrue
\fi
\savemultianswer@int@int%
}%
\long\def\savemultianswer@int@int#1#2\moodle@answer@rdelim{%
\def\test@i{#1}%
\ifx\test@i\@star
\ifmoodle@single
\setkeys{moodle}{fraction=100}%
\else
\setkeys{moodle}{fraction=\moodle@autopoints}%
\fi
\def\moodle@answertext{#2}%
\else
\def\moodle@answertext{#1#2}%
\fi
\ifx\moodle@fraction\@empty\relax%
\ifmoodle@single\relax
\setkeys{moodle}{fraction=0}%
\else% multiple
\setkeys{moodle}{fraction=\moodle@autosanctions}%
\fi
\fi
\trim@spaces@in\moodle@answertext
\trim@spaces@in\moodle@answertext
\moodle@checkfraction
\addto@xml[2]{\moodle@answers@xml}{}%
\xa\converttohtmlmacro\xa\moodle@answertext@html\xa{\moodle@answertext}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@answertext@html]]>}%
\ifx\moodle@feedback\@empty\relax\else
\trim@spaces@in\moodle@feedback
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{}%
}%
% WRITING QUESTION TO XML FILE
\gdef\writemultiquestion{%
\writetomoodle{}%
\moodle@writecommondata%
\ifmoodle@allornothing\else
\moodle@writesingle%
\fi
\moodle@writeshuffle%
\moodle@writeanswernumbering%
}%
% \end{macrocode}
%
% \subsubsection{True/False Question Front-End}
%
% \begin{macrocode}
% True/False has structure
% \begin{truefalse}[options]{name}%
% This is a matching question.
% \item[feedback={feedback for student answering incorrectly "true"}] % first item is for true
% \item* this is an other way of specifying answer-specific feedback
% \end{truefalse}%
%\moodle@makefrontend{truefalse}{}% We dont use the generic frontend because truefalse has no tunable penalty
\NewEnviron{truefalse}[2][]{%
\bgroup
\setkeys{moodle}{#1,questionname={#2}}%
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\expandafter\gatheritems\xa{\BODY}%
\let\moodle@questionheader=\gatheredheader
%First, the LaTeX processing
\item \textbf{\moodle@questionname}
\ifmoodle@handout
\moodle@makelatextag@qtype{truefalse}
\else
\moodle@latex@writetags
\par
\noindent
\moodle@makelatextag@qtype{truefalse}
\moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
\fi
\par
\noindent
\moodle@questionheader
\edef\moodle@generalfeedback{\expandonce\moodle@feedback}
\moodle@truefalse@latexprocessing
%Now, writing information to XML
\@moodle@ifgeneratexml{%
\setkeys{moodle}{penalty=1}%
\xa\questiontext\xa{\moodle@questionheader}% Save the question text.
\csname writetruefalsequestion\endcsname
\bgroup
\gdef\moodle@answers@xml{}%
\setkeys{moodle}{feedback={}}%
\xa\loopthroughitemswithcommand\xa{\xa\savetruefalseanswer}%
\ifnum\c@numgathereditems=1\relax%
\setcounter{currentitemnumber}{2}%
\savetruefalseanswer{}
\fi
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
\moodle@writeanswers%
\moodle@writetags%
\writetomoodle{}%
}{}%
\egroup
}%
% LATEX PROCESSING
\def\moodle@truefalse@latexprocessing{%
% \ifnum\c@numgathereditems>2\relax%
% \PackageError{moodle}{Expecting at max two answers with truefalse type}
% \fi
\setcounter{moodle@numcorrectanswers}{0}%
\begin{itemize} \setlength\itemsep{0pt}\setlength\parskip{0pt}%
\loopthroughitemswithcommand{\moodle@print@truefalse@answer}%
\ifnum\c@currentitemnumber=2%
\item \textbf{False}%
\fi
\end{itemize}
\ifmoodle@handout\else
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
\fi
\ifnum\c@moodle@numcorrectanswers=0\relax%
\PackageError{moodle}{No answer is explicitly marked as correct (*). Be sure one answer leads to points.}%
\fi
\ifnum\c@moodle@numcorrectanswers>1\relax%
\PackageError{moodle}{Two answers are explicitly marked as correct (*). Be sure only one answer leads to points.}%
\fi
}
\def\moodle@print@truefalse@answer#1{% here # is all what comes after "\item", that is "[options]* text"
\let\moodle@feedback=\@empty
\moodle@print@truefalse@answer@int#1\@rdelim % add an end delimiter:
}%
\newcommand\moodle@print@truefalse@answer@int[1][]{% with the optional argument, catch options and set them as keys
\setkeys{moodle}{#1}%
\moodle@print@truefalse@answer@int@int% applies to the rest: "* text\@rdelim"
}%
\def\moodle@print@truefalse@answer@int@int#1\@rdelim{% this is just to treat appart the case where nothing follows
\def\test@i{#1}
\trim@spaces@in\test@i
\ifx\test@i\@empty\relax
\moodle@print@truefalse@answer@int@int@empty
\else
\moodle@print@truefalse@answer@int@int@int#1\@rdelim
\fi
}%
\def\moodle@print@truefalse@answer@int@int@empty{%
\ifnum\c@currentitemnumber=1%
\def\moodle@answertext{True}%
\fi
\ifnum\c@currentitemnumber=2%
\def\moodle@answertext{False}%
\fi
\item \textbf{\moodle@answertext}%
\ifmoodle@handout\else
\ifx\moodle@feedback\@empty\relax\else
~\hfill \emph{$\rightarrow$ \moodle@feedback}%
\fi
\fi
}%
\def\moodle@print@truefalse@answer@int@int@int#1#2\@rdelim{%
\ifnum\c@currentitemnumber=1%
\def\moodle@answertext{True}%
\fi
\ifnum\c@currentitemnumber=2%
\def\moodle@answertext{False}%
\fi
\item \textbf{\moodle@answertext}%
\ifnum\c@currentitemnumber<3%
\def\test@i{#1}%
%\trim@spaces@in\test@i
\ifx\test@i\@star
\ifmoodle@handout\else
~$\checkmark$%
\fi
\stepcounter{moodle@numcorrectanswers}%
\else
~%
\fi
\ifmoodle@handout\else
\ifx\moodle@feedback\@empty\relax
\def\test@ii{#2}%
\trim@spaces@in\test@ii
\ifx\test@ii\@empty\relax\else
\ifx\test@i\@star%
\hfill \emph{$\rightarrow$ #2}%
\else%
\hfill \emph{$\rightarrow$ #1#2}%
\fi
\fi
\else
\hfill \emph{$\rightarrow$ \moodle@feedback}%
\fi
\fi
\fi
}%
% SAVING ANSWERS TO MEMORY
\def\savetruefalseanswer#1{%
\bgroup
\savetruefalseanswer@int#1\moodle@answer@rdelim
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\savetruefalseanswer@int[1][]{%
\setkeys{moodle}{#1}%
\savetruefalseanswer@int@int%
}%
\def\savetruefalseanswer@int@int#1\moodle@answer@rdelim{%
\def\test@i{#1}
\trim@spaces@in\test@i
\ifx\test@i\@empty\relax
\savetruefalseanswer@int@int@empty
\else
\savetruefalseanswer@int@int@int#1\moodle@answer@rdelim
\fi
}%
\def\savetruefalseanswer@int@int@empty{%
\setkeys{moodle}{fraction=0}%
\ifnum\c@currentitemnumber=1%
\def\moodle@answertext{true}%
\fi
\ifnum\c@currentitemnumber=2%
\def\moodle@answertext{false}%
\fi
\ifnum\c@currentitemnumber<3%
\addto@xml[2]{\moodle@answers@xml}{}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@answertext}%
\ifx\moodle@feedback\@empty\relax\else
\trim@spaces@in\moodle@feedback
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{}%
\fi
}%
\def\savetruefalseanswer@int@int@int#1#2\moodle@answer@rdelim{%
\def\test@i{#1}%
\ifx\test@i\@star
\setkeys{moodle}{fraction=100}%
\else
\setkeys{moodle}{fraction=0}%
\fi
\ifnum\c@currentitemnumber=1%
\def\moodle@answertext{true}%
\fi
\ifnum\c@currentitemnumber=2%
\def\moodle@answertext{false}%
\fi
\ifnum\c@currentitemnumber<3%
\addto@xml[2]{\moodle@answers@xml}{}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@answertext}%
\ifx\moodle@feedback\@empty\relax
\def\test@ii{#2}
\ifx\test@ii\@empty\relax\else
\ifx\test@i\@star
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{#2}%
\else%
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{#1#2}%
\fi%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
\fi
\else
\trim@spaces@in\moodle@feedback
\xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
\addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
\fi
\addto@xml[2]{\moodle@answers@xml}{}%
\fi
}%
% WRITING QUESTION TO XML FILE
\gdef\writetruefalsequestion{%
\writetomoodle{}%
\moodle@writecommondata%
}%
% \end{macrocode}
%
% \subsubsection{Matching Question Front-End}
%
% \begin{macrocode}
%\let\answer=\hfill
\moodle@makefrontend{matching}{\moodle@makelatextag@matching}%
% LATEX PROCESSING
\def\moodle@makelatextag@matching{%
\ifmoodle@handout\else
\ifmoodle@draganddrop
\moodle@makelatextagbox{Drag and drop}\relax%
\fi
\ifmoodle@shuffle
\moodle@makelatextagbox{Shuffle}\relax%
\fi
\fi
}
\def\moodle@matching@latexprocessing{%
\bgroup
%\let\answer=\hfill
\par%\noindent
\ifmoodle@handout
\NewList{questionlist}
\NewList{answerlist}
\fi
\def\matching@table@text{}%
% \ifnum\c@numgathereditems>2\relax%
% \PackageError{moodle}{Expecting at max two answers with truefalse type}
% \fi
\setcounter{moodle@numcorrectanswers}{0}% Here this counter is for "questions" (items on the left column)
\loopthroughitemswithcommand{\moodle@print@matching@answer}%
\ifnum\c@numgathereditems<3%
\PackageWarning{moodle}{Moodle expects at least three "answers" with matching type}%
\fi
\ifnum\c@moodle@numcorrectanswers<2%
\PackageWarning{moodle}{Moodle expects at least two "questions" with the matching type}%
\fi
\ifmoodle@handout
\ifmoodle@shuffle
\let\moodle@matching@loop=\ForEachRandomItem
\else
\let\moodle@matching@loop=\ForEachFirstItem
\fi
\moodle@matching@loop{questionlist}{Question}{
\xdef\test@i{\Question}%
\ExtractRandomItem{answerlist}{Answer}%
\ifx\test@i\@empty
\xdef\matching@table@text{\expandonce\matching@table@text & & $\bullet$~\expandonce\Answer\\}%
\else
\xdef\matching@table@text{\expandonce\matching@table@text\expandonce\Question~$\bullet$ & & $\bullet$~\expandonce\Answer\\}%
\fi
}%
\fi
\begin{tabular}{@{}>{\raggedleft}p{.45\linewidth}p{.1\linewidth}p{.45\linewidth}@{}}%
\matching@table@text
\end{tabular}%
\par
\ifmoodle@handout\else
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
\fi
\egroup
}
\long\def\moodle@print@matching@answer#1{%
\moodle@print@matching@answer@int#1 \@rdelim
}%
\newcommand\moodle@print@matching@answer@int[1][]{%
\moodle@print@matching@answer@int@int
}%
\long\def\moodle@print@matching@answer@int@int#1\answer#2\@rdelim{%
%\typeout{\string#1 \answer \string#2}%
\def\test@i{#1}%
\trim@spaces@in\test@i
\ifmoodle@handout
\ifx\test@i\@empty
\InsertLastItem{questionlist}{\@empty}%
\else
\InsertLastItem{questionlist}{#1}%
\fi
\InsertLastItem{answerlist}{#2}%
\else
\ifx\test@i\@empty
\g@addto@macro\matching@table@text{&&$\bullet$~#2\\}%
\else
\stepcounter{moodle@numcorrectanswers}%
\xa\g@addto@macro\xa\matching@table@text\xa{\test@i~$\bullet$&\leavevmode\cleaders\hb@xt@.44em{\hss$\cdot$\hss}\hfill\kern\z@&$\bullet$~#2\\}%
\fi
\fi
}%
% SAVING ANSWERS TO MEMORY
\long\def\savematchinganswer#1{%
\bgroup
\savematchinganswer@int#1 \moodle@answer@rdelim%
\passvalueaftergroup{\moodle@answers@xml}%
\egroup
}%
\newcommand\savematchinganswer@int[1][]{%
\setkeys{moodle}{#1}%
\savematchinganswer@int@int%\space
}%
\long\def\savematchinganswer@int@int#1\answer#2\moodle@answer@rdelim{%
%\typeout{\string#1 \answer \string#2}%
% Note that #1 may simply be \relax.
\def\moodle@subquestiontext{#1}%
\def\moodle@subanswertext{#2}%
\trim@spaces@in\moodle@subquestiontext
\xa\converttohtmlmacro\xa\moodle@subquestiontext@htmlized\xa{\moodle@subquestiontext}%
\trim@spaces@in\moodle@subanswertext
\ifmoodle@draganddrop
\xa\converttohtmlmacro\xa\moodle@subanswertext@htmlized\xa{\moodle@subanswertext}%
\fi
\addto@xml[2]{\moodle@answers@xml}{}%
\ifx\moodle@subquestiontext\@empty
\addto@xml[4]{\moodle@answers@xml}{ }%
\else
\addto@xml[4]{\moodle@answers@xml}{ \moodle@subquestiontext@htmlized]]>}%
\fi
\ifmoodle@draganddrop
% \show\moodle@subanswertext@htmlized
\addto@xml[4]{\moodle@answers@xml}{ \moodle@subanswertext@htmlized]]>}%
\else
% \show\moodle@subanswertext
\addto@xml[4]{\moodle@answers@xml}{ \moodle@subanswertext}%
\fi
% \ifx\moodle@feedback\@empty\relax\else
% \trim@spaces@in\moodle@feedback
% \xa\converttohtmlmacro\xa\moodle@feedback@html\xa{\moodle@feedback}%
% \addto@xml[4]{\moodle@answers@xml}{ \moodle@feedback@html]]>}%
% \fi
\addto@xml[2]{\moodle@answers@xml}{}%
}%
% WRITING QUESTION TO XML FILE
\gdef\writematchingquestion{%
\ifmoodle@draganddrop
\writetomoodle{}%
\else
\writetomoodle{}%
\fi
\moodle@writecommondata%
% \moodle@writesingle% %irrelevant for the matching type
\moodle@writeshuffle%
% \moodle@writeanswernumbering% %irrelevant for the matching type
}%
% \end{macrocode}
%
% \subsection{Cloze Questions}
% Because cloze questions are so complicated, they get their own section of code.
% The cloze strategy is as follows.
%
% All subquestions show up as part of the question body text.
% For each type of subquestion, we have a cloze-version environment
% that actually has 2 versions, depending on whether we are doing LaTeX or XML processing.
% So the main environment is quite typical:
% \begin{enumerate}
% \item Process the body as LaTeX.
% During this run, a |\begin{multi}| etc.~will be processed for display onscreen.
% \item Then save the body as the questiontext for XML.
% During this run, a |\begin{multi}| etc.~will be parsed and turned into
% cloze code as part of the XML questiontext.
% \end{enumerate}
% \begin{macrocode}
% LATEX PROCESSING
% SAVING ANSWERS TO MEMORY
\newif\ifmoodle@clozemode
\moodle@clozemodefalse
\NewEnviron{cloze}[2][]{%
\bgroup
\setkeys{moodle}{default grade=1}%
\setkeys{moodle}{#1,questionname={#2}}%
% A cloze question won't have any \item's in it, so we just use \BODY.
\moodle@enableclozeenvironments
%First, the LaTeX processing.
\item \textbf{\moodle@questionname}
\ifmoodle@handout
\moodle@makelatextag@qtype{cloze}
\else
\moodle@latex@writetags
\par
\noindent
\moodle@makelatextag@qtype{cloze}
\moodle@makelatextag@value{penalty}{penalty}
\fi
\par
\noindent
\BODY
\edef\moodle@generalfeedback{\expandonce\moodle@feedback}
%\csname moodle@cloze@latexprocessing\endcsname
\ifmoodle@handout\else
\ifx\moodle@generalfeedback\@empty\relax\else%
\fbox{\parbox{\linewidth}{\emph{\moodle@generalfeedback}}}%
\fi
\fi
%Now, writing information to memory.
\@moodle@ifgeneratexml{%
\xa\questiontext\xa{\BODY}% Save the question text as HTML.
\writeclozequestion
}{}%
\egroup%
}
\def\moodle@enableclozeenvironments{%
\let\multi=\clozemulti
\let\endmulti=\endclozemulti
\let\numerical=\clozenumerical
\let\endnumerical=\endclozenumerical
\let\shortanswer=\clozeshortanswer
\let\endshortanswer=\endclozeshortanswer
}
% WRITING QUESTION TO XML FILE
\gdef\writeclozequestion{%
\writetomoodle{}%
\moodle@writequestionname%
\moodle@writequestiontext%
\moodle@writegeneralfeedback%
\moodle@writepenalty%
\moodle@writehidden%
\moodle@writetags%
\writetomoodle{}%
}%
% \end{macrocode}
%
% \subsubsection{Cloze Multiple Choice Questions}
%
% \begin{macrocode}
\NewEnviron{clozemulti}[1][]{%
\bgroup
\setkeys{moodle}{default grade=1}%
\setkeys{moodle}{#1}%
\expandafter\gatheritems\xa{\BODY}%
\let\moodle@questionheader=\gatheredheader
\ifhtmlizer@active
%HTML version
\def\moodle@clozemulti@output{}%
\xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\moodle@questionheader}%
\def\clozemulti@coding{}%
\edef\clozemulti@coding{\csname moodle@default grade\endcsname:}%
\ifmoodle@multiple
\PackageWarning{moodle}{Cloze Multiresponse only supported by Moodle 3.5+}
\g@addto@macro{\clozemulti@coding}{MULTIRESPONSE}%
\else
\g@addto@macro{\clozemulti@coding}{MULTICHOICE}%
\fi
\ifcase\moodle@multi@mode\relax
% Case 0: dropdown box style
\ifmoodle@shuffle
\g@addto@macro{\clozemulti@coding}{_}%
\fi
\or
% Case 1: vertical style
\ifmoodle@multiple
\PackageError{moodle}{Vertical mode (dropdown box) incompatible with multiresponse.}
\else
\g@addto@macro{\clozemulti@coding}{_V}%
\fi
\else
% Case 2: horizontal radio buttons
\g@addto@macro{\clozemulti@coding}{_H}%
\fi
\ifmoodle@shuffle
\PackageWarning{moodle}{Cloze Multi Shuffling only supported by Moodle 3.0+}
\g@addto@macro{\clozemulti@coding}{S:}%
\else
\g@addto@macro{\clozemulti@coding}{:}%
\fi
\bgroup
\setkeys{moodle}{feedback={}}%
\loopthroughitemswithcommand{\saveclozemultichoiceanswer}%
\egroup
%\xa\g@addto@macro\xa\clozemulti@coding\xa{\clozerbrace}%
\xa\g@addto@macro\xa\moodle@clozemulti@output\xa{\xa\clozelbrace\clozemulti@coding\clozerbrace}%
%\show\moodle@clozemulti@output
\xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozemulti@output}%
\def\endclozemulti@code{\htmlize@patchendenvironment}%
\else
%LaTeX version
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\moodle@questionheader% %Any introductory text just continues to be typeset.
\par
\noindent
\moodle@makelatextag@qtype{multi}
\ifmoodle@handout\else
\moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
\moodle@makelatextag@multi
\fi
\def\cloze@multichoice@table@text{}%
\ifmoodle@handout\NewList{answerlist}\fi
%\let\moodle@feedback=\@empty
\loopthroughitemswithcommand{\moodle@print@clozemultichoice@answer}%
\ifmoodle@handout
\ifmoodle@shuffle
\let\moodle@clozemult@loop=\ForEachRandomItem
\else
\let\moodle@clozemult@loop=\ForEachFirstItem
\fi
\moodle@clozemult@loop{answerlist}{Answer}{
\xdef\cloze@multichoice@table@text{\expandonce\cloze@multichoice@table@text\expandonce\Answer}%
}%
\fi
\ifcase\moodle@multi@mode\relax
%Case 0: dropdown box style
\par\noindent
\ifmoodle@handout
\begin{tabular}[t]{|p{.45\linewidth}|}
\else
\begin{tabular}[t]{|p{.45\linewidth}|p{.45\linewidth}|}
% answer & feedback \\\hline\hline
\fi
\firsthline% (\firsthline is from the array package.)
\cloze@multichoice@table@text%
\end{tabular}%
\par%
\or
%Case 1: vertical style
\par\noindent
\begin{itemize}\setlength\itemsep{0pt}\setlength\parskip{0pt}%
\cloze@multichoice@table@text%
\end{itemize}%
\par%
\else
%Case 2: horizontal radio buttons
\par{\cloze@multichoice@table@text}\par%
\fi
\def\endclozemulti@code{\relax}%
\fi
\passvalueaftergroup\endclozemulti@code%
\passvalueaftergroup\htmlize@afteraction@hook%
\egroup%
}[\endclozemulti@code]%
\long\def\moodle@print@clozemultichoice@answer#1{%
\let\moodle@feedback=\@empty
\moodle@print@clozemultichoice@answer@int#1 \@rdelim%
}%
\newcommand\moodle@print@clozemultichoice@answer@int[1][]{%
\setkeys{moodle}{fraction=0,#1}%
\moodle@print@clozemultichoice@answer@int@int%
}%
\long\def\moodle@print@clozemultichoice@answer@int@int#1#2\@rdelim{%
\def\moodle@answertext{}%
% Case 0: "(answer) \\ \hline"
% Case 1: "\item (answer)"
% Case 2: "$\bullet~$(answer)\hfill"
\ifcase\moodle@multi@mode\relax
\relax% Case 0
\or
\g@addto@macro\moodle@answertext{\item}% Case 1
\else
\g@addto@macro\moodle@answertext{$\bullet~$}% Case 2
\fi
\def\test@i{#1}%
\ifx\test@i\@star
\setkeys{moodle}{fraction=100}%
\g@addto@macro\moodle@answertext{#2}%
\else
\g@addto@macro\moodle@answertext{#1#2}%
\fi
\trim@spaces@in\moodle@answertext
\trim@spaces@in\moodle@answertext
\ifmoodle@handout\else
\ifx\moodle@fraction\@hundred
\g@addto@macro\moodle@answertext{$~\checkmark$}%
\else
\moodle@checkfraction
\ifdim0pt=\moodle@fraction pt\relax\else
\xdef\moodle@answertext{\expandonce\moodle@answertext$~(\moodle@fraction\%)$}%
\fi
\fi
\fi
\ifcase\moodle@multi@mode\relax
% Case 0
\ifmoodle@handout\else
\xdef\moodle@answertext{\expandonce\moodle@answertext &\expandonce\emph{\expandonce\moodle@feedback}}%
\fi
\g@addto@macro\moodle@answertext{\\\hline}
\or % Case 1
\ifmoodle@handout\else
\ifx\moodle@feedback\@empty\relax\else
\xdef\moodle@answertext{\expandonce\moodle@answertext \hfill \expandonce\emph{$\rightarrow$ \expandonce\moodle@feedback}}%
\fi
\fi
\else % otherwise
\ifmoodle@handout\else
\ifx\moodle@feedback\@empty\relax\else
\xdef\moodle@answertext{\expandonce\moodle@answertext\,\expandonce\emph{$\rightarrow$ \expandonce\moodle@feedback}}%
\fi
\fi
\g@addto@macro\moodle@answertext{\hfill}% Case 2
\fi
\ifmoodle@handout
\def\temp{\InsertLastItem{answerlist}}%
\xa\temp\xa{\moodle@answertext}%
\else
\xdef\cloze@multichoice@table@text{\expandonce\cloze@multichoice@table@text\expandonce\moodle@answertext}%
\fi
}%
\long\def\saveclozemultichoiceanswer#1{%
\bgroup
\saveclozemultichoiceanswer@int#1 \moodle@answer@rdelim
\egroup
}%
\newcommand\saveclozemultichoiceanswer@int[1][]{%
\setkeys{moodle}{fraction=0,#1}%
\saveclozemultichoiceanswer@int@int%
}%
\long\def\saveclozemultichoiceanswer@int@int#1#2\moodle@answer@rdelim{%
\def\test@i{#1}%
\ifgatherbeginningofloop\else
\xa\gdef\xa\clozemulti@coding\xa{\clozemulti@coding\clozetilde}% separator between answers
\fi
\ifx\test@i\@star
\setkeys{moodle}{fraction=100}%
\def\moodle@answertext{#2}%
\else
\def\moodle@answertext{#1#2}%
\fi
\trim@spaces@in\moodle@answertext
\trim@spaces@in\moodle@answertext
\ifx\moodle@fraction\@hundred
\g@addto@macro\clozemulti@coding{=}%
\else
\moodle@checkfraction
\ifdim0pt=\moodle@fraction pt\relax\else
\xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherpercent\moodle@fraction\otherpercent}%
\fi
\fi
\xdef\clozemulti@coding{\expandonce\clozemulti@coding\expandonce\moodle@answertext}%
\ifx\moodle@feedback\@empty\else
\xdef\clozemulti@coding{\expandonce\clozemulti@coding\otherbackslash\otherhash\expandonce\moodle@feedback}%
\fi
}%
% \end{macrocode}
%
% \subsubsection{Cloze Numerical Questions}
%
% \begin{macrocode}
\NewEnviron{clozenumerical}[1][]{%
\bgroup
\expandafter\gatheritems\expandafter{\BODY}%
\let\moodle@questionheader=\gatheredheader
\setkeys{moodle}{default grade=1}%
\setkeys{moodle}{#1}%
\ifhtmlizer@active
%HTML version
\def\moodle@clozenumerical@output{}%
\xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\moodle@questionheader}%
\def\clozenumerical@coding{}%
\edef\clozenumerical@coding{\csname moodle@default grade\endcsname:NUMERICAL:}%
\bgroup
\setkeys{moodle}{feedback={}}%
\loopthroughitemswithcommand{\saveclozenumericalanswer}%
\egroup
%\xa\g@addto@macro\xa\clozenumerical@coding\xa{\otherrbrace}%
\xa\g@addto@macro\xa\moodle@clozenumerical@output\xa{\xa\clozelbrace\clozenumerical@coding\clozerbrace}%
\xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozenumerical@output}%
\def\endclozenumerical@code{\htmlize@patchendenvironment}%
\else
%LaTeX version
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\moodle@questionheader% %Any introductory text just continues to be typeset.
\par
\noindent
\moodle@makelatextag@qtype{numerical}
\ifmoodle@handout\else
\moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
\moodle@makelatextag@numerical
\par
\noindent
\def\cloze@numerical@table@text{}%
\loopthroughitemswithcommand{\moodle@print@clozenumerical@answer}%
\begin{tabular}[t]{|p{.45\linewidth}|p{.45\linewidth}|}
\firsthline% (\firsthline is from the array package.)
% answer & feedback \\\hline\hline
\cloze@numerical@table@text%
\end{tabular}%
\par%
\fi
\def\endclozenumerical@code{\relax}%
\fi
\passvalueaftergroup\endclozenumerical@code%
\passvalueaftergroup\htmlize@afteraction@hook%
\egroup
}[\endclozenumerical@code]%
\def\moodle@print@clozenumerical@answer#1{%
\let\moodle@feedback=\@empty
\bgroup
\moodle@print@clozenumerical@answer@int#1\@rdelim
\egroup
}%
\newcommand\moodle@print@clozenumerical@answer@int[1][]{%
\setkeys{moodle}{#1}%
\moodle@print@clozenumerical@answer@int@int%
}%
\def\moodle@print@clozenumerical@answer@int@int#1\@rdelim{%
\ifx\moodle@fraction\@hundred
\def\moodle@clozenumericalprint@fraction{$~\checkmark$}%
\else
\moodle@checkfraction
\edef\moodle@clozenumericalprint@fraction{$(~\moodle@fraction\%)$}%
\fi
\ifnum\z@=\moodle@tolerance
\def\moodle@clozenumericalprint@tolerance{}%
\else
\edef\moodle@clozenumericalprint@tolerance{$\,\pm\,$\moodle@printnum{\moodle@tolerance}}%
\fi
\xdef\test@i{\trim@spaces{#1}}%
\ifx\test@i\@star
\xdef\moodle@clozenumericalprint@line{#1~\moodle@clozenumericalprint@fraction & \expandonce\emph{\expandonce\moodle@feedback}}%
\else
\xdef\moodle@clozenumericalprint@line{\moodle@printnum{#1}\moodle@clozenumericalprint@tolerance~\moodle@clozenumericalprint@fraction & \expandonce\emph{\expandonce\moodle@feedback}}%
\fi
\xa\g@addto@macro\xa\cloze@numerical@table@text\xa{\moodle@clozenumericalprint@line \\\hline}%
}%
\def\saveclozenumericalanswer#1{%
\bgroup
\saveclozenumericalanswer@int#1\moodle@answer@rdelim
\egroup
}%
\newcommand\saveclozenumericalanswer@int[1][]{%
\setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
\saveclozenumericalanswer@int@int%
}%
\def\saveclozenumericalanswer@int@int#1\moodle@answer@rdelim{%
\ifgatherbeginningofloop\else
\xa\gdef\xa\clozenumerical@coding\xa{\clozenumerical@coding\clozetilde}% separator between answers
\fi
\def\moodle@answertext{#1}%
\trim@spaces@in\moodle@answertext
\ifx\moodle@fraction\@hundred
\g@addto@macro\clozenumerical@coding{=}%
\else
\moodle@checkfraction
\ifdim0pt=\moodle@fraction pt\relax\else
\xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherpercent\moodle@fraction\otherpercent}%
\fi
\fi
\ifx\moodle@answertext\@star
\xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\moodle@answertext}%
\else
\xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\moodle@answertext:\moodle@tolerance}%
\fi
\ifx\moodle@feedback\@empty\else
%\trim@spaces@in\moodle@feedback
\xdef\clozenumerical@coding{\expandonce\clozenumerical@coding\otherbackslash\otherhash\expandonce\moodle@feedback}%
\fi
}%
% \end{macrocode}
%
% \subsubsection{Cloze Short Answer Questions}
%
% \begin{macrocode}
\NewEnviron{clozeshortanswer}[1][]{%
\bgroup
\expandafter\gatheritems\expandafter{\BODY}%
\let\moodle@questionheader=\gatheredheader
\setkeys{moodle}{default grade=1}%
\setkeys{moodle}{#1}%
%Because nesting conditionals built by \csname doesn't work well,
%we'll test '\ifmoodle@case sensitive' now and save the result in \count0.
\csname ifmoodle@case sensitive\endcsname
\count0=1\relax
\else
\count0=0\relax
\fi
\ifhtmlizer@active
%HTML version
\def\moodle@clozeshortanswer@output{}%
\xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\moodle@questionheader}%
\def\clozeshortanswer@coding{}%
\ifnum\count0=1\relax
\edef\clozeshortanswer@coding{\csname moodle@default grade\endcsname:SHORTANSWER_C:}%
\else
\edef\clozeshortanswer@coding{\csname moodle@default grade\endcsname:SHORTANSWER:}%
\fi
\bgroup
\setkeys{moodle}{feedback={}}%
\loopthroughitemswithcommand{\saveclozeshortansweranswer}%
\egroup
%\xa\g@addto@macro\xa\clozeshortanswer@coding\xa{\otherrbrace}%
\xa\g@addto@macro\xa\moodle@clozeshortanswer@output\xa{\xa\clozelbrace\clozeshortanswer@coding\clozerbrace}%
\xa\gdef\xa\htmlize@afteraction@hook\xa{\moodle@clozeshortanswer@output}%
\def\endclozeshortanswer@code{\htmlize@patchendenvironment}%
\else
%LaTeX version
\global\advance\moodle@totalmarks by \csname moodle@default grade\endcsname pt
\moodle@questionheader% %Any introductory text just continues to be typeset.
\par
\noindent
\moodle@makelatextag@qtype{shortanswer}
\ifmoodle@handout\else
\moodle@makelatextag@value{default grade}{\moodle@marks{\csname moodle@default grade\endcsname}}
\moodle@makelatextag@shortanswer
\par
\noindent
\def\cloze@shortanswer@table@text{}%
\loopthroughitemswithcommand{\moodle@print@clozeshortanswer@answer}%
\begin{tabular}[t]{|p{.45\linewidth}|p{.45\linewidth}|}
\firsthline% (\firsthline is from the array package.)
% answer & feedback \\\hline\hline
\cloze@shortanswer@table@text%
\end{tabular}%
\par%
\fi
\def\endclozeshortanswer@code{\relax}%
\fi
\passvalueaftergroup\endclozeshortanswer@code%
\passvalueaftergroup\htmlize@afteraction@hook%
\egroup
}[\endclozeshortanswer@code]%
\def\moodle@print@clozeshortanswer@answer#1{%
\let\moodle@feedback=\@empty
\bgroup
\moodle@print@clozeshortanswer@answer@int#1\@rdelim
\egroup
}%
\newcommand\moodle@print@clozeshortanswer@answer@int[1][]{%
\setkeys{moodle}{#1}%
\moodle@print@clozeshortanswer@answer@int@int%
}%
\def\moodle@print@clozeshortanswer@answer@int@int#1\@rdelim{%
\ifx\moodle@fraction\@hundred
\def\moodle@clozeshortanswerprint@fraction{$~\checkmark$}%
\else
\moodle@checkfraction
\edef\moodle@clozeshortanswerprint@fraction{$~(\moodle@fraction\%)$}%
\fi
\xdef\moodle@clozeshortanswerprint@line{#1~\moodle@clozeshortanswerprint@fraction & \expandonce\emph{\expandonce\moodle@feedback}}%
\xa\g@addto@macro\xa\cloze@shortanswer@table@text\xa{\moodle@clozeshortanswerprint@line \\\hline}%
}%
\def\saveclozeshortansweranswer#1{%
\bgroup
\saveclozeshortansweranswer@int#1\moodle@answer@rdelim
\egroup
}%
\newcommand\saveclozeshortansweranswer@int[1][]{%
\setkeys{moodle}{fraction=100,#1}% %%%%%% DEFAULT VALUE IS 100%
\saveclozeshortansweranswer@int@int%
}%
\def\saveclozeshortansweranswer@int@int#1\moodle@answer@rdelim{%
\ifgatherbeginningofloop\else
\xa\gdef\xa\clozeshortanswer@coding\xa{\clozeshortanswer@coding\clozetilde}% separator between answers
\fi
\def\moodle@answertext{#1}%
\trim@spaces@in\moodle@answertext
\ifx\moodle@fraction\@hundred
\g@addto@macro\clozeshortanswer@coding{=}%
\else
\moodle@checkfraction
\ifdim0pt=\moodle@fraction pt\relax\else
\xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherpercent\moodle@fraction\otherpercent}%
\fi
\fi
\xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\moodle@answertext}%
\ifx\moodle@feedback\@empty\else
\xdef\clozeshortanswer@coding{\expandonce\clozeshortanswer@coding\otherbackslash\otherhash\expandonce\moodle@feedback}%
\fi
}%
% \end{macrocode}
%
% \section{Converting \LaTeX\ to HTML}
% A lot of work must now be done to convert the \LaTeX\ code
% of a question or answer into HTML code with embedded \TeX\ for math.
%
% \subsection{Catcode Setup}
% First, we create versions of the special characters with catcode 12, ``other.''
% \begin{macrocode}
{\catcode`\#=12\gdef\otherhash{#}%
\catcode`\~=12\gdef\othertilde{~}%
\catcode`\&=12\gdef\otherampersand{&}%
\catcode`\^=12\gdef\othercaret{^}%
\catcode`\$=12\gdef\otherdollar{$}%
\catcode`\%=12\gdef\otherpercent{%}
\catcode`\%=12\gdef\otherlbracket{[}
\catcode`\%=12\gdef\otherrbracket{]}}%
{\catcode`\ =12\gdef\otherspace{ }}%
{\ttfamily\catcode`\|=0\catcode`\\=12\relax|gdef|otherbackslash{\}}%
{\catcode`\[=1\catcode`\]=2\catcode`\{=12\catcode`\}=12%
\gdef\otherlbrace[{]\gdef\otherrbrace[}]\gdef\clozelbrace[{]\gdef\clozerbrace[}]]%
\edef\@otherlbrace{\otherlbrace}%
\edef\@otherrbrace{\otherrbrace}%
\edef\@otherlbracket{\otherlbracket}%
\edef\@otherrbracket{\otherrbracket}%
\edef\@clozelbrace{\clozelbrace}%
\edef\@clozerbrace{\clozerbrace}%
\edef\@otherdollar{\otherdollar}%
\edef\@otherbackslash{\otherbackslash}%
\edef\@othertilde{\othertilde}%
% \end{macrocode}
%
% Next, we define commands to change catcodes to a suitable verbatim mode
% for transcription.
%
% \begin{macrocode}
{ \catcode`\[=1\relax
\catcode`\]=2\relax
\catcode`\|=0\relax
|gdef|verbcatcodesweirdest[
|catcode`\{=12|relax
|catcode`\}=12|relax
|catcode`\\=12|relax
]%
}%
\def\verbcatcodes{%
\catcode`\$=12\relax
\catcode`\&=12\relax
\catcode`\#=12\relax
\catcode`\^=12\relax
\catcode`\_=12\relax
\catcode`\~=12\relax
\makeatletter
\catcode`\%=12\relax
\catcode`\ =12\relax\catcode\newlinechar=12\verbcatcodesweirdest}%
\def\normalcatcodes{%
\catcode`\\=0\relax
\catcode`\{=1\relax
\catcode`\}=2\relax
\catcode`\$=3\relax
\catcode`\&=4\relax
\catcode\endlinechar=5\relax
\catcode`\#=6\relax
\catcode`\^=7\relax
\catcode`\_=8\relax
\catcode`\ =10\relax
\makeatletter% We will be detokenizing and retokenizing internal control sequences, so we need this.
\catcode`\~=13\relax
\catcode`\%=14\relax}%
\def\retokenizingcatcodes{%
%For rescanning previously scanned text, all true comments will already be gone,
%but % signs may have been inserted by Cloze questions, so we want to treat them as 'other.'
%
% TODO: #'s are more worrisome.
\normalcatcodes
\catcode`\%=12\relax
}
% \end{macrocode}
%
% \subsection{Detokenization and Retokenization}
%
% We will be processing a \TeX\ token list.
% Based on its content, sometimes we will want it to be detokenized to
% individual characters, but other times we want it retokenized so that
% \TeX's own parsing mechanism can gather up the parameters of macros.
% We use the e\TeX\ primitive command |\scantokens| to do this.
%
% The following code (catcodes, groupings and all) defines a |\scantokens@to@macro| macro.
% That will assemble and disassemble strings of tokens
% using any changing schemes of catcodes we desire.
%
% We define |^^A| to be |\gdef\stm@saved|, while |^^B| and |^^C| are substitutes for |{| and |}|, respectively.
% This permits us to define |\scantokens@to@macro| in a peculiar catcode regime.
% \begin{macrocode}
\begingroup
\catcode`\^^A=13\gdef^^A{\gdef\stm@saved}%
\catcode`\^^B=1\catcode`\^^C=2\relax
\long\gdef\scantokens@to@macro#1#2#3{%
% #1 = control sequence to be defined
% #2 = command to change catcodes, e.g. \verbcatcodes,
% and define any command sequences
% #3 = text to be retokenized and saved into #1.
\bgroup
\def\texttorescan{#3}%
\catcode`\^^A=13\catcode`\^^B=1\catcode`\^^C=2\relax
\xa\def\xa\arg\xa{\xa^^A\xa^^B\texttorescan^^C}%
#2%
\catcode\endlinechar=9\relax%
%\scantokens always sees an end-of-line character at its end and converts it to a space.
%The catcode change sets \scantokens to ignore end-of-line chars.
%In practice, we're always calling \scantokens on previously scanned text anyway,
%so we won't miss any real end-of-line chars, since they were already converted to spaces.
\xa\scantokens\xa{\arg}%
\egroup
\xa\def\xa#1\xa{\stm@saved}%
}%
\endgroup%
\long\def\ultradetokenize@to@macro#1#2{%
\scantokens@to@macro#1{\verbcatcodes}{#2}%
}%
\def\retokenizenormal@to@macro#1#2{%
\scantokens@to@macro#1{\retokenizingcatcodes}{#2}%
}%
% \end{macrocode}
%
% \subsection{Level-Tracking}
%
% \subsubsection{TeX groups}
% While parsing, we'll need to keep track of how deeply nested in \TeX\ groups we are.
% \begin{macrocode}
\newcount\grouplevel
% \end{macrocode}
%
% \subsubsection{Math mode}
% While parsing, we'll need to keep track of whether
% we are in math mode (and how many levels deep the math mode might be nested).
% \begin{macrocode}
\newcount\moodle@mathmodedepth
\moodle@mathmodedepth=0\relax
\def\moodle@ifmathmode#1#2{%
\ifnum\moodle@mathmodedepth>0\relax
#1%
\else
#2%
\fi
}%
% \end{macrocode}
%
% \subsubsection{Nested Lists}
% While parsing, we'll need to keep track levels of nested list.
% \begin{macrocode}
\newcount\moodle@listdepth
\moodle@listdepth=0\relax
% \end{macrocode}
%
% \subsection{Separation}
%
% This code separates a string of tokens into two parts.
% Its parameters, |#1#2|, consist of tokenized text,
% plus one terminal |\@htmlize@stop|.
% We are trying to break up the text into its first group and the remainder.
% This |\@htmlize@stop| is needed in case |#2| has the form ``|{...}|'',
% since we don't want \TeX\ to strip the braces off.
% Thus |\@htmlize@remainder| will definitely end in ``|\@htmlize@stop|''.
% \begin{macrocode}
\long\def\htmlize@grabblock#1#2\htmlize@rdelim@ii{%
\long\def\htmlize@blockinbraces{#1}%
\long\def\htmlize@remainder{#2}%
}%
% \end{macrocode}
%
% The next line defines the macro |\@htmlize@stop@detokenized| to contain
% the string of tokens |\@htmlize@stop|, all of category code 12 (other) or 10 (letter).
% We'll need this for comparison purposes later.
% \begin{macrocode}
\ultradetokenize@to@macro\@htmlize@stop@detokenized{\@htmlize@stop}%
% \end{macrocode}
%
% The next line creates the macro |\htmlize@remove@stopcode|,
% which removes the characters ``|\@htmlize@stop |'' from the end of a
% detokenized sequence.
% Its syntax when called is simply |\htmlize@remove@stopcode |\meta{material},
% with no delimiters, since the ``|\@htmlize@stop |'' is itself the delimiter.
% \begin{macrocode}
\xa\def\xa\htmlize@remove@stopcode\xa#\xa1\@htmlize@stop@detokenized{#1}%
% \end{macrocode}
%
% \subsection{Main Code: the HTMLizer}
%
% \begin{macrocode}
\newif\ifhtmlizer@active
\htmlizer@activefalse
\newif\ifhtmlize@actioncs
\newif\ifhtmlize@expandcs
\newif\ifhtmlize@passcs
\long\def\@@begin@cs{\begin}%
\def\@@htmlize@stop{\@htmlize@stop}%
\long\def\converttohtmlmacro#1#2{%
\grouplevel=0\relax
\def\htmlize@output{}%
\htmlizer@activetrue%
\converttohtml@int{#2}%
\htmlizer@activefalse%
\let#1=\htmlize@output\relax
}
\long\def\converttohtml@int#1{%
\advance\grouplevel by 1\relax
\bgroup
\ultradetokenize@to@macro\htmlize@texttoscan{#1}%
\xa\htmlize@recursive@i\htmlize@texttoscan\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i%
\egroup
\advance\grouplevel by -1\relax
}%
\def\@lt{<}%
\def\@gt{>}%
\def\@dash{-}%
\long\def\htmlize@recursive@i#1#2#3\htmlize@rdelim@i{%
% #1#2#3 is a sequence of tokens. All should be categories 11 (letter) or 12 (other).
% It terminates with the control sequences \@htmlize@stop\@htmlize@stop\@htmlize@stop.
%\long\def\ds{(#1|#2|#3)}\show\ds
\def\test@i{#1}%
\def\test@ii{#2}%
\ifx\test@i\@@htmlize@stop
\let\htmlize@next@i=\relax
\else
\ifx\test@i\@otherlbrace%
\xa\g@addto@macro\xa\htmlize@output\xa{\otherlbrace}%
\bgroup
\normalcatcodes
%We need to rescan the input as TeX code,
% so TeX can automatically pull off the first group in braces.
% First, let's get rid of the terminal \@htmlize@stop codes.
{\def\@htmlize@stop{}\xdef\htmlize@scrap{#1#2#3}}%
\let\htmlize@text@to@rescan=\htmlize@scrap%
% Next, we retokenize the code.
\xa\retokenizenormal@to@macro\xa\htmlize@rescanned\xa{\htmlize@text@to@rescan}%
% Now break it up into two pieces.
\xa\htmlize@grabblock\htmlize@rescanned\@htmlize@stop\htmlize@rdelim@ii%
% The first piece, \htmlize@blockinbraces, will be passed as a unit to \converttohtml@int.
% The second part, \htmlize@remainder, will continue at this depth of grouping.
% Therefore we'll detokenize \htmlize@remainder here.
\xa\ultradetokenize@to@macro\xa\htmlize@remainder@detokenized\xa{\htmlize@remainder}%
\edef\htmlize@remainder@detokenized{\xa\htmlize@remove@stopcode\htmlize@remainder@detokenized}%
%
% Now build \htmlize@next@i.
% When done, should look like
% \converttohtml@int{\htmlize@blockinbraces}%
% \g@addto@macro\htmlize@output{\otherrbrace}%
% \htmlize@recursive@i\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i%
% but with all three arguments expanded.
% Note that we are running
\gdef\htmlize@scrap{\converttohtml@int}%
\xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\htmlize@blockinbraces}}%
\g@addto@macro\htmlize@scrap{\g@addto@macro\htmlize@output}%
\ifmoodle@clozemode
\xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherbackslash\otherrbrace}}%
% \moodle@ifmathmode{\xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherbackslash}}}%
% {}%
\else
\xa\g@addto@macro\xa\htmlize@scrap\xa{\xa{\otherrbrace}}%
\fi
\g@addto@macro\htmlize@scrap{\htmlize@recursive@i}%
\xa\g@addto@macro\xa\htmlize@scrap\xa{\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i}%
% Okay, that's done. It's stored in a global macro.
% Now we get it out of this group.
\egroup
\let\htmlize@next@i=\htmlize@scrap
\else
\ifx\test@i\@otherdollar%
% Math shift character.
\ifx\test@ii\@otherdollar
% Double dollar sign, so we're entering display math mode.
% We grab everything between $$...$$, sanitize it, and add it verbatim to
% our output.
\htmlize@displaymathshift@replace#1#2#3\htmlize@rdelim@iii%
\else
% Single dollar sign, so we're entering inline math mode.
% We grab everything between $...$, sanitize it, and add it verbatim to
% our output.
\htmlize@inlinemathshift@replace#1#2#3\htmlize@rdelim@iii%
\fi% \ifx\test@ii\@otherdollar
% Now we resume work.
% The \htmlize@xxxxxxmathshift@replace macro stored the remaining text in \htmlize@remaining@text.
% Note that since we never detokenized and retokenized #1#2#3,
% \htmlize@remaining@text still includes the terminating \@htmlize@stop\@htmlize@stop\@htmlize@stop.
\def\htmlize@next@i{\xa\htmlize@recursive@i\htmlize@remaining@text\htmlize@rdelim@i}%
\else
\ifx\test@i\@otherbackslash%
% Control sequence. Oh boy.
% There are three possible things to do:
% 1. Retokenize everything, so we get a token list.
% Expand this control sequence, the first one in the list,
% to obtain a new token list. Then resume processing that list.
% Examples: \def\emph#1{#1}, \def\rec#1{\frac{1}{#1}}, \def\inv{^{-1}}
% \& --> & \# --> #; etc.
% Environments: \begin{center}...\end{center} -->
...
% 2. Retokenize everything, so we get a token list.
% Let this first command (with its parameters) ACT.
% This may involve work in TeX's stomach (e.g., with counters)
% or with external files (e.g., image processing).
% The command may directly add material to \htmlize@output,
% but it should not typeset anything and should vanish from the
% input stream when it is done.
% When it's done, we somehow need to detokenize and resume
% processing the remainder of the input stream.
% Only commands explicitly crafted (or modified) to work
% with moodle.sty can possibly do all this!
% Examples: (modified) \includegraphics
% Environments: \begin{clozemulti}, \begin{enumerate}
% 3. Ignore that it's a command. Pass it right on as a character
% sequence to \htmlize@output.
% Examples: \alpha, \frac
% Environments: \begin{array}
%
% #2 is only for items on a specific list.
% #1 is anything that runs in TeX's mouth.
% We could keep a list and give users a way to add to it.
% I could also try expanding macros, using \ifcsmacro from etoolbox.sty
%
% The first step is to figure out what control sequence we're dealing with.
% First, let's get rid of the terminal \@htmlize@stop codes.
{\def\@htmlize@stop{}\xdef\htmlize@scrap{#1#2#3}}%
\let\htmlize@text@to@rescan=\htmlize@scrap%
% Next, we retokenize the code.
\xa\retokenizenormal@to@macro\xa\htmlize@rescanned\xa{\htmlize@text@to@rescan}%
% Now break it up into two pieces.
\xa\htmlize@grabblock\htmlize@rescanned\@htmlize@stop\htmlize@rdelim@ii%
\let\@htmlize@cs\htmlize@blockinbraces%
\edef\htmlize@cs@string{\xa\string\@htmlize@cs}%
% The first piece, \htmlize@blockinbraces, will contain the single token in \@htmlize@cs.
% We'll need to keep the second part, \htmlize@remainder, since it probably
% contains arguments to the cs in \@htmlize@cs.
%\edef\ds{Encountered '\xa\string\@htmlize@cs'}\show\ds
%
% N.B. that \@htmlize@cs is a macro *containing* a single control sequence.
% This is good for testing with \ifx.
% \htmlize@cs@string contains the cs as a string, e.g., the characters "\emph".
%
\ifx\@htmlize@cs\@@begin@cs
%This is a \begin. Begin environment-handling routine.
%
% Grab the first {...} from \htmlize@remainder, which is the argument
% to \begin.
\xa\htmlize@grabblock\htmlize@remainder\@htmlize@stop\htmlize@rdelim@ii%
\let\htmlize@envname=\htmlize@blockinbraces%
%We do not need the rest, so we won't pay any attention to the new
%content of \htmlize@remainder.
%
%Now environments are non-expandable,
%so there are only two possibilities: action or pass.
\xa\ifinlist\xa{\htmlize@envname}{\htmlize@env@actionlist}%
{% Action environment!
%\bgroup
%\def\ds{Encountered active environment \string\begin\{{\htmlize@envname}\}}\show\ds
\def\htmlize@next@i{\xa\htmlize@do@actionenv\htmlize@rescanned\@htmlize@stop\htmlize@actionsequence@rdelim}%
%The \bgroup is to active the environments.
%The matching \egroup is found in \htmlize@do@actionenv.
}{%An environment to pass to the HTML
%We just pass the backslash from "\begin" and move on.
\g@addto@macro\htmlize@output{#1}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
}%
\else%
%This is not an environment. Begin macro-handling routine.
\htmlize@actioncsfalse
\htmlize@expandcsfalse
\htmlize@passcsfalse
\xa\ifinlist\xa{\htmlize@cs@string}{\htmlize@cs@actionlist}%
{%Action sequence!
\htmlize@actioncstrue}%
{% Not action sequence!
\xa\ifinlist\xa{\htmlize@cs@string}{\htmlize@cs@expandlist}%
{%CS to be expanded!
\htmlize@expandcstrue%
}%
{%CS to be transcribed to XML
\htmlize@passcstrue%
}%
}%
%Now exactly one of \ifhtmlize@actioncs, \ifhtmlize@expandcs, and \ifhtmlize@passcs is true.
\ifhtmlize@actioncs
% It's an action-sequence.
%\edef\ds{Must let \xa\string\@htmlize@cs\ act!}\show\ds
%\show\htmlize@rescanned
\def\htmlize@next@i{\xa\htmlize@do@actioncs\htmlize@rescanned\@htmlize@stop\htmlize@actionsequence@rdelim}%
%\show\htmlize@rescanned
% Note that \htmlize@do@actioncs should patch the command to have it
% restart the scanning in time.
\else
\ifhtmlize@expandcs
% control sequence to be expanded
%\edef\ds{Must expand \xa\string\@htmlize@cs}\show\ds
\bgroup
\htmlize@redefine@expansionmacros
%The \expandafters first expand \htmlize@rescanned,
%and then expand its first token just once.
\xa\xa\xa\gdef\xa\xa\xa\htmlize@scrap\xa\xa\xa{\htmlize@rescanned}%
\egroup
\xa\ultradetokenize@to@macro\xa\htmlize@remaining@text\xa{\htmlize@scrap}%
\def\htmlize@next@i{\xa\htmlize@recursive@i\htmlize@remaining@text\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i}%
\else
% control sequence to be transcribed to XML.
%\edef\ds{Must pass on \xa\string\@htmlize@cs}\show\ds
\g@addto@macro\htmlize@output{#1}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\fi% \ifhtmlize@expandcs
\fi% \ifhtmlize@actioncs
\fi% \ifx\@htmlize@cs\@@begin@cs
\else%
\ifx\test@i\@othertilde%
% The ~ becomes non-breaking space
\g@addto@macro\htmlize@output{\otherampersand nbsp;}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\else
\ifx\test@i\@lsinglequote%
\ifx\test@ii\@lsinglequote%
% Double left quote
\g@addto@macro\htmlize@output{\otherampersand ldquo;}%
\def\htmlize@next@i{\htmlize@recursive@i#3\htmlize@rdelim@i}%
\else
\g@addto@macro\htmlize@output{\otherampersand lsquo;}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\fi% \ifx\test@ii\@lsinglequote%
\else
\ifx\test@i\@rsinglequote%
\ifx\test@ii\@rsinglequote% Double right quote
%AAedit 2021.01.06: in math mode, you should write 2 single right quotes, for second derivatives
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherampersand rsquo;\otherampersand rsquo;}}%
{\g@addto@macro\htmlize@output{\otherampersand rdquo;}}%
\def\htmlize@next@i{\htmlize@recursive@i#3\htmlize@rdelim@i}%
\else% Single right quote
\g@addto@macro\htmlize@output{\otherampersand rsquo;}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\fi% \ifx\test@ii\@rsinglequote%
\else
\ifx\test@i\@doublequote
\g@addto@macro\htmlize@output{\otherampersand rdquo;}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\else
\ifx\test@i\@lt
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherampersand lt;}}%
{\g@addto@macro\htmlize@output{<}}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\else
\ifx\test@i\@gt
\moodle@ifmathmode{\g@addto@macro\htmlize@output{\otherampersand gt;}}%
{\g@addto@macro\htmlize@output{>}}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\else
\ifx\test@i\@dash
\ifx\test@ii\@dash% en-dash (--)
\moodle@ifmathmode{\g@addto@macro\htmlize@output{--}}%
{\g@addto@macro\htmlize@output{\otherampersand ndash;}}%
\def\htmlize@next@i{\htmlize@recursive@i#3\htmlize@rdelim@i}%
\else
\g@addto@macro\htmlize@output{-}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\fi
\else
% Default case: write first token to output, call self on remaining tokens.
\g@addto@macro\htmlize@output{#1}%
\def\htmlize@next@i{\htmlize@recursive@i#2#3\htmlize@rdelim@i}%
\fi% \ifx\test@i\@dash
\fi% \ifx\test@i\@gt
\fi% \ifx\test@i\@lt
\fi% \ifx\test@i\@doublequote
\fi% \ifx\test@i\@rsinglequote%
\fi% \ifx\test@i\@lsinglequote%
\fi% \ifx\test@i\@othertilde%
\fi% \ifx\test@i\@otherbackslash%
\fi% \ifx\test@i\@otherdollar%
\fi% \ifx\test@i\@otherlbrace%
\fi% \ifx\test@i\@@htmlize@stop
\htmlize@next@i
}%
\def\@lsinglequote{`}%
\def\@rsinglequote{'}%
\def\@doublequote{"}%
% \end{macrocode}
%
% \subsection{Math Mode handling}
%
% In the following, note that the |\|\meta{*}|mathrightdelim|'s gobble an argument.
% This is so ``|$a$ is...|" can turn into
% ``\ldots |a\|\meta{*}|mathrightdelim{} is...|"
% and preserve a trailing space.
% \begin{macrocode}
\edef\inlinemathleftdelim{\otherbackslash(}%
\def\inlinemathrightdelim#1{\advancemathmodecounter{-1}%
\g@addto@macro\htmlize@output{\otherbackslash)}}%
\edef\displaymathleftdelim{\otherbackslash[}%
\def\displaymathrightdelim#1{\advancemathmodecounter{-1}%
\g@addto@macro\htmlize@output{\otherbackslash]}}%
\long\def\htmlize@inlinemath@recursive@i#1#2#3\htmlize@rdelim@i{%
% inspired by \htmlize@recursive@i
\def\test@i{#1}%
\ifx\test@i\@@htmlize@stop
\let\htmlize@next@i=\relax
\else
\ifx\test@i\@otherbackslash
\g@addto@macro\mathtext{#1#2}%
\def\htmlize@next@i{\xa\htmlize@inlinemath@recursive@i#3\htmlize@rdelim@i}%
\else
\ifx\test@i\@otherdollar
\let\htmlize@next@i=\relax
\g@addto@macro\aftertext{#2#3}%
\else
\g@addto@macro\mathtext{#1}%
\def\htmlize@next@i{\xa\htmlize@inlinemath@recursive@i#2#3\htmlize@rdelim@i}%
\fi
\fi
\fi
\htmlize@next@i
}
{\catcode`\$=12\relax%
\gdef\htmlize@inlinemathshift@replace#1#2\htmlize@rdelim@iii{%
%\def\ds{inline math shift has '#1' and '#2'}\show\ds
\xa\g@addto@macro\xa\htmlize@output\xa{\inlinemathleftdelim}%
\advancemathmodecounter{1}%
\gdef\mathtext{}%
\gdef\aftertext{}%
\htmlize@inlinemath@recursive@i#2\htmlize@rdelim@i%
\xdef\htmlize@remaining@text{\expandonce\mathtext%
\otherbackslash inlinemathrightdelim{}%
\expandonce\aftertext}%
%\show\htmlize@remaining@text
}%
\gdef\htmlize@displaymathshift@replace$$#1$$#2\htmlize@rdelim@iii{%
\xa\g@addto@macro\xa\htmlize@output\xa{\displaymathleftdelim}%
\advancemathmodecounter{1}%
\def\mathtext{#1}%
\def\aftertext{#2}%
\xdef\htmlize@remaining@text{\expandonce\mathtext%
\otherbackslash displaymathrightdelim{}%
\expandonce\aftertext}%
}%
}
% \end{macrocode}
%
% \subsection{Engines for Control Sequences}
%
% There are three kinds of control sequences that need special handling:
% \begin{enumerate}
% \item Action environments
% \item Action command sequences
% \item Expansion macros
% \end{enumerate}
%
% \subsubsection{Engine for running action environments}
% \begin{macrocode}
\long\def\htmlize@do@actionenv#1#2\@htmlize@stop\htmlize@actionsequence@rdelim{%
\bgroup %The corresponding \egroup is given in \htmlize@proceedwiththerest,
%to localize the changes to the environment definitions.
\htmlize@activate@environments
\gdef\htmlize@afteraction@hook{}%
#1#2\@htmlize@stop\htmlize@actionsequence@rdelim%
}
\def\htmlize@patchendenvironment{\swaptotrueendenvironment{\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook}}%
\def\swaptotrueendenvironment#1#2\if@ignore\@ignorefalse\ignorespaces\fi{#2\if@ignore\@ignorefalse\ignorespaces\fi#1}%
\long\def\htmlize@record@environment#1{%
\listadd{\htmlize@env@actionlist}{#1}%
}
\long\def\html@newenvironment#1#2{%
\listadd{\htmlize@env@actionlist}{#1}%
\g@addto@macro\htmlize@activate@environments{%
\xa\let\csname #1\endcsname\relax%
\xa\let\csname end#1\endcsname\relax%
\NewEnviron{#1}{%
#2%
}[\htmlize@patchendenvironment]%
}%
}
\def\htmlize@activate@environments{}%
% \end{macrocode}
%
% \subsubsection{Engine for running action command sequences}
%
% The following automatically adds the ``engine'' to do the command
% and then resume processing the \LaTeX\ into HTML.
% It uses the |xpatch| package, which says it works with anything
% defined using |\newcommand| etc. and |\newenvironment| etc.
% \begin{macrocode}
\gdef\htmlize@afteraction@hook{}%
\long\def\htmlize@do@actioncs#1#2\htmlize@actionsequence@rdelim{%
% #1#2 contains the current string to be rendered into HTML;
% N.B. it has been tokenized at this point,
% so TeX can process it directly.
% #1 = the command sequence we need to execute
% #2 = the rest of the string
%
% First, we patch the desired command so that, when it is over,
% it calls \htmlize@proceedwiththerest.
% We do this within the group, so as not to permanently change the command.
\bgroup
% The matching \egroup is issued in \htmlize@proceedwiththerest,
% so that the changes made by \htmlize@activate@css are localized to just the command itself.
\gdef\htmlize@afteraction@hook{}%
\htmlize@activate@css%
\def\test@i{#1}%
\ifx\test@i\@relax
\def#1{\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook}%
\else
\xapptocmd#1{\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook}{}{\PackageError{Could not patch the command \string#1!}}%
\fi
% Now we call that patched command.
#1#2\htmlize@actionsequence@rdelim%
%The matching \egroup now is built into the command #1.
}
\long\def\htmlize@proceedwiththerest#1\htmlize@actionsequence@rdelim{%
% The action cs has done its work.
% Now we gather up the remaining tokens, detokenize them,
% remove the \@htmlize@stop, and get back to work transcribing it.
\egroup %This \egroup matches the \bgroup that was issued either in \htmlize@do@actioncs or in \htmlize@do@actionenv
\ultradetokenize@to@macro\htmlize@remainder@detokenized{#1}%
%This will contain an extra \@htmlize@stop, so we remove it.
\xa\xa\xa\def\xa\xa\xa\htmlize@remainder@detokenized\xa\xa\xa{\xa\htmlize@remove@stopcode\htmlize@remainder@detokenized}%
%Now we get back to work transcribing the remainder.
\xa\htmlize@recursive@i\htmlize@remainder@detokenized\@htmlize@stop\@htmlize@stop\@htmlize@stop\htmlize@rdelim@i%
}
\long\def\htmlize@record@action#1{%
\xa\listadd\xa\htmlize@cs@actionlist\xa{\string#1}%
}
\def\htmlize@activate@css{}%
\def\html@action@def#1{%
\htmlize@record@action{#1}%
\xa\def\xa\htmlize@scrap\xa{\xa\let\xa#1\csname html@\string#1\endcsname}%
\xa\g@addto@macro\xa\htmlize@activate@css\xa{\htmlize@scrap}%
\xa\def\csname html@\string#1\endcsname% %And this \def\html@\oldcsname is follows by the remainder of the definition.
}
\def\html@action@newcommand#1[#2][#3]#4{%
%\message{>>> Defining #1[#2][#3]{...} ^^J}
\ifmoodle@draftmode
\else
\xa\html@action@def\csname #1\endcsname{\csname moodle@#1@int\endcsname}%
\fi
% Note that \htmlize@do@actioncs will 'patch' this by putting
% '\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook'
% at the end. We want those 3 tokens to occur instead after
% the graphics filename.
\xa\csdef{moodle@#1@int}##1##2##3{\csname moodle@#1@int@int\endcsname}%
% This gobbles up those three spurious tokens,
% which we will re-insert after our work is done.
\xa\newcommand\csname moodle@#1@int@int\endcsname[#2][#3]{%
#4%
% Now we re-insert the code to get the HTMLizing going again.
\xa\htmlize@proceedwiththerest\htmlize@afteraction@hook
}%
}
% \end{macrocode}
%
% \subsubsection{Engine for expansion control sequences}
%
% Calling |\htmlize@redefine@expansionmacros| will redefine
% the macros for us. It starts out empty.
% \begin{macrocode}
\def\htmlize@redefine@expansionmacros{}%
% \end{macrocode}
% If |\mymacro| needs no changes to be suited for expansion,
% you can simply call |\htmlize@record@expand{\mymacro}|
% or |\htmlregister{\mymacro}|
% to record that it should be expanded on its way to the HTML.
% Examples would be user-built macros such as |\inv|$\to$|^{-1}|
% or |\N|$\to$|\mathbb{N}|.
% \begin{macrocode}
\long\def\htmlize@record@expand#1{%
\xa\listadd\xa\htmlize@cs@expandlist\xa{\string#1}%
}
\let\htmlregister=\htmlize@record@expand
% \end{macrocode}
% Often users define a list of macros at the end of the preamble.
% It can be cumbersome to record individually these macros for expansion.
% By calling |\moodleregisternewcommands| they trigger the automatic
% expansion of macros defined subsequently using |\newcommand|,
% |\renewcommand|, |\providecommand| or their starred variants.
% \begin{macrocode}
\def\moodleregisternewcommands{%
%% INSPIRED FROM
%https://tex.stackexchange.com/questions/73271/how-to-redefine-or-patch-the-newcommand-command
\newcommand*{\saved@ifdefinable}{}
\let\saved@ifdefinable\@ifdefinable
\renewcommand{\@ifdefinable}[2]{%
\saved@ifdefinable{##1}{##2}%
\htmlregister{##1}
}%
\let\@@ifdefinable\@ifdefinable
}%
% \end{macrocode}
% On the other hand, if an alternate version of the macro is
% needed for HTML purposes, you can define its HTML version with
% |\html@def\mymacro...|
% Parameters are okay.
% An example would be
% |\html@def\emph#1{#1}|.
% \begin{macrocode}
\long\def\html@def#1{%
\htmlize@record@expand{#1}%
\xa\def\xa\htmlize@scrap\xa{\xa\let\xa#1\csname html@\string#1\endcsname}%
\xa\g@addto@macro\xa\htmlize@redefine@expansionmacros\xa{\htmlize@scrap}%
\xa\def\csname html@\string#1\endcsname%
}
% \end{macrocode}
% Note that when |\html@def| expands out, it ends with |\def\html@\oldcsname|
% which abuts directly on the remainder of the definition.
%
% \subsection{Specific Control Sequences for Action and Expansion}
%
% Now that we have that machinery in place,
% we define specific environments, action control sequences, and macros to
% expand to accomplish our purposes.
%
% \subsubsection{Action Environments}
% \begin{macrocode}
\htmlize@record@environment{clozemulti}
\htmlize@record@environment{multi}
\htmlize@record@environment{clozenumerical}
\htmlize@record@environment{numerical}
\htmlize@record@environment{clozeshortanswer}
\htmlize@record@environment{shortanswer}
\html@newenvironment{center}{\xdef\htmlize@afteraction@hook{