4

EDIT: The original question was unclear, not well-posed, posted too early and too much verbose. After having some rest and digging more in deep the issue, I am now able to answer by myself to almost the underlying points.

The general presentation and expectations are remained unchanged and the adopted solution is explained for people who would want to solve a similar issue. The question now deals only on how to "reset" the quiz when one has already activate the "Verify" button.


The aim is to display interactive multiple choice questions or quiz (MCQ) within a PDF handbook. The used tools are: hyperref, ocgx2, tikz and tcolorbox packages from TeXLive on Linux with Evince/Atril PDF viewer (Okular does not support OCGs). The result is obtained with the LuaLaTeX engine (pdfLaTeX should work).

The goal is here to display the quiz as in the first link below (whithout database at a first step: the quiz and its solution will be further recorded with the help of the tcolorbox package functionalities), but also to be able to mimic the layout of a MOOC platform (e.g. a French one: Fun MOOC). That is to say, on one hand, displaying the quiz with its proposals (rather straightforward with ocgx2) and, on the other hand, delegating the display of the solution to some clickable buttons to check, to reset, and to give explanations about the responses (and to save the score in a further work).

This general behaviour is wanted both for single and multiple solution MCQs.

A first approach for single solution MCQ with OCGs is given by:

(1) Multiple choice questions linked to solutions using Optional Content Groups (OCG)

Other useful links for starting with OCGs are AlexG's answers to the following questions:

(2) Clickable checkmarks in pdf with ocgs

(3) OCGX and hyperref: visibility and clickability of overlapping links

The key point is also to consider the AG's answer to this question:

(4) Creating a lot of checkbox'es to make visible/invisible arrows using tikzpicture environment

Borrowing the code from the fourth above link, it is quite straightforward to add an efficient "Reset" button, both to single and multiple solution MCQs. By the way, with no effort, one can also propose a "Select all" button for the multiple solution quiz.

To display the selected results (correct or not) after clicking the "Verify" button is also possible. It is done in a direct way for single solution MCQ, thanks to AG's answer in the fourth link above. As far as the multiple solution MCQ is concerned, the proposed solution is not elegant nor clever (there is still some misunderstood things): our skills are limited and certainly someone could improve this solution. Nevertheless, it works.

So the only remainded issue is the ability to "reset" the quiz automatically when one has already click on the "Verify" button, but when one wants to test other proposals. In such a case, the results are displayed without to have to click again the "Verify" button. (May be I'am still not clear... Test the MWE).

MWE EDIT 3 − 2019-05-23: Taking into account the comments

\documentclass{article}
\usepackage{xparse}
\usepackage{etoolbox}
\usepackage{xcolor}
\usepackage{fontawesome}
\usepackage{tikz}
\usepackage{calc}
\usepackage{tcolorbox}
\usepackage{hyperref}
\usepackage[tikz]{ocgx2}

\tcbuselibrary{%
    skins,
    breakable,
    xparse,
}

\hypersetup{%
    pdfborder=0 0 0,% no border to links
    colorlinks=true,%
    linkcolor=gray,
}

\definecolor{buttongray}{RGB}{200, 200, 200}

\tikzset{%
    quizbutton/.style={
        shape=rectangle, rounded corners=1pt,
        text=black, draw=#1!90,
        top color=#1!15!white, bottom color=#1!75,
        inner xsep=6pt, inner ysep=2pt,
    },
}

\tcbset{
    quizquestionstyle/.style={
        breakable, enhanced jigsaw,
        colframe=black!75,
        colback=black!2!white,
        coltitle=red!75!black,
        fonttitle={\normalfont\strut},
        boxrule=0.4pt, boxsep=0pt, arc=0.8pt,
        left=6pt, right=6pt,
        attach title to upper={\par\vspace{6pt}},
        before skip=4pt, after skip=6pt,
    },
}

\newcounter{quizquestion}
\newcounter{mcqproposal}% Multiple choice counter within a quiz question

\newcounter{mcqquiztotal}[quizquestion]% Total proposition counter within a quiz question
\newcounter{mcqsolutiontotal}[quizquestion]% Total number of (multiple) solutions within a quiz question

\newlength{\checkboxwidth}
\newlength{\checkgap}
\setlength{\checkgap}{0.5em}
\newlength{\symbolwidth}
\setlength{\symbolwidth}{10pt}

% \faCheck width = 10.O pt; \faTimes width = 7.85pt => same width in a box
\newcommand{\checktick}{%
    \makebox[\symbolwidth][c]{%
        \textcolor{green!60!black}{\normalfont\normalsize\faCheck}%
    }%
}
\newcommand{\crosstick}{%
    \makebox[\symbolwidth][c]{%
        \textcolor{red!60!black}{\normalfont\normalsize\faTimes}%
    }%
}

%-- Only one answer to multiple choice question (stared environment)

%- Defining a single solution MCQ environment
\NewTColorBox[use counter=quizquestion]{quizquestion*}{o g}{%
    % Syntax − #1 = more tcbox options, #2 = optional title
    quizquestionstyle,
    label={quizquestion:\thetcbcounter},
    lowerbox=ignored,
    IfValueTF={#2}%
        {title=\textbf{Quiz~\thetcbcounter\enspace---\enspace#2}}%
        {before upper=\textcolor{tcbcol@title}{\textbf{Quiz~\thetcbcounter}}\vspace*{2pt}},
    IfValueTF={#1}{#1}{},% More options
}

%- Traditional presentation of checked radio buttons
%- For inspiration and example, see the answers of Heiko Oberdiek to:
%-   https://tex.stackexchange.com/questions/236041/how-to-typeset-a-radio-button
%- Here, we just adapt our needs to the 'Fontawesome' icons
\newlength{\radius}
\settowidth{\radius}{\normalfont\normalsize\faCircleThin}
\addtolength{\radius}{-2.0pt}

%- Empty radio button
\newcommand{\freeRadioButton}{%
    \raisebox{-4pt}{%
    \begin{tikzpicture}
        \fill[color=white, radius=0.6\radius] circle;
        \node[color=gray] {\normalfont\normalsize\faCircleThin};
    \end{tikzpicture}%
    }%
}

%- Checked radio button
\newcommand{\checkedRadioButton}{%
    \raisebox{-4pt}{%
    \begin{tikzpicture}
        \fill[color=green!60!black, radius=0.6\radius] circle;
        \node[color=gray] {\normalfont\normalsize\faCircleThin};
        \fill[color=white, radius=1.4pt] circle;
    \end{tikzpicture}%
    }%
}

%- Defining a radio buttons command for layer switching
\NewDocumentCommand{\layerRadioButton}{m m m m}{% From Alexander Grann's answers on TeX.SE
    % Syntax − #1: radiobutton group name, #2: layer name, #3: layer id, #4: initial visibility
    \switchocg{#3}{\freeRadioButton}%
    \settowidth{\checkboxwidth}{\freeRadioButton}%
    \begin{ocg}[radiobtngrp=#1]{#2}{#3}{#4}%
        \hspace*{-\checkboxwidth}%
        \textcolor{green!60!black}{\checkedRadioButton}%
    \end{ocg}%
}

%- Defining a proposition for single solution MCQ
\NewDocumentCommand{\mcqproposalSingle}{o m}{%
    % Syntax − #1 = more tcbox options, #2 = answering proposal
    \begin{tcolorbox}[%
        breakable, enhanced,
        notitle, colframe=black!60, colback=white,
        boxrule=0.2pt, arc=0.4pt, boxsep = 0pt,
        left = 4pt, right = 4pt,
        top = 4pt, bottom = 4pt,
        before skip=4pt, after skip=4pt,
        IfValueTF={#1}{#1}{},% More options
        ]
        \stepcounter{mcqproposal}%
        \stepcounter{mcqquiztotal}%
        \parbox[t]{16pt}{%
            %\hspace*{2pt}%
            \layerRadioButton{Choice:\thequizquestion}%
                {mcqproposalsingle:\themcqproposal}{mcqproposalsingleref:\themcqproposal}{off}%
        }%
        \parbox[t]{\linewidth-16pt}{#2}%
        \end{tcolorbox}%
}

%- Defining the verification command/button for single solution MCQ
\NewDocumentCommand{\verifySingle}{m}{%
    % Syntax − #1 = the solely correct answer
    \noindent%
    \switchocg{checkchoiceref:\thequizquestion}{%
        \begin{tikzpicture}
            \node[quizbutton=buttongray] (checksolutionbutton)
                {\strut\footnotesize\textbf{Verify}};%
        \end{tikzpicture}%
    }%
    \begin{ocg}{CheckChoice:\thequizquestion}{checkchoiceref:\thequizquestion}{off}
        \hspace*{\checkgap}% Horizontal space between the button and the checkmark
        \foreach \X in {1,...,\value{mcqquiztotal}} {%
            \ifnum\X=#1
                \begin{ocg}[radiobtngrp=Choices:\thequizquestion]{mcqproposalsingle:\X}{mcqproposalsingleref:\X}{off}%
                \ifnum\numexpr\X=1\relax%
                    \else
                        \hspace*{-\symbolwidth}%
                    \fi
                    \raisebox{5pt}{\checktick}%
                \end{ocg}%
            \else
                \begin{ocg}[radiobtngrp=Choices:\thequizquestion]{mcqproposalsingle:\X}{mcqproposalsingleref:\X}{off}%
                    \ifnum\numexpr\X=1\relax%
                    \else
                        \hspace*{-\symbolwidth}%
                    \fi
                    \raisebox{5pt}{\crosstick}%
                \end{ocg}%
            \fi
        }%
    \end{ocg}%
}

%- Resetting a single solution MCQ
\NewDocumentCommand{\resetSingle}{}{%
    \def\ocglist{}%
    \foreach \X in {1,...,\value{mcqquiztotal}} {\xdef\ocglist{\ocglist\space mcqproposalsingleref:\X}}%
    \hideocg{\ocglist}{%
        \begin{tikzpicture}
            \node[quizbutton=buttongray] (resetbutton)
                {\strut\footnotesize\textbf{Reset}};
        \end{tikzpicture}%
    }%
}

%- Applying the different commands for a MCQ with a single solution
\AtBeginEnvironment{quizquestion*}{%
    \setcounter{mcqproposal}{0}%
    \let\mcqproposal\mcqproposalSingle%
    \let\verifyMCQ\verifySingle%
    \let\resetMCQ\resetSingle%
}

%-- Several answers to multiple choices question (normal i.e. not stared environment)

%- Defining a multiple solution MCQ environment
\NewTColorBox[use counter=quizquestion]{quizquestion}{o g}{%
    % Syntax − #1 = more options, #2 = optional title
    quizquestionstyle,
    label={quizquestion:\thetcbcounter},
    lowerbox=ignored,
    IfValueTF={#2}%
        {title=\textbf{Quiz~\thetcbcounter\enspace---\enspace#2}}%
        {before upper=\textcolor{tcbcol@title}{\textbf{Quiz~\thetcbcounter}}\vspace*{2pt}},
    IfValueTF={#1}{#1}{},% More options
}

%- Empty check button
\newcommand{\freeButton}{%
    \raisebox{-4pt}{%
    \begin{tikzpicture}
        \node[color=gray] {\normalfont\normalsize\faSquareO};
    \end{tikzpicture}%
    }%
}

%- Checked button
\newcommand{\checkedButton}{%
    \raisebox{-4pt}{%
    \begin{tikzpicture}
        \node[color=gray] {%
            %\normalfont\normalsize\faSquareO%
            \hspace*{-\checkboxwidth}\textcolor{green!60!black}{\faCheck}};
    \end{tikzpicture}%
    }%
}

%- Check box command for layer switching
\NewDocumentCommand{\layerCheckBox}{m m m}{% From Alexander Grann's answers on TeX.SE
    % Syntax − #1: layer name, #2: layer id, #3: initial visibility
    \switchocg{#2}{\freeButton}%
    \settowidth{\checkboxwidth}{\freeButton}%
    \begin{ocg}{#1}{#2}{#3}
        \checkedButton%
    \end{ocg}%
}

\NewDocumentCommand{\layerCheckBoxMultiple}{m m m}{% From Alexander Grann's answers on TeX.SE:
    % https://tex.stackexchange.com/questions/481812/
    % Syntax − #1: switch id,
    %          #2: layer ids to be toggled (space separated if multiple ids),
    %          #3: initial visibility
    \switchocg{#1 #2}{\faSquareO}%
    \settowidth{\checkboxwidth}{\normalfont\normalsize\faSquareO}%
    \begin{ocg}{\ifx\nil#1\nil#2\else#1\fi}{\ifx\nil#1\nil#2\else#1\fi}{#3}
        \hspace*{-\checkboxwidth}\textcolor{green!60!black}{\faCheck}%
    \end{ocg}%
}

%- Defining a proposition for multiple solution MCQ
\NewDocumentCommand{\mcqproposalMultiple}{o m}{%
    % Syntax − #1 = more tcbox options, #2 = answering proposal
    \begin{tcolorbox}[%
        breakable, enhanced,
        notitle, colframe=black!60, colback=white,
        boxrule=0.2pt, arc=0.4pt, boxsep = 0pt,
        left = 4pt, right = 4pt,
        top = 4pt, bottom = 4pt,
        before skip=4pt, after skip=4pt,
        IfValueTF={#1}{#1}{},% More options
        ]
        \stepcounter{mcqproposal}%
        \stepcounter{mcqquiztotal}%
        \parbox[t]{16pt}{%
            \hspace*{2pt}%
            %- Old
            \layerCheckBox{mcqproposalmultiple:\themcqproposal}{mcqproposalmultipleref:\themcqproposal}{off}%
            %- New
            %\layerCheckBoxMultiple{}{mcqproposalmultipleref:\themcqproposal}{off}%
        }%
        \parbox[t]{\linewidth-16pt}{#2}%
    \end{tcolorbox}%
    \newtoggle{Question\thequizquestion:\themcqproposal}%
}

%- Defining the verification command/button for multiple solution MCQ (awful syntax)
\NewDocumentCommand{\verifyMultiple}{m m g g g}{% Up to five correct answers: obvious minimum = 2
    % Syntax − The different integers arguments are referenced to the different proposals
    \newbool{Question\thequizquestion:#1}\boolfalse{Question\thequizquestion:#1}%
    \newbool{Question\thequizquestion:#2}\boolfalse{Question\thequizquestion:#2}%
    \IfValueT{#3}{%
        \newbool{Question\thequizquestion:#3}%
        \boolfalse{Question\thequizquestion:#3}%
    }%
    \IfValueT{#4}{%
        \newbool{Question\thequizquestion:#4}%
        \boolfalse{Question\thequizquestion:#4}%
    }%
    \IfValueT{#5}{%
        \newbool{Question\thequizquestion:#5}%
        \boolfalse{Question\thequizquestion:#5}%
    }%
    \noindent%
    \switchocg{checkchoicemultipleref:\thequizquestion}{%
        \begin{tikzpicture}
            \node[quizbutton=buttongray]
                (checksolutionmultiplebutton) {\strut\footnotesize\textbf{Verify}};
        \end{tikzpicture}%
    }
    \begin{ocg}{CheckChoiceMultiple:\thequizquestion}{checkchoicemultipleref:\thequizquestion}{off}
        \hspace{6.5pt}% <-- Empirical value to adjust the checkmark position like for the single solution! WHY?!!?
        \hspace*{\checkgap}% Horizontal space between the button and the checkmark
            \IfValueTF{#3}{%
                \IfValueTF{#4}{%
                    \IfValueTF{#5}{%
                        \switchocg{mcqproposalmultipleref:#1 mcqproposalmultipleref:#2 %
                            mcqproposalmultipleref:#3 mcqproposalmultipleref:#4 mcqproposalmultipleref:#5}{}%
                        \begin{ocg}{mcqproposalmultiple:#1}{mcqproposalmultipleref:#1}{off}%
                            \begin{ocg}{mcqproposalmultiple:#2}{mcqproposalmultipleref:#2}{off}%
                                \begin{ocg}{mcqproposalmultiple:#3}{mcqproposalmultipleref:#3}{off}%
                                    \begin{ocg}{mcqproposalmultiple:#4}{mcqproposalmultipleref:#4}{off}%
                                        \begin{ocg}{mcqproposalmultiple:#5}{mcqproposalmultipleref:#5}{off}%
                                            \raisebox{5pt}{\checktick}%
                                        \end{ocg}%
                                    \end{ocg}%
                                \end{ocg}%
                            \end{ocg}%
                        \end{ocg}%
                    }{% If value #5 False
                        \foreach \X in {1,...,\value{mcqquiztotal}} {%
                            \foreach \Y in {1,...,\X} {%
                                \foreach \Z in {1,...,\Y} {%
                                    \foreach \U in {1,...,\Z} {%
                                        \ifbool{Question\thequizquestion:#1}{}{%
                                            \ifbool{Question\thequizquestion:#2}{}{%
                                                \ifbool{Question\thequizquestion:#3}{}{%
                                                    \ifbool{Question\thequizquestion:#4}{}{%
                                                        \ifnum\U=\Z
                                                            \relax%
                                                        \else
                                                            \ifnum\Z=\Y
                                                                \relax%
                                                            \else
                                                                \ifnum\Y=\X
                                                                    \relax
                                                                \else
                                                                    \hspace*{-\symbolwidth}%
                                                                    %\X{:}\Y{:}\Z{:}\U{}\space%
                                                                    \ifnum\U=#1
                                                                        \ifnum\Z=#2
                                                                            \ifnum\Y=#3
                                                                                \ifnum\X=#4
                                                                                    \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y %
                                                                                        mcqproposalmultipleref:\Z mcqproposalmultipleref:\U}{}%
                                                                                    \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                                        \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                                            \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                                \begin{ocg}{mcqproposalmultiple:\U}{mcqproposalmultipleref:\U}{off}%
                                                                                                    \raisebox{5pt}{\checktick}%
                                                                                                \end{ocg}%
                                                                                            \end{ocg}%
                                                                                        \end{ocg}%
                                                                                    \end{ocg}%
                                                                                \else
                                                                                    \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y %
                                                                                        mcqproposalmultipleref:\Z mcqproposalmultipleref:\U}{}%
                                                                                    \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                                        \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                                            \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                                \begin{ocg}{mcqproposalmultiple:\U}{mcqproposalmultipleref:\U}{off}%
                                                                                                    \raisebox{5pt}{\crosstick}%
                                                                                                \end{ocg}%
                                                                                            \end{ocg}%
                                                                                        \end{ocg}%
                                                                                    \end{ocg}%
                                                                                \fi
                                                                            \else
                                                                                \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y %
                                                                                    mcqproposalmultipleref:\Z mcqproposalmultipleref:\U}{}%
                                                                                \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                                    \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                                        \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                            \begin{ocg}{mcqproposalmultiple:\U}{mcqproposalmultipleref:\U}{off}%
                                                                                                \raisebox{5pt}{\crosstick}%
                                                                                            \end{ocg}%
                                                                                        \end{ocg}%
                                                                                    \end{ocg}%
                                                                                \end{ocg}%
                                                                            \fi
                                                                        \else
                                                                            \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y %
                                                                                mcqproposalmultipleref:\Z mcqproposalmultipleref:\U}{}%
                                                                            \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                                \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                                    \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                        \begin{ocg}{mcqproposalmultiple:\U}{mcqproposalmultipleref:\U}{off}%
                                                                                            \raisebox{5pt}{\crosstick}%
                                                                                        \end{ocg}%
                                                                                    \end{ocg}%
                                                                                \end{ocg}%
                                                                            \end{ocg}%
                                                                        \fi
                                                                    \else
                                                                        \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y %
                                                                            mcqproposalmultipleref:\Z mcqproposalmultipleref:\U}{}%
                                                                        \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                            \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                                \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                    \begin{ocg}{mcqproposalmultiple:\U}{mcqproposalmultipleref:\U}{off}%
                                                                                        \raisebox{5pt}{\crosstick}%
                                                                                    \end{ocg}%
                                                                                \end{ocg}%
                                                                            \end{ocg}%
                                                                        \end{ocg}%
                                                                    \fi
                                                                \fi
                                                            \fi
                                                        \fi
                                                    }%
                                                }%
                                            }%
                                        }%
                                    }%
                                }%
                            }%
                        }%
                    }% End if value #5
                }{% If value #4 false
                    \foreach \X in {1,...,\value{mcqquiztotal}} {%
                            \foreach \Y in {1,...,\X} {%
                                \foreach \Z in {1,...,\Y} {%
                                    \ifbool{Question\thequizquestion:#1}{}{%
                                        \ifbool{Question\thequizquestion:#2}{}{%
                                            \ifbool{Question\thequizquestion:#3}{}{%
                                                \ifnum\Z=\Y
                                                    \relax%
                                                \else
                                                    \ifnum\Y=\X
                                                        \relax%
                                                    \else
                                                        \hspace*{-\symbolwidth}%
                                                        %\X{:}\Y{:}\Z{}\space%
                                                        \ifnum\Z=#1
                                                            \ifnum\Y=#2
                                                                \ifnum\X=#3
                                                                    \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y mcqproposalmultipleref:\Z}{}%
                                                                    \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                        \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                            \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                \raisebox{5pt}{\checktick}%
                                                                            \end{ocg}%
                                                                        \end{ocg}%
                                                                    \end{ocg}%
                                                                \else
                                                                    \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y mcqproposalmultipleref:\Z}{}%
                                                                    \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                        \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                            \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                                \raisebox{5pt}{\crosstick}%
                                                                            \end{ocg}%
                                                                        \end{ocg}%
                                                                    \end{ocg}%
                                                                \fi%
                                                            \else
                                                                \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y mcqproposalmultipleref:\Z}{}%
                                                                \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                    \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                        \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                            \raisebox{5pt}{\crosstick}%
                                                                        \end{ocg}%
                                                                    \end{ocg}%
                                                                \end{ocg}%
                                                            \fi%
                                                        \else
                                                            \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y mcqproposalmultipleref:\Z}{}%
                                                            \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                                                \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                                    \begin{ocg}{mcqproposalmultiple:\Z}{mcqproposalmultipleref:\Z}{off}%
                                                                        \raisebox{5pt}{\crosstick}%
                                                                    \end{ocg}%
                                                                \end{ocg}%
                                                            \end{ocg}%
                                                        \fi%
                                                    \fi
                                                \fi
                                            }%
                                        }%
                                    }%
                                }%
                            }%
                        }%
            }% End if value #4
        }{% If value #3 false
            \foreach \X in {1,...,\value{mcqquiztotal}} {%
                        \foreach \Y in {1,...,\X} {%
                    \ifbool{Question\thequizquestion:#1}{}{%
                        \ifbool{Question\thequizquestion:#2}{}{%
                            \ifnum\Y=\X
                                \relax%
                            \else
                                %\X{:}\Y{}\space%
                                \hspace*{-\symbolwidth}%
                                \ifnum\Y=#1
                                    \ifnum\X=#2
                                        \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y}{}%
                                        \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                            \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                \raisebox{5pt}{\checktick}%
                                            \end{ocg}%
                                        \end{ocg}%
                                    \else
                                        \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y}{}%
                                        \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                            \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                                \raisebox{5pt}{\crosstick}%
                                            \end{ocg}%
                                        \end{ocg}%
                                    \fi%
                                \else
                                    \switchocg{mcqproposalmultipleref:\X mcqproposalmultipleref:\Y}{}%
                                    \begin{ocg}{mcqproposalmultiple:\X}{mcqproposalmultipleref:\X}{off}%
                                        \begin{ocg}{mcqproposalmultiple:\Y}{mcqproposalmultipleref:\Y}{off}%
                                            \raisebox{5pt}{\crosstick}%
                                        \end{ocg}%
                                    \end{ocg}%
                                \fi%
                            \fi%
                        }%
                    }%
                }%
            }%
        }% End if value #3
    \end{ocg}% End of 'Verify' OCG definition
}

%- Resetting and/or selecting all items of a multiple solution MCQ
\NewDocumentCommand{\resetMultiple}{}{%
    \def\ocglist{}%
    \foreach \X in {1,...,\value{mcqquiztotal}} {\xdef\ocglist{\ocglist\space mcqproposalmultipleref:\X}}%
    \showocg{\ocglist}{%
        \begin{tikzpicture}
            \node[quizbutton=buttongray] (selectallbutton)
                {\strut\footnotesize\textbf{Select all}};
        \end{tikzpicture}%
    }%
    \qquad%
    \hideocg{\ocglist}{%
        \begin{tikzpicture}
            \node[quizbutton=buttongray] (resetbutton)
                {\strut\footnotesize\textbf{Reset}};
        \end{tikzpicture}%
    }%
}

%- Applying the different commands for a MCQ with multiple solutions
\AtBeginEnvironment{quizquestion}{%
    \setcounter{mcqproposal}{0}%
    \let\mcqproposal\mcqproposalMultiple%
    \let\verifyMCQ\verifyMultiple%
    \let\resetMCQ\resetMultiple%
}

\begin{document}


% Single solution MCQ
%--------------------

\begin{quizquestion*}{A relevant statement}

In short, what is the color of a black cat?

Choose the answer.

\mcqproposal[before skip=8pt]{The color is obviously red.}
\mcqproposal{The color may be green.}
\mcqproposal{The color is black.}
\mcqproposal[after skip=8pt]{The color is undoubtedly yellow.}

\verifyMCQ{3}
\qquad\hspace{3cm}\resetMCQ

\end{quizquestion*}


% Multiple solutions MCQ
%-----------------------

\begin{quizquestion}{Test of knowledge}

What are the different colors of an RGB image?

Check off the three exact assertions.

\mcqproposal[before skip=8pt]{Green.}
\mcqproposal{Yellow.}
\mcqproposal{Blue.}
\mcqproposal{Red.}
\mcqproposal[after skip=8pt]{Cyan.}

% Must be given in ascending order: if not => wrong results
%\verifyMCQ{1}{4}% Test with 2 correct choices
\verifyMCQ{1}{3}{4}% Correct answer of this particular quiz (3 choices)
%\verifyMCQ{1}{3}{4}{5}% Test with 4 correct choices
%\verifyMCQ{1}{2}{3}{4}{5}% Test with 5 correct choices
\qquad\hspace{3cm}\resetMCQ

\end{quizquestion}

\end{document}
  • Lovely concept and so far very well presented as a mwe in progress, Perhaps my understanding of your question is flawed, but using quiz 1 I don't see an issue (I suggest the red tick be a cross if possible) but selecting any other answer changes to the correct indication or pressing reset clears the answer How is that not required behaviour ? However there is a logic error in Quiz 2 I get an answer if I select 4 items thus always wrong except if I include yellow so rgb=gybr = green tick PS using acrobat OR evince on windows – user170109 May 19 at 0:44
  • 2
    For complex visibility relations we need so-called Optional Content Membership Dictionaries (OCMDs), which are based on OCGs and which are defined by the PDF speciification. I will think about their implementation in the ocgx2 package and a suitable interface. – AlexG May 19 at 18:26
  • @KJO Thanks for your feedback. For all MCQs, when the "Verify" button has been cliked after a first attempt, the issue is that if you want to test another set of anwers, the results are automatically displayed. We want that one has to click again the "Verify" button (to set a number of trials, etc.). About Quiz 2, the MWE has been posted after a test without modifying back to the right answers. Following your suggestion (planned but postponed), a red cross has been introduced. While doing so, the radio buttons have also been modified to match their traditional presentation (Second MWE). – ejazz May 21 at 15:40
  • @AlexG Thanks for the announce and, first of all, for sharing your work with all your useful packages. So, we'll be glad to hear from you soon ;-) – ejazz May 21 at 15:50
  • @ejazz Ok so now my take on your comment is I get a right wrong answer but to avoid it "sticking" until a new selection you want it to auto reset, If that is the case then no need for a reset button just use a timer to initiate the reset so user sees result for only x seconds – user170109 May 21 at 16:26
7

Package ocgx2 now provides the environment ocmd, which implements Optional Content Membership dictionaries according to the PDF spec. OCMDs are a kind of PDF layers whose visibility depend on the visibility status of other OCGs in the document. OCMDs are a convenient means for creating quizzes.

Let's suppose we inserted a number of quiz buttons, each of which toggles the visibility of an OCG. These OCGs are named red, green, blue, cyan, magenta, yellow and black. In order to answer the question correctly, the OCGs red, green and blue must be checked, but none of the other ones.

Now, the validation text "Correct ..." would be placed on a new PDF layer by means of the ocmd environment. The visibility of the OCMD will be calculated from the OCG visibilities during runtime according to a Boolean expression:

\begin{ocmd}{
  \And{
    red,green,blue, \Not{\Or{cyan,magenta,yellow,black}}
  }
}
  Correct. These are the components of the RGB model.
\end{ocmd}

The definition of the PDF layer for "Wrong" would look as

\begin{ocmd}{
  \Not{
    \And{
      red,green,blue, \Not{\Or{cyan,magenta,yellow,black}}
    }
  }
}
  Wrong.
\end{ocmd}

Complete example, based on the example given in the question. The visual appearance was simplified in order to reduce the amount of code and to make the OCG/OCMD-related code more obvious. In the first example, quiz buttons are added to a radio button group, such that only one of them can be checked at a time.

enter image description here

\documentclass{article}
\usepackage{ocgx2}
\usepackage{fontawesome5}
\usepackage{xcolor}
\usepackage{calc} %\widthof{...}

% quiz button
\NewDocumentCommand{\quizButton}{o m m m}{%
  % Syntax − #1: optional: radio button group
  %          #2: button shape: \faCircleThin, \faSquareO
  %          #3: verification id
  %          #4: choice id
  % action on click: toggle myself (choice layer), hide verifcation layer
  \makebox[0pt][l]{\actionsocg{#4}{}{#3}{#2}}%
  \begin{ocg}[\IfValueT{#1}{radiobtngrp=#1}]{#4}{#4}{off}% choice layer
    \makebox[\widthof{#2}]{\textcolor{green!60!black}{\faCheck}}%
  \end{ocg}%
}

% verify button
\NewDocumentCommand{\verifyButton}{m m m}{%
  % Syntax − #1: verification id
  %          #2: list of OCG ids of correct/required answer(s), comma separated
  %          #3: list of OCG ids of wrong answer(s), comma separated
  \showocg{#1}{\fbox{\strut Verify}}
  \begin{ocg}{#1}{#1}{off}% verification layer
    \makebox[0pt][l]{%
      \begin{ocmd}{\Not{\And{#2,\Not{\Or{#3}}}}}% "wrong" layer (OCMD)
        Wrong.
      \end{ocmd}%
    }%  
    \begin{ocmd}{\And{#2,\Not{\Or{#3}}}}% "correct" layer (OCMD)
      Correct.
    \end{ocmd}%
  \end{ocg}%  
}

% reset button
\ExplSyntaxOn
\NewDocumentCommand{\resetButton}{m}{%
  % Syntax − #1: list of OCG ids, comma separated
  \clist_set:Nn\l_tmpa_clist{#1} % save OCG ids as L3 clist variable
  \hideocg{\clist_use:Nn\l_tmpa_clist{~}}{\fbox{\strut Reset}}%
}
\ExplSyntaxOff

\parindent=0pt
\begin{document}


In short, what is the colour of a black cat? One correct answer.\\[8pt]
\quizButton[CatColours]{\faIcon[regular]{circle}}{vrfyCatCol}{red}    The colour is obviously red.\\
\quizButton[CatColours]{\faIcon[regular]{circle}}{vrfyCatCol}{green}  The colour may be green.\\
\quizButton[CatColours]{\faIcon[regular]{circle}}{vrfyCatCol}{black}  The colour is black.\\
\quizButton[CatColours]{\faIcon[regular]{circle}}{vrfyCatCol}{yellow} The colour is undoubtedly yellow.\\[8pt]
\verifyButton{vrfyCatCol}{black}{red,green,yellow}\hspace{0.3\linewidth}
\resetButton{vrfyCatCol,black,red,green,yellow}\\[16pt]

Which are the colour components of an RGB image? Multiple required assertions.\\[8pt]
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{magenta} Magenta.\\
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{green2}  Green.\\
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{cyan}    Cyan.\\
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{blue}    Blue.\\
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{red2}    Red.\\
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{black2}  Black.\\
\quizButton{\faIcon[regular]{square}}{vrfyRGBCol}{yellow2} Yellow.\\[8pt]
\verifyButton{vrfyRGBCol}{red2,green2,blue}{cyan,magenta,yellow2,black2}\hspace{0.3\linewidth}
\resetButton{vrfyRGBCol,red2,green2,blue,cyan,magenta,yellow2,black2}
\end{document}
  • 1
    Wonderful. Your answer is between my favorites :-) very good. – Sebastiano May 27 at 12:04
  • Alex I was interested in how this could be used for wider academic Q&A in which case the questioner would wish to accumulate a value for the complexity of the answer say 2 points for a simple one and 5 points for a more complex question. How would one allocate and collect such values ? In such a usage the Verify would best be worded differently say "Submit" and the reset be suppressed since the aim would be to ONLY allow one attempt at a modified answer(with no verification feedback), so I should test that for my self but pointers would help – user170109 May 27 at 12:05
  • @KJO Thanks for your feedback. Such advanced features involving calculation (even basic one) cannot be achieved without the additional help of embedded JavaScript, I guess. – AlexG May 27 at 12:14
  • 1
    @AndréC Thank you for your feedback. I will add some PDF documentation in the near future. – AlexG Jul 9 at 7:05
  • 1
    @AlexG I just tested it, it works perfectly. :-) – AndréC Sep 19 at 19:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.