Open neilhatfield opened 4 years ago
library(shiny) library(shinydashboard) library(shinyBS)
ui <- list( tags$head( tags$link(rel = "stylesheet", type = "text/css", href = "https://educationshinyappteam.github.io/Style_Guide/theme/boast.css")
),
dashboardPage( skin = "blue",
dashboardHeader(
title = "Fill In Blank Sample",
tags$li(class = "dropdown", actionLink("info", icon("info"))),
tags$li(class = "dropdown",
tags$a(href='https://github.com/EducationShinyAppTeam/BOAST',
icon("github"))),
tags$li(class = "dropdown",
tags$a(href='https://shinyapps.science.psu.edu/',
icon("home")))
),
### Create the sidebar/left navigation menu
dashboardSidebar(
sidebarMenu(
id = "tabs",
menuItem(text = "Overview", tabName = "Overview", icon = icon("dashboard")),
menuItem(text = "Fill In Blank", tabName = "FillInBlank", icon = icon("book")),
menuItem(text = "Reversable", tabName = "reversable", icon = icon("book"))
),
tags$div(
class = "sidebar-logo",
boastUtils::psu_eberly_logo("reversed")
)
),
### Create the content
dashboardBody(
tabItems(
#### Set up the Overview Page
tabItem(
tabName = 'Overview',
withMathJax(),
h1("Base functions for fill in blank and response questions"),
h2("Instructions"),
p("Each tab contains code for a slightly differant approach"),
tags$ol(
tags$li("Standard Fill in blank"),
tags$li("Reversible entries tab (currently still in standard
fill, coming soon to own tab)") ),
div(
style = "text-align: center",
bsButton(
inputId = "go1",
label = "GO!",
size = "large",
icon = icon(name = "bolt"),
style = "default"
)
),
br(),br(),
h2("Acknowledgements"),
p("This version of the app was developed and coded by Ethan Wright",
br(),
"I would like to extend a special thanks to the Shiny Program
Students. In particular Chenese who was an incredible help with the UI", br(), br(), br(), div(class = "updated", "Last Update: 5/29/2020 by EJW") ) ),
tabItem(
tabName = "Dropdown",
withMathJax(),
h2("Drop down menus"),
box(
title = strong("Sample 1"),
status = "primary",
collapsible = TRUE,
collapsed = TRUE,
width = '100%',
""
),
box(
title = strong("Sample 2"),
status = "primary",
collapsible = TRUE,
collapsed = FALSE,
width = '100%',
""
)
),
tabItem(
tabName = 'FillInBlank',
withMathJax(),
h2("Fill in blank standard (answers can't be reversed)"),
#HERE IS THE UI FOR PUTTING IN THE TEXT AND THE BLANKS
#IT SIMPLY CONSISTS OF 3 PARTS: TEXT OUTPUT, BLANK INPUT SPACES, AND HTML OUTPUT FOR THE IMAGE
#It's not pretty or fast TO TYPE but the use of display:inline-block is the only known
# way to get the text and the blanks to line up correctly that has been found
div(style = "display:inline-block", p("As the distance between points ")), #text
div(style = "display:inline-block", textInput(inputId = "word1", label = "")), #The blank to be filled
div(style = "display:inline-block", htmlOutput(outputId = "answer1")), #Image output, check or X
div(style = "display:inline-block", p(', their reliability ')), #Repeat
div(style = "display:inline-block", textInput(inputId = "word2", label = "")),
div(style = "display:inline-block", htmlOutput(outputId = "answer2")),
actionButton("submit", "submit Answer")
),
tabItem(
tabName = 'reversable',
withMathJax(),
h2("Fill in blank where answers are reversible"),
#order is
div(style="display:inline-block", p("As the distance between points ")),
div(style="display:inline-block", textInput(inputId = "word3", label = "")),
div(style ="display:inline-block", htmlOutput(outputId = "answer3")),
div(style = "display:inline-block", p(', their reliability ')),
div(style="display:inline-block", textInput(inputId = "word4", label = "")),
div(style ="display:inline-block", htmlOutput(outputId = "answer4")),
actionButton("submitReversable", "submit Answer")
)
)
)
) )
server <- function(input, output, session) {
observeEvent(input$go1, { updateTabItems(session = session, inputId = "tabs", selected = "Explore") })
checkAnswer <- function(answer, inputAnswer){ correct <- FALSE #Start out assuming incorrect. if(class(answer) == 'list') #if multiple right answers due to synonyms { for(accessNested in answer) { inputAnswer <- tolower(x = inputAnswer) if(inputAnswer %in% accessNested) { correct <- TRUE } } } else #If only 1 right answer {
inputAnswer <- tolower(x = inputAnswer)
if(answer == inputAnswer)
{
correct <-TRUE #If nested Answer equals input Answer it is correct
}
}
return(correct)
}
checkReversibleAnswer <- function(answer1, inputAnswer1, answer2, inputAnswer2){ if(checkAnswer(answer1, inputAnswer1)) { if(checkAnswer(answer2, inputAnswer2)){ return(TRUE) } else { return(FALSE) } } else if(checkAnswer(answer2, inputAnswer1)) { if(checkAnswer(answer1, inputAnswer2)){ return(TRUE) } else{ return(FALSE) } } else { return(FALSE) } }
correctAnswers <- list(increases = list('increases', 'increase', 'goes up', 'widens'), decreases = list('decreases', 'goes down'))
observeEvent(input$submit, {
#input$word# passes a word the user used on a fill in the blank
grade1 <- checkAnswer(answer = correctAnswers$increases, inputAnswer = input$word1)
grade2 <- checkAnswer(answer = correctAnswers$decreases, inputAnswer = input$word2)
#For each blank a result of T/F will deterimne which symbol is output
if(grade1){
output$answer1 <- renderUI({
img(src = "check.png", width = 30)
})
}
else
{
output$answer1 <- renderUI({
img(src = "cross.png", width = 30)
})
}
if(grade2){
output$answer2 <- renderUI({
img(src = "check.png", width = 30)
})
}
else
{
output$answer2 <- renderUI({
img(src = "cross.png", width = 30)
})
}
})
observeEvent(input$submitReversable, { grade3 <- checkReversibleAnswer(answer = correctAnswers$increases, inputAnswer1 = input$word3, answer2 = correctAnswers$decreases, inputAnswer2 = input$word4)
if(grade3){
output$answer3 <- renderUI({
img(src = "check.png", width = 30)
})
output$answer4 <- renderUI({
img(src = "check.png", width = 30)
})
}
else
{
output$answer3 <- renderUI({
img(src = "cross.png", width = 30)
})
output$answer4 <- renderUI({
img(src = "cross.png", width = 30)
})
}
}) }
shinyApp(ui = ui, server = server)
check.png and cross.png
Add guidance for doing in-line input fields (such as text input, drop-down).