Интервал времени между нажатиями на одну и ту же кнопку - блестящий R

Извините, что задали фиктивный вопрос. Я совершенно уверен, что у него есть простое решение, но я все еще не мог понять это.

У меня есть кнопка действия, я нажимаю на нее несколько раз, и у меня должен быть интервал времени между щелчками.

Пример,

Я нажимаю на кнопку сейчас, и снова через две минуты, снова через 4 минуты после второго щелчка, и снова через 5 минут после третьего щелчка и так далее.

2 минуты = разница во времени между вторым кликом и первым кликом

4 минуты = разница во времени между третьим кликом и вторым кликом

5 минут = разница во времени между четвертым кликом и третьим кликом

Я мог бы сделать это с двумя кнопками, что легко, но с одной кнопкой я понятия не имею, как это будет.

Спасибо,

3 ответа

Решение

Вы можете сделать это с закрытием. Замыкания позволяют функциям поддерживать свое состояние между вызовами.

Каждый раз timer() выполняется, он создает новую среду и инициализирует время в этой среде. Затем он создает новую функцию, которая поддерживает доступ к среде, в которой он был создан. Затем с помощью <<- оператор для изменения x Переменная на один уровень выше, вы можете хранить время каждый раз, когда вызывается функция.


library(shiny)

timer <- function(){
  x <- Sys.time()
  y <- function(){
    y <- x
    x <<- Sys.time()
    return(x-y)
  }
  return(y)
}

# Implement a simple shiny app with an action button that
# prints the result of running click()
ui <- fluidPage(
  actionButton("do", "Click Me")
)

server <- function(input, output, session) {
  # click is defined within the server function so each
  # session has their own click function with a stored
  # time.
  click <- timer()
  observeEvent(input$do, {print(click())})
}

shinyApp(ui, server)

Для получения дополнительной информации об этой технике, вы можете прочитать Advanced R: Функциональное программирование Хэдли Уикхэма

РЕДАКТИРОВАТЬ: Если вы хотите игнорировать первый щелчок / вернуть что-то еще при первом щелчке, вы можете сделать что-то вроде:

library(shiny)

timer <- function(){
  x <- NULL
  y <- function(){
    y <- x
    x <<- Sys.time()
    if(is.null(y))
      return("first click")
    return(x-y)
  }
  return(y)
}

# Implement a simple shiny app with an action button that
# prints the result of running click()
ui <- fluidPage(
  actionButton("do", "Click Me")
)

server <- function(input, output, session) {
  # click is defined within the server function so each
  # session has their own click function with a stored
  # time.
  click <- timer()
  observeEvent(input$do, {print(click())})
}

shinyApp(ui, server)

Вот простой пример. Вы можете сохранить все времена кликов в reactiveValобновить этот вектор с observeEvent в любое время actionButton щелкнуть, и использовать diff по этому вектору для расчета временных интервалов в секундах. Надеюсь это поможет!

library(shiny)
ui <-   fluidPage(
  actionButton('mybutton','press me'),
  textOutput('mytext'),
  textOutput('mytext2')
)

server <- function(input,output)
{
  click_times <- reactiveVal()
  observeEvent(input$mybutton, {
    click_times(c(click_times(),Sys.time()))
  })

  # print all intervals in seconds
  output$mytext <- renderText({
    if(length(click_times())<2)
    {'Less than two clicks!'} else {
      paste0('Time intervals: ', paste(round(diff(click_times()),2),collapse=' seconds, '),' seconds.')}
  })

  # print last interval in minutes:seconds format
  output$mytext2 <- renderText({
    if(length(click_times())<2)
    {'Less than two clicks!'} else {
      ct <- as.POSIXct(round(tail(diff(click_times()),1),2), origin = "1970-01-01", tz = "UTC")
      paste0('Last interval: ' ,format(ct,'%M:%S')) }
  })
}

shinyApp(ui,server)

Вы можете использовать пакет library(tictoc), С reactiveVal и использование самой кнопки в качестве счетчика.

library(shiny); library(tictoc)
ui <- fluidPage(actionButton("timer", "click me"), textOutput("text"))
server <- function(input, output, session) {
  time = reactiveVal()
  observeEvent(input$timer, handlerExpr = {
    time(capture.output(toc()))
    tic()})
  output$text = renderText({ifelse(is.null(time()), "start!", paste0(time(), " : Time difference between click No", input$timer, " and click No", max(0, input$timer - 1)))})
}
shinyApp(ui, server)
Другие вопросы по тегам