Программирование реактивного счетчика с помощью оператора условного цикла if в Shiny

Я пытался создать симулятор игры в кости / азартные игры с помощью Shiny, но у меня возникли две проблемы (хотя обе могут быть связаны с одной ошибкой, я не уверен). Я в основном создаю reactiveValue, изначально установленное на уровне 10000 (долларов) на сервере, вместе с функцией sample (), которая берет только от 1 до 6 (для шестигранной кости) и позволяет пользователю выбирать количество игральных костей. / бросает. Затем я настраиваю наблюдениеEvent, в котором цикл if определяет, что, если случайные числа, сгенерированные в функции sample (), равны или больше, чем количество игральных костей, которые будет отображать пользовательская ставка, и до тех пор, пока reactiveValue остается примерно 1, то пользователь может удвоить свои «деньги». Если их ставка меньше, чем было сгенерировано сэмплом, они проигрывают половину. Если они проигрывают так много, что их размер ниже единицы, то им больше не разрешается делать ставки или, по крайней мере, им говорят, что они разорены, но это не такая важная часть кода.

Прямо сейчас мне кажется, что я не могу заставить работать цикл if, поскольку он выдает ошибку: Предупреждение: ошибка в if: отсутствует значение, где требуется ИСТИНА / ЛОЖЬ

 library(shiny)

 ui <- fluidPage(
  pageWithSidebar(
   titlePanel("Feelin' Lucky?"),

       sidebarPanel(
         p("In this simulation, you can select the number of dice you would like to roll,
           and then make a 'bet' on the numbers that will show up with every roll. If there are more faces 
           than the number you guessed, then you still win. If there are less faces, however, 
           you will lose 'money,' displayed at the top of the main panel. Give it a try and
           good luck!"),
        numericInput("dicenum", "Enter the number of dice to roll:", 1),
  numericInput("face", "What face do you think will be rolled?", 1),
  numericInput("bet", "How many of this face do you think will be rolled?", 1), 
  actionButton("go1", "GO!")
),
mainPanel(
  htmlOutput("the.dough"),
  htmlOutput("the.bet"),
  textOutput("results"),
  htmlOutput("results2"),
  htmlOutput("warning")
  )
 )
 )

   server <- function(input, output, session) {

    money <- 10000
    output$the.dough <- renderText(
    paste(money)
     )

   buttonValue <- reactiveValues(go1=FALSE)

   rv <- reactiveValues(money.tot = 10000)

   observeEvent(input$go1,{

isolate({buttonValue$go1=TRUE})
      the.roll <- sample(1:6, size = input$dicenum, replace=TRUE)
  the.face <- as.numeric(input$face) #Dice Face Bet
  amount <- as.numeric(input$bet)


output$warning <- renderText({

  goop <- sum(the.roll==the.face) 

  if ((goop >= amount) & (rv$money.tot>1)) {
    rv$money.tot <- sum(rv$money.tot, rv$money.tot*2-rv$money.tot)

    paste("Well-done! You won the bid! You now have: $", rv$money.tot)
  } else if ((goop < amount) & (rv$money.tot>1)) {
    rv$money.tot <- rv$money.tot-(rv$money.tot/2)
    paste("Darn! It looks like you lost the bid! You now have: $", rv$money.tot)
  } else if (rv$money.tot<1) {
    paste("You are broke! You cannot bid anymore money!")

  } else {
    NULL }
  })

  })
      }

          shinyApp(ui, server)

Я просмотрел, что это означает, но я не могу найти случай, который бы точно объяснил, почему он делает это в моем сценарии, тем более что цикл if работает, когда он написан как базовый цикл R if, то есть без реактивности или Shiny. Пример рабочего цикла:

  rvv <- 10000

  face.guess <- 4
   throw <- sample(1:6, size = 10, replace = TRUE)
    guess.howmany <- 2

   if (sum(throw==face.guess)>=guess.howmany & rvv>1) {
    rvv <- sum(rvv, rvv*2-rvv)

   print("Woohoo!") 
    print(rvv)
  } else if (sum(throw==face.guess)<guess.howmany & rvv>1){
   print("Darn")
    rvv <- rvv-(rvv/2)
  print(rvv)
   } else if (rvv<1) {
  print("You are broke! You can't bid anymore money!") }

В других случаях цикл if действительно работает частично, но только для перехода к последней опции, каким-то образом уменьшая начальное значение reactiveValue до значения ниже 1 и объявляя их сломанными при первой ставке, что не должно быть возможным.

Мой компьютер сейчас тоже шаткий, поэтому я извиняюсь, если в приведенном выше есть проблемы с синтаксисом - отчасти это может быть из-за невозможности правильного копирования / вставки в данный момент.

Любая помощь высоко ценится!

РЕДАКТИРОВАТЬ: фиксированный код. Я также выяснил, что когда пользователь получает правильную ставку, возникает задержка, а затем возникает указанная выше ошибка. Когда они предполагают слишком много / ошибочно, отображается последняя опция (print («Вы разорены!»)), Которая, кажется, указывает на явную проблему с тем, как я вызываю другое условие («goop»). Я просто не понимаю, что.


person emc123    schedule 09.08.2019    source источник
comment
Пробовал ваше приложение, но кнопка действия не запускает никаких действий, когда я его тестировал.   -  person yusuzech    schedule 09.08.2019
comment
Привет, спасибо, возможно, я скопировал не ту итерацию. Приведенный выше код должен работать до тех пор, пока не будет выдана ошибка - хотя для отображения требуется, может быть, десять секунд.   -  person emc123    schedule 09.08.2019


Ответы (1)


Я нашел решение для этого: мне в основном пришлось взять цикл if за пределами renderText () и вместо этого встроить несколько рендеров в каждый шаг цикла if. Я скопировал исправленную серверную часть ниже. Наверное, не самое элегантное исправление, но оно работает так, как я хотел:

server <- function(input, output, session) {

   money <- 10000
   output$the.dough <- renderText(
    paste(money)
    )

  buttonValue <- reactiveValues(go1=FALSE)

  rv <- reactiveValues(money.tot = 10000)

  observeEvent(input$go1,{

    isolate({buttonValue$go1=TRUE})

    the.roll <- sample(1:6, size = input$dicenum, replace=TRUE)


    the.face <- as.numeric(input$face) #Dice Face Bet
    amount <- as.numeric(input$bet)
    goop <- sum(the.roll==the.face)

   if (isTRUE(goop >= amount) & isTRUE(rv$money.tot>1) & buttonValue$go1) {
      rv$money.tot <- sum(rv$money.tot, rv$money.tot*2-rv$money.tot)

      output$warning <- renderText({

       paste("Well-done! You won the bid! You now have: $", rv$money.tot)
        })
      } else if (isTRUE(goop < amount) & isTRUE(rv$money.tot>1) & buttonValue$go1) {
    rv$money.tot <- rv$money.tot-(rv$money.tot/2) 
    output$warning <- renderText({
    paste("Darn! It looks like you lost the bid! You now have: $", rv$money.tot)
    })

  } else if (isTRUE(rv$money.tot<1) & buttonValue$go1) {
    output$warning <- renderText({
    paste("You are broke! You cannot bid anymore money!")
    })
  } else {
    NULL }


output$results <- renderText(
  paste("You bid that there would be:", amount, "of the", the.face, "face.")

)
output$results2 <- renderText(
  paste("Actual Result:", as.numeric(sum(the.roll==the.face)), "of the", the.face)
)

  })

  }

Надеюсь, это поможет любому, кто пытается сделать что-то подобное!

person emc123    schedule 10.08.2019