---
title: "Example - Assignment with Key"
format: html
vignette: >
  %\VignetteIndexEntry{Example - Assignment with Key}
  %\VignetteEngine{quarto::html}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)
```

```{r setup}
library(parsermd)
library(stringr)
```

## Introduction

A common workflow in educational settings involves creating homework assignments that contain both student scaffolding and instructor solutions within the same document. This vignette demonstrates how to use `parsermd` to process such documents and automatically generate separate versions for students and instructors.

The typical workflow involves:

1. **Primary Document**: A single Qmd/Rmd file containing both student prompts and complete solutions
2. **Student Version**: Contains only student chunks with scaffolding and instructions
3. **Instructor Key**: Contains only solution chunks with complete answers
4. **Minimalist Key**: A streamlined version with solutions only (no instructional text)

## Sample Assignment Structure

Let's start by examining a sample homework assignment that follows this pattern. The assignment includes multiple exercises, each with two code chunks:

- **Student chunk**: labeled with `-student` suffix, contains scaffolding code
- **Solution chunk**: labeled with `-key` suffix, contains complete solutions

```{r show-assignment}
# Load the sample assignment
assignment_path = system.file("examples/hw03-full.qmd", package = "parsermd")
cat(readLines(assignment_path), sep = "\n")
```

## Parsing the Document

First, let's parse the assignment document to understand its structure:

```{r parse-document}
# Parse the assignment
rmd = parse_rmd(assignment_path)

# Display the document structure
print(rmd)
```

We can also examine the document as a tibble to better understand the chunk labels and structure:

```{r examine-tibble}
# Convert to tibble for easier inspection
as_tibble(rmd)
```

## Creating the Student Version

To create the student version, we need to:

1. Keep all markdown content (instructions, problem statements)
2. Keep only the student chunks (those with `-student` suffix)
3. Remove all solution chunks

```{r create-student-version}
# Select student chunks and all non-chunk content
student_version = rmd |>
  rmd_select(
    # Easier to specify the nodes we want to remove
    !has_label("*-key")
  )

# Display the student version structure
student_version
```

If we don't want to let the student on to the fact that the chunks are just for them we can use `rmd_modify()` to remove the `-student` suffix:

```{r remove-student-suffix}
student_version = student_version |>
  rmd_modify(
    function(node) {
      rmd_node_label(node) = stringr::str_remove(rmd_node_label(node), "-student")
      node
    },
    has_label("*-student")
  )

# Show the first few chunks to see the label changes
student_version
```

Let's see what the student version looks like as a document:

```{r student-document}
# Convert to document and display first few sections
as_document(student_version) |>
  cat(sep = "\n")
```

We can also save this to a file:

```{r save-student, eval=FALSE}
# Save student version (not run in vignette)
as_document(student_version) |>
  writeLines("homework-student.qmd")
```

## Creating the Instructor Key

For the instructor key, we want to:

1. Keep all markdown content for context
2. Keep only the solution chunks (those with `-key` suffix)
3. Remove all student chunks

```{r create-instructor-key}
# Select solution chunks and all non-chunk content
instructor_key = rmd |>
  rmd_select(
    # Again this is easier to specify the nodes we want to remove
    !has_label("*-student")
  )

# Display the instructor key structure
instructor_key
```

Let's examine the instructor key document:

```{r instructor-document}
# Convert to document
instructor_doc = as_document(instructor_key)

# Display first part of the document
cat(head(strsplit(instructor_doc, "\n")[[1]], 50), sep = "\n")
```

## Creating a Minimalist Key

Sometimes instructors may want a very streamlined version that contains only the solution code without all the instructional text. 

We can create this by:

1. Keeping only exercise headings and solution chunks
2. Removing all markdown instructions
3. Setting `#| include: false` for the `setup` chunk

```{r create-minimalist-key}
# Select only headings and solution chunks
minimalist_key = rmd |>
  rmd_select(
    # Keep yaml and exercise headings for structure
    has_type("rmd_yaml"),
    has_heading(c("Exercise *", "Bonus*")),
    # Keep only solution chunks
    has_label(c("*-key", "setup"))
  ) |>
  rmd_modify(
    function(node) {
      rmd_node_options(node) = list(include = FALSE)
      node
    },
    has_label("setup")
  )

# Display the minimalist key structure
minimalist_key
```

```{r minimalist-document}
# Convert to document
minimalist_doc = as_document(minimalist_key)
cat(minimalist_doc, sep = "\n")
```


## Best Practices

When creating homework assignments for processing with `parsermd`, consider these best practices:

1. **Clear Structure**: Use headings to organize exercises and maintain hierarchy
2. **Meaningful Labels**: Use descriptive chunk labels that identify the document components and their type (e.g., `ex1-student`, `ex2-key`)
3. **Testing**: Always test the generated versions to ensure they work correctly and you haven't lost anything important (e.g. your YAML front matter or your setup chunk)

