---
title: "Typical Use of `eatATA`: a Minimal Example"
author: "Benjamin Becker"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Typical Use of `eatATA`: a Minimal Example}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

`eatATA` efficiently translates test design requirements for Automated Test Assembly (`ATA`) into constraints for a Mixed Integer Linear Programming Model (MILP). A number of efficient and user-friendly functions are available that translate conceptual test assembly constraints to constraint objects for MILP solvers, like the `GLPK` solver. In the remainder of this vignette we will illustrate the use of `eatATA` using a minimal example. A general overview over `eatATA` can be found in the vignette [Overview of `eatATA` Functionality](overview.html).

## Setup
The `eatATA` package can be installed from `CRAN`. 

```{r installation, eval = FALSE}
install.packages("eatATA")
```

## Item Pool

First, `eatATA` is loaded into your `R` session. In this vignette we use a small simulated item pool, `items_mini`. The goal will be to assemble a single test form consisting of ten items, an average test time of eight minutes and maximum `TIF` at medium ability. We therefore calculate the `IIF` at medium ability and append it to the item pool using the `calculateIFF()` function.

```{r library, message = FALSE}
# loading eatATA
library(eatATA)

# item pool structure
str(items_mini)

# calculate and append IIF
items_mini[, "IIF_0"] <- calculateIIF(B = items_mini$difficulty, theta = 0)
```

In Table 1 you can see the first five items of the item pool.

```{r item pool, eval = TRUE, results = 'asis', echo = FALSE}
# create content bounderies in advance
knitr::kable(items_mini[1:5,], digits = 3, caption = "Table 1. First 5 Items of the Item Pool")
```

## Objective Function

Next, the objective function is defined: The `TIF` should be maximized at medium ability. For this, we use the `maxObjective()` function.

```{r objFun, message = FALSE}
testInfo <- maxObjective(nForms = 1, itemValues = items_mini$IIF,
                          itemIDs = items_mini$item)
```

## Constraints

Our further, fixed constraints are defined as additional constraint objects. 

```{r constraints, message = FALSE}
itemNumber <- itemsPerFormConstraint(nForms = 1, operator = "=", 
                                     targetValue = 10, 
                                     itemIDs = items_mini$item)

itemUsage <- itemUsageConstraint(nForms = 1, operator = "<=", 
                                 targetValue = 1, 
                                 itemIDs = items_mini$item)

testTime <- itemValuesDeviationConstraint(nForms = 1, 
                                itemValues = items_mini$time,
                                targetValue = 8 * 60, 
                                allowedDeviation = 5,
                                relative = FALSE, 
                                itemIDs = items_mini$item)
```

Alternatively, we could determine the appropriate test time based on the item pool using the `autoItemValuesMinMax()` function.

```{r test time, message = TRUE}
testTime2 <- autoItemValuesMinMaxConstraint(nForms = 1, 
                                itemValues = items_mini$time,
                                testLength = 10, 
                                allowedDeviation = 5,
                                relative = FALSE, 
                                itemIDs = items_mini$item)
```



## Solver usage

To automatically assemble the test form based on our constraints, we call the `useSolver()` function. In this function we define which solver should be used as back end. As a default solver, we recommend `GLPK`, which is automatically installed alongside this package.   

```{r solver, message = FALSE}
solver_out <- useSolver(list(itemNumber, itemUsage, testTime, testInfo),
                        solver = "GLPK")
```


## Inspect solution

The solution can be inspected directly via `inspectSolution()` or appended to the item pool via `appendSolution()`. Using the `inspectSolution()` function an additional row is created that calculates the column sums for all numeric variables. 

```{r inspect, message = FALSE}
inspectSolution(solver_out, items = items_mini, idCol = "item")
```

```{r append, message = FALSE}
appendSolution(solver_out, items = items_mini, idCol = "item")
```








