问题
Typically a Shiny server would spawn separate instances for individual users, so that multiple people can individually use the same app at the same time. This answer shows how to make a simple multi-user chat room using Shiny, and this answer explains how multiple users can connect to the same session via direct IP. I got the chat example to work, two users both see the messages immediately as they're being sent, and as such can chat to one another.
I'm wondering if it is at all possible to use Shiny for an (experiment) scenario where two users, interacting with one another, would see different GUI elements on their respective screens, and different output, depending on who's turn it is to "play". For example, if user1 is the "starting player", he would see three buttons and click one of them, a relevant image would pop up for user2 (not for user1), user2 clicks a button (that he thinks matches the image), and then a relevant image pops up for user1, and user1 clicks a "correct"/"incorrect" button to send feedback; they should not see who clicks which button, nor the image the other one sees (if actually hiding GUI elements is tricky, graying out/disabling them intermittently is also fine, as long as they don't see what the other does).
Or more graphically:
round 1
user1 user2
director guesser
what they see, step by step:
1. [three buttons] [ (blank) ]
2. [clicks one] [ ]
3 [ ] [sees an image & 3 buttons]
4. [ ] [clicks a button]
5. [sees image,2 butns] [ ]
6. [clicks button] [ ]
7. [ ] [sees the message "correct" or "incorrect"]
round 2
user1 user2
guesser director
1. [ ] [three buttons]
...
...
And for the next round they switch roles, and so on, for multiple rounds.
I've seen similar experimental scenarios implemented using Javascript (jsPsych, nodegame) and Python (psychopy, oTree), but I'm looking to understand if it's possible to do it in Shiny, and if so, how.
回答1:
I had the same challenge a couples of years ago when i implemented "Risk" (the board game) as a shiny app.
A quick outline how i approached it back then:
If you use the session
parameter in the server function, you can create a local/secret reactiveValue()
within that session / for that user and you can set reactiveValues()
outside the server function for "global infos" that are accessible across sessions.
The latter approach is probably the more surprising one as we are usually "forced" to define reactive
behaviour within the server function. But it works, see the example below.
Reproducible example:
library(shiny)
ui <- fluidPage({
uiOutput("moreControls")
})
global <- reactiveValues(info = "public info: I can be seen by everyone", amountUser = 0, userIdToPlay = 1)
server <- function(input, output, session) {
local <- reactiveValues(secret = paste0("My secret number is ", sample(6, 1)))
observe({
isolate(global$amountUser <- global$amountUser + 1)
isolate(local$userId <- global$amountUser)
})
observeEvent(input$finish,{
global$userIdToPlay <- 3 - global$userIdToPlay # assumes two players (for MVE)
})
output$moreControls <- renderUI({
global$userIdToPlay
isolate({
if(local$userId == global$userIdToPlay){
return(
tagList(
h2("my time to play"),
selectInput("a", "b", letters),
actionButton("finish", "finish")
)
)
}else{
return(
h2("not my time to play")
)
}
})
})
}
shinyApp(ui, server)
来源:https://stackoverflow.com/questions/56463169/can-r-shiny-display-different-views-for-two-simultaneous-users-interacting-with