% \iffalse % makeindex -s gglo.ist -o eq-pin2corr.gls eq-pin2corr.glo % makeindex -s gind.ist -o eq-pin2corr.ind eq-pin2corr.idx %<*copyright> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% eq-pin2corr.sty package, %% %% Copyright (C) 2021 D. P. Story %% %% dpstory@uakron.edu dpstory@acrotex.net %% %% %% %% This program can redistributed and/or modified under %% %% the terms of the LaTeX Project Public License %% %% Distributed from CTAN archives in directory %% %% macros/latex/base/lppl.txt; either version 1.2 of the %% %% License, or (at your option) any later version. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{eq-pin2corr} % [2021/02/20 v1.0 Applies PIN security to quizzes] %<*driver> \documentclass{ltxdoc} %\usepackage[colorlinks,hyperindex=false,linktocpage,bookmarksnumbered]{hyperref} \usepackage[colorlinks,hyperindex=false]{hyperref} \usepackage{fancyvrb} \usepackage{calc} %\usepackage{eq-pin2corr} %\def\texorpdfstring#1#2{#1} %\pdfstringdefDisableCommands{\let\\\textbackslash} \OnlyDescription % comment out for implementation details \EnableCrossrefs \CodelineIndex \RecordChanges \gdef\brpr#1{\texttt{\char123\relax#1\char125\relax}} \let\darg\brpr \let\env\texttt \let\opt\texttt \let\app\textsf \let\pkg\textsf \let\uif\textsf \def\EXCL{!} \def\visispace{\symbol{32}} \def\ameta#1{\ensuremath{\langle\textit{\texttt{#1}}\rangle}} \def\meta#1{\textsl{\texttt{#1}}} \def\SUB#1{\ensuremath{{}_{\mbox{\scriptsize\ttfamily#1}}}} \def\CMD#1{\textbackslash#1} \makeatletter \renewcommand\theparagraph{\texorpdfstring{\protect\P\protect\ }{\textparagraph}} \renewcommand\thesubparagraph{\texorpdfstring{\protect\P\protect\P\protect\ }{\textparagraph\textparagraph}} \renewcommand{\section} {\renewcommand{\@seccntformat}[1]{\thesection\quad}% \@startsection {section}{1}{\z@}% {-3.5ex \@plus -1ex \@minus -.2ex}% {2.3ex \@plus.2ex}% {\normalfont\Large\bfseries}} \renewcommand{\paragraph} {\renewcommand{\@seccntformat}[1]{\theparagraph\unskip\,}% \@startsection{paragraph}{4}{0pt}{6pt}{-3pt}{\bfseries}} \renewcommand{\subparagraph} {\renewcommand{\@seccntformat}[1]{\thesubparagraph\unskip\,}% \@startsection{subparagraph}{5}{\parindent}{6pt}{-3pt}{\bfseries}} \edef\amtIndent{\the\parindent} \newenvironment{aebQuote} {\list{}{\leftmargin\amtIndent}% \item\relax} {\endlist} \makeatother \InputIfFileExists{aebdocfmt.def}{\PackageWarning{eq-pin2corr}{Inputting aebdocfmt.def}} {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax \PackageInfo{eq-pin2corr}{aebdocfmt.def cannot be found}} \begin{document} \addtolength{\marginparwidth}{3pt} \GetFileInfo{eq-pin2corr.sty} \title{The \textsf{eq-pin2corr} Package} \author{D. P. Story\\ Email: \texttt{dpstory@uakron.edu}} \date{processed \today} \maketitle \setcounter{secnumdepth}{5} \setcounter{tocdepth}{5} \bgroup \value{secnumdepth}=3 \value{tocdepth}=3 \tableofcontents \egroup \DocInput{eq-pin2corr.dtx} \IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex}{\paragraph*{Index} The index goes here. Execute \begin{quote}\texttt{makeindex -s gind.ist -o eq-pin2corr.ind eq-pin2corr.idx}\end{quote} on the command line and recompile \texttt{eq-pin2corr.dtx}.} \IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here. Execute \begin{quote} \texttt{makeindex -s gglo.ist -o eq-pin2corr.gls eq-pin2corr.glo} \end{quote} on the command line and recompile \texttt{eq-pin2corr.dtx}.} \end{document} % % \fi % \MakeShortVerb{|} % \InputIfFileExists{aebdonotindex.def}{\PackageInfo{web}{Inputting aebdonotindex.def}} % {\PackageInfo{web}{cannot find aebdonotindex.def}} % \begin{macrocode} %<*package> % \end{macrocode} % % \section{Introduction} % This package is an add-on to the \env{quiz} environment of the \pkg{exerquiz} package. It uses % the \pkg{eq-save} package. To correct a quiz, the document consumer must press % the \uif{Correct} button of a quiz and successfully enter the correct PIN number. % % \changes{v1.0}{2021/02/20}{Completed documentation, publish package for first time} % % \paragraph*{Purpose.} This package adds PIN security to a quiz created by % the \env{quiz} environment. This package is designed for the educational % sector, for instructors who use the quizzes of \pkg{exerquiz} to assess their % students understanding of the course material. % % \paragraph*{PDF Viewers.} Discussion of PDF viewers for document author and document consumer. % \begin{aebQuote} % \begin{description} % \item[Instructor] Any PDF viewer may be used as a PDF previewer, \app{sumatraPDF}, for instance, % can be used, but it has not functionality. To test the newly created document % to see if it is functioning correctly, must use \app{Adobe Reader DC} or \app{Acrobat DC}.\footnote % {We use DC here to refer to actually any Adobe AA/AR application. Earlier versions of these applications % will work.} % \item[Document consumers (students)] The \pkg{exerquiz} and \pkg{eq-pin2tocorr} extensively % use JavaScript to perform many background tasks. For the student to have any success in this % workflow, he/she must use \app{Adobe Reader}. % \end{description} % \end{aebQuote} % \paragraph*{Workflow.} The package is designed for the following workflow: % \begin{enumerate} % \item The instructor creates the quiz using the \pkg{exerquiz} and % \pkg{eq-pin2corr} packages. % \item The instructor delivers the ``PDF quiz'' to each student. (System drive or email) % \item The student takes the quiz. The student can press the \uif{Correct} % but, unless he/she knows the PIN, the quiz is not marked up. % \item The student saves the PDF quiz in \app{Adobe Reader DC}. % \item The student returns the PDF to the instructor. (System drive or email) % \item The instructor presses the \uif{Correct} button to mark up the quiz % and record the grade of the student. The instructor saves the quiz. % \item The instructor returns the PDF, at some point, to the student. % \item Both instructor and student happily go on with their lives. % \end{enumerate} % \section{Options and package requirements} % \begin{macrocode} \newif\ifPINshowScore \PINshowScorefalse \DeclareOption{showscore}{\PINshowScoretrue} \DeclareOption{!showscore}{\PINshowScorefalse} \ProcessOptions\relax \RequirePackage{exerquiz}[2021/02/17] \RequirePackage{eq-save}[2021/02/17] % \end{macrocode} % \section{Package commands} % Implement local versions\DescribeMacro{\showScoreOn}\DescribeMacro{\showScoreOff}{} of the package options \opt{showscore} and \opt{!showscore}, % these are \cs{showScoreOn} and \cs{showScoreOff}. % \begin{macrocode} \def\showScoreOn{\PINshowScoretrue} \def\showScoreOff{\PINshowScorefalse} % \end{macrocode} % Define \DescribeMacro{\SaveAndSendMsg} a message that appears on the console when the PIN entered is not correct. % \begin{macrocode} \flJSStr[noquotes]{\SaveAndSendMsg}{Success! % Now save and send to the instructor} % \end{macrocode} % Make changes to the \uif{End Quiz} control and to the \uif{Correct} control. % Begin by modifying the \DescribeMacro{\postSubmitQuiz}\cs{postSubmitQuiz} command, which is a hook within the executing % code of the \uif{End Quiz} control. % \begin{macrocode} \begin{defineJS*}[\makeesc\@\makecmt\%]{\postSubmitQuiz} // Begin post submit quiz code% @ifPINSecurity% @ifPINshowScore@else var f = this.getField("ScoreField.@oField"); if ( f!=null ) { f.textSize=0; f.value = "@SaveAndSendMsg"; } else { var f = this.getField("PointsField.@oField"); if (f!=null) { f.textSize=0; f.value = "Success! Now save and send to instructor"; } }@fi@fi oRecordOfQuizData["ScoreData.@oField"]=% [1*Score,1*NQuestions,1*ptScore,1*NPointTotal]; oRecordOfQuizData["RightWrong.@oField"]=% eval(RightWrong.toSource()); oRecordOfQuizData["ProbDist.@oField"]=% eval(ProbDist.toSource()); cntCorrectResponses(); \end{defineJS*} % \end{macrocode} % The command name for the action of the \uif{End Quiz} control is % \DescribeMacro{\eQzBtnActns}\cs{eQzBtnActns}. % We save this and pre-pend a single code line, as needed. % \begin{macrocode} \let\eQzBtnActnsSave\eQzBtnActns \def\eQzBtnActns{\ifPINshowScore\else var bDisplaySilent=true;\r\fi \eQzBtnActnsSave } % \end{macrocode} % The command name for the action of the \uif{Correct} control is \cs{CorrBtnActionsJS} % we save this and later modify it. % \begin{macrocode} \let\CorrBtnActionsJSSave\CorrBtnActionsJS % \end{macrocode} % We can turn on and off the PIN feature by expanding \DescribeMacro{\usePINCorrBtn} % \cs{usePINCorrBtn} and \DescribeMacro{\restoreCorrBtn}\cs{restoreCorrBtn}. % \begin{macrocode} \newif\ifPINSecurity \PINSecurityfalse \def\usePINCorrBtn{\PINSecuritytrue \let\CorrBtnActionsJS\CorrBtnActionsPwdJS} \def\restoreCorrBtn{\PINshowScoretrue\PINSecurityfalse \let\CorrBtnActionsJS\CorrBtnActionsJSSave} % \end{macrocode} % The instructor can tediously press the \uif{Correction} button, or place % an entry, %\begin{Verbatim}[xleftmargin=\parindent,fontsize=\small, %commandchars={!()},codes={\catcode`\%=9}] %var _PinCode1 = "02JRVZdRgYgCA-Rtje8VkD"; %\end{Verbatim} %in the file \texttt{config.js}. If such a variable exists and its value %matches the PIN hash string, the instructor clicks the \uif{Correction} button %to get the quiz markup. Conceivably, the instructor might want different PIN names %and string hash values. The \DescribeMacro\classPINVar\cs{classPINVar} is a convenient %way of declaring the PIN variable name; eg, if |\classPINVar{_PinCode1}| is declared %prior to the \env{quiz} environment, the instructor need not manually enter the PIN. % \begin{macrocode} \def\classPINVar#1{\def\PINclassPV{#1}} \let\PINclassPV\@empty % \end{macrocode} % The modified action for the \uif{Correct} button. % we save this and later modify it. % \begin{macrocode} \begin{defineJS*}[\makeesc\!\makecmt\%]{\CorrBtnActionsPwdJS} !ifx!PINclassPV!@empty% var userPIN = "";!else% var userPIN = "!PINclassPV";!fi if (userPIN == "" ) userPIN = undefined; try { if ( typeof eval(userPIN) == "undefined") userPIN = undefined; } catch(e) { userPIN = undefined; } if (typeof userPIN == "undefined") { var resp=app.response({ cQuestion: "Enter the PIN number", cTitle: "View Answers", bPassword: true }); var _resp=Collab.hashString(resp); var _bQzResults = ( _resp ==_PinCode ); } else var _bQzResults = ( eval(userPIN) ==_PinCode ); if (_bQzResults) { RightWrong=eval("RightWrong.!currQuiz"); ProbDist=eval("ProbDist.!currQuiz"); correctQuiz("!currQuiz",3); DisplayQuizResults("!currQuiz",3,3); if (typeof correctSumryTbl == "function") correctSumryTbl("!currQuiz",3); } else { console.println("Something went wrong, \\ you entered an incorrect PIN Id, \\ or the class PIN Id (\\\\classPINVar) was incorrect or undefined"); console.show(); } \end{defineJS*} % \end{macrocode} % \DescribeMacro\declPINId\hskip-\marginparsep\texttt{\darg{\ameta{PIN-Id}}\darg{\ameta{hash-str}}} % Set the basic parameters of this PIN security scheme: the pin-id and its corresponding hash-string. % \begin{macrocode} \def\declPINId#1#2{\def\numPINId{#1}\def\hashPINId{#2}} \@onlypreamble\declPINId \declPINId{5243}{02JRVZdRgYgCA-Rtje8VkD} % PIN Id, hash-str \begin{insDLJS}{pin}{Pin Code} var _PinCode = "\hashPINId"; \end{insDLJS} % \end{macrocode} % \begin{macrocode} % % \end{macrocode} %\Finale