• No results found

The eq-pin2corr Package

N/A
N/A
Protected

Academic year: 2021

Share "The eq-pin2corr Package"

Copied!
11
0
0

Bezig met laden.... (Bekijk nu de volledige tekst)

Hele tekst

(1)

The eq-pin2corr Package

D. P. Story

Email: dpstory@uakron.edu processed June 5, 2021

Contents

1 Introduction 1

2 Options and package requirements 2

3 Package commands 2

3.1 PIN security on the Correct control . . . . 3

3.2 Declare PIN for Correction and Begin Quiz controls . . . . 5

3.3 Warn and Freeze on End Quiz . . . . 6

3.4 PIN Security on Begin Quiz . . . . 6

4 Tracking the number of Begin Quiz events 7 4.1 Placing a maximum on the number of resets . . . . 8

4.2 JavaScript support for tracking . . . . 8

5 Index 10

6 Change History 11

1 ∗package

1 Introduction

This package is an add-on to the quiz environment of the exerquiz package. It uses the eq-save package. To correct a quiz, the document consumer must press the Correct button of a quiz and successfully enter the correct PIN number.

Purpose. This package adds PIN security to a quiz created by the quiz envi-

ronment. This package is designed for the educational sector, for instructors who

use the quizzes of exerquiz to assess their students understanding of the course

material.

(2)

PDF Viewers. Discussion of PDF viewers for document author and document consumer.

Instructor Any PDF viewer may be used as a PDF previewer, 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 Adobe Reader DC or Acrobat DC.

1

Document consumers (students) The exerquiz and eq-pin2tocorr exten- sively use JavaScript to perform many background tasks. For the student to have any success in this workflow, he/she must use Adobe Reader.

Workflow. The package is designed for the following workflow:

1. The instructor creates the quiz using the exerquiz and eq-pin2corr packages.

2. The instructor delivers the “PDF quiz” to each student. (System drive or email)

3. The student takes the quiz. The student can press the Correct but, unless he/she knows the PIN, the quiz is not marked up.

4. The student saves the PDF quiz in Adobe Reader DC.

5. The student returns the PDF to the instructor. (System drive or email) 6. The instructor presses the Correct button to mark up the quiz and record

the grade of the student. The instructor saves the quiz.

7. The instructor returns the PDF, at some point, to the student.

8. Both instructor and student happily go on with their lives.

2 Options and package requirements

2 \newif\ifPINshowScore \PINshowScorefalse

3 \DeclareOption{showscore}{\PINshowScoretrue}

4 \DeclareOption{!showscore}{\PINshowScorefalse}

5 \ProcessOptions\relax

6 \RequirePackage{exerquiz}[2021/05/21]

7 \RequirePackage{eq-save}[2021/04/27]

3 Package commands

Implement local versions of the package options showscore and !showscore, these

\showScoreOn

\showScoreOff are \showScoreOn and \showScoreOff.

8 \def\showScoreOn{\PINshowScoretrue}

9 \def\showScoreOff{\PINshowScorefalse}

1

We use DC here to refer to actually any Adobe AA/AR application. Earlier versions of these

applications will work.

(3)

3.1 PIN security on the Correct control

Define a message that appears on the console when the PIN entered is not correct.

\SaveAndSendMsg

10 \flJSStr[noquotes]{\SaveAndSendMsg}{Success! %

11 Now save and send to the instructor}

Begin by modifying the \postSubmitQuiz command, which is a hook within the

\postSubmitQuizPIN

executing code of the End Quiz control.

12 \begin{defineJS*}[\makeesc\@\makecmt\%]{\postSubmitQuizPIN}

13 // Begin post submit quiz code%

14 @ifPINSecurity%

15 @ifPINshowScore@else

16 var f = this.getField("ScoreField.@oField");

17 if ( f!=null ) {

18 f.textSize=0;

19 f.value = "@SaveAndSendMsg";

20 } else {

21 var f = this.getField("PointsField.@oField");

22 if (f!=null) {

23 f.textSize=0;

24 f.value = "@SaveAndSendMsg";

25 }

26 }@fi@fi

27 oRecordOfQuizData["ScoreData.@oField"]=%

28 [1*Score,1*NQuestions,1*ptScore,1*NPointTotal];

29 oRecordOfQuizData["RightWrong.@oField"]=%

30 eval(RightWrong.toSource());

31 oRecordOfQuizData["ProbDist.@oField"]=%

32 eval(ProbDist.toSource());

33 cntCorrectResponses();

34 \end{defineJS*}

The command name for the action of the End Quiz control is \eQzBtnActns. We

\eQzBtnActns

save this and pre-pend a single code line, as needed.

35 \let\eQzBtnActnsSave\eQzBtnActns

36 \def\makeEndQuizPIN{%

37 \let\eQzBtnActns\eQzBtnActnsPIN

38 \let\postSubmitQuiz\postSubmitQuizPIN

39 }

40 \def\eQzBtnActnsPIN{\ifPINshowScore\else

41 var bDisplaySilent=true;\r\fi

42 \eQzBtnActnsSave

43 }

44 %\makeEndQuizPIN

The command name for the action of the Correct control is \CorrBtnActionsJS we save this and later modify it.

45 \let\CorrBtnActionsJSSave\CorrBtnActionsJS

We can turn on and off the PIN feature by expanding \usePINCorrBtn and

\usePINCorrBtn

\restoreCorrBtn.

\restoreCorrBtn

(4)

46 \newif\ifPINSecurity \PINSecurityfalse

47 \def\usePINCorrBtn{\PINSecuritytrue

48 \makeEndQuizPIN % dps5-25

49 \let\CorrBtnActionsJS\CorrBtnActionsPwdJS}

50 \def\restoreCorrBtn{\PINshowScoretrue\PINSecurityfalse

51 \restoreEndQuiz % dps5-25

52 \let\CorrBtnActionsJS\CorrBtnActionsJSSave}

The instructor can tediously press the Correction button, or place an entry, var _PinCode1 = "02JRVZdRgYgCA-Rtje8VkD";

in the file config.js. If such a variable exists and its value matches the PIN hash string, the instructor clicks the Correction button to get the quiz markup.

Conceivably, the instructor might want different PIN names and string hash val- ues. The \classPINVar is a convenient way of declaring the PIN variable name;

\classPINVar

eg, if \classPINVar{_PinCode1} is declared prior to the quiz environment, the instructor need not manually enter the PIN.

53 \def\classPINVar#1{\def\PINclassPV{#1}}

54 \let\PINclassPV\@empty

Causes the interactive parts of a quiz to be readonly. This can be passed into the

\FreezeThisQuiz

End Quiz control so that when the student presses End Quiz the quiz will be frozen (after a warning); or through the Correct button, then the returned quiz will be readonly.

55 \newif\ifFreezeQuiz\FreezeQuizfalse

56 \def\FreezeThisQuiz{\FreezeQuiztrue}

57 \def\FreezeThisQuizNot{\FreezeQuizfalse}

The modified action for the Correct button. we save this and later modify it.

\CorrBtnActionsPwdJS

58 \begin{defineJS*}[\makeesc\|\makecmt\%]{\CorrBtnActionsPwdJS}

59 |ifx|PINclassPV|@empty%

60 var userPIN = "";|else%

61 var userPIN = "|PINclassPV";|fi

62 if (userPIN == "") userPIN = undefined;

63 try {

64 if ( typeof eval(userPIN) == "undefined") userPIN = undefined;

65 } catch(e) { userPIN = undefined; }

66 if (typeof userPIN == "undefined") {

67 var resp=app.response({

68 cQuestion: "Enter the PIN number",

69 cTitle: "View Answers",

70 bPassword: true

71 });

72 var _resp=Collab.hashString(resp);

73 if (resp != null) var _bQzResults = ( _resp ==_PinCode );

74 } else var _bQzResults = ( eval(userPIN) ==_PinCode );

75 if (_bQzResults) {

(2021/05/24) Do nothing if no quiz data

76 if (typeof oRecordOfQuizData["ScoreData.|currQuiz"]!="undefined") {

(5)

77 RightWrong=eval("RightWrong.|currQuiz");

78 ProbDist=eval("ProbDist.|currQuiz");

79 correctQuiz("|currQuiz",3);

80 DisplayQuizResults("|currQuiz",3,3);

81 if (typeof correctSumryTbl == "function")

82 correctSumryTbl("|currQuiz",3);%

(2021/05/22) If \ifFreezeQuiz is true, we add some code to freeze all operational components of this quiz.

83 |ifFreezeQuiz

84 var aFrzExt=new Array("obj.","grpobj.","essay.",%

85 "beginQuiz.","endQuiz.");

86 for (var i=0; i<aFrzExt.length; i++) {

87 var f=this.getField(aFrzExt[i]+"|currQuiz");

88 if (f!=null) f.readonly=true;

89 }|fi

90 } else {

91 var retn=app.alert({%

92 cMsg: "No quiz data, do you want to mark it anyway?",%

93 cTitle: "AcroTeX", nIcon: 2, nType: 2});

94 if (retn==4) {

95 var bDisplaySilent=false;

96 InitializeQuiz("|currQuiz",1,0);

97 var f=this.getField("ScoreData.|currQuiz");

98 f.value="0;0;0;0";

99 cntCorrectResponses();

100 correctQuiz("|currQuiz",3);

101 DisplayQuizResults("|currQuiz",3,3,false);

102 if (typeof correctSumryTbl == "function")

103 correctSumryTbl("|currQuiz",3);

104 }

105 }

106 } else {

107 if (resp != null) {

108 console.clear()

109 console.println("Something went wrong, %

110 you entered an incorrect PIN Id, %

111 or the class PIN Id (\\\\classPINVar) was incorrect or undefined");

112 app.beep(0);

113 console.show();

114 }

115 }

116 \end{defineJS*}

3.2 Declare PIN for Correction and Begin Quiz controls

Two PIN-related commands are defined: (1) \declPINId is for security on the Correct control; (2) \declRePINId is for security on the Begin Quiz control.

{PIN-Id}{hash-str} Set the basic parameters of this PIN security scheme for

\declPINId

(6)

the Correct control: the pin-id and its corresponding hash-string.

117 \def\declPINId#1#2{\def\numPINId{#1}\def\hashPINId{#2}}

118 \@onlypreamble\declPINId

119 \declPINId{5243}{02JRVZdRgYgCA-Rtje8VkD} % PIN Id, hash-str

{PIN-Id}{hash-str} Set the basic parameters of this PIN security scheme on

\declRePINId

the Begin Quiz control: the pin-id and its corresponding hash-string.

120 \def\declRePINId#1#2{\def\numRePINId{#1}\def\hashRePINId{#2}}

121 \@onlypreamble\declRePINId

122 \declRePINId{1234}{By9mbLF0NJMA2sN2x4D0VB}

123 \begin{insDLJS}{pin}{Pin Code}

124 var _PinCode = "\hashPINId";

125 var _rePinCode = "\hashRePINId";

126 \end{insDLJS}

3.3 Warn and Freeze on End Quiz

(2021/05/22) Optional modifications to the End Quiz control.

\useWarnEndQuiz

127 \def\useWarnEndQuiz{\let\EndQuizG@te\EndQuizG@tePIN}

128 \flJSStr{\EndQuizG@te@Msg}{Warning:

129 Are you sure you want to end this quiz?\r\r

130 The quiz will be frozen and no more changes will be allowed.

131 Click ’Yes’ to end the quiz or ’No’ to continue working on the quiz.}

132 \def\PINgobii#1#2{}

133 \begin{defineJS}[\makeesc\|\makecmt\%]{\EndQuizG@tePIN}

134 // Begin insertion of new code

135 var retn=app.alert({cMsg: |EndQuizG@te@Msg,%

136 cTitle: "AcroTeX", nIcon: 2, nType: 2});

137 if (retn==4) {

Freeze this quiz; we make a relevant fields readonly.

138 var aFrzExt=new Array("mc.","obj.","grpobj.",%

139 "beginQuiz.","endQuiz.");

140 for (var i=0; i<aFrzExt.length; i++) {

141 var f=this.getField(aFrzExt[i]+"|currQuiz");

142 if (f!=null) f.readonly=true;

143 }%

144 |PINgobii

145 \end{defineJS}

The \PINglobii vacuums up ‘{’, which appears in \eQzBtnActns of exerquiz, in the line *EndQuizG@te{.

3.4 PIN Security on Begin Quiz

(2021/05/29) This command redefines the Begin Quiz control to require PIN se-

\useBeginQuizPIN

curity to retake the quiz.

146 \def\useBeginQuizPIN{%

147 \ifx\BeginQuizG@te\BeginQuizG@tePIN\else

(7)

148 \let\BeginQuizG@te\BeginQuizG@tePIN\fi}

\restoreBeginQuiz is defined in exerquiz, but because of a typo, it was originally defined as \restorBeginQuiz (no ‘e’); until the changes trickle through the sys- tem, we cover ourselves by \leting \restoreBeginQuiz to \restorBeginQuiz, if the correct spelling of the command does not already exist.

149 \@ifundefined{restoreBeginQuiz}{\let\restoreBeginQuiz\restorBeginQuiz}{}

150 \flJSStr{\BeginQuizG@te@Msgi}{Enter the PIN number

151 to retake this quiz}

152 \flJSStr{\BeginQuizG@te@Msgii}{Press the Begin Quiz control to begin

153 the quiz again}

154 \def\PINgobiii#1#2#3{}

155 \begin{defineJS}[\makeesc\|\makecmt\%]{\BeginQuizG@tePIN}

156 if (typeof oRecordOfQuizData["ScoreData.|currQuiz"] != "undefined" ) {

157 var resp=app.response({

158 cQuestion: |BeginQuizG@te@Msgi,

159 cTitle: "AcroTeX",

160 bPassword: true

161 });

162 var _respHash=_resp=Collab.hashString(resp);

163 if (_resp == _rePinCode) {

164 oRecordOfQuizData["ScoreData.|currQuiz"]=undefined;

165 app.alert(|BeginQuizG@te@Msgii);

166 var f=this.getField("tallyresets.|currQuiz");

167 if (f!=null) f.value=1+f.value;

168 }

169 } else {

170 |PINgobiii

171 \end{defineJS}

\PINglobiii gobbles the three tokens ‘{\jsR’, which appear in the definition of

\@initQuiz in exerquiz, in the line \BeginQuizG@te\space\jsLB\jsR\jsT.

4 Tracking the number of Begin Quiz events

A command \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.

[options] The \qzResetTally text field, similar to \sqTallyTotal, is used to

\qzResetTally

count the number of times a student needs to retake the same quiz.

The default appearance of \qzResetTally

172 \def\qzTallyTotalDefaults{%

173 \rawPDF{}\W{1}\BC{0 0 0}\S{I}\textColor{1 0 0 rg}

174 \Q{2}}

The definition of \qzResetTally

175 \newcommand\qzResetTally[1][]{%

(8)

176 \textField[\presets{\qzTallyTotalDefaults}#1\DV{0}\V{0}

177 \Ff{\FfReadOnly}

178 ]{tallyresets.\currQuiz}{\TBW}{\DefaultHeightOfWidget}}

4.1 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.

{qz-name}{num} A command that sets the maximum number of retakes num

\setMaxRetakes

(nonneg integer) by declaring \setMaxRetakes prior to the quiz qz-name.

\nMaxRetakes{qz-name} is a public macro that expands to the max number

\nMaxRetakes

of retakes ( num).

179 \newcommand{\setMaxRetakes}[2]{\expandafter

180 \def\csname1MaxReset#1\endcsname{#2}}

181 \def\nMaxRetakes#1{\@nameuse{1MaxReset#1}}

4.2 JavaScript support for tracking

Modifies \BeginQuizG@te (exerquiz, 2021/05/21 or later). \useBeginQuizPIN

\useBeginQuizCnt

also modifies \BeginQuizG@te. These two are incompatible; one will overwrite the other. \restoreBeginQuiz retores Begin Quiz to its default definition.

182 \def\useBeginQuizCnt{%

183 \ifx\BeginQuizG@te\BeginQuizG@teCNT\else

184 \let\BeginQuizG@te\BeginQuizG@teCNT\fi}

The message that appears in an alert dialog box after the student has started the

\maxRetake@Msg

quiz more than the max number, as set by \setMaxRetakes.

185 \flJSStr[noquotes]{\maxRetake@Msg}{You have taken the quiz the maximum

186 number of times permitted ("+nMaxReset+"). You will not be allowed to

187 continue to re-take this quiz. Move on with your life.}

The action added to Begin Quiz, it determines if \qzResetTally is present for the current quiz and if so, increments the current value.

188 \begin{defineJS}[\makeesc\|\makecmt\%]{\BeginQuizG@teCNT}

189 if (typeof oRecordOfQuizData["ScoreData.|currQuiz"] != "undefined" )

190 {

191 var _bOKReset=true;

192 var f=this.getField("tallyresets.|currQuiz");

193 if (f!=null) var value=1*f.value;%

194 |expandafter|ifx|csname1MaxReset|currQuiz|endcsname|relax|else

195 var nMaxReset=|csname1MaxReset|currQuiz|endcsname;

196 if (f!=null && value==nMaxReset) {

197 app.alert("|maxRetake@Msg");

198 _bOKReset=false;

199 }|fi

200 if (_bOKReset) {

201 oRecordOfQuizData["ScoreData.|currQuiz"]=undefined;

(9)

202 app.alert(|BeginQuizG@te@Msgii);

203 if (f!=null) f.value=1+value;

204 }

205 } else {

206 |PINgobiii

207 \end{defineJS}

\PINglobiii gobbles the three tokens ‘{\jsR’, which appear in the definition of

\@initQuiz in exerquiz, in the line \BeginQuizG@te\space\jsLB\jsR\jsT.

208 /package

(10)

5 Index

Numbers written in italic refer to the page where the corresponding entry is described; numbers underlined refer to the code line of the definition; numbers in roman refer to the code lines where the entry is used.

Symbols

\% . . . . 12, 58, 133, 155, 188

\@onlypreamble . . . . 118, 121

\| . . . . 58, 133, 155, 188

B

\BC . . . 173

\BeginQuizG@te . . . . 147, 148, 183, 184

\BeginQuizG@te@Msgi . . . 150

\BeginQuizG@te@Msgii . . . 152

\BeginQuizG@teCNT . . . 183, 184, 188

\BeginQuizG@tePIN . . . 147, 148, 155

C

\classPINVar . . . 4, 53

\CorrBtnActionsJS . . . . 45, 49, 52

\CorrBtnActionsJSSave . . . 45, 52

\CorrBtnActionsPwdJS . . . . 4, 49, 58

\currQuiz . . . 178

D

\DeclareOption . . . 3, 4

\declPINId . . . 5, 117–119

\declRePINId . . . 6, 120–122

\DefaultHeightOfWidget . . . 178

\DV . . . 176

E

\EndQuizG@te . . . 127

\EndQuizG@te@Msg . . . 128

\EndQuizG@tePIN . . . . 127, 133

\eQzBtnActns . . . . 3, 35, 37

\eQzBtnActnsPIN . . . 37, 40

\eQzBtnActnsSave . . . 35, 42

F

\Ff . . . 177

\FfReadOnly . . . 177

\flJSStr . . . 10, 128, 150, 152, 185

\FreezeQuizfalse . . . 55, 57

\FreezeQuiztrue . . . 56

\FreezeThisQuiz . . . 4, 56

\FreezeThisQuizNot . . . 57

H

\hashPINId . . . . 117, 124

\hashRePINId . . . . 120, 125

I

\ifFreezeQuiz . . . 55

\ifPINSecurity . . . 46

\ifPINshowScore . . . 2, 40

M

\makecmt . . . . 12, 58, 133, 155, 188

\makeEndQuizPIN . . . . 36, 44, 48

\makeesc . . . . 12, 58, 133, 155, 188

\maxRetake@Msg . . . 8, 185

N

\nMaxRetakes . . . 8, 181

\numPINId . . . 117

\numRePINId . . . 120

P

\PINclassPV . . . 53, 54

\PINgobii . . . 132

\PINgobiii . . . 154

\PINSecurityfalse . . . 46, 50

\PINSecuritytrue . . . 47

\PINshowScorefalse . . . 2, 4, 9

\PINshowScoretrue . . . 3, 8, 50

\postSubmitQuiz . . . 38

\postSubmitQuizPIN . . . . 3, 12, 38

\presets . . . 176

\ProcessOptions . . . 5

Q

\Q . . . 174

\qzResetTally . . . 7, 175

\qzTallyTotalDefaults . . . . 172, 176

R

\r . . . . 41, 129

\rawPDF . . . 173

\RequirePackage . . . 6, 7

\restorBeginQuiz . . . 149

\restoreBeginQuiz . . . 149

\restoreCorrBtn . . . 3, 50

\restoreEndQuiz . . . 51

(11)

S

\S . . . 173

\SaveAndSendMsg . . . 3, 10

\setMaxRetakes . . . 8, 179

\showScoreOff . . . 2, 9

\showScoreOn . . . 2, 8

T

\TBW . . . 178

\textColor . . . 173

\textField . . . 176

U

\useBeginQuizCnt . . . 8, 182

\useBeginQuizPIN . . . 6, 146

\usePINCorrBtn . . . 3, 47

\useWarnEndQuiz . . . 6, 127

V

\V . . . 176

W

\W . . . 173

6 Change History

v1.0 (2021/02/20)

General: Completed documentation, publish

package for first time . . . 1 v1.1 (2021/05/22)

General: Added \ifFreezeQuiz switch and

\FreezeThisQuiz convenience macro . . . 4

Define \useWarnEndQuiz and

\EndQuizG@tePIN . . . 6 v2.0 (2021/05/29)

General: Define \useBeginQuizCnt . . . 8

Define \useBeginQuizPIN . . . 6

Referenties

GERELATEERDE DOCUMENTEN

If they don’t know the answer, or the answer is wrong, the question passes to the next team, till a team knows the correct answer.. Then this team gets

Als ieder groepje een antwoord heeft opgeschreven laat u met een klik het juiste antwoord zien op het digibord..

Mail ze dan naar Aduis (info@aduis.nl) en wij plaatsen deze dan als downlaod op onze web

Mail ze dan naar Aduis (info@aduis.nl) en wij plaatsen deze dan als downlaod op onze web

Het vrouwtje brengt twee keer per jaar tot 7 jongen op

De geluidsgolven die daardoor ontstaan worden door objecten en prooien teruggekaatst, en zo weet de vleermuis precies waar objecten en prooien zich

Planeten zijn geen sterren, ze geven geen licht, je ziet ze omdat ze door de zon worden beschenen.. Planeten

Mail ze dan naar Aduis (info@aduis.nl) en wij plaatsen deze dan als downlaod op onze web