Use Custom `navigation`-Function to Implement a Booklet Design
booklets.Rmd
This example shows how to use the package
ShinyItemBuilder
for an assessment using
Booklets.
library(ShinyItemBuilder)
For illustration purposes, the items which are included as
demo01
in the package ShinyItemBuilder
are
used. After calling getDemoPool("demo01")
the object
item_pool
contains information about 6 CBA ItemBuilder
Tasks:
item_pool <- getDemoPool("demo01")
item_pool[,c("Project","Task")]
Project | Task | |
---|---|---|
1 | SinglePageItems_00START.zip | task0 |
2 | SinglePageItems_01SC.zip | task0 |
3 | SinglePageItems_02MC.zip | task0 |
4 | SinglePageItems_03TXT.zip | task0 |
5 | SinglePageItems_04LIKERT.zip | task0 |
6 | SinglePageItems_05END.zip | task0 |
The idea of using a Booklet Design is that each test-taker is assigned to a booklet out of a all defined booklets . For simplicity, we illustrate this with different booklets:
booklets <- data.frame(Booklet = c(1,1,1,2,2,2),
ItemIndex=c(2,3,6,4,5,6))
To define the booklets, we refer to the items from the
item_pool
, taking the row name as ItemIndex
.
Hence, the goal is to have two booklets, one with items
01SC
, 02MC
and 05END
(Booklet
)
and one with items 03TXT
, 04LIKERT
and
05END
(Booklet
):
Booklet | ItemIndex | Project | Task |
---|---|---|---|
1 | 2 | SinglePageItems_01SC.zip | task0 |
1 | 3 | SinglePageItems_02MC.zip | task0 |
1 | 6 | SinglePageItems_05END.zip | task0 |
2 | 4 | SinglePageItems_03TXT.zip | task0 |
2 | 5 | SinglePageItems_04LIKERT.zip | task0 |
2 | 6 | SinglePageItems_05END.zip | task0 |
To implement the booklet design, we need to overwrite the navigation function.
assessment_config <- getConfig(Verbose = T)
After calling getConfig()
, the object
assessment_config
already contains the (default)
implementation of the navigation
-function:
assessment_config$navigation
#> function (pool, session, direction = "NEXT")
#> {
#> current_item <- getValueForTestTaker(session, "current-item-in-pool",
#> default = 1, store = F)
#> if (current_item == 0 && direction == "START") {
#> current_item <- 1
#> }
#> else {
#> if (direction == "NEXT") {
#> if (current_item >= dim(assessment_env$pool)[1]) {
#> current_item <- -1
#> }
#> else {
#> current_item <- current_item + 1
#> }
#> }
#> else if (direction == "PREVIOUS") {
#> if (current_item > 0) {
#> current_item <- -1
#> }
#> else {
#> }
#> }
#> else if (direction == "CANCEL") {
#> current_item <- -2
#> }
#> }
#> setValueForTestTaker(session, "current-item-in-pool", current_item)
#> current_item
#> }
#> <bytecode: 0x56075605fc28>
#> <environment: 0x560756057170>
This function can be overwritten by assigning a new function
navigation = function(pool, session, direction="NEXT")
with
the same signature. In this new function, we first define the booklets.
In the next step, we create a variable current_booklet
that
stores the booklet assigned to the current test-taker.
To achieve persistence, we use the function
getValueForTestTaker().
The following arguments are used:
The first argument is the object session
(i.e., the session
variable with which the function navigation
was called).
The second argument "current-booklet"
is a self-chosen name
for the booklet variable. The third argument is the default
value which should be used if there is no entry with the name
"current-booklet"
for this session yet. Here we use the R
function sample
to randomly select a booklet. Finally, we
pass TRUE
for the store
argument to save the
selected booklet for this session and not re-set it on the next
call.
The remaining part of the function is almost unchanged. The variable
current_item
refers to the row index of the current item in
the item_pool
. To initialize the current_item
we use the first item defined for a particular booklet:
current_item <- booklets[booklets$Booklet==current_booklet,"ItemIndex"][1]
.
To update the current_item
we first find the row of the
current item in the item_pool
as
current_item_index <- which(booklets[booklets$Booklet==current_booklet,"ItemIndex"]==current_item)
,
update the current_item_index
according to the requested
navigation direction
and then store the
current_item
using the booklet design:
assessment_config$navigation = function(pool, session, direction="NEXT"){
booklets <- data.frame(Booklet = c(1,1,1,2,2,2),
ItemIndex=c(2,3,6,4,5,6))
current_booklet <- getValueForTestTaker(session, "current-booklet",
default=sample(unique(booklets$Booklet),1), store = T)
current_item <- getValueForTestTaker(session, "current-item-in-pool",
default=0,
store = F)
if (current_item==0 && direction=="START"){
current_item <- booklets[booklets$Booklet==current_booklet,"ItemIndex"][1]
}
else
{
current_item_index <- which(booklets[booklets$Booklet==current_booklet,"ItemIndex"]==current_item)
if (direction=="NEXT"){
if (current_item_index >= length(booklets[booklets$Booklet==current_booklet,"ItemIndex"]))
{
current_item <- -1 # end the assessment
}
else
{
current_item_index <- current_item_index + 1 # move to the next item
current_item <- booklets[booklets$Booklet==current_booklet,"ItemIndex"][current_item_index]
}
}
else if (direction=="PREVIOUS"){
if (current_item_index > 1){
current_item_index <- current_item_index - 1 # move to the previous item
current_item <- booklets[booklets$Booklet==current_booklet,"ItemIndex"][current_item_index]
}
}
else if (direction=="CANCEL"){
current_item <- -1 # end the assessment
}
}
setValueForTestTaker(session, "current-item-in-pool",current_item)
current_item
}
The value current_item <- -1
is used to identify that
the assessment was finished for the current test-taker (either because
all items of the selected booklet were administered or because the
assessment was canceled).