Using two templates with custom name in exams2pdf - r-exams

I am using exams2pdf() to generate two PDF files as:
exams2pdf(file = "ICvar.Rmd",
name = "icvar",
engine = "knitr",
verbose = FALSE,
texdir = "tmptex",
template = c("exam", "solution")
)
But I get this error:
Error in base::file(out_tex[j], open = "w+", encoding = encoding) : invalid 'description' argument
Any ideas why?
Also, is it possible to use custom templates in exams2nops() like template = c("exam", "solution") to produce two PDF files, the first with the questions; the second with the solutions? I read the vignette but could not find any information and adding template to options in exams2nops() does nothing.

The problem is that you only provide a single name = "icvar" but actually need two distinct names for template = "exam" and template = "solution", respectively. Hence, lacking a second name lead to the somewhat cryptic error message. A simple solution is to provide a vector of two name = c("icex", "icsol"), say.
Additionally, I have just committed a fix to the development version on R-Forge that points this out more clearly in ?exams2pdf, throws an intelligible warning, and provides a workaround. If you use your code above, name is changed to name = c("icvar_exam", "icvar_solution") automatically.
As for exams2nops(): Internally this essentially sets up a standardized template via make_nops_template() and then calls exams2pdf(). No additional templates can be provided. The reason for this is that all the convenient options in the NOPS template (e.g., adding an intro, selecting the language, switching to twocolumn layout, etc.) would only work for the NOPS template but not the other templates provided. Therefore, if you want to produce a solution sheet you have to use another call to exams2pdf() (or exams2html() or exams2pandoc()) after setting the same random seeds as for exams2nops().

Related

How to have parameters in the LaTeX template?

I have a LaTeX template, which I use with exam2pdf and where I would like to have the date of the exam as a parameter, whose value should be passed from R. Is that possible?
Yes, you can do this in two and a half ways:
(1) Via the header argument
You can set exams2pdf(..., header = ..., template = ...) where the content of the header is inserted into the template by replacing the %% \exinput{header} placeholder. Thus, when writing the template you can decide where exactly the header code ends up in the LaTeX code and you can make sure that the appropriate commands/packages are available. The header can then be specified in the following ways:
LaTeX code:
You can include something like header = "\\command{value}". There could be more complex pieces of LaTeX code, involving multiple lines, etc.
List of commands and values:
Instead of the full LaTeX code it might be more R-like to use a list specification like header = list(command = "value"). This is transformed internally to the LaTeX code mentioned above.
List of functions:
Finally you can also have a specification like header = list(command = valuefun) where valuefun is a function(i) so that you return a different string for the i-th random version of the exam.
List of all of the above:
A list consisting of unnamed character strings, named character string, and named functions can be used as well, combining all three specifications above.
More details are provided in the vignette("exams", package = "exams") which explains the design of exams2pdf() and how it can be leveraged. It also includes some examples which you can also copy to your working directory via exams_skeleton(write = "exams2pdf", ...). You can look at the exam.tex LaTeX template that is shipped with the package to see how you can insert a date and an ID (depending on the i-th iteration) into the PDF. For example:
exams2pdf("capitals.Rmd", template = "exam.tex",
header = list(Date = "2022-02-22", ID = function(i) paste("\\#", i)))
(2) Write a template generator
For the purposes from your question strategy (1) should be sufficient, I guess. However, if you need more control over what is done in the LaTeX template, then my recommendation would be to write a dynamic template generator. This is how exams2nops() is set up. It takes a lot of arguments that can be set by the user and then proceeds as follows:
Depending on the user arguments a corresponding nops.tex template is written in a temporary directory.
Then exams2pdf(..., template = "/path/to/nops.tex") is called to use this custom temporary template.
Some details, especially the counter for the i-th ID is still handled through the header argument.

Is exams' solution pdf first page editable? [duplicate]

When I try to generate the exams' solution with the exams2nops(...template="solution"...) I get the following error message:
Error in exams2pdf(file, n = n, nsamp = nsamp, dir = dir, name = name, :
formal argument "template" matched by multiple actual arguments
How can I produce an exams' solution with the exams2nops?
You cannot do that in one go, you need two runs after setting the same seed, e.g.,
set.seed(1)
exams2nops(my_exam)
set.seed(1)
exams2pdf(my_exam, template = "my_solution.tex")
You can use the solution.tex provided within the package as a starting point for my_solution.tex. But you may want to translate it to your natural language, use the name of your university, possibly insert a logo, add your actual exam name, possibly some into text etc. In exams2pdf() you need to add these things in the template LaTeX file directly.
won't the template="solution" not work in the exams2pdf? Also, can we do something like:
usepackage = "pdfpages", intro = intro2,... ?

Ho to hide the exam ID on the title page of a NOPS exam?

I'm using exams2nops() from R/exams to prepare multiple variants of an exam (as part of an open-book-exam). I'd like to obscure the variant/group of exam a test-taker is assigned to (in order to prevent "team work" during the open book exam: "Hey guys, who else is in group 1 ?!").
By default, the exams2nops() function will print the exam ID automatically on the title page (in my case: 20112600001):
It appears there's no argument in the exams2nops() function to prevent the exam ID to be printed on the title page of the PDF exam. I am unsure where to adapt the underlying TeX template.
So my question is: How to suppress the exam ID on the title page of the PDF for NOPS exams?
You are correct that this is not possible in exams2nops(), the simple reason being that the ID is essential for automatically evaluating NOPS exams after scanning them. Thus, if you want to scan the NOPS PDF file you must not remove the ID. The standard strategy for making team work on the same ID impossible would be to simply generate a different random PDF with a different ID for every participant.
If you are not actually scanning the exam, then I would recommend using exams2pdf() rather than exams2nops() and simply "roll your own" LaTeX template. If you want to take inspiration from the NOPS template, then you can create one on the fly (here with 2 exercises) via:
make_nops_template(2, file = "mynops.tex")
Note, however, that this has quite a few options that can be controlled through appropriate header commands in exams2pdf(), e.g.,
exams2pdf(c("anova", "boxplots"),
template = "mynops.tex",
header = list(
nopsinstitution = "Sauer School of Statistics",
nopstitle = "Exam",
nopscourse = " (AWM)",
"newcommand{\\mylogo}" = ""
)
)
In addition to the elements above, one would usually specify Date, ID and the NOPS language comments (see ?nops_language). But rather than using the header argument for this I would recommend to edit mynops.tex "by hand" and hard-code all the relevant aspects, including omitting the ID.

Is it possible to to export from reporttools?

I am using tableNominal{reporttools} to produce frequency tables. The way I understand it, tableNominal() produces latex code which has to be copied and pasted onto a text file and then saved as .tex. But is it possible to simple export the table produced as can be done in print(xtable(table), file="path/outfile.tex"))?
You may be able to use either latex or latexTranslate from the "Hmisc" package for this purpose. If you have the necessary program infrastructure the output gets sent to your TeX engine. (You may be able to improve the level of our answers by adding specific examples.)
Looks like that function does not return a character vector, so you need to use a strategy to capture the output from cat(). Using the example in the help page:
capture.output( TN <- tableNominal(vars = vars, weights = weights, group = group,
cap = "Table of nominal variables.", lab = "tab: nominal") ,
file="outfile.tex")

RGoogleDocs - uploadDoc does not replace doc with same name

I am using the RGoogleDocs package to upload a string of text to a document.
The following code is a minimal working example.
library(RGoogleDocs)
gpasswd = "mypassword"
auth = getGoogleAuth("example#gmail.com", gpasswd)
con = getGoogleDocsConnection(auth)
uploadDoc("test1", con, name = "d")
The problem: if I run this code twice two files named "d" appear.
In other words, the file is not replaced, even though in the function guide ?uploadDoc expected behaviour reads as
uploadDoc(content, con, name, type = as.character(findType(content)),
binary = FALSE, asText = FALSE, folder = NULL, ...)
-
name the name of the new document to be created (or the document to be replaced).
(Farrel Buchinsky brought this to my attention. It is often best to contact a package's author/maintainer if there is a problem as we don't necessarily follow both R-help and SO.)
Noah is right in saying just deleteDoc() and the uploadDoc().
We can do this in the uploadDoc() also.
I've just added a replace parameter to uploadDoc() (default is TRUE)
and that will (when I solve a possibly related bug)
a) move the current document, if it exists, to a temporary name
b) upload the new document to the target name,
c) delete the temporary document if the upload was successful
or, if not, move the temporary document back to the original name.
Something is up internally when testing this, but this should be in the next release.
I think the function guide here is a bit misleading. The uploadDoc function just creates a new document, and Google doesn't prevent you from having multiple docs named the same thing.
There is a stub in RGoogleDocs for updateDoc(), but it's been on the horizon for a while (last update of the package was 10/2009). I played for a few minutes, but would take some real digging to get it working.
Not a satisfying answer, but you could always just issue a deleteDoc() before re-uploading by the same name.

Resources