%% %% This is file `eq-save.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% eq-save.dtx (with options: `copyright,package') %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% eq-save package, %% %% Copyright (C) 2017-2021 %% %% dpstory@uakron.edu %% %% %% %% 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}[1997/12/01] \ProvidesPackage{eq-save} [2021/02/17 v1.2 eq-save: save exerquiz quizzes and resume (dps)] \DeclareOption{devmode}{\def\devMode{true}} \DeclareOption{!devmode}{\def\devMode{false}} \def\devMode{false} \ProcessOptions \RequirePackage{exerquiz}[2017/07/30] \RequirePackage{atbegshi} \edef\ap@restoreCats{% \catcode`\noexpand\"=\the\catcode`\"\relax \catcode`\noexpand\,=\the\catcode`\,\relax \catcode`\noexpand\(=\the\catcode`\(\relax \catcode`\noexpand\!=\the\catcode`\!\relax } \@makeother\"\@makeother\,\@makeother\(\@makeother\! \newcommand\nameField[4][]{\textField[#1 \AAkeystroke{chk4PassToQuestions(event);} \AAformat{if(typeof oRecordOfQuizData=="undefined") \r\t var oRecordOfQuizData=new Object();\r try{IhrNameFormat(event);}catch(e){} }]{#2}{#3}{#4}} \newcommand{\hiddenScoreData}{\makebox[0pt][l]{% \textField[\F\FHidden\V{({})}\DV{({})}\AAformat{% if(typeof oRecordOfQuizData=="undefined")\r\t oRecordOfQuizData={};}\BG{}\BC{}]{holdScoreData}{0bp}{0bp}}} \AtBeginShipoutFirst{\hiddenScoreData} \newcommand{\sField}[3][]{\textField[\Ff{\FfReadOnly}#1]% {\eqsroot.Score}{#2}{#3}} \newcommand{\ooField}[3][]{\textField[\Ff{\FfReadOnly}#1]% {\eqsroot.OutOf}{#2}{#3}} \newcommand{\sooField}[3][]{\textField[\Ff{\FfReadOnly}#1]% {\eqsroot.ScoreComb}{#2}{#3}} \newcommand{\psField}[3][]{\textField[\Ff{\FfReadOnly}#1]% {\eqsroot.ptScore}{#2}{#3}} \newcommand{\pooField}[3][]{\textField[\Ff{\FfReadOnly}#1]% {\eqsroot.ptOutOf}{#2}{#3}} \newcommand{\psooField}[3][]{\textField[\Ff{\FfReadOnly}#1]% {\eqsroot.ptScoreComb}{#2}{#3}} \newcommand{\clearAllField}[3][]{\pushButton[\CA{Clear All}#1 \AAmouseup{clearAllSQElements();}]{globalClearAll}{#2}{#3}} \newcommand{\eqsSetActionKeys}{% \setActionKeys{% \AddAAKeystroke{\if\eqQuizType\isSQZ event.target.isCorrect=(retn)?1:0;\r\t oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r\t cntCorrectResponses();\fi} \AddAAMouseUpMC{\if\eqQuizType\isSQZ event.target.isCorrect=\Ans@choice;\r oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r cntCorrectResponses();\fi} \AddAAMouseUpMS{\if\eqQuizType\isSQZ event.target.isCorrect=\Ans@choice;\r oRecordOfQuizData[event.target.name]=event.target.isCorrect;\r cntCorrectResponses();\fi} }% } \def\postInitQuiz{% var f=this.getField("ScoreData.\oField");\r f.value="0;0;0;0";\r cntCorrectResponses();} \def\postSubmitQuiz{% oRecordOfQuizData["ScoreData.\oField"]=% [1*Score,1*NQuestions,1*ptScore,1*NPointTotal];\r\t\t cntCorrectResponses();\r } \thisPageAction{\JS{if(!restoreQuizData.hasRestoredData)\r\t var rqdTO=(app.setTimeOut("restoreQuizData();app.clearTimeOut(rqdTO);% restoreQuizData.hasRestoredData=true",1000));}}{} \begin{willSave} isAQuizUnfinishedAtSave(); if (typeof oRecordOfQuizData !="undefined") collectQuizData(); \end{willSave} \flJSStr[noquotes,noparens]{\EnterNameFirstMsg}{You must enter your name first!} \def\declareScorePhrase#1{\def\dclScorePhse(##1)(##2){#1}} \declareScorePhrase{#1+"\space\eqOutOf\space"+#2} \def\BeginNoPeeking{\def\IhrNamePO{\thisPageAction{% \JS{if(!_docDevMode&&!_passToQuestions){\r\t this.pageNum=0;\r\t NoNameMsg=app.setTimeOut("app.alert('\EnterNameFirstMsg');% app.clearTimeOut(NoNameMsg);",25);}}}{}}% \IhrNamePO \AtBeginShipout{\IhrNamePO}% } \newcommand{\DeclareReportRootName}[1]{\def\eqsroot{#1}% \eqsSetActionKeys} \DeclareReportRootName{SUMRY} \@onlypreamble{\DeclareReportRootName} \let\jsCodeForQzs\@empty\def\semiColon{;}\let\itsNonEmpty=0 \def\jsForQzs#1\@nil{\jsForQzsi#1;;\@nil} \def\jsForQzsi#1;#2\@nil{\def\argii{#2}\ifx\argii\semiColon \let\eqs@next\relax\else \let\itsNonEmpty=1% \g@addto@macro\jsCodeForQzs{var #1=new Object();^^J}% \def\eqs@next{\jsForQzsi#2\@nil}\fi\eqs@next} \AtEndOfPackage{\InputIfFileExists{qzlist-\jobname.cut}{}{}} \let\jsForQzsHold\@empty \let\cListOfQuizNames\@empty \let\cListOfSQuizNames\@empty \let\eqsHandleOpen=0 \def\saveListofQzs{% \ifx\ListOfQuizNames\@empty\else \let\jsForQzsHold\@empty \let\cListOfQuizNames\@empty \edef\ListOfQuizNames{\expandafter\@gobble\ListOfQuizNames} \immediate\openout\CommentStream=qzlist-\jobname.cut \let\eqsHandleOpen=1 \expandafter\@for\expandafter \@qz\expandafter:\expandafter=\ListOfQuizNames\do{% \edef\@tmpExp{\noexpand \g@addto@macro\noexpand\jsForQzsHold{\@qz;}}\@tmpExp \edef\@tmpExp{\noexpand \g@addto@macro\noexpand\cListOfQuizNames{,"\@qz"}}\@tmpExp }% \fi \ifx\ListOfSQuizNames\@empty\else \if\eqsHandleOpen0 \let\jsForQzsHold\@empty \immediate\openout\CommentStream=qzlist-\jobname.cut \let\eqsHandleOpen=1\fi \let\cListOfSQuizNames\@empty \edef\ListOfSQuizNames{\expandafter\@gobble\ListOfSQuizNames} \expandafter\@for\expandafter\@qz \expandafter:\expandafter=\ListOfSQuizNames\do{% \edef\@tmpExp{\noexpand\g@addto@macro\noexpand \jsForQzsHold{\@qz;}}\@tmpExp \edef\@tmpExp{\noexpand \g@addto@macro\noexpand\cListOfSQuizNames{,"\@qz"}}\@tmpExp }% \immediate\write\CommentStream{% \string\jsForQzs\space\jsForQzsHold\string\@nil} \fi \if\eqsHandleOpen1 \ifx\ListOfQuizNames\@empty\else \immediate\write\CommentStream{% \string\def\string\cListOfQuizNames{\expandafter \@gobble\cListOfQuizNames}} \fi \ifx\ListOfSQuizNames\@empty\else \immediate\write\CommentStream{% \string\def\string\cListOfSQuizNames{\expandafter \@gobble\cListOfSQuizNames}} \fi \fi } \AtEndDocument{\saveListofQzs} \dlJSStr{\eqerrUnfinishQuizAtSave} {One of your quizzes is not finished, you will lose those responses.} \begin{insDLJS}{gcnt}{eq-save: Save and Resume JS support} var _passToQuestions=false; var oRecordOfQuizData; var _docDevMode=\devMode; var aQzList=new Array(\cListOfQuizNames); var aSqList=new Array(\cListOfSQuizNames); \jsCodeForQzs% cntCorrectResponses.nCorrectInDoc=0; cntCorrectResponses.nOutOfInDoc=0; cntCorrectResponses.nPtsCorrectInDoc=0; cntCorrectResponses.nPtsOutOfInDoc=0; %but results from \env{quiz} environments are not known until the student presses the `End Quiz' button. function cntCorrectResponses() { var f=this.getField("\eqsroot"); if (f==null) return; var g=f.getArray(); var fld1="\eqsroot.Score"; var fld2="\eqsroot.OutOf"; var fld3="\eqsroot.ScoreComb"; var fld4="\eqsroot.ptScore"; var fld5="\eqsroot.ptOutOf"; var fld6="\eqsroot.ptScoreComb"; cntCorrectResponses.nCorrectInDoc=0; cntCorrectResponses.nOutOfInDoc=0; cntCorrectResponses.nPtsCorrectInDoc=0; cntCorrectResponses.nPtsOutOfInDoc=0; var pos,baseName; for (var i=0; i2) { // multiple selection if (f.exportValues[0][0]==1) { cntCorrectResponses.nOutOfInDoc+=1; if (f.isBoxChecked(0)) { cntCorrectResponses.nCorrectInDoc+=1; } } } else { // multiple choice cntCorrectResponses.nOutOfInDoc+=1; if (f.value[0]==1) { cntCorrectResponses.nCorrectInDoc+=1; } } } } addInQuizResults(); f=this.getField(fld1); if(f!=null)f.value=cntCorrectResponses.nCorrectInDoc; f=this.getField(fld2); if(f!=null)f.value=cntCorrectResponses.nOutOfInDoc var f=this.getField(fld3); if (f!=null)f.value=(\dclScorePhse(cntCorrectResponses.nCorrectInDoc)% (cntCorrectResponses.nOutOfInDoc)); f=this.getField(fld4); if(f!=null)f.value=cntCorrectResponses.nPtsCorrectInDoc; f=this.getField(fld5); if(f!=null)f.value=cntCorrectResponses.nPtsOutOfInDoc var f=this.getField(fld6); if (f!=null) f.value=(\dclScorePhse(cntCorrectResponses.nPtsCorrectInDoc)% (cntCorrectResponses.nPtsOutOfInDoc)); } function addInQuizResults() { var results,value,score,outof; cntCorrectResponses.nPtsCorrectInDoc=% cntCorrectResponses.nCorrectInDoc; cntCorrectResponses.nPtsOutOfInDoc=cntCorrectResponses.nOutOfInDoc; for (var i=0; i