cjerzak commited on
Commit
0e88fab
·
verified ·
1 Parent(s): 177c265

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +127 -81
app.R CHANGED
@@ -300,120 +300,166 @@ server <- function(input, output, session) {
300
  # Prepare a storage structure for caching multiple results
301
  cachedResults <- reactiveValues(data = list())
302
 
 
 
 
303
  # Dynamic update of factor choices
304
  observe({
305
  if (input$case_type == "Average") {
306
- factors <- colnames(FACTOR_MAT_FULL)[!colnames(FACTOR_MAT_FULL) %in% c("Office")]
 
307
  } else {
308
- factors <- colnames(FACTOR_MAT_FULL)[!colnames(FACTOR_MAT_FULL) %in% c("Office", "Party.affiliation", "Party.competition")]
 
309
  }
310
  updateSelectInput(session, "factor", choices = factors, selected = factors[1])
311
  })
312
-
313
- # Auto-compute results on startup with defaults
314
- session$onFlushed(function() {
315
- withProgress(message = "Loading default results...", value = 0, {
316
- incProgress(0.2, detail = "Looking up precomputed results...")
317
-
318
- # Use default values: Average case, All respondents, lambda 0.01
319
- lambda_input <- 0.01
320
- label <- "Case=Average, Group=All, Lambda=0.01"
321
- lam_char <- gsub("\\.", "PT", as.character(lambda_input))
322
- filename <- paste0("Average_All_lambda", lam_char, ".rds")
323
-
324
- file_path <- file.path("AppResults", filename)
325
- if (file.exists(file_path)) {
326
- Qoptimized <- readRDS(file_path)
327
- cachedResults$data[[label]] <- Qoptimized
328
- incProgress(0.8, detail = "Finishing up...")
329
- updateSelectInput(session, "previousResults",
330
- choices = names(cachedResults$data),
331
- selected = label)
332
- }
333
- })
334
- }, once = TRUE)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
 
336
  # Generate a new result and cache it
337
- # -- In app_ono.R, inside `server` definition --
338
  observeEvent(input$compute, {
339
- withProgress(message = "Retrieving results...", value = 0, {
340
- incProgress(0.2, detail = "Looking up precomputed results...")
341
-
342
- # Isolate input values to prevent reactive dependencies
343
- case_type <- isolate(input$case_type)
344
- respondent_group <- isolate(input$respondent_group)
345
- lambda_input <- isolate(input$lambda_input)
346
-
347
- # Construct a human-readable label
348
- if (case_type == "Average") {
349
- label <- paste("Case=Average, Group=", respondent_group,
350
- ", Lambda=", lambda_input, sep="")
351
- lam_char <- gsub("\\.", "PT", as.character(lambda_input))
352
- filename <- paste0("Average_", respondent_group,
353
- "_lambda", lam_char, ".rds")
354
- } else {
355
- label <- paste("Case=Adversarial, Lambda=", lambda_input, sep="")
356
- lam_char <- gsub("\\.", "PT", as.character(lambda_input))
357
- filename <- paste0("Adversarial_lambda", lam_char, ".rds")
358
- }
359
-
360
- # Read the matching pre-computed .rds file from disk
361
- file_path <- file.path("AppResults", filename)
362
- Qoptimized <- readRDS(file_path)
363
-
364
- # Store the loaded results in our reactive cache
365
- cachedResults$data[[label]] <- Qoptimized
366
-
367
- incProgress(0.8, detail = "Finishing up...")
368
-
369
- # Update the choice list for previous results
370
- updateSelectInput(session, "previousResults",
371
- choices = names(cachedResults$data),
372
- selected = label)
 
 
 
 
 
 
 
 
 
 
 
373
  })
374
- }, ignoreInit = TRUE)
375
 
376
  # Reactive to pick the result the user wants to display
377
  selectedResult <- reactive({
378
- validate(
379
- need(input$previousResults != "", "No result computed or selected yet.")
380
- )
381
- cachedResults$data[[input$previousResults]]
 
 
 
 
 
382
  })
383
 
384
  # Render strategy plot
385
  output$strategy_plot <- renderPlot({
386
- req(selectedResult())
 
 
387
  factor_name <- input$factor
388
- pi_star_list <- selectedResult()$pi_star_point
389
- pi_star_se_list <- selectedResult()$pi_star_se
390
- n_strategies <- selectedResult()$n_strategies
391
- plot_factor(pi_star_list = pi_star_list,
392
- pi_star_se_list = pi_star_se_list,
393
- factor_name = factor_name,
 
394
  n_strategies = n_strategies)
395
  })
396
 
397
  # Render Q value
398
  output$q_value <- renderText({
399
- req(selectedResult())
400
- q_point <- selectedResult()$Q_point
401
- q_se <- selectedResult()$Q_se
 
 
402
  show_se <- length(q_se) > 0
 
403
  if(show_se){ show_se <- q_se > 0 }
404
- if(!show_se){ render_text <- paste("Estimated Q Value:", sprintf("%.3f", q_point)) }
405
- if(show_se){ render_text <- paste("Estimated Q Value:", sprintf("%.3f ± %.3f", q_point, 1.96 * q_se)) }
406
- sprintf("%s (Runtime: %.3f s)",
 
 
 
 
 
407
  render_text,
408
- selectedResult()$runtime_seconds)
409
  })
410
 
411
  # Show which set of parameters (label) is currently selected
412
  output$selection_summary <- renderText({
 
413
  input$previousResults
414
  })
415
  }
416
 
417
  # Run the app
418
- shinyApp(ui, server)
419
-
 
300
  # Prepare a storage structure for caching multiple results
301
  cachedResults <- reactiveValues(data = list())
302
 
303
+ # Track if initial load has been done
304
+ initialLoadDone <- reactiveVal(FALSE)
305
+
306
  # Dynamic update of factor choices
307
  observe({
308
  if (input$case_type == "Average") {
309
+ factors <- colnames(FACTOR_MAT_FULL)[!colnames(FACTOR_MAT_FULL) %in%
310
+ c("Office")]
311
  } else {
312
+ factors <- colnames(FACTOR_MAT_FULL)[!colnames(FACTOR_MAT_FULL) %in%
313
+ c("Office", "Party.affiliation", "Party.competition")]
314
  }
315
  updateSelectInput(session, "factor", choices = factors, selected = factors[1])
316
  })
317
+
318
+ # Auto-compute results on startup with defaults
319
+ observe({
320
+ # Only run once when the app starts
321
+ if (!initialLoadDone() && !is.null(input$case_type) && !is.null(input$lambda_input)) {
322
+ withProgress(message = "Loading default results...", value = 0, {
323
+ incProgress(0.2, detail = "Looking up precomputed results...")
324
+
325
+ # Use default values
326
+ case_type <- "Average"
327
+ respondent_group <- "All"
328
+ lambda_input <- 0.01
329
+
330
+ label <- paste("Case=Average, Group=All, Lambda=0.01", sep="")
331
+ lam_char <- gsub("\\.", "PT", as.character(lambda_input))
332
+ filename <- paste0("Average_All_lambda", lam_char, ".rds")
333
+
334
+ # Read the matching pre-computed .rds file from disk
335
+ file_path <- file.path("AppResults", filename)
336
+
337
+ if (file.exists(file_path)) {
338
+ Qoptimized <- readRDS(file_path)
339
+
340
+ # Store the loaded results in our reactive cache
341
+ cachedResults$data[[label]] <- Qoptimized
342
+
343
+ incProgress(0.8, detail = "Finishing up...")
344
+
345
+ # Update the choice list for previous results
346
+ updateSelectInput(session, "previousResults",
347
+ choices = names(cachedResults$data),
348
+ selected = label)
349
+
350
+ # Mark initial load as done
351
+ initialLoadDone(TRUE)
352
+ }
353
+ })
354
+ }
355
+ })
356
 
357
  # Generate a new result and cache it
 
358
  observeEvent(input$compute, {
359
+ withProgress(message = "Retrieving results...", value = 0, {
360
+ incProgress(0.2, detail = "Looking up precomputed results...")
361
+
362
+ # Don't isolate - let reactive dependencies work
363
+ case_type <- input$case_type
364
+ respondent_group <- input$respondent_group
365
+ lambda_input <- input$lambda_input
366
+
367
+ # Construct a human-readable label
368
+ if (case_type == "Average") {
369
+ label <- paste("Case=Average, Group=", respondent_group,
370
+ ", Lambda=", lambda_input, sep="")
371
+ lam_char <- gsub("\\.", "PT", as.character(lambda_input))
372
+ filename <- paste0("Average_", respondent_group,
373
+ "_lambda", lam_char, ".rds")
374
+ } else {
375
+ label <- paste("Case=Adversarial, Lambda=", lambda_input, sep="")
376
+ lam_char <- gsub("\\.", "PT", as.character(lambda_input))
377
+ filename <- paste0("Adversarial_lambda", lam_char, ".rds")
378
+ }
379
+
380
+ # Read the matching pre-computed .rds file from disk
381
+ file_path <- file.path("AppResults", filename)
382
+
383
+ if (file.exists(file_path)) {
384
+ Qoptimized <- readRDS(file_path)
385
+
386
+ # Store the loaded results in our reactive cache
387
+ cachedResults$data[[label]] <- Qoptimized
388
+
389
+ incProgress(0.8, detail = "Finishing up...")
390
+
391
+ # Update the choice list for previous results
392
+ # Use immediate = TRUE to ensure the update happens right away
393
+ isolate({
394
+ updateSelectInput(session, "previousResults",
395
+ choices = names(cachedResults$data),
396
+ selected = label)
397
+ })
398
+
399
+ } else {
400
+ showNotification(paste("Results file not found:", filename),
401
+ type = "error", duration = 5)
402
+ }
403
+ })
404
  })
 
405
 
406
  # Reactive to pick the result the user wants to display
407
  selectedResult <- reactive({
408
+ req(input$previousResults)
409
+ req(length(cachedResults$data) > 0)
410
+
411
+ # Ensure the selected result exists
412
+ if (input$previousResults %in% names(cachedResults$data)) {
413
+ cachedResults$data[[input$previousResults]]
414
+ } else {
415
+ NULL
416
+ }
417
  })
418
 
419
  # Render strategy plot
420
  output$strategy_plot <- renderPlot({
421
+ result <- selectedResult()
422
+ req(result)
423
+
424
  factor_name <- input$factor
425
+ pi_star_list <- result$pi_star_point
426
+ pi_star_se_list <- result$pi_star_se
427
+ n_strategies <- result$n_strategies
428
+
429
+ plot_factor(pi_star_list = pi_star_list,
430
+ pi_star_se_list = pi_star_se_list,
431
+ factor_name = factor_name,
432
  n_strategies = n_strategies)
433
  })
434
 
435
  # Render Q value
436
  output$q_value <- renderText({
437
+ result <- selectedResult()
438
+ req(result)
439
+
440
+ q_point <- result$Q_point
441
+ q_se <- result$Q_se
442
  show_se <- length(q_se) > 0
443
+
444
  if(show_se){ show_se <- q_se > 0 }
445
+
446
+ if(!show_se){
447
+ render_text <- paste("Estimated Q Value:", sprintf("%.3f", q_point))
448
+ } else {
449
+ render_text <- paste("Estimated Q Value:", sprintf("%.3f ± %.3f", q_point, 1.96 * q_se))
450
+ }
451
+
452
+ sprintf("%s (Runtime: %.3f s)",
453
  render_text,
454
+ result$runtime_seconds)
455
  })
456
 
457
  # Show which set of parameters (label) is currently selected
458
  output$selection_summary <- renderText({
459
+ req(input$previousResults)
460
  input$previousResults
461
  })
462
  }
463
 
464
  # Run the app
465
+ shinyApp(ui, server)