From 5bf15133ae1a0745a8a5093950961c4e23dd8f5b Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sat, 16 Jun 2018 14:40:57 +0900 Subject: add eq-save --- texmf-dist/doc/latex/eq-save/README.md | 30 + texmf-dist/doc/latex/eq-save/eqsave-man.pdf | Bin 0 -> 249427 bytes texmf-dist/doc/latex/eq-save/eqsave-man.tex | 351 +++++++++++ .../doc/latex/eq-save/examples/eqsave-name.tex | 134 +++++ .../doc/latex/eq-save/examples/eqsave-noname.pdf | Bin 0 -> 108324 bytes .../doc/latex/eq-save/examples/eqsave-noname.tex | 124 ++++ texmf-dist/source/latex/eq-save/eq-save.dtx | 646 +++++++++++++++++++++ texmf-dist/source/latex/eq-save/eq-save.ins | 60 ++ texmf-dist/tex/latex/eq-save/eq-save.sty | 384 ++++++++++++ 9 files changed, 1729 insertions(+) create mode 100644 texmf-dist/doc/latex/eq-save/README.md create mode 100644 texmf-dist/doc/latex/eq-save/eqsave-man.pdf create mode 100644 texmf-dist/doc/latex/eq-save/eqsave-man.tex create mode 100644 texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex create mode 100644 texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf create mode 100644 texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex create mode 100644 texmf-dist/source/latex/eq-save/eq-save.dtx create mode 100644 texmf-dist/source/latex/eq-save/eq-save.ins create mode 100644 texmf-dist/tex/latex/eq-save/eq-save.sty (limited to 'texmf-dist') diff --git a/texmf-dist/doc/latex/eq-save/README.md b/texmf-dist/doc/latex/eq-save/README.md new file mode 100644 index 00000000..47c13ad8 --- /dev/null +++ b/texmf-dist/doc/latex/eq-save/README.md @@ -0,0 +1,30 @@ +The eq-save Package +Author: D. P. Story +Dated: 2018-04-07 + +In the past, Adobe Reader did not save form data; consequently, work done by +the student is lost when the AeB document is closed. In the more recent +versions, beginning perhaps with version~11, AR can save form data. The +eq-save package was written at a user's request to save all the quiz data so +that the student does not lose his/her results after saving and closing the +document. + +Use this package if you are writing tutorial or worksheets using the exerquiz +package, the package enables the student to continue reading and work through +the document over several sessions. + +Interactive document, such as those produced by AeB (including exerquiz) +require Adobe Reader. Any such AeB document must be viewed in AR, outside a +browser. + +What's New (2018-04-07) Bug fix, occassionally the data was not being +recorded correctly. + +Package works for dvips/Distiller, pdflatex, lualatex, and xelatex. + +Enjoy! + +Now, I must get back to my retirement. + +dps +dpstory at uakron dot edu diff --git a/texmf-dist/doc/latex/eq-save/eqsave-man.pdf b/texmf-dist/doc/latex/eq-save/eqsave-man.pdf new file mode 100644 index 00000000..f7467bc9 Binary files /dev/null and b/texmf-dist/doc/latex/eq-save/eqsave-man.pdf differ diff --git a/texmf-dist/doc/latex/eq-save/eqsave-man.tex b/texmf-dist/doc/latex/eq-save/eqsave-man.tex new file mode 100644 index 00000000..5efff180 --- /dev/null +++ b/texmf-dist/doc/latex/eq-save/eqsave-man.tex @@ -0,0 +1,351 @@ +\documentclass{article} +\usepackage[fleqn]{amsmath} +\usepackage[ + web={centertitlepage,designv,forcolorpaper,tight*,latextoc,pro}, + eforms,aebxmp +]{aeb_pro} +\usepackage{eq-save} +\usepackage[ImplMulti]{dljslib} +\usepackage{graphicx,array,fancyvrb} +\usepackage{aeb_mlink} +%\usepackage{myriadpro} +%\usepackage{calibri} +\usepackage[altbullet]{lucidbry} + +\def\hardspace{{\fontfamily{cmtt}\selectfont\symbol{32}}} + +\usepackage{acroman} +\usepackage[active]{srcltx} + +\urlstyle{tt} + +\def\STRUT{\rule{0pt}{14pt}} +\useBeginQuizButton[\CA{Begin}] +\useEndQuizButton[\CA{End}] + +\makeatletter +\newcount\hesheCnt \hesheCnt=-1 +\def\heshe{\@ifstar{\heshei}{\global\advance\hesheCnt1\relax\heshei}} +\def\heshei{\ifodd\hesheCnt she\else he\fi} +\def\HeShe{\@ifstar{\HeShei}{\global\advance\hesheCnt1\relax\HeShei}} +\def\HeShei{\ifodd\hesheCnt She\else He\fi} +\def\hisher{\@ifstar{\hisheri}{\global\advance\hesheCnt1\relax\hisheri}} +\def\hisheri{\ifodd\hesheCnt her\else his\fi} +\def\himher{\@ifstar{\himheri}{\global\advance\hesheCnt1\relax\himheri}} +\def\himheri{\ifodd\hesheCnt her\else him\fi} +\makeatother + +\DeclareDocInfo +{ + university={\AcroTeX.Net}, + title={The \textsf{eq-save} Package}, + author={D. P. Story}, + email={dpstory@acrotex.net}, + subject=Documentation for the eq-save package, + talksite={\url{www.acrotex.net}}, + version={1.1, 2018/04/07}, + Keywords={LaTeX, form field, hints, AcroTeX}, + copyrightStatus=True, + copyrightNotice={Copyright (C) \the\year, D. P. Story}, + copyrightInfoURL={http://www.acrotex.net} +} + +\universityLayout{fontsize=Large} +\titleLayout{fontsize=LARGE} +\authorLayout{fontsize=Large} +\tocLayout{fontsize=Large,color=aeb} +\sectionLayout{indent=-62.5pt,fontsize=large,color=aeb} +\subsectionLayout{indent=-31.25pt,color=aeb} +\subsubsectionLayout{indent=0pt,color=aeb} +\subsubDefaultDing{\texorpdfstring{$\bullet$}{\textrm\textbullet}} + +\chngDocObjectTo{\newDO}{doc} +\begin{docassembly} +var titleOfManual="The eq-save Package"; +var manualfilename="Manual_BG_Print_eq-save.pdf"; +var manualtemplate="Manual_BG_Brown.pdf"; // Blue, Green, Brown +var _pathToBlank="C:/Users/Public/Documents/ManualBGs/"+manualtemplate; +var doc; +var buildIt=false; +if ( buildIt ) { + console.println("Creating new " + manualfilename + " file."); + doc = \appopenDoc({cPath: _pathToBlank, bHidden: true}); + var _path=this.path; + var pos=_path.lastIndexOf("/"); + _path=_path.substring(0,pos)+"/"+manualfilename; + \docSaveAs\newDO ({ cPath: _path }); + doc.closeDoc(); + doc = \appopenDoc({cPath: manualfilename, oDoc:this, bHidden: true}); + f=doc.getField("ManualTitle"); + f.value=titleOfManual; + doc.flattenPages(); + \docSaveAs\newDO({ cPath: manualfilename }); + doc.closeDoc(); +} else { + console.println("Using the current "+manualfilename+" file."); +} +var _path=this.path; +var pos=_path.lastIndexOf("/"); +_path=_path.substring(0,pos)+"/"+manualfilename; +\addWatermarkFromFile({ + bOnTop:false, + bOnPrint:false, + cDIPath:_path +}); +\executeSave(); +\end{docassembly} + + +\begin{document} + +\maketitle + +\selectColors{linkColor=black} +\tableofcontents +\selectColors{linkColor=webgreen} + + +\section{Introduction} + +In this documentation, the one reading an \AEB\footnote{{\AcroTeX} eDucation +Bundle} document is referred to as a student, as that is the intended target +audience for education materials developed by the various packages of \AEB. + +The \pkg{exerquiz} package defines the \env{oQuestion}, \env{shortquiz}, and +\env{quiz} environments that are used to pose interactive questions to +students. The original concept of \pkg{exerquiz} was as an integral component +in the development of education materials such as digital tutorials or +worksheets. A student may work through such a document, learning concepts and +answering questions to reinforce {\hisher} understanding. + +In the past, \app{Adobe Reader} (now \app{Adobe Acrobat Reader})---henceforth +referred to as \app{AR}--- did not save form data; consequently, work done by +the student is lost when the document is closed. In the more recent versions, +beginning perhaps with version~11, \app{AR} can now save form data. The +\pkg{eq-save} package was written at a user's request to save all the quiz +data so that the student does not lose {\hisher} results after saving and +closing the document. + +To be clear, when a {\PDF} (by \app{AR}) document is saved, the form data is +also saved: the value of the field and properties of the field, such as +border color, are saved. However, \pkg{exerquiz} keeps running tallies on the +student's progress through the document, these are in the form of JavaScript +variables, arrays and objects; the current values of these are \emph{not +saved} with the document. Therefore, if the student saves the \PDF, it is +necessary to save a minimal amount of information that can later be used to +reconstruct the state of the document at the time student saved and closed the +document. This `state data' is saved to a hidden text field. When the +document is opened again, this hidden field is read, and the state of the +document is minimally restored. + +\section{Requirements and options of the package} + +The \pkg{eq-save} package, being a support package, requires \pkg{exerquiz}, +dated 2017/07/30 or later. Use the package in the usual way, +\begin{Verbatim}[xleftmargin=\amtIndent,commandchars=!()] +\documentclass{article} +\usepackage[!ameta(options)]{exerquiz} +\usepackage[!ameta(options)]{eq-save} +\end{Verbatim} +There are only two options for \pkg{eq-save}, these are \opt{devmode} and +\opt{!devmode}.\marginpar{\small\hfill\mbox{\parbox[t]{\marginparwidth}{\raggedleft +\mbox{Options:\hspace{15pt}} \opt{devmode} \opt{!devmode}}}} As we shall see +below, there is an optional `gatekeeper' command \cs{nameField}. The student +is not allowed to peek at the document until a name is entered (preferably +the student's own name) into the \cs{nameField}. When the \cs{nameField} and +its companion \cs{BeginNoPeeking} are present it is rather inconvenient to +develop the document, create and test quizzes because the author must first +pass the `gatekeeper'. When the \opt{devmode} is in force, entering a name in +\cs{nameField} is no longer required to view the rest of the document. The +other option, \opt{!devmode} is the opposite of \opt{devmode}, that is, when +\cs{nameField} and \cs{BeginNoPeeking} are present in the document, the +student (or author) must enter a name into the name field before viewing the +rest of the document. The \opt{!devmode} option is the default, passing no +option is the same as passing \opt{!devmode}. + +\section{Basic commands} + +Actually, without any of the supporting commands, yet to be described, the +document may be saved, closed, opened again. The responses to questions +within the \env{oQuestion} and \env{shortquiz} environments are as when they +were saved, the same is true for a full quiz of a \env{quiz} environment. So +what is the need for this document? This package provides \emph{bookkeeping +services}. Before continuing, let's illustrate by example. Answer one of the +\env{shortquiz} questions and answer both questions from the \env{quiz} +environment. Save the document, open and return to the page. When you return +answer (correctly) the other question and/or change the answer for the other +questions.\previewOff +\begin{shortquiz*}[sQz1] +Answer each of these to test your understanding. +\begin{questions} + \item Select the two mathematicians recognized as the originators of Calculus.\marginpar{\small\raggedleft \emph{Hint:} N\&L} +\begin{manswers}{5} + \bChoices + \Ans0 Banach\eAns + \Ans1 Newton\eAns + \Ans0 Hilbert\eAns + \Ans1 Liebniz\eAns + \eChoices +\end{manswers} + \item $ 1 + 16 = \RespBoxMath[\rectW{.5in}]{17}{1}{.0001}{[0,1]}\olBdry\relax\CorrAnsButton{17}$ + \item Which of the individuals below is the originator of \TeX? +\begin{answers}{5} + \bChoices + \Ans0 Goossens\eAns + \Ans0 Rahtz\eAns + \Ans0 Mittelback\eAns + \Ans0 Lamport\eAns + \Ans1 Knuth\eAns + \eChoices +\end{answers} +\end{questions} +\end{shortquiz*} +\noindent +Now complete this quiz consisting of the first two questions above, for simplicity. +\begin{quiz*}{qz1} +Respond to each without error. Passing is 100\%. +\begin{questions} + \item Select the two mathematicians recognized as the originators of Calculus. +\begin{manswers}{5} + \bChoices + \Ans0 Banach\eAns + \Ans1 Newton\eAns + \Ans0 Hilbert\eAns + \Ans1 Liebniz\eAns + \eChoices +\end{manswers} + \item $ 1 + 16 = \RespBoxMath[\rectW{.5in}]{17}{1}{.0001}{[0,1]}$ +\end{questions} +\end{quiz*}\cgBdry[.5em]\ScoreField\currQuiz\CorrButton\currQuiz\hfill Answers: \AnswerField[\rectW{1in}]\currQuiz\vcgBdry[6pt] +\hfill\ding{172}\enspace\sooField{1in}{11bp}\cgBdry\clearAllField{}{11bp}\vcgBdry[12pt] +The field labeled with `\ding{172}' is one of the new fields, as is the one +to its right. As you work through the above questions, the field keeps track +of your success rate in all quizzes (from the \env{oQuestion}, +\env{shortquiz}, and \env{quiz} environments). When you save, close, and open +again, the tally continues where it left off. Ideal for working through a +long document. The field `\textsf{Clear All}' clears all quiz results as well as +the field labeled `\ding{172}', then all is forgotten. + +Before continuing on to the discussion of the various commands of this +package, several observations are appropriate. +\begin{itemize} + \item As soon as you respond to an \emph{immediate-feedback question} (a question + from either the \env{oQuestion} or \env{shortquiz} environment), the + total number of questions of this type is known, its 4 for this set of + questions. In the \textcolor{red}{Quiz}, problem~1 is a multiple + selection (MS) question with two correct answers; problem~2 has one correct + answer; problem~3 is multiple choice (MC), only one correct question. + There is a total of 4 ($\text{two}+\text{one}+\text{one}=4$). + \item As you answer more immediate-feedback questions, or change your + answers from a correct ones to an incorrect ones, the tally changes + appropriately, but always says `out of 4' (in this set of quizzes). + \item The quiz (as constructed from the \env{quiz} environment) has only + two questions, but the tally box does not know this until + `\textsf{Begin}' and `\textsf{End}' are pressed. A quiz consists of + \emph{delayed-feedback} questions. + + \item Results (for the quiz) are not known until the `\textsf{End}' button + is pressed, then the tally field `\ding{172}' is updated. You'll note + that the multiple selection (MS) question only contributes one (1) to + the `out of' number, that's because MS is scored differently than it is + for immediate-feedback. + +\end{itemize} + +\subsection{Bookkeeping commands}\previewOff + +The `bookkeeping' commands are create text field to hold ongoing tally data. +\bVerb\takeMeasure{\string\sooField[\ameta{opts}]\darg{\ameta{width}}\darg{\ameta{height}}}% +\setlength\aebscratch{\bxSize}% +\def\1{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\makebox[0pt][l]{\hspace{.5in}\enspace\normalfont(score field)}\sField[\textSize{7}]{.5in}{9bp}}}% +\def\2{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\makebox[0pt][l]{\hspace{.5in}\enspace\normalfont(`out of' field)}\ooField[\textSize{7}]{.5in}{9bp}}}% +\def\3{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\makebox[0pt][l]{\hspace{.5in}\enspace\normalfont(combined score field)}\sooField[\textSize{7}]{.5in}{9bp}}}% +\begin{dCmd}[commandchars=!()]{\bxSize} +!1\sField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +!2\ooField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +!3\sooField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +\end{dCmd} +\eVerb All three field generate a text field with dimensions \ameta{width} +and \ameta{height}, the \meta{opt} allows you to pass \pkg{eforms} field +options to change the appearance of the field. \cs{sField} holds only the number of question answered correctly; +\cs{ooField} holds the `out of' value, the number of questions detected; \cs{sooField} is a combination of +the first two values, typically is displays `3 out of 6'. The `out of' phrase is the expansion of \cs{eqOutOf}, a command +defined and documented in \pkg{exerquiz}. A convenience way of redefining the `out of' phrase is through \cs{declareScorePhrase}: +\bVerb\takeMeasure{\string\declareScorePhrase\darg{\#1+"\string\space\string\eqOutOf\string\space"+\#2}}% +\setlength\aebscratch{\bxSize}% +\def\1{\makebox[0pt][l]{\hspace{\aebscratch}\enspace\normalfont(default definition)}}% +\begin{dCmd}[commandchars=!()]{\bxSize} +\declareScorePhrase{!ameta(JS-str)} +!1\declareScorePhrase{#1+"\space\eqOutOf\space"+#2} +\end{dCmd} +\eVerb The argument \ameta{JS-str} is a JavaScript string. It is phrased using \texttt{\#1} and \texttt{\#2}, which at +compile time, are replaced with JavaScript variables that will hold the score value and the `out of' value. + +\newtopic With \pkg{exequiz} you can also assign points for questions in \env{quiz} environments; as a consequence, there is +a similar set of commands to those above. +\bVerb\takeMeasure{\string\psooField[\ameta{opts}]\darg{\ameta{width}}\darg{\ameta{height}}}% +\begin{dCmd}[commandchars=!()]{\bxSize} +\psField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +\pooField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +\psooField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +\end{dCmd} +\eVerb These fields report the point totals. For \env{oQuestion} and \env{shortquiz} environments, each question is only 1 point, but +for \env{quiz} environment you can assign points using the \cs{PTs} command, as illustrated the documentation of \AEB. We do not illustrate +this set of commands in the documentation. + +To clear all the fields just described, as well as all fields in the \env{oQuestion}, \env{shortquiz} and +\env{quiz} environment, insert the \cs{clearAllField} into your document. +\bVerb\takeMeasure{\string\clearAllField[\ameta{opts}]\darg{\ameta{width}}\darg{\ameta{height}}}% +\begin{dCmd}[commandchars=!()]{\bxSize} +\clearAllField[!ameta(opts)]{!ameta(width)}{!ameta(height)} +\end{dCmd} +\eVerb The interpretation of the parameters are as above. + + +\subsection{Gatekeeper commands} + +The application that inspired this package was the Professor of the course did not want the student to look at the quizzes +until {\heshe} entered {\hisher*} name. As a result, should you want this sort of `security', include the \cs{nameField} +and \cs{BeginNoPeeking} commands. The latter should begin on the first page you don't want your students to look upon until +they enter their names. +\bVerb\takeMeasure{\string\flJSStr[noquotes,noparens]\darg{\string\EnterNameFirstMsg}\darg{\ameta{msg}}}% +\begin{dCmd}[commandchars=!()]{\bxSize} +\nameField[!ameta(opts)]{!ameta(name)}{!ameta(width)}{!ameta(height)} +\BeginNoPeeking +!STRUT\flJSStr[noquotes,noparens]{\EnterNameFirstMsg}{!ameta(msg)} +\end{dCmd} +\eVerb The \meta{name} field allows you to enter a personalized field name, +such as `\texttt{IhrName}', or something. The other parameters are the same +as above and are described briefly in the description of \cs{sField}. + +When the student enters {\hisher} name, the document is cleared: all fields +that support questions from the \env{oQuestion}, \env{shortquiz}, and +\env{quiz} environments; all fields whose commands begin with `s', `oo', +`soo', `ps', `poo', and `psoo' fields, as described above. This is a weak +security measure to make it more difficult for a student to just take the +worksheet of an `A' student and simply remove the name and enter {\hisher} +own name. Of course, unless students supervised in a lab, these measures are +only inconveniences. + +There are two JavaScript strings that can be rephrased or localized. The default +declarations are, +\begin{Verbatim}[xleftmargin=\amtIndent,commandchars=!()] +\flJSStr[noquotes,noparens]{\EnterNameFirstMsg} +!qquad{You must enter your name first!} +!STRUT\dlJSStr{\eqerrUnfinishQuizAtSave}{One of your quizzes +!qquad(is not finished, you will lose those responses.)} + +\end{Verbatim} + +\section{Demonstration files} + +There are two sample files, \texttt{eqsave-name.tex} and +\texttt{eqsave-noname.tex}, found in the \texttt{examples} folder. The first +has uses the gatekeeper commands (these are \cs{sField} and \cs{BeginNoPeeking}), while the +second one does not; otherwise, the files are the same. + +\section{My retirement} + +Now, I simply must get back to it. \dps + +\end{document} diff --git a/texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex b/texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex new file mode 100644 index 00000000..743b464c --- /dev/null +++ b/texmf-dist/doc/latex/eq-save/examples/eqsave-name.tex @@ -0,0 +1,134 @@ +\documentclass{article} +\usepackage[fleqn]{amsmath} +\usepackage{web} +\usepackage{exerquiz} +\usepackage[!devmode]{eq-save} +\usepackage[ImplMulti]{dljslib} + +\def\lfootScore{\sField{.25in}{11bp}} +\def\lfootOutOf{\ooField{.25in}{11bp}} +\def\rfootPtsScore{\psField{.25in}{11bp}} +\def\rfootPtsOutOf{\pooField{.25in}{11bp}} + +\lfooter{Score {\lfootScore} out of {\lfootOutOf}} +\rfooter{Points {\rfootPtsScore} out of {\rfootPtsOutOf}} + + +\previewOff +\sqTurnOffAlerts +\PTsHook{($\eqPTs^{\text{pts}}$)} + +\parindent0pt + +\begin{document} + +\begin{center}\bfseries\large + Demonstrating the \texttt{eq-save} package\\ + Gatekeeper commands present\\[3pt] + \normalfont\normalsize Herr Dr Prof Story +\end{center} + +Answer some of the questions, save the document, then reopen it and continue +the `worksheet'. The tallies should continue from the values current at the +time the document was saved.\medskip + +Begin by entering your name in the input box below.\medskip + +\textbf{Warning:} Clearing or changing the name field clears all quizzes. After you begin, do not change +your name field or all entries will be lost.\bigskip + +Ihr Name: \nameField{IhrName}{2in}{11bp} + +\newpage +% separate the name field from the rest of the content, insert \BeginNoPeeking +\BeginNoPeeking + +\begin{oQuestion}{oQ1} +It is well known that $ 1 + 16 = \RespBoxMath{17}{1}{.0001}{[0,1]}$ +\end{oQuestion} + +\begin{shortquiz*}[sQ1] +Solve each of the following without error. +\begin{questions} + +\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$ +\item Enter the \emph{last name} of the Herr Dr Prof of this course. +\[ + \text{The Herr Dr Prof is }\RespBoxTxt{1}{0}{1}{Story} +\] + \item Which of the following is true +\begin{answers}{4} +\bChoices + \Ans1 true\eAns + \Ans0 false\eAns +\eChoices +\end{answers} +\item From the list below, select the mathematicians recognized as the originators of Calculus. +\begin{manswers}{4} +\bChoices + \Ans1 Newton\eAns + \Ans0 Gauss\eAns + \Ans1 Leibniz\eAns + \Ans0 Banach\eAns +\eChoices +\end{manswers} +\end{questions} +\end{shortquiz*} + + +\useBeginQuizButton +\useEndQuizButton + +\begin{quiz*}{qz1} +Solve each without error. +\begin{questions} + \item Which of the following is true +\begin{answers}{2} + \Ans1 true & \Ans0 false +\end{answers} +\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$ +\item From the list below, select the mathematicians recognized as the originators of Calculus. +\begin{manswers}{4} +\bChoices + \Ans1 Newton\eAns + \Ans0 Gauss\eAns + \Ans1 Leibniz\eAns + \Ans0 Banach\eAns +\eChoices +\end{manswers} +\end{questions} +\end{quiz*}\quad\ScoreField\currQuiz\olBdry\CorrButton\currQuiz + + + +\newpage + +The quiz on this page has points associated with each question, the points are tabulated separately, +and entered into the fields in the right footer. The questions above are figured in as 1 point each. + +\begin{quiz*}{qz2} +Solve each without error. +\begin{questions} + \item\PTs{2} Which of the following is true +\begin{answers}{2} +\bChoices + \Ans1 true\eAns + \Ans0 false\eAns +\eChoices +\end{answers} +\item\PTs{3} Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$ +\item\PTs{4} From the list below, select the mathematicians recognized as the originators of Calculus. +\begin{manswers}{4} +\bChoices + \Ans1 Newton\eAns + \Ans0 Gauss\eAns + \Ans1 Leibniz\eAns + \Ans0 Banach\eAns +\eChoices +\end{manswers} +\end{questions} +\end{quiz*}\quad\PointsField\currQuiz\olBdry\CorrButton\currQuiz + + +\medskip\noindent\sooField{1in}{11bp}\olBdry\clearAllField{}{11bp} +\end{document} diff --git a/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf new file mode 100644 index 00000000..5ec4b41a Binary files /dev/null and b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.pdf differ diff --git a/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex new file mode 100644 index 00000000..4ec47d6c --- /dev/null +++ b/texmf-dist/doc/latex/eq-save/examples/eqsave-noname.tex @@ -0,0 +1,124 @@ +\documentclass{article} +\usepackage[fleqn]{amsmath} +\usepackage{web} +\usepackage{exerquiz} +\usepackage[!devmode]{eq-save} +\usepackage[ImplMulti]{dljslib} + +\def\lfootScore{\sField{.25in}{11bp}} +\def\lfootOutOf{\ooField{.25in}{11bp}} +\def\rfootPtsScore{\psField{.25in}{11bp}} +\def\rfootPtsOutOf{\pooField{.25in}{11bp}} + +\lfooter{Score {\lfootScore} out of {\lfootOutOf}} +\rfooter{Points {\rfootPtsScore} out of {\rfootPtsOutOf}} + + +\previewOff +\sqTurnOffAlerts +\PTsHook{($\eqPTs^{\text{pts}}$)} + +\parindent0pt + +\begin{document} + + +\begin{center}\bfseries\large + Demonstrating the \texttt{eq-save} package\\ + No Gatekeeper commands present\\[3pt] + \normalfont\normalsize Herr Dr Prof Story +\end{center} + +Answer some of the questions, save the document, then reopen it and continue +the `worksheet'. The tallies should continue from the values current at the +time the document was saved.\medskip + +\begin{oQuestion}{oQ1} +It is well known that $ 1 + 16 = \RespBoxMath{17}{1}{.0001}{[0,1]}$ +\end{oQuestion} + +\begin{shortquiz*}[sQ1] +Solve each of the following without error. +\begin{questions} + +\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$ +\item Enter the \emph{last name} of the Herr Dr Prof of this course. +\[ + \text{The Herr Dr Prof is }\RespBoxTxt{1}{0}{1}{Story} +\] + \item Which of the following is true +\begin{answers}{4} +\bChoices + \Ans1 true\eAns + \Ans0 false\eAns +\eChoices +\end{answers} +\item From the list below, select the mathematicians recognized as the originators of Calculus. +\begin{manswers}{4} +\bChoices + \Ans1 Newton\eAns + \Ans0 Gauss\eAns + \Ans1 Leibniz\eAns + \Ans0 Banach\eAns +\eChoices +\end{manswers} +\end{questions} +\end{shortquiz*} + + +\useBeginQuizButton +\useEndQuizButton + +\begin{quiz*}{qz1} +Solve each without error. +\begin{questions} + \item Which of the following is true +\begin{answers}{2} + \Ans1 true & \Ans0 false +\end{answers} +\item Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$ +\item From the list below, select the mathematicians recognized as the originators of Calculus. +\begin{manswers}{4} +\bChoices + \Ans1 Newton\eAns + \Ans0 Gauss\eAns + \Ans1 Leibniz\eAns + \Ans0 Banach\eAns +\eChoices +\end{manswers} +\end{questions} +\end{quiz*}\quad\ScoreField\currQuiz\olBdry\CorrButton\currQuiz + + + +\newpage + +The quiz on this page has points associated with each question, the points are tabulated separately, +and entered into the fields in the right footer. The questions above are figured in as 1 point each. + +\begin{quiz*}{qz2} +Solve each without error. +\begin{questions} + \item\PTs{2} Which of the following is true +\begin{answers}{2} +\bChoices + \Ans1 true\eAns + \Ans0 false\eAns +\eChoices +\end{answers} +\item\PTs{3} Calculate: $ 8 \cdot 11 = \RespBoxMath{88}{1}{.0001}{[0,1]}$ +\item\PTs{4} From the list below, select the mathematicians recognized as the originators of Calculus. +\begin{manswers}{4} +\bChoices + \Ans1 Newton\eAns + \Ans0 Gauss\eAns + \Ans1 Leibniz\eAns + \Ans0 Banach\eAns +\eChoices +\end{manswers} +\end{questions} +\end{quiz*}\quad\PointsField\currQuiz\olBdry\CorrButton\currQuiz + + +\medskip\noindent\sooField{1in}{11bp}\olBdry\clearAllField{}{11bp} +\end{document} diff --git a/texmf-dist/source/latex/eq-save/eq-save.dtx b/texmf-dist/source/latex/eq-save/eq-save.dtx new file mode 100644 index 00000000..180d42fe --- /dev/null +++ b/texmf-dist/source/latex/eq-save/eq-save.dtx @@ -0,0 +1,646 @@ +% \iffalse +%<*copyright> +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% eq-save package, %% +%% Copyright (C) 2017-2018 %% +%% 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} +% [2018/04/07 v1.1 eq-save: save exerquiz quizzes and resume (dps)] +%<*driver> +\documentclass{ltxdoc} +\usepackage[colorlinks,hyperindex=false]{hyperref} +\usepackage{calc} +\let\uif\textsf\let\app\textsf +\let\pkg\textsf\let\env\texttt +\let\opt\texttt +\def\ameta#1{$\langle\textit{\texttt{#1}}\rangle$} +\def\psf#1{\textsf{\textbf{#1}}} +%\pdfstringdefDisableCommands{\let\\\textbackslash} +\OnlyDescription % comment out for implementation details +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\InputIfFileExists{aebdocfmt.def}{\PackageInfo{eq-save}{Inputting aebdocfmt.def}} + {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax + \PackageInfo{eq-save}{aebdocfmt.def cannot be found}} +\begin{document} +\def\CMD#1{\textbackslash#1} + \GetFileInfo{eq-save.sty} + \title{\textsf{eq-save}: Saving \pkg{exerquiz} quizzes and resuming} + \author{D. P. Story\\ + Email: \texttt{dpstory@acrotex.net}} + \date{processed \today} + \maketitle + \tableofcontents + \let\Email\texttt + \renewenvironment{theglossary}{% + \let\efill\relax + \begin{itemize}}{\end{itemize}} + \value{GlossaryColumns}=1 + \DocInput{eq-save.dtx} +\IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex}{\paragraph*{Index} The index goes here.\\Execute + \texttt{makeindex -s gind.ist -o eq-save.ind eq-save.idx} on the command line and recompile + \texttt{eq-save.dtx}.} +\IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here.\\Execute + \texttt{makeindex -s gglo.ist -o eq-save.gls eq-save.glo} on the command line and recompile + \texttt{eq-save.dtx}.} +\end{document} +% +% \fi +% \MakeShortVerb{|} +% \InputIfFileExists{aebdonotindex.def}{\PackageInfo{web}{Inputting aebdonotindex.def}} +% {\PackageInfo{web}{cannot find aebdonotindex.def}} +% \begin{macrocode} +% Begin Package +%<*package> +% \end{macrocode} +% The option \IndexOpt{devmode}\opt{devmode} does not require the user to enter his or her name +% in the name field, if the \cs{nameField} and \cs{BeginNoPeeking} commands are present; otherwise it has no effect. +% The \IndexOpt{!devmode}\opt{!devmode} is the logical negation of \opt{devmode}, its the same as no option +% passed. +% \begin{macrocode} +\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\! +% \end{macrocode} +% \changes{v1.0}{2017/08/12}{Wrote initial documentation, set version as v1.0} +% \section{Introduction} +% Work, on what ultimately became this package, was initiated by a user Manfred~S. He and his team were writing +% practice documents for their students that included \env{oQuestion}, \env{shortquiz}, and \env{quiz} environments from the +% \pkg{exerquiz} package. It was desired for the student to enter his/her name first, then begin the practice document. +% After a while, the student may become tired or disinterested, so he/she save the document. +% He wanted to take advantage of the ability of Adobe Acrobat Reader 11 or greater (DC and beyond) to save the form data, +% something it couldn't do prior. Later the student becomes motivated and returns to the document to continue working through +% the questions. +% +% Sounds good, but wait! \env{oQuestion}, \env{shortquiz}, and \env{quiz} environments were not designed +% for this. There are a lot of JavaScript variables, arrays, objects containing information about the quizzes as they are +% attempted. This data is normally disposed of when the reader takes another quiz. Certainly, as the user saves and closes +% the document all variables, arrays, objects are lost. This package attempts to save all essential information when +% the user saves the document, the information is saved in a hidden text field. Upon opening the document again, +% the essential data is restored. +% +% A professor might want this feature for a tutorial. The tutorial (rather long) can have questions from +% \env{oQuestion}, \env{shortquiz}, and \env{quiz} environments. The student can save, and return to the +% reading of the tutorial and the answering of the questions. A self-paced tutorial does not need a name field +% to act as a `gatekeeper' to the document, as is the need of Manfred~S. +% +% +% \section{Commands of this package} +% The \DescribeMacro{\nameField}\cs{nameField} command insert a text field into which the student enters +% his name; otherwise, he cannot continue to the next page. Changing your name after you've begun to work +% on the questions clears the answer to all quizzes; this is an annoyance factor, a feeble attempt to reduce +% cheating. When \cs{nameField} is used, the top of the next page should be \cs{BeginNoPeeking}. +% \begin{macrocode} +\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}} +% \end{macrocode} +% \DescribeMacro{\hiddenScoreData}\cs{hiddenScoreData} text field. +% It has zero dimensions, takes up no (horizontal) {\TeX} space, and is hidden. It is placed under the name field. +% This field, when the document is saved, receive all essential quiz data. It is read again when the document +% is opened to restore the quiz data. We give this field an initial value, for otherwise, the PDF viewer will +% not scan this field on opening. +% \begin{macrocode} +\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} +% \end{macrocode} +% We place this field on the first page, upper left corner. It will be scanned by the PDF viewer (Reader) +% and it will define the object \texttt{oRecordOfQuizData} that will hold essential quiz data. +% +% \paragraph*{Displaying and clearing results} As the user/student progresses through the documents, he +% can see his success rate by viewing the text fields below. +% +% The \DescribeMacro{\sooField}\cs{sooField} (soo=score out of) displays the combined score: `12 out of 16', for example. +% The phase may be redefined for language purposes by redeclaring the command \cs{declareScorePhrase}, the English +% declaration is \verb~\declareScorePhrase{#1+"\space\eqOutOf\space"+#2}~, see the documentation above for this command. +% +% The \DescribeMacro{\sField}\cs{sField} is one that holds only the score, while +% \DescribeMacro{\ooField}\cs{ooField} holds the `out of' value. +% \begin{macrocode} +\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}} +% \end{macrocode} +% Now we do the same thing for the points score. \DescribeMacro{\psField}\cs{psField} holds the total +% number of points awarded; \DescribeMacro{\pooField}\cs{pooField} is the total number of points; +% \DescribeMacro{\psooField}\cs{psooField} +% \begin{macrocode} +\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}} +% \end{macrocode} +% We supply a global clearing button. This button clear all results in the document, questions posed +% by \env{oQuestions}, \env{shortquiz}, and \env{quiz} environments. +% \begin{macrocode} +\newcommand{\clearAllField}[3][]{\pushButton[\CA{Clear All}#1 + \AAmouseup{clearAllSQElements();}]{globalClearAll}{#2}{#3}} +% \end{macrocode} +% +% \paragraph*{Set action keys} We modify certain action keys to save the information we'll need later when the document is saved. +% The \cs{setActionKeys} is a new feature of \pkg{exerquiz} (2017/07/29) and is used to add JavaScript +% actions to certain key elements of the quiz environments. This is how we are able to preserve and later +% restore the quiz data. The command \DescribeMacro{\eqsSetActionKeys}\cs{eqsSetActionKeys} is expanded +% when \cs{DeclareReportRootName} is expanded. If the author declares a new root, the \cs{setActionKeys}, +% which depend on \cs{eqsroot}, must be re-emitted. +% \begin{macrocode} +\newcommand{\eqsSetActionKeys}{% + \setActionKeys{% +% \end{macrocode} +% (2018/04/07) Removing \cs{AddAAFormat}, there is no test for null later in the code. +% \changes{v1.1}{2018/04/07}{No need for the change to \string\cs{AddAAFormat}} +% \begin{macrocode} +% \AddAAFormat{\if\eqQuizType\isSQZ +% if (typeof event.target.isCorrect=="undefined")\r\t +% event.target.isCorrect=null;\fi} + \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} + }% +} +% \end{macrocode} +% \paragraph*{Modify actions of Begin Quiz and End Quiz} These actions may be modified using the +% two commands \cs{postInitQuiz} and \cs{postSubmitQuiz}. They are used to insert the \texttt{cntCorrectResponses()} call +% into the action performed by the `Begin Quiz' and `End Quiz' buttons. \emph{It is assumed the document +% author is not otherwise using these two commands.} +% \begin{macrocode} +\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 +} +% \end{macrocode} +% \paragraph*{Open Page Action} We add a page open event to restore the data as needed. We only do this once +% per document session. +% \begin{macrocode} +\thisPageAction{\JS{if(!restoreQuizData.hasRestoredData)\r\t + var rqdTO=(app.setTimeOut("restoreQuizData();app.clearTimeOut(rqdTO);% + restoreQuizData.hasRestoredData=true",1000));}}{} +% \end{macrocode} +% \paragraph*{Action prior to saving} It is important to save the quiz data, we can only do that if we save +% it to a field, the value of the field will be saved. We save the data to a hidden text field +% \texttt{"holdScoreData"}, this field is required. +% \begin{macrocode} +\begin{willSave} +isAQuizUnfinishedAtSave(); +if (typeof oRecordOfQuizData !="undefined") collectQuizData(); +\end{willSave} +% \end{macrocode} +% \paragraph*{No peeking} If the \cs{nameField} command is used, +% use \DescribeMacro{\BeginNoPeeking}\cs{BeginNoPeeking} command can optionally appear on the +% first page that contain content the author does not want the user to peek at. The +% JavaScript string \DescribeMacro{\EnterNameFirstMsg}\cs{EnterNameFirstMsg} appears in the alert +% box if the user goes to a forbidden page without first enther his name into the \cs{nameField}. +% May be redefined for local languages. +% \begin{macrocode} +\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);}}}{}}% +% Page option for this page + \IhrNamePO +% page open for all other pages + \AtBeginShipout{\IhrNamePO}% +} +% \end{macrocode} +% The command \DescribeMacro{\DeclareReportRootName}\cs{DeclareReportRootName} may never need to be used, but just +% in case, it can only be used once in the preamble. It names the parent (or root) name of the text fields that +% will contain the running summary of the user's efforts in the document. The default root name is \texttt{SUMRY}. +% \begin{macrocode} +\newcommand{\DeclareReportRootName}[1]{\def\eqsroot{#1}% + \eqsSetActionKeys} +\DeclareReportRootName{SUMRY} +\@onlypreamble{\DeclareReportRootName} +% \end{macrocode} +% One of the problems is the quizzes and shortquizzes are not known when the document is first +% opened. Normally this is not a problem, but in this application we need to know them. This problem +% is solved by two events: at the end of the document the list of quizzes is known, it is save to +% the auxiliary file \texttt{qzlist-\string\jobname.cut}, then this file is input back into the preamble, parsed, +% and entered into the document level JavaScript through the command \cs{jsCodeForQzs}. The contents +% of the aux file may look like: \texttt{\string\jsForQzs\space qz1;qz2;oQ1;sQ1;\string\@nil}. The internal command +% \DescribeMacro{\jsCodeForQzs}\cs{jsCodeForQzs} parses this line at the semicolons; as a result, \cs{jsCodeForQzs} +% expands to +%\begin{verbatim} +%var qz1=new Object(); +%var qz2=new Object(); +%var oQ1=new Object(); +%var sQ1=new Object(); +%\end{verbatim} +% \begin{macrocode} +\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} +% \end{macrocode} +% We input the file that is created at the end of the document. We do a \cs{AtEndOfPackage} because +% the command \cs{jsCodeForQzs} must be well defined by the time the document JavaScript are inserted. +% \begin{macrocode} +\AtEndOfPackage{\InputIfFileExists{qzlist-\jobname.cut}{}{}} +% \end{macrocode} +% At the end of the document after all quizzes and shortquizzes are known, we save them to +% the file \texttt{qzlist-\string\jobname.cut}, they are then input in the preamble. +% The \DescribeMacro{\saveListofQzs}\cs{saveListofQzs} writes the name of each quiz to an +% semi-colon delimited list. +% \begin{macrocode} +\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 +} +% \end{macrocode} +% Expand \cs{saveListofQzs} at the end of the document. +% \begin{macrocode} +\AtEndDocument{\saveListofQzs} +% \end{macrocode} +% \section{Document JavaScript} +% \begin{macrocode} +\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; +% \end{macrocode} +%\leavevmode\IndexJS{cntCorrectResponses()}is the workhorse of \pkg{eq-save}. It keeps tabs on the +%total number of correct answers and the total number of questions. All \env{shortquiz}es are known immediately, +%but results from \env{quiz} environments are not known until the student presses the `End Quiz' button. +% \begin{macrocode} +function cntCorrectResponses() { + var f=this.getField("\eqsroot"); + if (f==null) return; + var g=f.getArray(); +% \end{macrocode} +% \textbf{Naming convention:}\\\null\qquad\texttt{\string\eqsroot.ScoreComb}, +% \texttt{\string\eqsroot.Score}, \texttt{\string\eqsroot.OutOf}\\[3pt] +% It is expected that the length \texttt{g.length=1\string|2\string|3}\\\null\quad +% if \texttt{g.length=1}, we expect the field to be \texttt{\string\eqsroot.ScoreComb},\\\null\quad +% if \texttt{g.length=2}, we expect \texttt{\string\eqsroot.Score} +% and \texttt{\string\eqsroot.OutOf}, and\\\null\quad +% if \texttt{g.length=3}, report all three +% \begin{macrocode} + 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(); +% \end{macrocode} +% We now display the totals results. +% \begin{macrocode} + 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)); +} +% \end{macrocode} +% \leavevmode\IndexJS{addInQuizResults()} is called by \texttt{cntCorrectResponses()} to add in the results +% from the quizzes, if known. Because `Begin Quiz' and `End Quiz' can be links (not recommended) we save +% the results of the quiz as the value of the field \texttt{ScoreData.\ameta{quizName}}. \pkg{exerquiz} +% package save the quiz data in the form \texttt{"Score;\penalty0NQuestions;\penalty0ptScore;\penalty0NPointTotal"}. +% This string can be split and the individual +% values may be retrieved. +% \begin{macrocode} +function addInQuizResults() { + var results,value,score,outof; +% \end{macrocode} +% Coming into this function, the calculations so far are for \env{oQuestion} and \env{shortquiz} environments, these normally +% don't have points assigned, and we do not support them if they do. Instead, we'll assign them to the points +% \begin{macrocode} + cntCorrectResponses.nPtsCorrectInDoc=% +cntCorrectResponses.nCorrectInDoc; + cntCorrectResponses.nPtsOutOfInDoc=cntCorrectResponses.nOutOfInDoc; + for (var i=0; i +% \end{macrocode} +\endinput diff --git a/texmf-dist/source/latex/eq-save/eq-save.ins b/texmf-dist/source/latex/eq-save/eq-save.ins new file mode 100644 index 00000000..6f4531a0 --- /dev/null +++ b/texmf-dist/source/latex/eq-save/eq-save.ins @@ -0,0 +1,60 @@ +%% +%% This file will generate fast loadable files and documentation +%% driver files from the doc files in this package when run through +%% LaTeX or TeX. +%% +%% Copyright 1999-2016 D. P. Story +%% +%% This file is part of the `AcroTeX eDucation Bundle'. +%% ------------------------------------------- +%% +%% It may be distributed under the conditions of the LaTeX Project Public +%% License, either version 1.2 of this license or (at your option) any +%% later version. The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.2 or later is part of all distributions of LaTeX +%% version 1999/12/01 or later. +%% +%% --------------- start of docstrip commands ------------------ +%% +\def\filedate{2017/07/29} +\def\batchfile{eq-save.ins} + +\input docstrip +\ifx\generate\undefined + \Msg{**********************************************} + \Msg{*} + \Msg{* This installation requires docstrip} + \Msg{* version 2.4 or later.} + \Msg{*} + \Msg{* An older version of docstrip has been input} + \Msg{*} + \Msg{**********************************************} + \errhelp{Move or rename old docstrip.tex and get a newer one.} + \errmessage{Old docstrip in input path} + \batchmode + \csname @@end\endcsname\end +\fi + +\keepsilent +\askforoverwritefalse +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\preamble +\endpreamble + +\generate +{% + \file{eq-save.sty}{\from{eq-save.dtx}{copyright,package}} +} + +\Msg{***************************************************************} +\Msg{*} +\Msg{* \space To finish the installation you have to copy the files } +\Msg{*} +\Msg{* \space *.sty, *.cfg and *.def into a directory searched by TeX} +\Msg{*} +\Msg{***************************************************************} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\endinput diff --git a/texmf-dist/tex/latex/eq-save/eq-save.sty b/texmf-dist/tex/latex/eq-save/eq-save.sty new file mode 100644 index 00000000..8bbaee95 --- /dev/null +++ b/texmf-dist/tex/latex/eq-save/eq-save.sty @@ -0,0 +1,384 @@ +%% +%% 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-2018 %% +%% 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} + [2018/04/07 v1.1 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; +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