philchalmers / mirtCAT

Computerized Adaptive Testing with Multidimensional Item Response Theory
http://philchalmers.github.io/mirtCAT/
91 stars 28 forks source link

Fast input cancel timer action #31

Closed MagnusNordmo closed 3 years ago

MagnusNordmo commented 4 years ago

Hi Phil! I've found a slight bug that occurs under a particular circumstance. If you use an item timer and press Next before the time required by shinyGUI = list(time_before_answer), the timer stops but doesnt push the test forward. Im looking at the code now but i'm not sure what causes this.

To recreate this bug, you need to press the Next button before the elapsed seconds supplied with time_before_answer.

library(mirtCAT)

df <- data.frame(Questions = c('First is correct','Second is correct'),
                 Options = matrix(c(1,2,3,4,5),ncol = 5,byrow = T),
                 Type = 'radio',
                 Timer = c(10,10),
                 Answer = c(1,2))

shinyGUI = list(time_before_answer = 3,forced_choice = F)

results <- mirtCAT(df = df,shinyGUI = shinyGUI)

Hope you are doing well!

Sincerely Magnus

philchalmers commented 4 years ago

Hi Magnus,

Interesting, the behaviour seems correct when no responses are present, but when a response is selected and clicked within the first three seconds the GUI proceeds to the next question rather than pausing. I'll look into why this is the case, thanks.

philchalmers commented 4 years ago

Should be patched now. Thanks for the report!

MagnusNordmo commented 3 years ago

Dear Phillip.

Unfortunately, it looks like the original timer bug still persist in the newest version of mirtCAT. If the next button is pressed within the time_before_answer is up, the screen freezes at time 0:00, exposing the item for unlimited time and making the response invalid. This also happens if an option is selected. When using custom buttons (good_dogs), selecting an item and pressing next before the time_before_answer time is up, mirtCAT produces an error message:

Warning: Error in : Internal error throw for customTypes with timer

See the minimal reproducible example

The desired response is that the test-taker cannot press the next button within a few seconds of the items appearing. If the timer runs out with no selected response the test should just move to the next item. Ideally, if an item is selected and the timer runs out, without the test-taker pressing next, the selected response should be registered as an answer, when the timer reaches 0

Sincerely Magnus Nordmo


#Minimal reproducible example of item-timer failure

library(mirtCAT)
options(StringsAsFactors = FALSE)

questions <- c('What is the capitol of Norway?',
               'Who just got elected President?',
               'What is 5 times 4?')

# Alternatives
options <- matrix(c('Reykjavik', 'Moscow', 'Oslo', 'Stockholm', 'Copenhagen', 'Warsaw',
                    'Biden', 'Jaques Chirack', 'Bush', 'Clinton', 'Goore', 'Musk',
                    '15', '35', '10', '5', '45', '40'),ncol = 6,byrow = T)

options <- matrix(paste0('<p style="font-size:2vw">',options,'</p>'), nrow = nrow(options))

#Answers
answers <- c('Oslo',
             'Biden',
             '40')

answers <- paste0('<p style="font-size:2vw">',answers,'</p>')

# Custom answers
good_dogs <- function(inputId, df_row){
  return(list(h2(HTML(df_row$Question)),
              radioButtons(inputId = inputId, label='', inline = T,
                           choiceNames = list(HTML(df_row$Option.1),
                                              HTML(df_row$Option.2),
                                              HTML(df_row$Option.3),
                                              HTML(df_row$Option.4),
                                              HTML(df_row$Option.5),
                                              HTML(df_row$Option.6)),
                           choiceValues = list(HTML(df_row$Option.1),
                                               HTML(df_row$Option.2),
                                               HTML(df_row$Option.3),
                                               HTML(df_row$Option.4),
                                               HTML(df_row$Option.5),
                                               HTML(df_row$Option.6)),
                           selected = '')
  ))
}

df <- data.frame(Question = questions, Option = options, Answers = answers, Type = "myQ", Timer = c(rep(30,3)), stringsAsFactors = F)

shinyGUI = list(forced_choice = F,
                time_before_answer = 5)

#Run
results <- mirtCAT(df = df, shinyGUI = shinyGUI,customTypes = list(myQ = good_dogs))

mirtCAT_preamble()

createShinyGUI()
philchalmers commented 3 years ago

Managing customTypes is quite tricky in that it's rather difficult to sift through all the possible inputs in an automated way. The best I can do in this case is if the user has selected an option, but they click Next before the valid item time has passed, then the option is removed and the would have to try again (though the timer keeps progressing and at some point their response will be accepted). This is different than the native types supported which will actually preserve the previous response option. Would this fix be sufficient for your purpose?

philchalmers commented 3 years ago

I've added this as the new default behaviour rather than the error thrown. It's not overly noticeable unless you're looking for it. The alternative approach, which I'm not opposed to, is to have the package always remove the previous responses if they are within the invalid time window, and print a warning message for the user to "slow the hell down"....or something to that extent :stuck_out_tongue_winking_eye: