## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

## ----installation, eval = FALSE-----------------------------------------------
#  install.packages("eatATA")

## ----library, message = FALSE-------------------------------------------------
# loading eatATA
library(eatATA)

## ----import items, message = FALSE--------------------------------------------
items_path <- system.file("extdata", "items.xlsx", package = "eatATA")

items <- as.data.frame(readxl::read_excel(path = items_path), stringsAsFactors = FALSE)

## ----inspect items, message = FALSE-------------------------------------------
head(items)

## ----dummies to factors, error = TRUE-----------------------------------------
# clean data set (categorical dummy variables must contain only 0 and 1)
items <- dummiesToFactor(items, dummies = c("MC", "CMC", "short_answer", "open"), facVar = "itemFormat")
items <- dummiesToFactor(items, dummies = paste0("diff_", 1:5), facVar = "itemDiff")
items[c(24, 33, 37, 47, 48, 54, 76), ]

## ----data cleaning, message = FALSE-------------------------------------------
# make new factor with three levels: "MC", "open" and "else"
items <- dummiesToFactor(items, dummies = c("MC", "open"), facVar = "MC_open_none")
# clean data set (NA should be 0)
for(ty in c(paste0("diff_", 1:5), "CMC", "short_answer")){
  items[, ty] <- ifelse(is.na(items[, ty]), yes = 0, no = items[, ty])
}
# make factors of CMC dummi
items$f_CMC <- factor(items$CMC, labels = paste("CMC", c("no", "yes"), sep = "_"))

# example item format
table(items$short_answer)

## ----fixed variables, message = FALSE-----------------------------------------
# set up fixed variables
nItems <- nrow(items)  # number of items
nForms <- 14           # number of blocks

## ----target constraints-------------------------------------------------------
# optimize average time
av_time <- minimaxObjective(nForms, itemValues = items$time, targetValue = 10,
                             itemIDs = items$item)

## ----item usage constraints---------------------------------------------------
itemOverlap <- itemUsageConstraint(nForms, targetValue = 1, 
                                   operator = "=", itemIDs = items$item) 

## ----categorical constraints--------------------------------------------------
# item formats
mc_openItems <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$MC_open_none, 
                                     itemIDs = items$item)
cmcItems <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$f_CMC, itemIDs = items$item)
saItems <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$short_answer, 
                                allowedDeviation = 1, itemIDs = items$item)

# difficulty categories
Items1 <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$diff_1, 
                               allowedDeviation = 1, itemIDs = items$item)
Items2 <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$diff_2, 
                               allowedDeviation = 1, itemIDs = items$item)
Items3 <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$diff_3, 
                               allowedDeviation = 1, itemIDs = items$item)
Items4 <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$diff_4, 
                               allowedDeviation = 1, itemIDs = items$item)
Items5 <- autoItemValuesMinMaxConstraint(nForms = nForms, itemValues = items$diff_5, 
                               allowedDeviation = 1, itemIDs = items$item)

## ----exclusion demo-----------------------------------------------------------
# item exclusions variable
items$exclusions[1:5]

## ----exclusion constraints----------------------------------------------------
# item exclusions
exclusionTuples <- itemTuples(items, idCol = "item", 
                                       infoCol = "exclusions", sepPattern = ", ")
excl_constraints <- itemExclusionConstraint(nForms = 14, itemTuples = exclusionTuples, 
                                            itemIDs = items$item)

## ----item numbers constraints-------------------------------------------------
# number of items per test form
min_Nitems <- floor(nItems / nForms) - 3
noItems <- itemsPerFormConstraint(nForms = nForms, operator = ">=", 
                                  targetValue = min_Nitems, itemIDs = items$item)


## ----prepare constraints, eval = T--------------------------------------------
# Prepare constraints
constr_list <- list(itemOverlap, mc_openItems, cmcItems, saItems, 
                      Items1, Items2, Items3, Items4, Items5, 
                      excl_constraints,
                      av_time)

## ----solver_local, eval = FALSE, echo = FALSE---------------------------------
#  # Local optimization chunk; prevents occasional errors on servers if no feasible solution is found
#  output_local <- capture.output(solver_raw_local <- useSolver(constr_list, nForms = nForms, nItems = nItems,
#                          itemIDs = items$item, solver = "GLPK", timeLimit = 30))
#  saveRDS(solver_raw_local, "use_case_solver_out.RDS")
#  saveRDS(output_local, "use_case_output.RDS")
#  

## ----solver, eval = FALSE, message=TRUE---------------------------------------
#  # Optimization
#  solver_raw <- useSolver(constr_list, nForms = nForms, nItems = nItems,
#                          itemIDs = items$item, solver = "GLPK", timeLimit = 10)
#  

## ----solver_load, eval = TRUE, echo = FALSE-----------------------------------
solver_raw <- readRDS("use_case_solver_out.RDS")
output_local <- readRDS("use_case_output.RDS")
output_local
message("The solution is feasible, but may not be optimal")

## ----inspect solution---------------------------------------------------------
out_list <- inspectSolution(solver_raw, items = items, idCol = "item", colSums = TRUE,
                            colNames = c("time", "subitems", 
                                         "MC", "CMC", "short_answer", "open",
                                         paste0("diff_", 1:5)))

# first two booklets
out_list[1:2]

## ----block exclusions---------------------------------------------------------
analyzeBlockExclusion(solverOut = solver_raw, item = items, idCol = "item", 
                      exclusionTuples = exclusionTuples)


## ----append solution----------------------------------------------------------
out_df <- appendSolution(solver_raw, items = items, idCol = "item")

## ----export solution to excel, eval = FALSE-----------------------------------
#  devtools::install_github("beckerbenj/eatAnalysis")
#  
#  eatAnalysis::write_xlsx(out_df, filePath = "example_excel.xlsx",
#                          row.names = FALSE)

