5

We currently use R/exams to create exams in our coding course. We found students could easily copy & paste the code chunk and run it without thinking. Example:

output example

We thus wonder if there is an argument/option in R/exam or other packages that could prevent this case, e.g., converting the code chunk into images. Then, the students cannot copy & paste our code.

HiMifeng
  • 61
  • 4
  • 1
    You could add this answer to your HTML content https://stackoverflow.com/a/8957470/3212698 – mhovd Dec 07 '22 at 11:01
  • 5
    However, if you instead want to test if students are able to read the flow of the program, you could instead write the question in pseudocode. – mhovd Dec 07 '22 at 11:02
  • Thanks! but what if I cannot modify the output HTML content... Is there a setting I could change in the R markdown script? – HiMifeng Dec 07 '22 at 11:39
  • Also, are you unable to limit the students access to an instance of R? – mhovd Dec 07 '22 at 13:20

3 Answers3

5

Let me play the LockPickingLawyer a little bit here. Even if you manage to provide the code as an image, we are able to OCR and run it very easily and the solution would benefit those who know how to do it.

text <- tesseract::ocr("https://i.stack.imgur.com/wSRv5.png")  ## imgur url from OP
cat(text)

## copy-paste and run
x = -2
if(x > 0){
  x<- x +1
} else if(x == 0){
  x<-x-1
} else {
  x <- x * (-1)
}
x
# [1] 2

So why not asking why the result is 2 or, "describe in words for each line what the code does" instead?

jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • 2
    Exactly. There is a solution to create an image from text but it doesn't prevent cheating. There is no code that will do that, so I think maybe the question is better asked on academia Stack Exchange. – SamR Dec 07 '22 at 13:03
  • 1
    I don't think OP is looking to stop 'cheating' in the strictest sense - only to make sure students actually engage with questions rather than just Ctrl+C/V without thinking. – Captain Hat Dec 07 '22 at 13:35
3

A partial solution

We can generate html outputs from code chunks using reprex::reprex(), and then save images of the rendered output using webshot2::webshot().

It's a very limited solution, but all the main parts are there. Right now the output is very small and I can't work out how to resize it. reprex() also evaluates the code, which means the output is included (the very thing you were hoping to avoid). But it think webshot() might still be the way to go.

Here's a reproducible Quarto file that proves the concept:

---
title: "testing-code-images"
author: "Dave Lovell"
format: html
editor: visual
---

```{r libs}
library(webshot2)
library(reprex)
```

## Code example

```{r codeExample}
#| echo: false
#| fig.width: 6
snippet <- reprex(
  x = {
    y <- -2
    
    if(y > 0) y <- y * 2
    
    y
  },
  venue = "html"  # so we can pass to webshot()
)

# Write snippet output to html file
writeLines(snippet, "test-file.html")

# Capture the html file as an image
webshot(url = "test-file.html",
        file = "test-image.png") # make it bigger

# Don't need to keep the files
file.remove("test-image.png")
file.remove("test-file.html")
```

Output:

html file generated

Captain Hat
  • 2,444
  • 1
  • 14
  • 31
2

General comments

There isn't a readily available option to generate the image but the building blocks are available to write a little bit of code yourself. In particular the R/exams packages provides a tex2image() function which can take a LaTeX code chunk and turn it into an image which you can subsequently embed in the question.

Worked example

Below I provide a worked example which also randomly inserts some elements into the code:

```{r, include=FALSE}
## code as character string
code <- "
x <- %s

if (x > %s) {
  x <- x + 1
} else if (x == %s) {
  x <- x - 1
} else {
  x <- x * (-1)
}

x
"

## random inputs
x <- sample(-9:9, 1)
y <- sample(-3:3, 1)
code <- sprintf(code, x, y, y)

## screenshot
img <- tex2image(c("\\begin{verbatim}", code, "\\end{verbatim}"),
  name = "code", dir = ".", resize = 220)

## solution
sol <- eval(parse(text = code))
```

Question
========
The following code results in which output?
\
![R code](code.png)


Meta-information
================
exname: Conditional execution (with screenshot)
extype: num
exsolution: `r sol`

The idea is to first set up the code (or a code template) as a character string, then insert some randomized elements, generate the image, evaluate the code output and then prepare in the usual R/exams way. You might have to play with the resize argument to control the size of the image in a suitable way.

Further recommendations

Personally, I'm not fond of such workarounds because they feel like introducing additional hurdles which are not really about learning R. Using these strategies might also incentivize students to find workarounds like using OCR (see the other answers).

Instead, I usually try to change the answer format to single-choice or multiple-choice, based on qualitative statements. For example, for the code from your original post:

  • For any positive input, one unit is added. [true]
  • If the input is not positive, one unit is substracted. [false]
  • One unit is added to all non-negative inputs. [false]

And so on...

Achim Zeileis
  • 15,710
  • 1
  • 39
  • 49