diff options
author | Karl Berry <karl@freefriends.org> | 2021-06-05 21:11:32 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-06-05 21:11:32 +0000 |
commit | f963a899e682e2f4b5b24d37c136e0684b5101ff (patch) | |
tree | f0c540fe5bce0c1d5570e57ddf219bc491dd66bf /Master/texmf-dist/source/latex/eq-pin2corr | |
parent | 78c395ca6a30c6898aba7674a4cdf2f07821e9e4 (diff) |
eq-pin2corr (5jun21)
git-svn-id: svn://tug.org/texlive/trunk@59477 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/eq-pin2corr')
-rw-r--r-- | Master/texmf-dist/source/latex/eq-pin2corr/eq-pin2corr.dtx | 328 |
1 files changed, 287 insertions, 41 deletions
diff --git a/Master/texmf-dist/source/latex/eq-pin2corr/eq-pin2corr.dtx b/Master/texmf-dist/source/latex/eq-pin2corr/eq-pin2corr.dtx index 091ba8a94f4..537bc48894d 100644 --- a/Master/texmf-dist/source/latex/eq-pin2corr/eq-pin2corr.dtx +++ b/Master/texmf-dist/source/latex/eq-pin2corr/eq-pin2corr.dtx @@ -16,7 +16,7 @@ %</copyright> %<package>\NeedsTeXFormat{LaTeX2e} %<package>\ProvidesPackage{eq-pin2corr} -%<package> [2021/02/20 v1.0 Applies PIN security to quizzes] +%<package> [2021/05/29 v2.0 Applies PIN security to quizzes] %<*driver> \documentclass{ltxdoc} %\usepackage[colorlinks,hyperindex=false,linktocpage,bookmarksnumbered]{hyperref} @@ -52,6 +52,19 @@ {-3.5ex \@plus -1ex \@minus -.2ex}% {2.3ex \@plus.2ex}% {\normalfont\Large\bfseries}} +\renewcommand{\subsection} + {\renewcommand{\@seccntformat}[1]{\thesubsection\quad}% + \@startsection {subsection}{1}{\z@}% + {-3.5ex \@plus -1ex \@minus -.2ex}% + {2.3ex \@plus.2ex}% + {\normalfont\large\bfseries}} +\renewcommand{\subsubsection} + {\renewcommand{\@seccntformat}[1]{\thesubsubsection\quad}% + \@startsection {subsubsection}{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}} @@ -63,8 +76,9 @@ {\list{}{\leftmargin\amtIndent}% \item\relax} {\endlist} +\let\@latex@warning\@gobble \makeatother -\InputIfFileExists{aebdocfmt.def}{\PackageWarning{eq-pin2corr}{Inputting aebdocfmt.def}} +\InputIfFileExists{aebdocfmt.def}{\PackageInfo{eq-pin2corr}{Inputting aebdocfmt.def}} {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax \PackageInfo{eq-pin2corr}{aebdocfmt.def cannot be found}} \begin{document} @@ -147,8 +161,8 @@ \DeclareOption{showscore}{\PINshowScoretrue} \DeclareOption{!showscore}{\PINshowScorefalse} \ProcessOptions\relax -\RequirePackage{exerquiz}[2021/02/17] -\RequirePackage{eq-save}[2021/02/17] +\RequirePackage{exerquiz}[2021/05/21] +\RequirePackage{eq-save}[2021/04/27] % \end{macrocode} % \section{Package commands} % Implement local versions\DescribeMacro{\showScoreOn}\DescribeMacro{\showScoreOff}{} of the package options \opt{showscore} and \opt{!showscore}, @@ -157,37 +171,38 @@ \def\showScoreOn{\PINshowScoretrue} \def\showScoreOff{\PINshowScorefalse} % \end{macrocode} +% \subsection{PIN security on the \textsf{Correct} control} % 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. +% \DescribeMacro\postSubmitQuizPIN +% Begin by modifying the \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{defineJS*}[\makeesc\@\makecmt\%]{\postSubmitQuizPIN} // 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) { + var f = this.getField("ScoreField.@oField"); + if ( f!=null ) { f.textSize=0; - f.value = "Success! Now save and send to instructor"; - } - }@fi@fi - oRecordOfQuizData["ScoreData.@oField"]=% + f.value = "@SaveAndSendMsg"; + } else { + var f = this.getField("PointsField.@oField"); + if (f!=null) { + f.textSize=0; + f.value = "@SaveAndSendMsg"; + } + }@fi@fi + oRecordOfQuizData["ScoreData.@oField"]=% [1*Score,1*NQuestions,1*ptScore,1*NPointTotal]; - oRecordOfQuizData["RightWrong.@oField"]=% + oRecordOfQuizData["RightWrong.@oField"]=% eval(RightWrong.toSource()); - oRecordOfQuizData["ProbDist.@oField"]=% + oRecordOfQuizData["ProbDist.@oField"]=% eval(ProbDist.toSource()); - cntCorrectResponses(); + cntCorrectResponses(); \end{defineJS*} % \end{macrocode} % The command name for the action of the \uif{End Quiz} control is @@ -195,10 +210,15 @@ eval(ProbDist.toSource()); % We save this and pre-pend a single code line, as needed. % \begin{macrocode} \let\eQzBtnActnsSave\eQzBtnActns -\def\eQzBtnActns{\ifPINshowScore\else +\def\makeEndQuizPIN{% + \let\eQzBtnActns\eQzBtnActnsPIN + \let\postSubmitQuiz\postSubmitQuizPIN +} +\def\eQzBtnActnsPIN{\ifPINshowScore\else var bDisplaySilent=true;\r\fi \eQzBtnActnsSave } +%\makeEndQuizPIN % \end{macrocode} % The command name for the action of the \uif{Correct} control is \cs{CorrBtnActionsJS} % we save this and later modify it. @@ -210,8 +230,10 @@ eval(ProbDist.toSource()); % \begin{macrocode} \newif\ifPINSecurity \PINSecurityfalse \def\usePINCorrBtn{\PINSecuritytrue + \makeEndQuizPIN % dps5-25 \let\CorrBtnActionsJS\CorrBtnActionsPwdJS} \def\restoreCorrBtn{\PINshowScoretrue\PINSecurityfalse + \restoreEndQuiz % dps5-25 \let\CorrBtnActionsJS\CorrBtnActionsJSSave} % \end{macrocode} % The instructor can tediously press the \uif{Correction} button, or place @@ -226,18 +248,31 @@ eval(ProbDist.toSource()); %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. +%\changes{v1.1}{2021/05/22}{Added \string\cs{ifFreezeQuiz} switch and \string\cs{FreezeThisQuiz} +%convenience macro} % \begin{macrocode} \def\classPINVar#1{\def\PINclassPV{#1}} \let\PINclassPV\@empty % \end{macrocode} +% \DescribeMacro\FreezeThisQuiz +% Causes the interactive parts of a quiz to be readonly. This can be passed +% into the \uif{End Quiz} control so that when the student presses \uif{End Quiz} +% the quiz will be frozen (after a warning); or through the \uif{Correct} button, +% then the returned quiz will be readonly. +% \begin{macrocode} +\newif\ifFreezeQuiz\FreezeQuizfalse +\def\FreezeThisQuiz{\FreezeQuiztrue} +\def\FreezeThisQuizNot{\FreezeQuizfalse} +% \end{macrocode} +% \DescribeMacro\CorrBtnActionsPwdJS % 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; +\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; } @@ -247,34 +282,245 @@ if (typeof userPIN == "undefined") { cTitle: "View Answers", bPassword: true }); - var _resp=Collab.hashString(resp); - var _bQzResults = ( _resp ==_PinCode ); + var _resp=Collab.hashString(resp); + if (resp != null) 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); +% \end{macrocode} +% (2021/05/24) Do nothing if no quiz data +% \begin{macrocode} + if (typeof oRecordOfQuizData["ScoreData.|currQuiz"]!="undefined") { + RightWrong=eval("RightWrong.|currQuiz"); + ProbDist=eval("ProbDist.|currQuiz"); + correctQuiz("|currQuiz",3); + DisplayQuizResults("|currQuiz",3,3); + if (typeof correctSumryTbl == "function") + correctSumryTbl("|currQuiz",3);% +% \end{macrocode} +% (2021/05/22) If \cs{ifFreezeQuiz} is true, we add some code to freeze all operational +% components of this quiz. +% \begin{macrocode} +|ifFreezeQuiz + var aFrzExt=new Array("obj.","grpobj.","essay.",% +"beginQuiz.","endQuiz."); + for (var i=0; i<aFrzExt.length; i++) { + var f=this.getField(aFrzExt[i]+"|currQuiz"); + if (f!=null) f.readonly=true; + }|fi + } else { + var retn=app.alert({% +cMsg: "No quiz data, do you want to mark it anyway?",% +cTitle: "AcroTeX", nIcon: 2, nType: 2}); + if (retn==4) { + var bDisplaySilent=false; + InitializeQuiz("|currQuiz",1,0); + var f=this.getField("ScoreData.|currQuiz"); + f.value="0;0;0;0"; + cntCorrectResponses(); + correctQuiz("|currQuiz",3); + DisplayQuizResults("|currQuiz",3,3,false); + if (typeof correctSumryTbl == "function") + correctSumryTbl("|currQuiz",3); + } + } } else { - console.println("Something went wrong, \\ -you entered an incorrect PIN Id, \\ + if (resp != null) { + console.clear() + console.println("Something went wrong, % +you entered an incorrect PIN Id, % or the class PIN Id (\\\\classPINVar) was incorrect or undefined"); - console.show(); + app.beep(0); + 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. +% +% \subsection{Declare PIN for \textsf{Correction} and \textsf{Begin Quiz} controls} +% Two PIN-related commands are defined: (1) \cs{declPINId} is for security on the +% \uif{Correct} control; (2) \cs{declRePINId} is for security on the \uif{Begin Quiz} +% control.\medskip +% +% \noindent\DescribeMacro\declPINId\hskip-\marginparsep\texttt{\darg{\ameta{PIN-Id}}\darg{\ameta{hash-str}}} +% Set the basic parameters of this PIN security scheme for the \uif{Correct} control: +% 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 +% \end{macrocode} +% \DescribeMacro\declRePINId\hskip-\marginparsep\texttt{\darg{\ameta{PIN-Id}}\darg{\ameta{hash-str}}} +% Set the basic parameters of this PIN security scheme on the \uif{Begin Quiz} control: +% the pin-id and its corresponding hash-string. +% \begin{macrocode} +\def\declRePINId#1#2{\def\numRePINId{#1}\def\hashRePINId{#2}} +\@onlypreamble\declRePINId +\declRePINId{1234}{By9mbLF0NJMA2sN2x4D0VB} \begin{insDLJS}{pin}{Pin Code} var _PinCode = "\hashPINId"; +var _rePinCode = "\hashRePINId"; \end{insDLJS} % \end{macrocode} +% \subsection{Warn and Freeze on \textsf{End Quiz}} +% \DescribeMacro\useWarnEndQuiz +% (2021/05/22) Optional modifications to the \uif{End Quiz} control. +% \changes{v1.1}{2021/05/22}{Define \string\cs{useWarnEndQuiz} and +% \string\cs{EndQuizG@tePIN}} +% \begin{macrocode} +\def\useWarnEndQuiz{\let\EndQuizG@te\EndQuizG@tePIN} +\flJSStr{\EndQuizG@te@Msg}{Warning: +Are you sure you want to end this quiz?\r\r +The quiz will be frozen and no more changes will be allowed. +Click 'Yes' to end the quiz or 'No' to continue working on the quiz.} +\def\PINgobii#1#2{} +\begin{defineJS}[\makeesc\|\makecmt\%]{\EndQuizG@tePIN} +// Begin insertion of new code + var retn=app.alert({cMsg: |EndQuizG@te@Msg,% +cTitle: "AcroTeX", nIcon: 2, nType: 2}); + if (retn==4) { +% \end{macrocode} +% Freeze this quiz; we make a relevant fields readonly. +% \begin{macrocode} + var aFrzExt=new Array("mc.","obj.","grpobj.",% +"beginQuiz.","endQuiz."); + for (var i=0; i<aFrzExt.length; i++) { + var f=this.getField(aFrzExt[i]+"|currQuiz"); + if (f!=null) f.readonly=true; + }% +|PINgobii +\end{defineJS} +% \end{macrocode} +% The \cs{PINglobii} vacuums up `\verb*! {!', which appears in \cs{eQzBtnActns} of +% \pkg{exerquiz}, in the line \verb*!*EndQuizG@te {!. +% +% \subsection{PIN Security on \textsf{Begin Quiz}} +% +% \DescribeMacro\useBeginQuizPIN (2021/05/29) This command redefines the \uif{Begin Quiz} control to +% require PIN security to retake the quiz. +% \changes{v2.0}{2021/05/29}{Define \string\cs{useBeginQuizPIN}} +% \begin{macrocode} +\def\useBeginQuizPIN{% + \ifx\BeginQuizG@te\BeginQuizG@tePIN\else + \let\BeginQuizG@te\BeginQuizG@tePIN\fi} +% \end{macrocode} +% \cs{restoreBeginQuiz} is defined in \pkg{exerquiz}, but because of a typo, +% it was originally defined as \cs{restorBeginQuiz} (no `e'); until the changes trickle +% through the system, we cover ourselves by \cs{let}ing \cs{restoreBeginQuiz} +% to \cs{restorBeginQuiz}, if the correct spelling of the command does not already +% exist. +% \begin{macrocode} +\@ifundefined{restoreBeginQuiz}{\let\restoreBeginQuiz\restorBeginQuiz}{} +% \end{macrocode} +% \begin{macrocode} +\flJSStr{\BeginQuizG@te@Msgi}{Enter the PIN number +to retake this quiz} +\flJSStr{\BeginQuizG@te@Msgii}{Press the Begin Quiz control to begin +the quiz again} +\def\PINgobiii#1#2#3{} +% \end{macrocode} +% \begin{macrocode} +\begin{defineJS}[\makeesc\|\makecmt\%]{\BeginQuizG@tePIN} +if (typeof oRecordOfQuizData["ScoreData.|currQuiz"] != "undefined" ) { + var resp=app.response({ + cQuestion: |BeginQuizG@te@Msgi, + cTitle: "AcroTeX", + bPassword: true + }); + var _respHash=_resp=Collab.hashString(resp); + if (_resp == _rePinCode) { + oRecordOfQuizData["ScoreData.|currQuiz"]=undefined; + app.alert(|BeginQuizG@te@Msgii); + var f=this.getField("tallyresets.|currQuiz"); + if (f!=null) f.value=1+f.value; + } +} else { +|PINgobiii +\end{defineJS} +% \end{macrocode} +% \cs{PINglobiii} gobbles the three tokens `\verb*! {\jsR!', which appear in the definition of \cs{@initQuiz} in +% \pkg{exerquiz}, in the line \verb*!\BeginQuizG@te\space\jsLB\jsR\jsT!. +% +% \section{Tracking the number of \textsf{Begin Quiz} events} +% A command \cs{qzResetTally} is defined to hold the number of times a user has taken +% the same quiz. This field is readonly, and does not reset, unless you have know how to do it. +% \begin{macrocode} +% \end{macrocode} +% \DescribeMacro{\qzResetTally}\hskip-\marginparsep\texttt{[\ameta{options}]} +% The \cs{qzResetTally} text field, similar to \cs{sqTallyTotal}, is used to +% count the number of times a student needs to retake the same quiz. +% \begin{macrocode} +% \end{macrocode} +% The default appearance of \cs{qzResetTally} +% \begin{macrocode} +\def\qzTallyTotalDefaults{% + \rawPDF{}\W{1}\BC{0 0 0}\S{I}\textColor{1 0 0 rg} + \Q{2}} +% \end{macrocode} +% The definition of \cs{qzResetTally} +% \begin{macrocode} +\newcommand\qzResetTally[1][]{% + \textField[\presets{\qzTallyTotalDefaults}#1\DV{0}\V{0} + \Ff{\FfReadOnly} + ]{tallyresets.\currQuiz}{\TBW}{\DefaultHeightOfWidget}} +% \end{macrocode} +% \subsection{Placing a maximum on the number of resets} +% The next level of complication is to add a restriction onto the number of +% times the user can retake the quiz.\medskip\par +% +% \noindent +% \DescribeMacro\setMaxRetakes\hskip-\marginparsep\texttt{\darg{\ameta{qz-name}}\darg{\ameta{num}}} +% A command that sets the maximum number of retakes \ameta{num} (nonneg integer) by declaring \cs{setMaxRetakes} prior +% to the quiz \ameta{qz-name}. \DescribeMacro\nMaxRetakes\cs{nMaxRetakes\darg{\ameta{qz-name}}} +% is a public macro that expands to the max number of retakes (\ameta{num}). +% \begin{macrocode} +\newcommand{\setMaxRetakes}[2]{\expandafter + \def\csname1MaxReset#1\endcsname{#2}} +\def\nMaxRetakes#1{\@nameuse{1MaxReset#1}} +% \end{macrocode} +% \subsection{JavaScript support for tracking} +% \DescribeMacro\useBeginQuizCnt Modifies \cs{BeginQuizG@te} (\pkg{exerquiz}, 2021/05/21 or later). +% \cs{useBeginQuizPIN} also modifies \cs{BeginQuizG@te}. These two are incompatible; +% one will overwrite the other. \cs{restoreBeginQuiz} retores \uif{Begin Quiz} to its default definition. +% \changes{v2.0}{2021/05/29}{Define \string\cs{useBeginQuizCnt}} +% \begin{macrocode} +\def\useBeginQuizCnt{% + \ifx\BeginQuizG@te\BeginQuizG@teCNT\else + \let\BeginQuizG@te\BeginQuizG@teCNT\fi} +% \end{macrocode} +% \DescribeMacro\maxRetake@Msg The message that appears in an alert dialog box +% after the student has started the quiz more than the max number, as set by +% \cs{setMaxRetakes}. +% \begin{macrocode} +\flJSStr[noquotes]{\maxRetake@Msg}{You have taken the quiz the maximum +number of times permitted ("+nMaxReset+"). You will not be allowed to +continue to re-take this quiz. Move on with your life.} +% \end{macrocode} +% The action added to \uif{Begin Quiz}, it determines if \cs{qzResetTally} is present for the current quiz +% and if so, increments the current value. +% \begin{macrocode} +\begin{defineJS}[\makeesc\|\makecmt\%]{\BeginQuizG@teCNT} +if (typeof oRecordOfQuizData["ScoreData.|currQuiz"] != "undefined" ) +{ + var _bOKReset=true; + var f=this.getField("tallyresets.|currQuiz"); + if (f!=null) var value=1*f.value;% +|expandafter|ifx|csname1MaxReset|currQuiz|endcsname|relax|else + var nMaxReset=|csname1MaxReset|currQuiz|endcsname; + if (f!=null && value==nMaxReset) { + app.alert("|maxRetake@Msg"); + _bOKReset=false; + }|fi + if (_bOKReset) { + oRecordOfQuizData["ScoreData.|currQuiz"]=undefined; + app.alert(|BeginQuizG@te@Msgii); + if (f!=null) f.value=1+value; + } +} else { +|PINgobiii +\end{defineJS} +% \end{macrocode} +% \cs{PINglobiii} gobbles the three tokens `\verb*! {\jsR!', which appear in the definition of \cs{@initQuiz} in +% \pkg{exerquiz}, in the line \verb*!\BeginQuizG@te\space\jsLB\jsR\jsT!. % \begin{macrocode} %</package> % \end{macrocode} |