6

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}
AlexG
  • 54,894
ejazz
  • 1,047
  • 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 –  May 19 '19 at 00: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 '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 '19 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 '19 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 –  May 21 '19 at 16:26
  • @ejazz I am getting a problem with compiling mwe under MiKTeX (should not be different ?) can you double check your fresh edit above runs for you –  May 21 '19 at 17:38
  • @ejazz Yeah, it's almost done. Just be patient. – AlexG May 22 '19 at 07:00
  • @KJO It's a matter of choice. IMO, it's better to manage things independently without timer: having a "Reset" button to restart from a blank quiz, and a "Verify" button to trig the number of trials, the score, etc. For the compiling issue, you are right: a closing parenthesis was missing in the \resetMultiple command definition (sorry, copy/paste mistake...). For multiple solution MCQ, I agree, the interface is not satisfying and the different use cases have still to be "secured". I do think that a next release of the ocgx2 package will soon give us an entire satisfaction! – ejazz May 23 '19 at 11:57
  • My initial simple take each time (not looking into code) is that Quiz1 is good enough without the reset Quiz2 is still a bit quirky in that selecting 4 gives both the greentick for 3 right but also red cross for selecting 4 or more it may be logical outcome 4 = both true and false but a simple result if = 3 right =tick else cross should clear that anomaly –  May 23 '19 at 12:44
  • Looking at this just as a user I may be missing the point with quiz1 I can select until I get the right answer simples for me ! (best NOT be green for selection but say neutral violet) HOWEVER in a real quiz that's not what the questioner may desire so It should be only ONE Verify (submit) allowed. Reset would only need to apply when resetting for all questions. ~ With question 2 similar principle only one shot at "submit" or verify and reset only applies when starting over. its not of much value to have "student" just attempt random attempts like I am doing so a green tick appears –  May 23 '19 at 13:10

1 Answers1

11

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 \NewDocumentCommand{\resetButton}{m}{% % Syntax − #1: list of OCG ids, comma separated \hideocg{#1}{\fbox{\strut Reset}}% }

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

AlexG
  • 54,894
  • 1
    Wonderful. Your answer is between my favorites :-) very good. – Sebastiano May 27 '19 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 –  May 27 '19 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 '19 at 12:14
  • At its most basic I envisioned verify as whiteout (easy) but score=score+5 may not need complex math just a hidden counter –  May 27 '19 at 12:36
  • @AlexG Honestly, really impressive! Useful, direct, concise and effective. Exactly what I was looking for (and certainly other people). Many thanks. – ejazz May 28 '19 at 08:58
  • @ejazz Thank you. Your question was a great inspiration, showing the need for this PDF feature be made accessible on the LaTeX level. – AlexG May 28 '19 at 09:08
  • I discovered this feature by looking at the readme file, but without really understanding it. By doing a limited search at tex.stackexchange, I discover this answer. Could you make a small documentation in PDF format, even if it means reproducing the different examples you gave on tex.stackechange? Thank you again for this wonderful package that I use every day to show interactive slideshows to my students.

    Translated with www.DeepL.com/Translator

    – AndréC Jul 09 '19 at 06:59
  • 1
    @AndréC Thank you for your feedback. I will add some PDF documentation in the near future. – AlexG Jul 09 '19 at 07:05
  • @AlexG I am making progress in understanding OCMD :-) . In my opinion, there is an inconsistency in the syntax of OCG lists. Indeed \switcthocg{ list separated by spaces } is followed by a list separated by spaces while \AllOn{ list separated by commas } is followed by a list separated by commas. A similar separating character would, in my humble opinion, be more consistent. – AndréC Sep 18 '19 at 15:45
  • @AndréC Thank you for your comment, you are absolutely right! I am not happy with this either. I would have preferred the comma throughout the package. But I adopted the syntax from ocgx for the link-making commands to maintain compatibility. The space used as a separator is a bit unusual in LaTeX and I don't like it. So I used the comma for new things. Perhaps I should add support for the comma to all commands that are taken from ocgx and adjust the documentation. The space would be kept for backwards compatibilty. I put this on my todo list. – AlexG Sep 18 '19 at 17:37
  • @AndréC : Comma-separated lists ought to work now, while using space as separator is kept for compatibility. It is automatically detected. Would you please test? https://gitlab.com/agrahn/ocgx2/raw/master/ocgx2.sty . – AlexG Sep 19 '19 at 12:59
  • 1
    @AlexG I just tested it, it works perfectly. :-) – AndréC Sep 19 '19 at 19:49