%%
%% 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; i<this.numFields; i++) {
    fname=this.getNthFieldName(i);
    baseName=fname+"..";
    pos=baseName.indexOf(".");
    baseName=baseName.substring(pos+1);
    pos=baseName.indexOf(".");
    baseName=baseName.substring(0,pos);
    if (aQzList.indexOf(baseName)!=-1) {
      continue;
    }
    pos=fname.indexOf(".");
    var root=fname.substring(0,pos);
    if (root=="obj"|root=="grpobj") {
      var f=this.getField(fname);
      cntCorrectResponses.nOutOfInDoc+=1;
      if (f.isCorrect==1) {
          cntCorrectResponses.nCorrectInDoc+=1;
      }
    } else if (root=="mcq"||root=="mck"){
        continue;
      } else if (fname.substring(0,2)=="mc") {
      var tst4qz="mcq"+fname.substring(2);
      var otst4qz=this.getField(tst4qz);
      if (otst4qz!=null)continue;
      var f=this.getField(fname);
      var aResults=fname.match(/\./g);
      if (aResults.length>2) {
        // 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<aQzList.length; i++) {
    var f=this.getField("ScoreData."+aQzList[i]);
    if (f!=null) {
      if (f.value!="") {
        aTmp=f.value.split(";");
        cntCorrectResponses.nCorrectInDoc+=(1*aTmp[0]);
        cntCorrectResponses.nOutOfInDoc+=(1*aTmp[1]);
        cntCorrectResponses.nPtsCorrectInDoc+=(1*aTmp[2]);
        cntCorrectResponses.nPtsOutOfInDoc+=(1*aTmp[3]);
      }
    }
  }
}
function clearAllSQElements() {
  var fname;
  // clear any short quizzes and any supportive elements
  for (var i=0; i<aSqList.length; i++) {
    ProcessIt = false;
    if ( typeof eval(aSqList[i])== "undefined" )
      eval(aSqList[i])= new Object();
    if (typeof appAlerts[aSqList[i]] == "undefined")
      appAlerts[aSqList[i]] = new Object();
    this.resetForm(new Array("mc."+aSqList[i],"obj."+aSqList[i],%
"tally."+aSqList[i],"grpobj."+aSqList[i]));
    var f = this.getField("obj."+aSqList[i]);
    if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty%
\defaultColorJS\else\defaultColorJSLoc\fi;
    f = this.getField("grpobj."+aSqList[i]);
    if ( f != null ) f.strokeColor=\ifx\defaultColorJSLoc\@empty%
\defaultColorJS\else\defaultColorJSLoc\fi;
    f = this.getField("rbmarkup."+aSqList[i]);
    if ( f != null ) f.display=display.hidden;
    eval(aSqList[i]).Grp = {};
    appAlerts[aSqList[i]].bAfterValue=false;
    ProcessIt=true;
  }
  isAQuizUnfinished.check=true;
  // clear any quizzes and any supportive elements
  for (var i=0; i<aQzList.length; i++) {
    InitializeQuiz(aQzList[i],1);
    aQuizControl[aQzList[i]] = 0;
  }
  this.resetForm(["\eqsroot","holdScoreData","ScoreData"]);
  oRecordOfQuizData=new Object();
}
chk4PassToQuestions.entered=false;
function chk4PassToQuestions(event) {
  if(event.willCommit) {
    if (chk4PassToQuestions.entered) {
      _passToQuestions=false;
      clearAllSQElements();
      this.dirty=false;
      return;
    }
    if(event.value!="") {
      var value=""+event.value;
      value = value.replace(/\s/g,"");
      if(value==null || value.length==0) {
        _passToQuestions=false;
        chk4PassToQuestions.entered=false;
      } else {
        _passToQuestions=true;
        chk4PassToQuestions.entered=true;
        clearAllSQElements();
        this.dirty=false;
      }
    }
  }
}
function collectQuizData() {
  var f=this.getField("holdScoreData");
  f.value=(oRecordOfQuizData.toSource());
}
restoreQuizData.hasRestoredData=false;
function restoreQuizData() {
  var f=this.getField("holdScoreData");
  try{oRecordOfQuizData=eval(f.value);}catch(e){return;}
  for (fname in oRecordOfQuizData) {
    f=this.getField(fname);
    if (typeof oRecordOfQuizData[fname]=="object") {
      // name of field is endQuiz.qzname
      var pos=fname.indexOf(".");
      var qzName=fname.substring(pos+1);
      if (fname.indexOf("ScoreData.")) {
        lstOfQuizzes[qzName]=eval(qzName);
        Score=1*oRecordOfQuizData[fname][0];
        NQuestions=1*oRecordOfQuizData[fname][1];
        ptScore=1*oRecordOfQuizData[fname][2];
        NPointTotal=1*oRecordOfQuizData[fname][3];
        var h=this.getField("ScoreData."+qzName);
        h.value=Score+";"+NQuestions+";"+ptScore+";"+NPointTotal;
      }
    } else f.isCorrect=oRecordOfQuizData[fname];
  }
}
function IhrNameFormat(event){
  if(event.value!="") {
    var value=""+event.value;
    value = value.replace(/\s/g,"");
    if(value==null || value.length==0) {
      _passToQuestions=false;
      chk4PassToQuestions.entered=false;
    } else {
      _passToQuestions=true;
      chk4PassToQuestions.entered=true;
      this.dirty=false;
    }
  } else {
   chk4PassToQuestions.entered=false;
   _passToQuestions=false;
  }
}
function isAQuizUnfinishedAtSave()
{
    for ( var qtfield in aQuizControl )
        if ( aQuizControl[qtfield] == 1 )
        {
            eqAppAlert(\eqerrUnfinishQuizAtSave, 3);
            return false;
        }
    return true;
}
\end{insDLJS}
\ap@restoreCats
\endinput
%%
%% End of file `eq-save.sty'.
