%% %% This is file `thorshammer.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% thorshammer.dtx (with options: `copyright,package') %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% thorshammer.sty package, %% %% Copyright (C) 2020 D. P. Story %% %% dpstory@uakron.edu dpstory@acrotex.net %% %% %% %% 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} \ProvidesPackage{thorshammer} [2021/06/24 v1.5.11 Support commands for Thor's way] \RequirePackage{xkeyval} \edef\th@dquoteCat{\the\catcode`\"} \catcode`\"=12\relax \DeclareOptionX{nocfg}{\let\th@loadCFG\dl@NO} \let\th@loadCFG\dl@YES \newif\ifthtestmode\thtestmodefalse \DeclareOptionX{testmode}{\thtestmodetrue} \DeclareOptionX{!testmode}{\thtestmodefalse} \newif\ifthordinary \thordinaryfalse \DeclareOptionX{ordinary}{\thtestmodetrue\thordinarytrue} \newif\ifbasicmethods\basicmethodstrue \newif\ifuseclassOpt\useclassOptfalse \def\bUseClass{false} \DeclareOptionX{useclass}{\useclassOpttrue \def\bUseClass{true}\basicmethodsfalse } \newif\ifth@allowfreeze \th@allowfreezetrue \DeclareOptionX{usebatch}{\th@allowfreezefalse \ExecuteOptionsX{useclass}} \DeclareOptionX{batchdistr}{\ExecuteOptionsX{usebatch}% \AtEndOfPackage{\distrToStudentsOff \let\distrToStudentsOff\relax\let\distrToStudentsOff\relax}} \ProcessOptionsX \edef\thOrdQz{\ifthordinary true\else false\fi} \RequirePackage{insdljs}[2021/06/19] \ifx\usedAdbFuncs\dl@NO \def\inputAltAdbFncs{\InputIfFileExists{altadbfncs.def}% {\PackageInfo{insdljs}{Inputting code for usealtadobe option}}% {\PackageWarning{insdljs}{Cannot find altadbfncs.def.\MessageBreak Reinstall or refresh your file name database.}}}% \let\usedAdbFuncs\dl@YES \else \let\inputAltAdbFncs\relax \fi \inputAltAdbFncs \RequirePackage{exerquiz}[2021/05/29] \RequirePackage{eq-save}[2021/04/27] \let\execjs\dl@YES \@ifundefined{CommentStream}{\newwrite\CommentStream}{} \def\csarg#1#2{\expandafter#1\csname#2\endcsname} \providecommand{\eqSP}{\string\040} \def\thPageOne{\setcounter{page}{1}} \def\setInitMag#1{\setkeys{thim}{mag=#1}} \define@choicekey+{thim}{mag}[\val\nr]% {fitpage,actualsize,fitwidth,fitheight,% fitvisible,inheritzoom}[fitpage]% {\edef\th@initmag{\@nameuse{dl@\val}}} {\PackageWarning{thorshammer}{% Bad choice for initial magnification,\MessageBreak permissible values are fitpage, actualsize,\MessageBreak fitwidth, fitheight, fitvisible, and\MessageBreak inheritzoom. Try again}} \def\th@initmag{\dl@fitpage} \addToDocOpen{\JS{% var stmot=app.setTimeOut("this.calculate=false;",100);}} \addToDocOpen{\GoToD[\Page{1}\th@initmag]} \def\instrPathIsCHTTP{\def\thInstrFS{CHTTP}} \let\thInstrFS\@empty \newcommand\instrPath{\@ifstar {\gdef\InstrPathFull{false}\instrPath@i} {\gdef\InstrPathFull{true}\instrPath@i}} \def\instrPath@i#1{\gdef\InstrPath{"#1"}} \def\InstrPathFull{true} \def\InstrPath{this.path.replace(reRmFn,"")} \def\classPathIsCHTTP{\def\thClassFS{CHTTP}} \let\thClassFS\@empty \newcommand\classPath{\@ifstar {\gdef\ClassPathFull{false}\classPath@i} {\gdef\ClassPathFull{true}\classPath@i}} \def\classPath@i#1{\gdef\ClassPath{"#1"}} \def\ClassPath{this.path.replace(reRmFn,"")} \def\ClassPathFull{true} \def\thQzHeaderL#1{\def\th@QzHeaderLQ{\makebox[0pt][l]{#1}}} \def\th@QzHeaderL{\th@QzHeaderLQ} \thQzHeaderL{Thor's Class} \def\th@QzHeaderLS{\th@HeaderOffset\th@QzHeaderLQ} \def\thQzHeaderCQ#1{\def\th@QzHeaderCQ{\makebox[0pt][c]{#1}}} \thQzHeaderCQ{Quiz \thQuizName} \def\th@QzHeaderC{\th@QzHeaderCQ} \def\thQzHeaderCS#1{\def\th@QzHeaderCS{\makebox[0pt][c]{#1}}} \thQzHeaderCS{Solutions: \thQuizName} \def\thQzHeaderR#1{\def\t@hQzHeaderR{\makebox[0pt][r]{#1}}} \thQzHeaderR{\thepage} \@ifundefined{ps@webheadings}{% \def\th@setHeaders{% \renewcommand{\@oddhead}{\th@QzHeaderL\hfil\th@QzHeaderC\hfil \t@hQzHeaderR}\renewcommand{\@evenhead}{\@oddhead}}% }{% \def\th@setHeaders{% \lheader{\th@QzHeaderL}% \cheader{\th@QzHeaderC}% \rheader{\t@hQzHeaderR}}% } \def\eq@normallheader{% \@ifundefined{ps@webheadings}{% \def\th@QzHeaderL{\th@QzHeaderLS}% \def\th@QzHeaderC{\th@QzHeaderCS}% }{% \lheader{\th@QzHeaderLS}% \cheader{\th@QzHeaderCS}% } } \def\rhPgNumsOnly{\thQzHeaderL{}\thQzHeaderCQ{}\thQzHeaderCS{}} \AtBeginDocument{\th@setHeaders} \newif\ifthCoverPage \thCoverPagefalse \newcommand{\DeclareCoverPage}[1]{\thCoverPagetrue \def\thIsCP{true}\def\thCvrPg{#1}} \def\thIsCP{false}\def\thCvrPg{0} \@onlypreamble\DeclareCoverPage \def\useNameToCustomize{\def\thUseNameToCustomize{true}} \def\thUseNameToCustomize{false} \def\enumQuizzes#1{\def\bUseClass{true}\basicmethodsfalse \ClassEntriestrue\def\ClassPathFull{true}\def\InstrPathFull{true}% \def\ClassPath{this.path.replace(reRmFn,"")}% \def\InstrPath{this.path.replace(reRmFn,"")}% \bgroup\@tempcnta#1\relax \@whilenum\@tempcnta>\z@\do{\classMember{}{}{}% \advance\@tempcnta\m@ne}\egroup \def\thEnumQuizzes{#1}\def\bEnumQuizzes{true}} \def\thEnumQuizzes{0}\def\bEnumQuizzes{false} \newcommand{\distrQuizzes}{% \ifuseclassOpt \def\th@next{\PackageWarning{thorshammer} {Use have specified the useclass option or higher\MessageBreak yet you employ \string\distrQuizzes, these are\MessageBreak incompatible. Assuming the specified package option}}% \else \let\th@next\th@distrQuizzes \fi\th@next } \def\th@distrQuizzes{\def\bUseClass{true}\basicmethodsfalse \ClassEntriestrue\bgroup\@makeother\_\th@distrQuizzes@i} \def\rmSTAR#1*\@nil{\def\@folder{#1}} \def\tstForSTAR#1*#2*\@nil{\def\@rgi{#1}\ifx\@rgi\@empty \def\ISSTAR{*}\rmSTAR#2\@nil\else\let\ISSTAR\@empty\fi}% \def\th@distrQuizzes@i#1{\@tempcnta\z@ \@tfor\@folder:=#1\do{\advance\@tempcnta\@ne \expandafter\tstForSTAR\@folder**\@nil \edef\x{\noexpand\classMember{}{}\ISSTAR{\@folder}}\x }\xdef\enumQuizzes{\the\@tempcnta}% \gdef\bDistrQuizzes{true}\egroup } \def\bDistrQuizzes{false} \@ifundefined{executeSave} {\def\executeSave(){% console.println("automatically saving this file...");^^J% var retn=aebTrustedFunctions(this,aebDocSaveAs,% {cPath:this.path,bCopy:false})}}{} \@ifundefined{docassembly} {\newenvironment{docassembly}{% \execJS[\mkClFlsSpcls]{docassembly}}{\endexecJS}} {\renewenvironment{docassembly}{% \execJS[\mkClFlsSpcls]{docassembly}}{\endexecJS}} \ifbasicmethods\let\th@namePresets\@empty\else \def\th@namePresets{\Ff\FfReadOnly\BC{}}\fi \newcommand\FirstName[3][]{\th@bMrkQz\textField[% \presets{\th@namePresets}#1]{Name.first}{#2}{#3}} \newcommand\LastName[3][]{\textField[% \presets{\th@namePresets}#1]{Name.last}{#2}{#3}} \def\th@bMrkQz{\@ifundefined{bMrkQz\currQuiz} {\rlap{\textField[\Ff\FfReadOnly\BC{}\BG{}]{bMrkQz}{0pt}{0pt}}% \@namedef{bMrkQz\currQuiz}{}}{}} \def\th@fullnamePresets{\Ff\FfReadOnly\BG{}\BC{}} \def\thfullnameFmt#1{\def\th@fullnameFmt##1##2{#1}} \thfullnameFmt{#1+" "+#2} \newcommand{\FullName}[3][]{\textField[% \presets{\th@fullnamePresets}#1\AAcalculate{% var fName=this.getField("Name.first").value;\r var lName=this.getField("Name.last").value;\r event.value=\th@fullnameFmt{fName}{lName};}]{FullName}{#2}{#3}} \def\pwdInstrFldTU#1{\def\pwdInstrFld@TU{#1}} \pwdInstrFldTU{Enter password to mark this quiz} \newcommand{\pwdInstrFld}[4][]{% opts, pwd, wd, ht \@ifundefined{\currQuiz-nQs}{\def\nQs{0}} {\edef\nQs{\@nameuse{\currQuiz-nQs}}}% \textField[\cmd{\bParams{\currQuiz}{\nQs}{"#2"}\eParams} \Ff\FfPassword\AAkeystroke{\pwdKeyJS} \protect\AA\protect\Ff\TU{\pwdInstrFld@TU}#1% ]{pwdtxt}{#3}{#4}} \def\markQzFldCA#1{\def\markQzFld@CA{#1}} \markQzFldCA{Mark It} \def\markQzFldTU#1{\def\markQzFld@TU{#1}} \markQzFldTU{Press to mark this quiz} \newcommand{\markQz}[3][]{% \@ifundefined{\currQuiz-nQs}{\def\nQs{0}}% {\edef\nQs{\@nameuse{\currQuiz-nQs}}}% \makebox[0pt][l]{\textField[\BC{}\BG{}\H{S}\AAformat{% var f=this.getField("MarkIt");\r var g=this.getField("freezeQz");\r if(typeof _thorshammer!="undefined" && _thorshammer){\r\t if(f!=null)f.display=display.visible;\r\t } else{\r\t if(f!=null)f.display=display.hidden;\r\t if(g!=null)g.display=display.hidden;\r }}]{hideTxtFldMI}{0pt}{0pt}}% \pushButton[\cmd{\bParams{\currQuiz}{\nQs}\eParams}\F\FHidden \AAmouseup{\commonPassKey}\CA{\markQzFld@CA} \TU{\markQzFld@TU}\protect\AA\protect\F#1% ]{MarkIt}{#2}{#3}} \def\freezeQuizFldTU#1{\def\freezeQuizFld@TU{#1}} \freezeQuizFldTU{Make all fields readonly, cannot be undone} \def\freezeQuizFldCA#1{\def\freezeQuizFld@CA{#1}} \freezeQuizFldCA{Freeze Quiz} \newcommand\freezeQuiz[3][]{\pushButton[\cmd{\let\%\defjsLB} \CA{\freezeQuizFld@CA}\F\FHidden \TU{\freezeQuizFld@TU}\AAmouseup{freezeQuizMU()} \protect\AA\protect\F #1]{freezeQz}{}{11bp}} \def\instrSaveFldTU#1{\def\instrSaveFld@TU{#1}} \instrSaveFldTU{Save and close this file to the current folder} \def\instrSaveFldCA#1{\def\instrSaveFld@CA{#1}} \instrSaveFldCA{Save \string& Close} \newcommand\instrSave[3][]{\pushButton[% \CA{\instrSaveFld@CA}\F\FHidden \TU{\instrSaveFld@TU}\AAmouseup{% var f=this.getField("studentenGrade");\r var str=""+f.value;\r str=str.replace(/\string\s/g,"");\r if (str=="")\r\t app.alert("You did not award the student a final mark." +"\\n\\nAward the mark and then save.");\r else {\r\t aebTrustedFunctions(this,aebSaveAs);\r\t this.closeDoc(true);\r }}\protect\AA\protect\F #1]{freezeQz}{}{11bp}} \AtEndOfPackage{\ifth@allowfreeze\let\freezeOrSave\freezeQuiz \else\let\freezeOrSave\instrSave\fi} \newcommand{\studentReport}[3][]{% \textField[\BC{}\BG{}\F\FHidden\Ff\FfReadOnly\protect\Ff#1% ]{studentenReport}{#2}{#3}} \newcommand{\studentGrade}[3][]{\textField[\F\FHidden\protect\F \BC{red}\BG{}\Q1\textSize{12}\textColor{blue} \AAkeystroke{event.change=event.change.toUpperCase()}#1% ]{studentenGrade}{#2}{#3}} \def\thQHFirstName#1{\def\th@QHFirstName{\textbf{#1}\space}} \thQHFirstName{First name:} \def\thQHLastName#1{\def\th@QHLastName{\textbf{#1}\space}} \thQHLastName{Last name:} \def\thQHPoints#1{\def\th@QHPoints{\textbf{#1}\space}} \thQHPoints{Points:} \def\thQHGrade#1{\def\th@QHGrade{\textbf{#1}\space}} \thQHGrade{Grade:} \newcommand{\thQuizHeader}{\let\Hy@EveryPageAnchor\relax \@ifstar{\thPageOne\thQuizHeaderLayout} {\newpage\thPageOne\thQuizHeaderLayout}% } \newcommand\thQuizHeaderLayout{\noindent \th@QHFirstName\FirstName{1.5in}{13bp}\vcgBdry[3pt] \th@QHLastName\LastName{1.5in}{13bp}\vcgBdry[6pt] \begin{minipage}[t]{1.2in}\kern0pt \makebox[0pt][r]{\raggedleft\markQz{}{11bp}% \hspace{\marginparsep}}% \th@QHPoints\studentReport{\widthof{000/000}}{11bp}\vcgBdry[6pt] \makebox[0pt][r]{\raggedleft\freezeOrSave{}{11bp}% \hspace{\marginparsep}}% \th@QHGrade\studentGrade{14bp}{14bp}\vcgBdry[6pt] \end{minipage}\hfill \begin{minipage}[t]{\linewidth-1em-1.2in}\kern0pt \begin{sumryTblAux}{\currQuiz} \displaySumryTbl[ntables=1,showmarkup]{\currQuiz} \end{sumryTblAux} \end{minipage}} \def\completeMsgFldV#1{\def\completeMsgFld@V{#1}} \completeMsgFldV{Congratulations, you have completed the quiz, before doing anything else, you need to save this document.} \newcommand{\completeMsgFld}[3][]{\textField[\F\FHidden\Ff\FfMultiline \Ff\FfReadOnly\V{\completeMsgFld@V} \DV{\completeMsgFld@V}]{postQzMsg}{#2}{#3}} \def\ShrtPtsFldFmt{\bgroup\obeyspaces\ShrtPtsFldFmt@i} \def\ShrtPtsFldFmt@i#1{\egroup\flJSStr[noquotes]{\ShrtPtsFld@Fmt}{#1}} \ShrtPtsFldFmt{"Short Pts: "+event.value} \newcommand{\ShrtPtsFld}[2][]{% \PointsField[\AAformat{if(event.value!="") event.value=\ShrtPtsFld@Fmt}\F\FHidden\protect\AA \protect\F#1]{#2}} \def\LngPtsFldFmt{\bgroup\obeyspaces\LngPtsFldFmt@i} \def\LngPtsFldFmt@i#1{\egroup\flJSStr[noquotes]{\LngPtsFld@Fmt}{#1}} \LngPtsFldFmt{"Long Pts: "+event.value} \newcommand{\LngPtsFld}[2][]{% \textField[\presets{\PointsFieldDefaults}\F\FHidden \AAformat{if(event.value!="") event.value=\LngPtsFld@Fmt} \AAcalculate{var f=this.getField("essayMrkUp");\r if(f!=null)EFSimple_Calculate("SUM",% new Array("essayMrkUp.\currQuiz"));} ]{EssayField.\currQuiz}{\PtFW}{\DefaultHeightOfWidget}} \def\TotalsFldFmt{\bgroup\obeyspaces\TotalsFldFmt@i} \def\TotalsFldFmt@i#1{\egroup\flJSStr[noquotes]{\TotalsFld@Fmt}{#1}} \TotalsFldFmt{"Total: "+event.value+"\space\eqOutOf\space"% +NPointTotal} \newcommand{\TotalsFld}[2][]{% \textField[\presets{\PointsFieldDefaults}\F\FHidden \AAformat{try{event.value=(\TotalsFld@Fmt)}catch(e){}} \AAcalculate{EFSimple_Calculate("SUM",% new Array("PointsField.\currQuiz","EssayField.\currQuiz"));\r var\eqSP f=this.getField("studentenReport");\r f.value=(1*event.value)+"\eqSP/\eqSP"+\theeqpointvalue; }]{TotalsField.\currQuiz}{\PtFW}{\DefaultHeightOfWidget}} \newcommand{\thQuizTrailer}{\raisebox{\baselineskip-\fboxsep}% {\makebox[0pt][l]{\parbox[t]{3in}{\kern0pt \completeMsgFld{3in}{3\baselineskip}}}}% \makebox[0pt][l]{\hspace{3in}\quad \ifthtestmode\CorrButton{\currQuiz}\else \stuSaveBtn{}{11bp}\fi}\parbox[t]{3in} {\ShrtPtsFld{\currQuiz}\vcgBdry[6pt] \LngPtsFld{\currQuiz}\vcgBdry[6pt] \TotalsFld{\currQuiz}}} \def\essayQFldTU#1{\def\essayQFld@TU{#1}} \essayQFldTU{Assign points to extended responses} \def\EsW{33bp}\def\EsH{14bp} \def\essayQ#1{\let\qMark@HookSave\qMark@Hook \def\qMark@Hook{\makebox[0pt][r]{\smash {\raisebox{-7bp+\fboxsep}{\stepcounter{questionno}\textField[% \cmd{\bParams{#1}\eParams}\F\FHidden\Q{1} \AAkeystroke{\essayQKey} \AAformat{if(event.value!="") event.value=event.value +((event.value==1)?" \eqptLabel":" \eqptsLabel")} \TU{\essayQFld@TU} ]{essayMrkUp.\currQuiz.\thequestionno}{\EsW}{\EsH}% \addtocounter{questionno}{-1}}}}\global \let\qMark@Hook\qMark@HookSave}} \def\essayitem#1{\essayQ{#1}\item\PTs{#1}} \begin{defineJS}[\makeesc\@]{\pwdKeyJS} if (event.willCommit) { if (event.value==@p(3)) { @commonPassKey } } \end{defineJS} \begin{defineJS}[\makeesc\@\makecmt\%]{\commonPassKey} if(typeof aQuizzesInDoc=="undefined") var aQuizzesInDoc=new Array(); if (aQuizzesInDoc.indexOf("@oField")) aQuizzesInDoc.push("@oField"); if (typeof @oField=="undefined") var @oField=new Object; restoreQuizData(); this.calculate=true; @ifthtestmode@else% var f=this.getField("postQzMsg"); if (f!=null) f.display=display.hidden;@fi var f=this.getField("pbStuSvCl"); if (f!=null) f.display=display.hidden; var f=this.getField("ScoreField.@p(1)"); if (f!=null) f.display=display.visible; var f=this.getField("PointsField.@p(1)"); if (f!=null) f.display=display.visible; var f=this.getField("EssayField.@p(1)"); if (f!=null) f.display=display.visible; var f=this.getField("TotalsField.@p(1)"); if (f!=null) f.display=display.visible; var f=this.getField("essayMrkUp"); if (f!=null) f.display=display.visible; correctQuiz("@p(1)",@p(2)); var f=this.getField("qzreset"); if (f!=null) f.display=display.visible; var f=this.getField("freezeQz"); if (f!=null) f.display=display.visible; var f=this.getField("studentenReport"); if (f!=null) f.display=display.visible; var f=this.getField("studentenGrade"); if (f!=null) f.display=display.visible; if (typeof correctSumryTbl == "function") correctSumryTbl("@p(1)",@p(2)); \end{defineJS} \def\NoNumEnteredMsg#1{\flJSStr*[noquotes]{\cNoNumEnteredMsg}{#1}} \NoNumEnteredMsg{"You did not enter a number, % enter a nonnegative number only"} \def\TooMuchCreditMsg#1{\flJSStr*[noquotes]{\cTooMuchCredit}{#1}} \TooMuchCreditMsg{"You've assigned too much credit for this % problem, assigning the maximum instead"} \begin{defineJS}[\makeesc\@\makecmt\%]{\essayQKey} if (event.willCommit) { var qpts=(1*event.value); if (isNaN(qpts)) { app.alert(@cNoNumEnteredMsg); event.rc=false; } else if (qpts<0) { event.value=-1*event.value; qpts=1*event.value; } if (event.rc) { if (qpts > @p(1) ) { app.alert(@cTooMuchCredit); qpts=@p(1); } // update ProbDist array ProbDist[@thequestionno]=qpts; // see if table is present if (typeof correctSumryTbl == "function") { f=this.getField("% @dlcombine(@currQuiz)(SanityCheckPts).@thequestionno"); var thesePts= qpts + (( qpts == 1 )?% " @eqptLabel":" @eqptsLabel"); f.value=thesePts; // add color var cb=this.getField("% @dlcombine(@currQuiz)(SanityCheck).@thequestionno"); if (qpts==@p(1)) cb.strokeColor=@rghtColorJS; else if (qpts>0) cb.strokeColor=@partialColorJS; else cb.strokeColor=@wrngColorJS; } event.value=qpts; } } \end{defineJS} \def\instrAutoSaveOn{\def\instrAutoSave{true}} \def\instrAutoSaveOff{\def\instrAutoSave{false}} \instrAutoSaveOn \def\instrAutoCloseOn{\def\instrAutoClose{true}} \instrAutoCloseOn \def\instrAutoCloseOff{\def\instrAutoClose{false}} \def\MarkWarningMsg#1{\dlJSStr*[noquotes]{\MarkWarning@Msg}{#1}} \MarkWarningMsg{"You did not award the student a final mark.\ \\n\\nAward the mark and then save."} \def\flattenOn{\def\bFlattenState{false}} \def\flattenOff{\def\bFlattenState{true}} \ifbasicmethods\flattenOff\else\flattenOn\fi \begin{insDLJS}{jsforthor}{thorshammer: Freeze/Save Doc} var sndSaveWarning=\SecondSave@Msg; var isthereCvrPg=\thIsCP; var cvrPgNum="\thCvrPg"; function freezeQuizMU() { var f, fname; var bOK=true; var f=this.getField("studentenGrade"); var str=""+f.value; str=str.replace(/\s/g,""); if (str=="") { app.alert(\MarkWarning@Msg); bOK=false; } var SolnSet=this.info.SolnSet; if (bOK&&SolnSet!=""){ var SolnPath=this.info.SolnPath; // var SolnSet=this.info.SolnSet; var qzbasename=this.info.qzBaseName; aebTrustedFunctions(this,aebInsertPages,{ nPage: (this.numPages-1), cPath: SolnPath+"/"+qzbasename+"-"+SolnSet+".pdf" }) }; if(\instrAutoSave&&bOK) { // var cSave="\jobname"; var docFN=this.documentFileName; docFN=docFN.substring(0,docFN.length-4); var cSave=(\thUseNameToCustomize)?"\jobname":docFN; if(\thUseNameToCustomize) { var f=this.getField("Name.first"); if(f!=null)cSave+=("-"+f.value+"_"); f=this.getField("Name.last"); if(f!=null)cSave+=(f.value); cSave+=("-g"); } var oRetn=aebTrustedFunctions(this,aebBrowseForDoc,{bSave:true,% cFilenameInit: cSave }); bOK=(typeof oRetn=="object"); if(bOK) { for (var i=0; i0\relax \FncyHdrsFmtNoTitleQuiz\fi\else \aebTitleQuiz\protect\ \ifnum\@eqquestiondepth=0\else\\\relax \FncyHdrsFmtQuestion\fi \fi %\space \ifcase\@eqquestiondepth \ifx\aebTitleQuiz\@empty\FncyHdrsFmtNoTitleQuiz\fi \or \string\llap{\arabic{eqquestionnoi}.\space}% \or \string\llap{\arabic{eqquestionnoi}.\space}% (\alph{eqquestionnoii})\space \or \string\llap{\arabic{eqquestionnoi}.\space}% (\alph{eqquestionnoii})% (\roman{eqquestionnoiii})\space \fi } \dclrFncyQzHdrsFmt{\myFQHFmt} \let\ReturnTo\@gobbletwo \let\bWebCustomize\endinput \let\eWebCustomize\relax \providecommand{\inputWebCfg}{% \let\bWebCustomize\relax \let\eWebCustomize\endinput \let\ExecuteOptions@SAVE\ExecuteOptions \let\ExecuteOptions\@gobble \makeatletter \InputIfFileExists{web.cfg}{}{}\makeatother \let\ExecuteOptions\ExecuteOptions@SAVE \let\bWebCustomize\endinput \let\eWebCustomize\relax } \def\classEntriesDef{["","","",false]} \newif\ifClassEntries\ClassEntriesfalse \let\classEntries\@gobble \def\classMember{\ClassEntriestrue\@ifstar {\let\th@star\ef@YES\classMember@i} {\let\th@star\ef@NO\classMember@i}} \newcommand\classMember@i[2]{% \@ifstar{\let\th@exstar\ef@YES\classMember@ii{#1}{#2}} {\let\th@exstar\ef@NO\classMember@ii{#1}{#2}}} \newcommand\classMember@ii[3]{% \ifx\th@exstar\ef@YES\def\AbsPth{true}\else \def\AbsPth{false}\fi \ifx\th@star\ef@NO \ifx\th@exstar\ef@YES \g@addto@macro\classEntries{,["#1","#2","#3",true]}\else \g@addto@macro\classEntries{,["#1","#2","#3",false]}\fi \else \g@addto@macro\classEntries{,["}% \pdfstringdef\x{#1}\expandafter \g@addto@macro\expandafter\classEntries\expandafter{\x}% \g@addto@macro\classEntries{","}% \pdfstringdef\x{#2}\expandafter \g@addto@macro\expandafter\classEntries\expandafter{\x}% \g@addto@macro\classEntries{","}% \pdfstringdef\x{#3}\expandafter \g@addto@macro\expandafter\classEntries\expandafter{\x}% \ifx\th@exstar\ef@YES \g@addto@macro\classEntries{",true]}\else \g@addto@macro\classEntries{",false]}\fi \fi} \def\autoCopyOn{\def\autoCopy{true}} \def\autoCopyOff{\def\autoCopy{false}} \autoCopyOn \newcommand{\cFS}[1]{\def\@rgi{#1}\ifx\@rgi\@empty \let\cFSth\@empty\else\def\cFSth{CHTTP}\fi} \let\cFSth\@empty \def\distrToStudentsOn{\def\distrToStudents{true}}\distrToStudentsOn \def\distrToStudentsOff{\def\distrToStudents{false}} \def\distrToInstrOn{\def\distrToInstr{true}}\distrToInstrOn \def\distrToInstrOff{\def\distrToInstr{false}} \def\th@QzVer{0} \def\QzVer{1} \newcommand{\declareQuizBody}[1]{% \bgroup\@tempcnta\th@QzVer\relax \advance\@tempcnta\@ne \edef\th@qbCnt{\the\@tempcnta}% \csarg\xdef{#1-QzVer}{\th@qbCnt}\egroup \csarg\def{#1}{\immediate\openout\CommentStream #1.cut \let\verbatim@out\CommentStream \immediate\write\verbatim@out{\string \def\string\QzVer{\@nameuse{#1-QzVer}}}% \verbatimwrite}% \csarg\def{end#1}{\endverbatimwrite \immediate\closeout\CommentStream}} \newcounter{th@qzCnt} \def\theth@qzCnt{\alph{th@qzCnt}} \let\qzLtr\theth@qzCnt % dps5-29 \newcommand{\InputQuizBody}[1]{\newpage %\thPageOne \@ifundefined{thisQuizOrig}{\edef\thisQuizOrig{\thisQuiz} \let\Hy@EveryPageAnchor\relax}{}\stepcounter{th@qzCnt}% \edef\x{\thisQuizOrig\theth@qzCnt}\expandafter \th@DeclareQuiz\expandafter{\x}% \renewcommand\sqslsecrunhead{}% \InputIfFileExists{#1.cut}{}{} \immediate\closeout\quiz@solns %\th@QzHeaderLS \let\eq@normallheader\relax \newpage \@ifundefined{ps@webheadings}{% \def\th@QzHeaderL{\th@QzHeaderLS}% \def\th@QzHeaderC{\th@QzHeaderCS}% }{% \lheader{\th@QzHeaderLS}% \cheader{\th@QzHeaderCS}% } \includequizsolutions*\relax \global\therearequizsolutionsfalse \renewcommand\sqslsecrunhead{\eq@sqslsecrunhead}% \eq@noformstrue \immediate\openout \quiz@solns \jobname.qsl \ifthordinary\else \@ifundefined{ps@webheadings}{% \def\th@QzHeaderL{\th@QzHeaderLQ}% \def\th@QzHeaderC{\th@QzHeaderCQ}% }{% \lheader{\th@QzHeaderLQ}% \cheader{\th@QzHeaderCQ}% }% \fi } \def\mkClFlsSpcls{\let\oct\eqbs\let\u\relax} \newenvironment{makeClassFiles}{% \execJS[\mkClFlsSpcls]{mcfthor}}{\endexecJS} \def\setClassArray{\ifClassEntries \classEntries\else\classEntriesDef\fi} \def\setArrayLength{\ifbasicmethods0\else lst.length\fi} \def\setfilesuffix{\ifuseclassOpt"-"+fN+"_"+lN\else \ifbasicmethods""\else"-"+(i+1)\fi\fi+".pdf"} \begin{defineJS}[\dfnJSCR{^^J}\let\u\relax\makeesc\@]{\sadQuizzes} if(@bFlattenState) this.addScript({ cName: "thorshammer: Do not flatten", cScript:"var _flattenThisDoc=false;" }); if (@autoCopy) { var bUseClass=@bUseClass; var reRmFn=new RegExp(this.documentFileName,"i"); var instrPath=@InstrPath; var cLast=instrPath[instrPath.length-1]; if (cLast=="/") instrPath=instrPath.substring(0,instrPath.length-1); var classPath=@ClassPath; cLast=classPath[classPath.length-1]; if (cLast=="/") classPath=classPath.substring(0,classPath.length-1); var thInstrFS="@thInstrFS"; var thClassFS="@thClassFS"; var isthereCvrPg=@thIsCP; var cvrPgNum="@thCvrPg"; console.println("autocopy "+((@autoCopy)?"on":"off")); var retn; var solnSuffix=""; var oSolnSuffix=new Object; var parentoDoc=this; var workingFolder=this.path; var pos=workingFolder.lastIndexOf("/"); workingFolder=workingFolder.substring(0,pos+1); var _workingFolder=""; // console.println("working folder: " + workingFolder); var willSaveScript='isAQuizUnfinishedAtSave();\r' +'if (oRecordOfQuizData !=undefined) collectQuizData();'; var oHSD=this.getField("holdScoreData"); var Rect=oHSD.rect; this.removeField("holdScoreData"); var hsdFmt='if(typeof oRecordOfQuizData=="undefined")\r\t\ oRecordOfQuizData=new Object;'; var restQD='@restoreQD'; if(isthereCvrPg) {// -------- extract cover pages ------------ var aCvrPgRng=cvrPgNum.split("-"); if (aCvrPgRng[0]=="") { console.println("Start Range not specified, using 0 instead"); var bPg=0; } else var bPg=aCvrPgRng[0]; var ePg=(aCvrPgRng.length>1)?aCvrPgRng[1]:aCvrPgRng[0]; var oDoc=aebTrustedFunctions(this,aebExtractPages, {nStart: bPg, nEnd: ePg}); // save cover page(s) to the instructor folder _workingFolder=(@InstrPathFull)?"":workingFolder; aebDocSaveAs.msg="Cannot access the local folder " + _workingFolder+instrPath+"/@jobname-cvrpg.pdf"; var retn=aebTrustedFunctions(oDoc,aebDocSaveAs, {cFS:thInstrFS,cPath: _workingFolder+instrPath+"/@jobname-" +"cvrpg.pdf",bCopy:false}); oDoc.dirty=false; oDoc.closeDoc(true); // delete cover page before continuing, will reinsert it later this.deletePages({nStart: bPg, nEnd: ePg}); this.dirty=false; } // ------- end cover page code -------------- var nQz=aQuizzesInDoc.length; // number of quizzes this doc var bOkBasicSolns=false; var f=this.getField("thsolns4"); if (f != null ) { console.println("There are solutions"); bOkBasicSolns=true; var g=f.getArray(); for (var i=0; i var oDoc=aebTrustedFunctions(this,aebExtractPages, {nStart: bPg, nEnd: ePg}); // save _workingFolder=(@InstrPathFull)?"":workingFolder; aebDocSaveAs.msg="Cannot access the local folder " + _workingFolder+instrPath+"/@jobname-"+solnSuffix+".pdf"; var retn=aebTrustedFunctions(oDoc,aebDocSaveAs, {cFS:thInstrFS,cPath: _workingFolder+instrPath+"/@jobname-" +solnSuffix+".pdf",bCopy:false}); // close oDoc.dirty=false; oDoc.closeDoc(true); // delete solution page before continuing this.deletePages({ nStart: bPg, nEnd: ePg}); this.dirty=false; } } } // ------ begin creating custom quizzes for class members ------ var cnt=0; // determines which quiz to generate var lst=new Array(@setClassArray); var l=(bUseClass)?@setArrayLength:1; // dps for (var i=0; i < l; i++) { var qzName=aQuizzesInDoc[cnt]; // console.println("Working on " + qzName); var fN=lst[i][0]; var lN=lst[i][1]; var folder=lst[i][2]; var isAbsPth=lst[i][3]; // dps if (folder!="")folder+="/"; // pre-populate with the student's name this.getField("Name.first").value=fN; this.getField("Name.last").value=lN; // extract quiz // var f=this.getField("Name.first."+cnt); var f=this.getField("bMrkQz."+cnt); var bPg=f.page; // var f=this.getField("Name.first."+(cnt+1)); var f=this.getField("bMrkQz."+(cnt+1)); var ePg=(f==null)?(this.numPages-1):(f.page-1); // ------------- extraction of quiz pages -------------- if(bUseClass)var oDoc=aebTrustedFunctions(this,aebExtractPages, {nStart: bPg, nEnd: ePg}); else oDoc=this; // dps // extracting preserves doc JS but not doc actions oDoc.setAction({cTrigger: "WillSave", cScript: willSaveScript}); oDoc.addScript({ cName: "oRecordOfQuizData Obj Declaration", cScript: hsdFmt}); var oDocHSD=oDoc.addField({ cName: "holdScoreData", cFieldType: "text", nPageNum: 0, oCoords: Rect }); oDoc.setPageAction({ nPage: 0, cTrigger: "Open", cScript: restQD }); oDoc.info.qzBaseName="@jobname"; if(isAbsPth) // dps oDoc.info.StudentPath=folder; else oDoc.info.StudentPath=classPath+"/"+folder; var bOkSolns=(typeof oSolnSuffix[qzName]!="undefined"); if(bOkSolns) oDoc.info.SolnSet=oSolnSuffix[qzName]; oDoc.info.SolnPath=_workingFolder+instrPath+"/"; if(isthereCvrPg) oDoc.info.CvrPg="cvrpg"; oDoc.info.cFS=thInstrFS; // Insert cover page, if any. if (isthereCvrPg) { if (typeof bCVMsg == "undefined") { console.println("Inserting cover page from " + _workingFolder+instrPath+"/@jobname-cvrpg.pdf"); var bCVMsg=true; } if (cnt==0) var _cvrPath=_workingFolder+instrPath; aebTrustedFunctions(oDoc,aebInsertPages, {nPage: -1, cPath: _cvrPath+"/@jobname-cvrpg.pdf"}); } var filesuffix=@setfilesuffix; // Now save this as a copy if(bUseClass) { _workingFolder=(@InstrPathFull)?"":workingFolder; aebDocSaveAs.msg="Cannot access the local folder " + _workingFolder+instrPath+"/@jobname-"+fN+"_"+lN+".pdf"; if(@distrToInstr) retn=aebTrustedFunctions(oDoc,aebDocSaveAs, {cFS:thInstrFS, cPath: _workingFolder+instrPath+"/@jobname"+filesuffix, bCopy:true}); var _workingFolderC=(@ClassPathFull)?"":workingFolder; if(isAbsPth) var cPath=folder+"@jobname"+filesuffix; else var cPath=_workingFolderC+classPath+"/"+folder +"@jobname"+filesuffix aebDocSaveAs.msg="Cannot access the path "+ cPath; if(@distrToStudents) retn=aebTrustedFunctions(oDoc,aebDocSaveAs, {cFS:thClassFS, cPath: cPath, bCopy:true}); oDoc.dirty=false; oDoc.closeDoc(true); } cnt=++cnt % nQz } } this.resetForm(["Name"]); console.println("automatically saving this file..."); var toSa=app.setTimeOut("aebTrustedFunctions(this,aebSaveAs);\ app.clearTimeOut(toSa);",50); \end{defineJS} \let\sadMultQuizzes\sadQuizzes \let\rasSolns\sadQuizzes \def\InputClassData#1{\def\InputCl@ssData{#1}\mkClFlsSpcls \InputIfFileExists{#1.cfg} {\PackageInfo{thorshammer}{Inputting class file #1.cfg}} {\PackageWarning{thorshammer} {Cannot find the class file #1.cfg}}} \newcommand\InputFormattedClass[2][\classMember]{\ClassEntriestrue \begingroup \mkClFlsSpcls \endlinechar=-1 \let\procThisLine\relax \let\bClassData\relax \let\re@dOK\dl@YES \newread\fmtclass \immediate\openin\fmtclass=#2.cfg \loop \read\fmtclass to \classmember \ifeof\fmtclass\let\re@dOK\dl@NO \else \expandafter \ifx\classmember\endinput\let\re@dOK\dl@NO \else \ifx\classmember\@empty %\let\procThisLine\relax \else \expandafter\procThisLine\classmember \expandafter\ifx\classmember\bClassData \def\procThisLine{#1}\fi \fi \fi \fi \ifx\re@dOK\dl@YES\repeat \immediate\closein\fmtclass \endgroup } \def\th@InputCFG{\InputIfFileExists{thorshammer.cfg} {\PackageInfo{thorshammer} {Inputting the configuration file}} {\PackageInfo{thorshammer} {No configuration file found}}} \ifx\th@loadCFG\dl@YES\expandafter\th@InputCFG\fi \catcode`\"=\th@dquoteCat \endinput %% %% End of file `thorshammer.sty'.