diff --git a/DESCRIPTION b/DESCRIPTION
index 69ea063..0f4c95f 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,37 +1,45 @@
Package: gmoTree
Title: Get and Modify 'oTree' Data
-Version: 1.2.0
-Date: 2024-09-30
+Version: 1.3.0
+Date: 2024-12-06
Authors@R:
- person(given = "Patricia F.", family = "Zauchner",
- role = c("aut", "trl", "cre", "cph"),
- email = "patricia.zauchner@gmx.at",
- comment = c("https://orcid.org/0000-0002-5938-1683", "University of Bremen"))
+ person("Patricia F.", "Zauchner", , "patricia.zauchner@gmx.at", role = c("aut", "trl", "cre", "cph"),
+ comment = c(ORCID = "https://orcid.org/0000-0002-5938-1683", "University of Bremen"))
Description: Efficiently manage and process data from 'oTree' experiments.
- Import 'oTree' data and clean them by using
- functions that handle messy data, dropouts, and other problematic cases.
- Create IDs, calculate the time, transfer
- variables between app data frames, and delete sensitive information.
- Review your experimental data prior to running
- the experiment and automatically generate a detailed summary
- of the variables used in your 'oTree' code.
- Information on 'oTree' is found in Chen, D. L., Schonger, M., &
- Wickens, C. (2016) .
+ Import 'oTree' data and clean them by using functions that handle
+ messy data, dropouts, and other problematic cases. Create IDs,
+ calculate the time, transfer variables between app data frames, and
+ delete sensitive information. Review your experimental data prior to
+ running the experiment and automatically generate a detailed summary
+ of the variables used in your 'oTree' code. Information on 'oTree' is
+ found in Chen, D. L., Schonger, M., & Wickens, C. (2016)
+ .
License: GPL (>= 3)
URL: https://zauchnerp.github.io/gmoTree/,
- https://github.com/ZauchnerP/gmoTree/,
- https://github.com/ZauchnerP/gmoTree
+ https://github.com/ZauchnerP/gmoTree/,
+ https://github.com/ZauchnerP/gmoTree
BugReports: https://github.com/ZauchnerP/gmoTree/issues
-Depends: R (>= 4.4.0)
-Imports: data.table (>= 1.15.4), dplyr (>= 1.1.4), knitr (>= 1.47),
- openxlsx (>= 4.2.5.2), pander (>= 0.6.5), plyr (>= 1.8.9),
- rlang (>= 1.1.4), rlist (>= 0.4.6.2), rmarkdown (>= 2.27),
- stringr (>= 1.5.1)
-Suggests: testthat (>= 3.2.1), withr (>= 3.0.0)
-VignetteBuilder: knitr
+Depends:
+ R (>= 4.4.0)
+Imports:
+ data.table (>= 1.15.4),
+ dplyr (>= 1.1.4),
+ knitr (>= 1.47),
+ openxlsx (>= 4.2.5.2),
+ pander (>= 0.6.5),
+ plyr (>= 1.8.9),
+ rlang (>= 1.1.4),
+ rlist (>= 0.4.6.2),
+ rmarkdown (>= 2.27),
+ stringr (>= 1.5.1)
+Suggests:
+ testthat (>= 3.2.1),
+ withr (>= 3.0.0)
+VignetteBuilder:
+ knitr
BuildVignettes: true
Config/testthat/edition: 3
Encoding: UTF-8
LazyData: true
-RoxygenNote: 7.3.2
NeedsCompilation: no
+RoxygenNote: 7.3.2
diff --git a/NEWS.md b/NEWS.md
index 58810d1..ad2efd8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,6 +1,35 @@
-**Changes in CITATION file and NEWS file are not documented.**
+**Changes in CITATION file, NEWS file are not documented.**
-# gmoTree 1.2.0
+# gmoTree 1.3.0
+
+* Changes in ```codebook()```
+ * Bug fixes
+ * Resolved an issue with ```Constants``` vector presentations in the output files
+ * Fixed incorrect handling of equal signs (```=```) in documentation
+ and choices.
+ * New arguments
+ * ```splitvarname``` to deal with long variable names. Caveat: In some cases, columns may still overlap. Control your output carefully.
+ * ```sep_list``` to decide on list presentation or newline presentation in the output file
+ * ```initial``` to include the initial values in the codebook
+ * Enhancements
+ * New preamble text
+ * ```output_format```
+ * Expanded the input possibilities for greater flexibility
+ * Changed default of ```output_format``` to ```pdf_document_simple```
+ * Improved handling of quotations
+ * Better presentations of quotations inside strings
+ * Quotation marks are now presented as straight and not smart form
+ * Removed non-escaped quotation marks from the output
+ * Improved list handling
+ * Values are now saved in list format and not as vectors
+ * Types of variables now correspond better to the types of the original variables
+ * Improved list presentation in output files for better readability
+ * Enhanced error and warning messages
+ * The function can now better deal better with empty arguments in the oTree code
+* Linted older functions (more readable)
+* Website changes
+
+# gmoTree 1.2.1
* New function
* ```codebook()```: Create a codebook for the oTree code
diff --git a/R/apptime.R b/R/apptime.R
index d900bf4..032f991 100644
--- a/R/apptime.R
+++ b/R/apptime.R
@@ -90,7 +90,7 @@ apptime <- function(oTree,
} else {
# If apps are defined, check if they are there
if (length(apps[apps %in% names(oTree)]) != length(apps)) {
- if (length(apps[apps %in% names(oTree)]) > 0) {
+ if (length(apps[apps %in% names(oTree)]) > 0L) {
warning(
"The following app(s) is/are not in ",
"the list of oTree data frames: ",
@@ -110,7 +110,7 @@ apptime <- function(oTree,
}
# Seconds or minutes ####
- if (seconds == TRUE) {
+ if (seconds) {
divsec <- 1L
} else {
divsec <- 60L # Divide seconds by 60 to get minutes
@@ -121,7 +121,7 @@ apptime <- function(oTree,
stop("There is no \"Time\" data frame.")
}
- if (nrow(oTree$Time) == 0) {
+ if (nrow(oTree$Time) == 0L) {
stop("Your \"Time\" data frame is empty.")
}
@@ -492,7 +492,7 @@ apptime <- function(oTree,
duration <- duration / divsec
- if (duration == 0) {
+ if (duration == 0L) {
duration <- NA
}
@@ -620,7 +620,7 @@ apptime <- function(oTree,
if (nrow(singledurations) == 0L) {
if (!is.null(duplicate_participants) &&
- length(duplicate_participants) > 1) {
+ length(duplicate_participants) > 1L) {
# Duplicate data
@@ -726,7 +726,7 @@ apptime <- function(oTree,
output[["messages"]] <- unique(message_vector)
output[["first_app_one_page"]] <- firststageproblemparticipants
- if (length(warningparticipants > 0L)) {
+ if (length(warningparticipants) > 0L) {
output[["warnings"]] <- unique(warningparticipants)
}
@@ -858,7 +858,7 @@ apptime <- function(oTree,
# Time for app for all participants ####
output <- all_time()
- if (length(output) == 1 &&
+ if (length(output) == 1L &&
grepl("Durations not calculated", output)) {
next
}
@@ -866,11 +866,10 @@ apptime <- function(oTree,
}
- if (!is.null(pcode)) {
- if (length(onepersonnoapp) > 0) {
+ if (!is.null(pcode) && length(onepersonnoapp) > 0L) {
warning("Duration could not be calculated for the person in app(s): ",
paste(onepersonnoapp, collapse = ", "), ".")
- }
+
}
diff --git a/R/assignv_to_aaw.R b/R/assignv_to_aaw.R
index e3a351e..f5b9475 100644
--- a/R/assignv_to_aaw.R
+++ b/R/assignv_to_aaw.R
@@ -115,9 +115,9 @@ assignv_to_aaw <- function(oTree,
# Make indices
indices <- c(
- 1:which(names(oTree$all_apps_wide) == resafter),
+ 1L:which(names(oTree$all_apps_wide) == resafter),
ncol(oTree$all_apps_wide), # Put the new variable here
- (which(names(oTree$all_apps_wide) == resafter) + 1):
+ (which(names(oTree$all_apps_wide) == resafter) + 1L):
(ncol(oTree$all_apps_wide) - 1L)
)
diff --git a/R/codebook.R b/R/codebook.R
index 8b239f3..0818e47 100644
--- a/R/codebook.R
+++ b/R/codebook.R
@@ -13,7 +13,7 @@
#'
#' Caution 2: If there are commas in the value strings, they might be
#' used to split the text. Please manually insert a backslash symbol
-#' in front of the commas to avoid that.
+#' in front of the commas to avoid that (i.e., escape them).
#' E.g. \code{"Yes, I will"} -> \code{"Yes\, I will"}.
#'
#' Caution 3: This code cannot interpret variables that were imported from other
@@ -27,6 +27,11 @@
#' If you experience issues with newer versions or more complex code structures,
#' please open an issue on GitHub.
#'
+#' Caution 5: Custom exports are not part of the codebook.
+#'
+#' Further info: \code{None} values are presented as "None" (i.e. as a string)
+#' in the list and in the codebook.
+#'
#' @param path Character. Path of the oTree experiment.
#' @param fsource Character. \code{"init"} if information should be taken
#' from the \code{init.py} files (newer oTree code with 5.x
@@ -42,25 +47,36 @@
#' the function's output will be saved.
#' Only absolute paths are allowed for this parameter.
#' Relative paths can be specified in the \code{output_file} parameter.
-#' @param output_file Character. The name of the output file generated by the function.
+#' @param output_file Character.
+#' The name of the output file generated by the function.
#' The file name can be provided with or without an extension.
#' Relative paths are also allowed in the file name.
-#' @param output_format Character. Format of the file output.
-#' This is the format that is passed to the \code{output_format}
+#' @param output_format Character. Specifies the format of the file output.
+#' This value is passed to the \code{output_format}
#' argument of \link[rmarkdown:render]{rmarkdown::render}.
-#' You must use either \code{"pdf_document"}, \code{"html_document"}, \code{"word_document"}, \code{"odt_document"}, \code{"rtf_document"}, \code{"md_document"}, or \code{"latex_document"}.
-#' @param output_open Logical. \code{TRUE} if file output should be opened after creation.
-#' @param app_doc Logical. \code{TRUE} if app documentation should be included in
-#' output file.
+#' Allowed options are: \code{"html_document"}, \code{"word_document"}, \code{
+#' "odt_document"}, \code{"rtf_document"}, \code{"md_document"}, \code{
+#' "latex_document"}, \code{"pdf_document"}, \code{"pdf_document_simple"},
+#' or their short forms \code{"html"}, \code{"word"}, \code{"odt"}, \code{
+#' "rtf"}, \code{"md"}, \code{"latex"}, \code{"pdf"}, \code{"pdf_simple"}.
+#' Important: The \code{"pdf_document"} format uses \code{xelatex} for
+#' PDF generation.
+#' If your document does not require advanced LaTeX features,
+#' it is recommended to use \code{"pdf_document_simple"}.
+#' @param output_open Logical. \code{TRUE} if file output should
+#' be opened after creation.
+#' @param app_doc Logical. \code{TRUE} if app documentation should be
+#' included in the output file.
#' @param app Character. Name of the included app(s).
#' Default is to use all apps.
-#' This argument can not be used simultaneously as the argument \code{app_rm}.
+#' Cannot be used simultaneously with \code{app_rm}.
#' @param app_rm Character. Name of the excluded app(s).
#' Default is to exclude no apps.
-#' This argument can not be used simultaneously as the argument app.
+#' Cannot be used simultaneously with \code{app}.
#' @param doc_info Logical. \code{TRUE} if a message with information on all
-#' variables without documentation should also be returned.
-#' @param sort Character. Vector that specifies the order of
+#' variables without documentation should also be returned. \code{FALSE} if
+#' this message should be suppressed.
+#' @param sort Character vector. Vector that specifies the order of
#' the apps in the codebook.
#' @param settings_replace Character or \code{NULL}.
#' Specifies how to handle references to settings variables.
@@ -69,10 +85,11 @@
#' Use \code{"user"} to replace references with the variables
#' provided in the \code{user_settings} argument.
#' Use \code{NULL} to leave references to settings variables unchanged.
-#' Caution: This function does not use variables defined in \code{SESSION_CONFIGS}.
+#' Caution: This function does not use variables defined
+#' in \code{SESSION_CONFIGS}.
#' If you vary settings variables in \code{SESSION_CONFIGS},
-#' set \code{settings_replace} to \code{"user"} and manually replace them using the
-#' \code{user_settings} argument.
+#' set \code{settings_replace} to \code{"user"} and manually replace
+#' them using the \code{user_}\code{settings} argument.
#' @param user_settings List. List of variables in the \code{settings.py} file
#' that are used to replace setting variable references.
#' This is only used if \code{settings_replace = "user"} and should be used when
@@ -80,20 +97,30 @@
#' @param preamb Logical.
#' \code{TRUE} if a preamble should be printed that explains
#' how oTree saves variables.
+#' @param encoding Character. Encoding of the created Markdown file.
+#' As in \link[knitr:knit]{knitr::knit}, this argument is
+#' always assumed to be \code{UTF-8}
+#' and ignored.
+#' @param title Character. Title of output file.
+#' @param subtitle Character. Subtitle of output file.
#' @param include_cons Logical.
#' \code{TRUE} if there should be a section for the constants in the codebook.
#' @param params List.
#' List of variable name and value pairs to be passed to the RmD file.
#' Only relevant if argument output \code{"file"} or \code{"both"} if chosen.
-#' @param date Date that is passed to the Rmd file.
+#' @param date Character or \code{NULL}. Date that is passed to the Rmd file.
#' Either \code{"today"}, \code{NULL}, or a user defined date.
#' Only relevant if argument output \code{"file"} or \code{"both"} if chosen.
-#' @param encoding Character. Encoding of the created Markdown file.
-#' As in \link[knitr:knit]{knitr::knit}, this argument is
-#' always assumed to be \code{UTF-8}
-#' and ignored.
-#' @param title Character. Title of output file.
-#' @param subtitle Character. Subtitle of output file.
+#' @param splitvarname Logical. \code{TRUE} if long variable names should be
+#' split across multiple lines in the output file tables.
+#' If \code{FALSE}, table columns should adjust to fit the longest
+#' variable names.
+#' @param sep_list Character. Determines how sub-lists are displayed
+#' in the file output. Use \code{"newline"} to separate sub-lists with
+#' newline characters (`\\n`), or \code{"vector"} to display them as
+#' strings in `c(...)` format.
+#' @param initial Logical. \code{TRUE} if initial values should be included
+#' in the output file. \code{FALSE} if they should not be included.
#' @import knitr
#' @import pander
#' @import rmarkdown
@@ -130,7 +157,7 @@
#' app = "bargaining",
#' doc_info = FALSE)
#'
-#' # Show the structure of the codebook
+#' # Show the structure of the codebook
#' str(combined_codebook, 1)
#' str(combined_codebook$bargaining$Player, 1)
#'
@@ -142,7 +169,7 @@
#' app_rm = "bargaining",
#' doc_info = FALSE)
#'
-#' # Show the structure of the codebook
+#' # Show the structure of the codebook
#' str(combined_codebook, 1)
#' str(combined_codebook$bargaining$Player, 1)
#'
@@ -151,11 +178,19 @@
#' path = system.file("extdata/ocode_z", package = "gmoTree"),
#' fsource = "model",
#' output = "list",
-#' doc_info = TRUE)
+#' doc_info = FALSE)
#'
#' # Show the structure of the codebook
#' str(combined_codebook, 1)
#'
+#' # Show information on missing documentation or complex code
+#' combined_codebook <- codebook(
+#' path = system.file("extdata/ocode_new", package = "gmoTree"),
+#' fsource = "init",
+#' output = "list",
+#' app_rm = "bargaining",
+#' doc_info = TRUE)
+#'
#' \dontrun{
#'
#' # Create a codebook PDF with authors' names and todays' date
@@ -196,9 +231,9 @@
codebook <- function(path = ".",
fsource = "init",
output = "both",
- output_dir = getwd(),
+ output_dir = NULL,
output_file = "codebook",
- output_format = "pdf_document",
+ output_format = "pdf_document_simple",
output_open = TRUE,
app_doc = TRUE,
app = NULL,
@@ -213,12 +248,13 @@ codebook <- function(path = ".",
title = "Codebook",
subtitle = "created with gmoTree",
params = NULL,
- date = "today") {
+ date = "today",
+ splitvarname = FALSE,
+ sep_list = "newline",
+ initial = TRUE) {
- output_dir_input <- substitute(output_dir)
-
- # Stop part 1
- # Path and fsource ####
+ # Stop and load
+ # Source original code ####
# Define path
if (!is.null(path)) {
# Change Windows paths to paths that can be read by Ubuntu
@@ -246,85 +282,158 @@ codebook <- function(path = ".",
stop("fsource must be either \"init\", \"model\", or \"models\"!")
}
- # Others ####
- # Check output format
- if (!is.character(output) ||
- length(output) != 1L ||
- !(output %in% c("list", "both", "file"))) {
- stop("Output should be \"list\", \"both\", or \"file\"!")
- }
+ if (fsource == "model" || fsource == "models") {
+
+ files <- list.files(path,
+ pattern = "models\\.py",
+ full.names = TRUE,
+ recursive = TRUE)
- # Check pandoc
- if (output != "list") {
- pandoc.installed <- system('pandoc -v', ignore.stdout = TRUE, ignore.stderr = TRUE) == 0
+ } else if (fsource == "init") {
+ files <- list.files(path,
+ pattern = "__init__\\.py",
+ full.names = TRUE,
+ recursive = TRUE)
+
+ # Exclude files from the _builtin folders
+ files <- files[grepl("(? 1L ||
- !(output_format %in% allowed_formats)) {
- stop("Output format should be one of the following: ",
- paste0(allowed_formats, collapse = ", "), "!")
- }
-
- # Create variables, and environment ####
-
-
- # Create a new environment
- env <- new.env()
-
- # Settings.py file
- env$settingspy <- TRUE
- env$settingslist <- c()
+ # Create a new environment and initialize
+ env <- new.env(parent = emptyenv())
+ env$settingspy <- TRUE # Is there a settings.py file?
+ env$settingslist <- character() # Settings vars that cannot be replaced
+ env$usettingslist <- character() # User sett. vars that cannot be replaced
+ env$equalvariables <- character() # Vars with unescaped equal signs?
# Create vector of variables without documentation
env$nodocs <- character()
@@ -382,36 +479,13 @@ codebook <- function(path = ".",
# Background functions ####
- # Paths and directories ####
-
- # Define and create output dir
- if (!is.null(output_dir)) {
-
- # If dir is a relative path
- if (grepl("^\\.", x = output_dir)) {
- stop("Please don't use relative paths in output_dir!")
- }
-
- # If dir is not there
- if (!dir.exists(output_dir)) {
-
- stop("The directory ",
- output_dir,
- " does not exist yet. ",
- "Please create it manually before running this function.")
- }
-
- # Change Windows paths to paths that can be read by Ubuntu
- output_dir <- gsub("\\\\", "/", output_dir)
- }
-
# Stop if ####
# Settings_replace
if (length(user_settings) > 0L &&
settings_replace != "user") {
- stop("settings_replace must be set to \"user\"",
- "if user_settings are not empty!")
+ stop("settings_replace must be set to \"user\" ",
+ "if \"user_settings\" are not empty!")
}
# Check if only app or app_rm is specified
@@ -421,53 +495,74 @@ codebook <- function(path = ".",
# Helping functions ####
process_lists <- function(variablevalue,
- type = "s",
- folder_name = folder_name,
- env = env) {
+ folder_name,
+ current_class,
+ variable,
+ env) {
+ skip <- FALSE
+ returnlist <- list()
+
+ # One level list (vector, sublist) ####
+ if (!grepl("^\\[\\s*\\[\\s*\\[", variablevalue) &&
+ !grepl("^\\[\\s*\\[", variablevalue) &&
+ startsWith(variablevalue, "["
+ )) {
+
+ skip <- TRUE
+
+ # make [..] to list(...) ####
+ variablevalue <- gsub(pattern = "\\[",
+ replacement = "\\list(",
+ x = variablevalue)
+
+ variablevalue <- gsub(pattern = "\\]",
+ replacement = "\\)",
+ x = variablevalue)
+
+ # Transform string of vector to normal vector ####
+ variablevalue <- evaluatestring(variablevalue)
- # Empty list
- if (variablevalue == "[]") {
- return(variablevalue)
+ returnlist <- variablevalue
}
- # Three level list
- if (stringr::str_detect(string = unlist(variablevalue),
- pattern = "^\\[{3,}")) {
+ # Three level list, sublists ####
+ if (!skip &&
+ stringr::str_detect(string = unlist(variablevalue),
+ pattern = "^\\[\\s*\\[\\s*\\[")) {
- # Not sure if ever needed
- stop("This function does not support lists with more than two levels.")
+ stop("This function does not support lists with more than two levels.",
+ " Found in: $", folder_name, "$", current_class,
+ "$", variable, ".")
}
- # Two level lists vs. one level = vector
- if (startsWith(variablevalue,
- "[[")) {
+ # Two level lists ####
+ if (!skip &&
+ grepl("^\\[\\s*\\[", variablevalue)) {
# Replace first and last square brackets
variablevalue <- sub(x = variablevalue,
- pattern = "^\\[",
+ pattern = "^ *\\[",
replacement = "")
-
variablevalue <- sub(x = variablevalue,
- pattern = "\\][^]]*$",
+ pattern = "\\][^]] *$",
replacement = "")
# Extract each [ ... ] block
if (stringr::str_detect(variablevalue, "\\[")) {
- variablevalue <- unlist(stringr::str_match_all(variablevalue,
- pattern = "\\[.*?\\]"))
+ variablevalue <- unlist(
+ stringr::str_match_all(variablevalue,
+ pattern = "\\s*\\[.*?\\]\\s*"))
}
- # Replace first and last square brackets
+ # Replace first and last square brackets from these blocks
variablevalue <- sub(x = variablevalue,
- pattern = "^\\[",
+ pattern = "^\\s*\\[ *",
replacement = "")
variablevalue <- sub(x = variablevalue,
- pattern = "\\][^]]*$",
+ pattern = "\\s*\\][^]]*$",
replacement = "")
- returnlist <- list()
-
for (variablevalue_i in seq_along(variablevalue)) {
elem <- variablevalue[variablevalue_i]
@@ -475,35 +570,24 @@ codebook <- function(path = ".",
# Split the element into key and value
parts <- stringr::str_split(elem, ",")[1L]
- # Clean and assign key and value
- parts <- clean_string(parts,
- quotes = TRUE,
- folder_name = folder_name)
+ # Parts must be in list format afterwards because of mixed types
+ parts <- as.list(parts[[1L]])
+ parts <- lapply(X = parts,
+ clean_string,
+ equal = FALSE, # Important!!
+ quotes = TRUE,
+ current_class = current_class,
+ folder_name =
+ paste(folder_name,
+ errorinfo = "called by parts"),
+ variable = variable)
+
+ parts <- lapply(parts,
+ evaluatestring)
returnlist[[variablevalue_i]] <- parts
}
- } else if (startsWith(variablevalue, "[")) {
-
- # make [..] to c(...) ####
- variablevalue <- gsub(pattern = "\\[",
- replacement = "\\c(",
- x = variablevalue)
-
- variablevalue <- gsub(pattern = "\\]",
- replacement = "\\)",
- x = variablevalue)
-
- # Transform string of vector to normal vector ####
-
- try({
- tmp <- eval(parse(text = variablevalue))
- if (!is.function(tmp)) {
- variablevalue <- tmp
- }
- }, silent = TRUE)
-
- returnlist <- variablevalue
}
if (length(returnlist) == 1L) {
@@ -522,7 +606,7 @@ codebook <- function(path = ".",
env = env) {
# This is called by process_settings and process_files
- # Get variable names ####
+ # Get variable names
# Only those that are on the same indent are measured!
pattern <- paste0("^\\s{",
normalspace,
@@ -544,21 +628,21 @@ codebook <- function(path = ".",
# Check if "with" occurs
if (grepl(x = matches, pattern = "\\nwith")) {
env$complexcons <-
- c(env$complexcons, paste0("> App", folder_name, "(",
- current_class, ") (with)\n"))
+ c(env$complexcons, paste0("> $", folder_name, "$",
+ current_class, " (with)\n"))
}
# Check if "read_csv" occurs
if (grepl(x = matches, pattern = "read_csv")) {
env$complexcons <-
- c(env$complexcons, paste0("> App ", folder_name, "(",
- current_class, ") (read_csv)\n"))
+ c(env$complexcons, paste0("> $", folder_name, "$",
+ current_class, " (read_csv)\n"))
}
# Get everything until the second variable is mentioned and modify
for (cons_sett_i in seq_along(all_cons_sett_vars)) {
- if (all_cons_sett_vars[cons_sett_i] != "with" && # Unnecessary, there is no = sign
+ if (all_cons_sett_vars[cons_sett_i] != "with" && # TODO? Unnecessary, there is no = sign
all_cons_sett_vars[cons_sett_i] != "from") {
# Make pattern
@@ -588,26 +672,24 @@ codebook <- function(path = ".",
text = matches,
perl = TRUE)))
- varval <- clean_string(varval,
- equal = TRUE,
- n = TRUE,
- quotes = FALSE,
- space = TRUE,
- brackets = FALSE,
- sbrackets = FALSE,
- folder_name = folder_name)
+ varval <- clean_string(string = varval,
+ folder_name = folder_name,
+ equal = TRUE,
+ n = TRUE,
+ quotes = TRUE,
+ space = TRUE,
+ brackets = FALSE,
+ sbrackets = FALSE,
+ current_class = current_class,
+ variable = variable)
# Deal with lists ####
if (startsWith(varval, "[")) {
-
- varval <- process_lists(varval)
-
- # Stop if list contains another list
- if (any(vapply(varval, is.list,
- FUN.VALUE = logical(1L)))) {
- # Not sure if ever needed
- stop("This function does not support overly complex lists.")
- }
+ varval <- process_lists(varval,
+ folder_name,
+ current_class,
+ all_cons_sett_vars[cons_sett_i],
+ env)
}
# Replace variable references within Constants/settings ####
@@ -634,15 +716,34 @@ codebook <- function(path = ".",
perl = TRUE)
} else {
+ # Make all to characters
+ replacementlist <- lapply(
+ filevars[[current_class]][[
+ all_cons_sett_vars[j]]],
+ as.character)
+
+ # Make lists
+ for (i in seq_along(replacementlist)) {
+ replacementlist[i] <-
+ paste0("list(",
+ paste(replacementlist[[i]],
+ collapse = ", "),
+ ")"
+ )
+ }
+
+ listvec <- "c(" # This should never happen
+ if (is.list(replacementlist)) {
+ listvec <- "list("
+ }
varval <-
gsub(x = varval,
pattern = paste0("(? $", folder_name, "$",
+ current_class, "$", variable,
+ " (unmatched brackets)\n"))
}
# Square brackets
@@ -716,10 +806,11 @@ codebook <- function(path = ".",
} else if (opensq == 1L && closesq == 0L) {
string <- gsub(x = string, pattern = "\\[", replacement = "")
} else if (opensq != closesq) {
+ # e.g. if there are more than one opening bracket
env$complexcons <-
- c(env$complexcons, paste0("> App", folder_name, "(",
- current_class,
- ") (unmatched square brackets)\n"))
+ c(env$complexcons, paste0("> $", folder_name, "$",
+ current_class, "$", variable,
+ " (unmatched square brackets)\n"))
} # Don't remove square brackets if they are first and last yet!
@@ -728,6 +819,8 @@ codebook <- function(path = ".",
# Clean string
clean_string <- function(string,
+ folder_name, # For error info
+ current_class,
equal = TRUE,
n = TRUE,
space = TRUE,
@@ -735,80 +828,184 @@ codebook <- function(path = ".",
brackets = TRUE,
sbrackets = TRUE,
lastcomma = TRUE,
- current_class = current_class,
- folder_name = folder_name) {
+ variable) {
- # Save real quotes first
- string <- gsub(pattern = "\\\\\"",
- replacement = "<>",
- x = string)
-
- # Remove = signs
+ # Remove unescaped equal signs ####
+ # (those usually only happen at the start)
if (equal) {
- string <- gsub(pattern = "=",
- replacement = "",
- x = string)
+ # Remove equal
+ string <- stringr::str_replace_all(string, "(?>",
+ x = string,
+ perl = TRUE)
+
+ string <- gsub(pattern = "\\\\\\'", # One more because of '
+ replacement = "<>",
+ x = string,
+ perl = TRUE)
+
+ # Remove line breaks ####
if (n) {
- string <- gsub(pattern = "\\n",
+ # Line breaks breaking strings
+ string <- gsub(pattern = paste0("\\\"",
+ "\\s*",
+ "\\n", # removes \n
+ "\\s*",
+ "\\\""),
replacement = "",
x = string)
- }
- # Remove quotes: " or \".
- # Don't remove ' or \' because those are essential parts of text
- # Will be done in the end
- if (quotes) {
- # Important! Must be done before any \ removals
- string <- gsub(pattern = "\\\"|\"",
+ string <- gsub(pattern = paste0("\\\"",
+ "\\s*",
+ "\\\\\\n", # removes \\\n
+ "\\s*",
+ "\\\""),
replacement = "",
x = string)
+
+ # Normal line breaks
+ string <- gsub(pattern = "\\n",
+ replacement = " ",
+ x = string)
+
}
- # Trim white space
+ # Trim white space again ####
if (space) {
string <- trimws(string)
}
- # Remove last comma in a string
+ # Remove last comma in a string ####
if (lastcomma) {
string <- gsub(pattern = ",$",
replacement = "",
x = string)
}
- # Ensure that brackets are processed last
- if (brackets && !is.na(string)) {
- string <- replace_unmatched_parentheses(string, folder_name)
- }
+ # Brackets (ensure that brackets are processed last!) ####
+ if (brackets) { # && !is.na(string)
+ string <- replace_unmatched_parentheses(string = string,
+ current_class = current_class,
+ folder_name = folder_name,
+ variable = variable,
+ env = env)
- # Remove two single quotes only if they are at the beginning and end of the string
- # Must be done at the end because they could also be used as apostrophes
- if (quotes) {
-
- # Documentation
- string <- gsub(pattern = "^'''(.*)'''$",
- replacement = "\\1", # Keep the content in the middle
- x = string,
- perl = TRUE)
-
- # Normal quotes
- string <- gsub(pattern = "^'(.*)'$",
- replacement = "\\1", # Keep the content in the middle
- x = string,
- perl = TRUE)
}
-
- # Get real quotes back
- string <- gsub(pattern = "<>",
+ # Get real quotes back ####
+ string <- gsub(pattern = "<>",
replacement = "\"",
x = string)
+ string <- gsub(pattern = "<>",
+ replacement = "\'",
+ x = string)
+
+ # Return ####
+ return(string)
+ }
+
+ removefirstlastquote <- function(string) {
+
+ if (is.character(string)) {
+ # Escaped
+ string <- sub("^\\\\\"(.*)\\\\\"$", "\\1", string)
+
+ string <- sub("^\\\\\'(.*)\\\\\'$", "\\1", string)
+
+ # Non-escaped
+ string <- sub("^\\\"(.*)\\\"$", "\\1", string)
+ string <- sub("^\\\'(.*)\\\'$", "\\1", string)
+
+ string <- trimws(string)
+
+ return(string)
+
+ } else {
+ return(string)
+
+ }
+ }
+
+ evaluatestring <- function(string) {
+ # Converts a string representation of a vector/list
+ # into an actual vector/list and
+ # evaluates any arithmetic expressions within the string
+
+ try({
+ # Remove spaces after ( and before )
+ string <- gsub("\\s*c\\(\\s*", "c\\(", string)
+ string <- gsub("\\s*\\)", "\\)", string)
+ # Len should be read as length
+ string <- gsub("^\\blen\\b\\(", "length\\(", string)
+
+ # Create a custom environment where None is defined as "None"
+ custom_env <- new.env()
+ custom_env$None <- "None"
+
+ # Evaluate the string in the custom environment
+ tmp <- eval(parse(text = string), envir = custom_env)
+
+ if (!is.function(tmp)) {
+ string <- tmp
+ }
+
+ }, silent = TRUE)
+
+ if (!is.null(string)) {
+ return(string)
+ }
+ }
+
+ removedocstrings <- function(string) {
+
+ string <- gsub(pattern = "(?s)^'''(.*)'''$",
+ replacement = "\\1", # Keep the content in the middle
+ x = string,
+ perl = TRUE)
+
+ string <- gsub(pattern = '(?s)^"""\\n*(.*)\\n*"""$',
+ replacement = "\\1", # Keep the content in the middle
+ x = string,
+ perl = TRUE)
+
+ # Nonescaped double quotes +
+ string <- gsub(pattern = '(?s)^"""(.*)"""$',
+ replacement = "\\1", # Keep the content in the middle
+ x = string,
+ perl = TRUE)
+
+ # Escaped double quotes +
+ string <- gsub(pattern = '(?s)^\\\"\\\"\\\"(.*)\\\"\\\"\\\"$',
+ replacement = "\\1", # Keep the content in the middle
+ x = string,
+ perl = TRUE)
+
return(string)
+ }
+ delprint <- function(string) {
+ if (is.character(string)) {
+ string <-
+ gsub(
+ x = string,
+ pattern = "print\\(.*\\)",
+ replacement = "")
+ string <- trimws(string)
+ }
+ return(string)
}
# Function to split each element at the last comma
@@ -824,6 +1021,7 @@ codebook <- function(path = ".",
return(c(stringr::str_trim(f_split_parts[1L]),
stringr::str_trim(f_split_parts[2L])))
} else {
+
return(part)
}
}
@@ -951,11 +1149,21 @@ codebook <- function(path = ".",
if (!is.null(myreplacement)) {
# First remove possible preceding +
# (in Pyhon, a + adds strings together)
- string <- sub(pattern = paste0("\\+\\s*", fullvarpattern),
+
+ # Part before
+ string <- sub(pattern = paste0("['\"]?",
+ "\\s*",
+ "\\+",
+ "\\s*", fullvarpattern),
replacement = fullvarpattern,
x = string)
- string <- sub(pattern = paste0(fullvarpattern, "\\s*", "\\+"),
+ # Part after
+ string <- sub(pattern = paste0(fullvarpattern,
+ "\\s*",
+ "\\+",
+ "\\s*",
+ "['\"]?"),
replacement = fullvarpattern,
x = string)
@@ -968,29 +1176,51 @@ codebook <- function(path = ".",
c(env$warnings,
paste0("Variable ", fullvarpattern,
" in folder ", folder_name,
- " is not in Constants and cannot be replaced!",
- " Check your code before continuing making the",
- " codebook and running the experiment!"))
+ " is not in Constants and cannot be replaced:"))
}
}
}
}
+
return(string)
}
# Replace settings values references by actual values
settings_replace_f <- function(mystring,
- folder_name = NULL, # Folder name
- combined_codebook = combined_codebook,
- user_settings = user_settings,
- settings_replace = settings_replace,
+ folder_name, # app
+ combined_codebook,
+ user_settings,
+ settings_replace,
+ env,
e_variable = NULL,
- e_key = NULL) {
+ e_key = NULL
+ ) {
+
+ mystring <- mystring[[1L]]
+
+ if (is.null(mystring) ||
+ (length(mystring) == 1L && is.na(mystring))) {
- pattern <- "settings\\.[_a-zA-Z0-9]+"
+ env$warnings <-
+ c(env$warnings,
+ "There is an unusual variable in your data! Variable: ",
+ e_variable, ".")
- # First check for sub-lists
- # Not necessary here because they are already sub-lists!
+ return(mystring)
+
+ } else if (length(mystring) == 1L && mystring == "") {
+
+ return(mystring)
+ }
+
+ if (!is.character(mystring)) {
+ return(mystring)
+ }
+
+ pattern <- "(? Folder \"", folder_name,
- "\", variable: \"", e_variable,
- "\", reference: \"settings.", settings_var,
- "\".\n"))
+ paste0("> $", folder_name,
+ "$", e_variable,
+ ", reference \"settings.", settings_var,
+ "\"\n"))
} else {
myreplacement <- combined_codebook[["settings"]][[settings_var]]
}
+
} else if (!is.null(settings_replace) &&
- settings_replace == "user"){
+ settings_replace == "user") {
if (!is.null(user_settings) &&
settings_var %in% names(user_settings)) {
+
myreplacement <- user_settings[[settings_var]]
} else {
-
- stop("Variable \"", settings_var, "\" in app \"", folder_name,
- "\" (and maybe others) is not in user_settings!")
+ env$usettingslist <- c(env$usettingslist,
+ paste0("> $", folder_name,
+ "$", e_variable,
+ ", reference \"settings.",
+ settings_var,
+ "\"\n"))
}
}
# Replace variable within the whole string
if (!is.null(myreplacement)) {
-
if (length(myreplacement) == 1L) {
# Replace single value
@@ -1057,61 +1291,45 @@ codebook <- function(path = ".",
x = mystring)
} else {
- # If all numeric
-
- if (suppressWarnings(anyNA(as.integer(myreplacement)))) {
- mystring <-
- gsub(x = mystring,
- pattern = fullvarpattern,
- replacement = paste0("c(\"",
- paste(myreplacement,
- collapse = "\",\""),
- "\")"),
- perl = TRUE)
+ if (grepl(mystring,
+ pattern = paste0("^", fullvarpattern, "$"))) {
+ mystring <- myreplacement
} else {
-
- # Replace with a vector
- mystring <-
- gsub(x = mystring,
- pattern = fullvarpattern,
- replacement = paste0("c(",
- paste(myreplacement,
- collapse = ","),
- ")"),
- perl = TRUE)
+ # Here exceptionally with c() because
+ # of future calculations with it
+ mystring <- sub(pattern = fullvarpattern,
+ replacement = paste0("c(", paste(myreplacement,
+ collapse = ", "),
+ ")"),
+ x = mystring)
}
+
}
} else {
- # Do nothing because this is dealt with before
+ # Do nothing! env$(u)settingslist was filled above
}
}
}
+ } else {
+ # If there are no references to settings, return string
+
+ return(mystring)
}
# If numeric, then evaluate
if (length(mystring) == 1L) {
- try({
-
- tmp <- eval(parse(text = mystring))
- if (!is.null(tmp) && !is.function(tmp)) {
- mystring <- tmp
-
- }
- }, silent = TRUE)
+ # Here, we can also see sublists e.g. "c(1,2,3)"
+ mystring <- evaluatestring(mystring) # WARum geht das nicht?
} else {
- # If single elements contain calculations
+ # Evaluate single elements
for (mystring_i in seq_along(mystring)) {
- try({
- tmp <- eval(parse(text = mystring[mystring_i]))
- if (!is.null(tmp) && !is.function(tmp)) {
- mystring[mystring_i] <- tmp
- }
- }, silent = TRUE)
+ val <- mystring[mystring_i]
+ mystring[mystring_i] <- evaluatestring(val)
}
}
@@ -1151,7 +1369,7 @@ codebook <- function(path = ".",
# Sometimes, init.py only has 1 line in old oTree
if (length(file_content) <= 2L) {
stop("At least one of your init-files is empty. ",
- "Try using argument \"fsource = model\".")
+ "Try using the argument \"fsource = \'model\'\".")
}
file_content <- remove_line_comments(file_content)
@@ -1179,8 +1397,13 @@ codebook <- function(path = ".",
pattern = "^doc",
replacement = "")
- matches <- clean_string(matches,
- folder_name = folder_name)
+ matches <- clean_string(string = matches,
+ quotes = TRUE,
+ current_class = current_class,
+ folder_name = folder_name,
+ variable = NULL)
+
+ matches <- removefirstlastquote(matches)
filevars[["doc"]] <- matches
}
@@ -1206,43 +1429,92 @@ codebook <- function(path = ".",
env = env)
# Clean constants
- for (cons_i in seq_along(filevars[["Constants"]])) {
+ for (cons_var_i in seq_along(filevars[["Constants"]])) {
# If there is a second level
- if ((length(filevars[["Constants"]][[cons_i]])) > 1L) {
+ if (length(filevars[["Constants"]][[cons_var_i]]) > 1L) {
- for (cons_j in seq_along(filevars[["Constants"]][[cons_i]])) {
+ for (cons_l2 in seq_along(filevars[["Constants"]][[cons_var_i]])) {
- # Delete print()
- filevars[["Constants"]][[cons_i]][[cons_j]] <-
- gsub(
- x = filevars[["Constants"]][[cons_i]][[cons_j]],
- pattern = "print\\(.*\\)",
- replacement = "")
+ # Delete print command
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]] <-
+ delprint(filevars[["Constants"]][[cons_var_i]][[cons_l2]])
# Replace all references to the settings with the actual variables
- filevars[["Constants"]][[cons_i]][[cons_j]] <-
- settings_replace_f(
- mystring = filevars[["Constants"]][[cons_i]][[cons_j]],
+
+ if (length(filevars[["Constants"]][[cons_var_i]][[cons_l2]]) ==
+ 1L) {
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]] <-
+ settings_replace_f(
+ mystring = filevars[["Constants"]][[cons_var_i]][[cons_l2]],
+ folder_name = folder_name,
+ combined_codebook = combined_codebook,
+ user_settings = user_settings,
+ settings_replace = settings_replace,
+ e_variable = paste0(
+ names(filevars[["Constants"]])[[cons_var_i]],
+ ", element: ",
+ cons_l2
+ ), env = env
+ )
+
+ # Remove first and last quote
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]] <-
+ removefirstlastquote(
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]]
+ )
+
+ } else {
+
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]] <- sapply(
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]],
+ settings_replace_f,
folder_name = folder_name,
combined_codebook = combined_codebook,
user_settings = user_settings,
settings_replace = settings_replace,
- e_variable = names(filevars[["Constants"]][cons_i])[[cons_j]])
-
+ e_variable = paste0(
+ names(filevars[["Constants"]])[[cons_var_i]],
+ ", element: ",
+ cons_l2),
+ env = env,
+ simplify = FALSE
+ )
+
+ # Remove first and last quote
+ filevars[["Constants"]][[cons_var_i]][[cons_l2]] <-
+ sapply(filevars[["Constants"]][[cons_var_i]][[cons_l2]],
+ removefirstlastquote,
+ simplify = FALSE
+ )
+ }
}
} else {
+
+ # Delete print command
+ filevars[["Constants"]][[cons_var_i]] <-
+ delprint(filevars[["Constants"]][[cons_var_i]])
+
# Replace all references to the settings with the actual variables
- filevars[["Constants"]][[cons_i]] <-
- settings_replace_f(
- mystring = filevars[["Constants"]][[cons_i]],
+ if (is.character(filevars[["Constants"]][[cons_var_i]])) {
+ repl <- settings_replace_f(
+ mystring = filevars[["Constants"]][[cons_var_i]],
folder_name = folder_name,
combined_codebook = combined_codebook,
user_settings = user_settings,
settings_replace = settings_replace,
- e_variable = names(filevars[["Constants"]][cons_i]))
+ e_variable = names(filevars[["Constants"]])[[cons_var_i]],
+ env = env)
+
+ filevars[["Constants"]][[cons_var_i]] <- repl
+ # Remove first and last quote
+ filevars[["Constants"]][[cons_var_i]] <- removefirstlastquote(
+ filevars[["Constants"]][[cons_var_i]]
+ )
+
+ }
}
}
}
@@ -1255,6 +1527,7 @@ codebook <- function(path = ".",
if (line_nr == player_lines[1L]) {
matches <- file_content[(line_nr + 1L):player_lines[2L]]
current_class <- "Player"
+
} else {
matches <- file_content[(line_nr + 1L):group_lines[2L]]
current_class <- "Group"
@@ -1282,7 +1555,7 @@ codebook <- function(path = ".",
# Strip spaces etc.
variables <- trimws(variables)
- # Variable info ####
+ # Variable values ####
for (variables_i in seq_along(variables)) {
variable <- variables[variables_i]
@@ -1326,12 +1599,15 @@ codebook <- function(path = ".",
perl = TRUE
)
+ # Remove print from matches
+ varmatches <- delprint(varmatches)
+
# Get variable information ####
# Get field
field <-
stringr::str_extract(varmatches, "(?<=models\\.)[^(]+")
- # Remove field from matches + last )
+ # Remove field from matches
varmatches <- sub(
pattern = paste0(" *= *models\\.", field),
replacement = "",
@@ -1339,17 +1615,19 @@ codebook <- function(path = ".",
perl = TRUE
) # First bracket stays but this is okay and stripped later.
+ # Remove last part of matches
if (grepl(x = varmatches,
pattern = "\\)[\n ]*$",
perl = TRUE)) {
+
+ # Remove last closing bracket
varmatches <- sub(
- pattern = "\\)$",
+ pattern = "\\,*[\n ]*\\)[\n ]*$",
replacement = "",
x = varmatches,
perl = TRUE
)
- } else { # "Else" is just for development / should not happen
- stop("Internal gmoTree error!")
+
}
# If there are no arguments
@@ -1363,29 +1641,29 @@ codebook <- function(path = ".",
varmatches, sep = " ")
}
- # If documentation does not start with doc, add it
- # Not sure if ever needed
- if (stringr::str_detect(varmatches, "^ *\"\"\"|^ *'''")) {
- varmatches <- paste("doc = ", varmatches)
- }
-
# Variable information ####
# First split its content at every = sign ####
- parts <- stringr::str_split(stringr::str_trim(varmatches),
- " *= *")[[1L]]
- # Now the value of one variable is together with
- # the variable name of the next variable
- # Apply split_at_last_comma to each element
- # except the first and last
+ # Check for unescaped equal signs in choice options
+ # = within square brackets
+ list_with_equals_pattern <- "\\[[^\\]]*[^\\\\]=[^\\]]*\\]"
- if (length(parts) > 2) {
- split_parts <- unlist(lapply(parts[2L:(length(parts) - 1L)],
- split_at_last_comma))
- } else {
- split_parts <- c()
+ if (grepl(pattern = list_with_equals_pattern,
+ x = varmatches,
+ perl = TRUE)) {
+
+ paste(variable)
+ env$equalvariables <- c(env$equalvariables,
+ paste0("\n> $", folder_name, "$",
+ current_class, "$",
+ variable))
+
+ next
}
+ split_pattern <- "(? 2L) {
+
+ # Now the value of one variable is together with
+ # the variable name of the next variable
+ # Apply split_at_last_comma to each element
+ # except the first and last
+
+ split_parts <- unlist(lapply(parts[2L:(length(parts) - 1L)],
+ split_at_last_comma))
+
parts <- c(parts[1L],
split_parts,
parts[length(parts)])
@@ -1403,6 +1690,18 @@ codebook <- function(path = ".",
"Please contact the maintainer with details.")
}
+ if (length(parts) %% 2L != 0L) {
+ env$equalvariables <- c(env$equalvariables,
+ paste0("\n> $", folder_name, "$",
+ current_class, "$",
+ variable))
+
+ next
+
+ } else {
+
+ }
+
# Make key value frame ####
# Create an empty list to store your kv_frame
kv_frame <- data.frame(key = c(),
@@ -1422,11 +1721,14 @@ codebook <- function(path = ".",
"\\n",
"")
+ # Clean key
kv_frame$key <-
sapply(kv_frame$key,
clean_string,
quotes = TRUE,
- folder_name = folder_name)
+ current_class = current_class,
+ folder_name = folder_name,
+ variable = variable)
# Choices need to be specified #####
if ("choices" %in% kv_frame$key) {
@@ -1437,11 +1739,10 @@ codebook <- function(path = ".",
text <- trimws(text)
# In case the kv_frame works with square brackets
- numbrack <- length(unlist(gregexpr(pattern = "\\[",
+ numbrackets <- length(unlist(gregexpr(pattern = "\\[",
text = text)))
- if (numbrack > 1L) { # If key - value pairs
-
+ if (numbrackets > 1L) { # If key - value pairs
# Replace first and last square brackets
text <- sub(x = text,
pattern = "^\\[",
@@ -1461,47 +1762,59 @@ codebook <- function(path = ".",
unlist(stringr::str_match_all(text,
pattern = "\\[.*?\\]"))
- # Combine into a single data frame
+ # If choices, combine into a single data frame
# (not dict because values can appear several times)
choices <- data.frame(
- key <- c(),
- value <- c())
+ choices_key <- c(),
+ choices_value <- c())
for (elem in text) {
+
# Split the element into key and value
parts <- stringr::str_split(string = elem,
pattern = ",",
n = 2L)[[1L]]
# Clean and assign key and value
- key <- clean_string(parts[1L],
- quotes = TRUE,
- folder_name = folder_name)
-
- value <- clean_string(parts[2L],
- quotes = TRUE,
- folder_name = folder_name)
+ # Key
+ choices_key <- clean_string(string = parts[1L],
+ quotes = TRUE,
+ current_class = current_class,
+ folder_name = folder_name,
+ variable = variable)
+ choices_key <- removefirstlastquote(choices_key)
+
+ # Value
+ choices_value <- clean_string(string = parts[2L],
+ quotes = TRUE,
+ equal = TRUE,
+ current_class = current_class,
+ folder_name = folder_name,
+ variable = variable)
- value <- cons_replace(value, filevars,
- folder_name, env = env)
+ choices_value <- cons_replace(choices_value, filevars,
+ folder_name, env = env)
- value <- settings_replace_f(
- mystring = value,
+ choices_value <- settings_replace_f(
+ mystring = choices_value,
folder_name = folder_name,
combined_codebook = combined_codebook,
user_settings = user_settings,
settings_replace = settings_replace,
- e_variable = variable)
+ e_variable = variable,
+ env = env)
+
+ choices_value <- removefirstlastquote(choices_value)
# Return key-value pair
choices <- rbind(choices,
data.frame(
- key = key,
- value = value))
+ key = choices_key,
+ value = choices_value))
}
+ } else if (numbrackets == 1L) {
- } else if (numbrack == 1L) {
# If not key-value pairs. E.g. choices=[1, 2, 3]
# Replace first and last square brackets
@@ -1520,7 +1833,7 @@ codebook <- function(path = ".",
choices <-
stringr::str_split(text, "(? 0L) {
+ stop("\nThe following variable(s) cannot be read properly by gmoTree. ",
+ "\nPlease escape any equal signs in the values of the oTree code!",
+ paste0(env$equalvariables, collapse = ""))
+ }
# Adjust settings ####
if ("settings" %in% names(combined_codebook)) {
@@ -1703,6 +2015,7 @@ codebook <- function(path = ".",
# Sort apps in codebook ####
if (!is.null(sort)) {
+
sort <- c("settings", sort)
if (
@@ -1738,111 +2051,202 @@ codebook <- function(path = ".",
}
}
- # If file ####
- if (output == "file" || output == "both") {
-
- # If other files already have this name ####
- nr_suffix <- 0L
-
- # Output extension as in output_format
- output_form_ext <- sub(pattern = "_.*$",
- replacement = "",
- x = output_format)
-
- output_form_ext[output_form_ext == "word"] <- "docx"
- output_form_ext[output_form_ext == "latex"] <- "tex"
-
- # Check if file extension is already in file name (strip if yes)
- output_file <- sub(pattern = paste0("\\.",
- output_form_ext,
- "$"),
- replacement = "",
- x = output_file)
-
- # Check for non-fitting file extensions
- if (!(tolower(tools::file_ext(output_file)) == "" ||
- tolower(tools::file_ext(output_file)) == tolower(output_form_ext)
- )) {
- stop("You are not allowed to use file extensions in the ",
- "output_file that do not correspond to the output format! ",
- "Your output_file extension is ",
- tools::file_ext(output_file),
- ". The extension according to your output_format should be ",
- output_form_ext, ".")
- }
+ # Make output file ####
+ if (output == "file" || output == "both") {
+
+ # If other files already have this name ####
+ nr_suffix <- 0L
+
+ # Output extension as in output_format
+ output_form_ext <- sub(pattern = "_.*$",
+ replacement = "",
+ x = output_format)
+
+ output_form_ext[output_form_ext == "word"] <- "docx"
+ output_form_ext[output_form_ext == "latex"] <- "tex"
+
+ # Check if file extension is already in file name (strip if yes)
+ output_file <- sub(pattern = paste0("\\.",
+ output_form_ext,
+ "$"),
+ replacement = "",
+ x = output_file)
+
+ # Check for non-fitting file extensions
+ if (!(tolower(tools::file_ext(output_file)) == "" ||
+ tolower(tools::file_ext(output_file)) == tolower(output_form_ext)
+ )) {
+ stop("You are not allowed to use dots in your output_file names or ",
+ "file extensions in the ",
+ "output_file that do not correspond to the output format! ",
+ "Your output_file extension is ",
+ tools::file_ext(output_file),
+ ". The extension according to your output_format should be ",
+ output_form_ext, ".")
+ }
- # Define dictionary that has to be checked
- checkdir <- dirname(output_file)
+ # Define dictionary that has to be checked
+ checkdir <- dirname(output_file)
- # Check if there are files with the same name in the folder
- nr_doc_same <- sum(
- grepl(pattern = paste0("^", basename(output_file),
- "[_\\d]*\\.", output_form_ext),
- x = list.files(checkdir),
- perl = TRUE))
+ # Check if there are files with the same name in the folder
+ nr_doc_same <- sum(
+ grepl(pattern = paste0("^", basename(output_file),
+ "[_\\d]*\\.", output_form_ext),
+ x = list.files(checkdir),
+ perl = TRUE))
+
+ # If yes, add number to file
+ if (nr_doc_same > 0L) {
+ nr_suffix <- nr_doc_same + 1L
+ output_file <- paste0(output_file, "_", nr_suffix)
+ }
+
+ # Make parameters ####
+ params2 <- list(
+ app_doc = app_doc,
+ preamb = preamb,
+ include_cons = include_cons,
+ title = title,
+ date = date,
+ subtitle = subtitle,
+ encoding = encoding,
+ combined_codebook = combined_codebook,
+ splitvarname = splitvarname,
+ sep_list = sep_list,
+ initial = initial)
+
+ if (!is.null(params)) {
+
+ if (is.list(params)) {
+ params <- utils::modifyList(params2, params)
- # If yes, add number to file
- if (nr_doc_same > 0L) {
- nr_suffix <- nr_doc_same + 1L
- output_file <- paste0(output_file, "_", nr_suffix)
}
+ } else {
+ params <- params2
+ }
- # Make parameters ####
- params2 <- list(
- app_doc = app_doc,
- preamb = preamb,
- include_cons = include_cons,
- title = title,
- date = date,
- subtitle = subtitle,
- encoding = encoding)
+ if (!is.null(params[["date"]]) && params[["date"]] == "today") {
+ params[["date"]] <- format(Sys.time(), "%d %B %Y")
+ }
- if (!is.null(params)) {
+ # Make output ####
- if (is.list(params)) {
+ # Specify output_format
+ output_format2 <- output_format
+ output_options <- NULL
- params <- utils::modifyList(params2, params)
+ pdflist <- list(pdf = FALSE)
+ latexengine <- list(latex_engine = NA)
- } else {
- stop("params must be a list!")
- }
- } else {
- params <- params2
- }
+ if (output_format2 == "pdf_document") {
- if (!is.null(params[["date"]]) && params[["date"]] == "today") {
- params[["date"]] <- format(Sys.time(), "%d %B %Y")
- }
+ # Xelatex better for multilingual documents
+ output_format2 <- rmarkdown::pdf_document(
+ latex_engine = "xelatex",
+ md_extensions = "-smart")
- # Make output ####
- tryCatch({
+ pdflist <- list(pdf = TRUE)
+ latexengine <- list(latex_engine = "xelatex")
- # Specify output_format
- if (output_format == "pdf_document") {
- output_format <- rmarkdown::pdf_document(latex_engine = "xelatex")
- }
+ # Count longest variable value
+ maxlen <- 0L
- # Don't use output_dir here,
- # because that's already included in file name!
- created_file <- rmarkdown::render(
- input = system.file("rmd", "codebook.Rmd", package = "gmoTree"),
- output_format = output_format,
- output_file = output_file,
- params = params,
- clean = TRUE # Encoding is ignored here! Always UTF-8
- )
+ for (folder in names(combined_codebook)) {
+
+ if (folder != "settings" && folder != "user_settings") {
+
+ for (class in names(combined_codebook[[folder]])) {
+
+ if (class != "doc" &&
+ !is.null(combined_codebook[[folder]][[class]])) {
+
+ for (variable in
+ names(combined_codebook[[folder]][[class]])) {
- # Open
- created_file <- normalizePath(created_file)
+ if ((class == "Player" || class == "Group") &&
+ "choices" %in% names(combined_codebook[[folder]][[class]][[variable]])) {
- if (output_open) {
- utils::browseURL(created_file)
+ lenofval <-
+ length(
+ combined_codebook[[folder]][[class]][[variable]][["choices"]])
+
+ maxlen <- pmax(lenofval, maxlen)
+
+ } else if (class == "Constants") {
+
+ lenofval <-
+ length(
+ combined_codebook[[folder]][[class]][[variable]])
+
+ maxlen <- pmax(lenofval, maxlen)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ # Check for many variable values
+ if (maxlen > 20L) {
+ # 20 is tested on my computer. There might be better solutions!
+ warning("One of your variables has many values ",
+ "(no of values/sublists = ",
+ maxlen,
+ ") and may cause serious problems in the PDF output! ",
+ "(Some PDF viewers such as NITRO might struggle with it.) ",
+ "If you experience any problems, use \"output_format = ",
+ "pdf_document_simple\", first knit to Latex, or open ",
+ "and save again with a PDF reader that can handle ",
+ "long table cells. ")
}
- message("File saved in ", created_file)
- }, error = function(e) {
- message("Error in rmarkdown::render: ", e$message)
- })
+ } else if (output_format2 == "pdf_document_simple") {
+ output_format2 <- rmarkdown::pdf_document(
+ md_extensions = "-smart")
+
+ pdflist <- list(pdf = TRUE)
+ latexengine <- list(latex_engine = "pdflatex")
+
+ } else if (output_format2 == "html_document") {
+ output_format2 <- rmarkdown::html_document(md_extensions = "-smart")
+ pdflist <- list(pdf = FALSE)
+
+ } else if (output_format2 == "latex_document") {
+ output_format2 <- rmarkdown::latex_document(
+ md_extensions = "-smart")
+
+ pdflist <- list(pdf = TRUE)
+ latexengine <- list(latex_engine = "")
+
+ } else {
+ pdflist <- list(pdf = FALSE)
+ latexengine <- list(latex_engine = NA)
+ }
+
+ params <- utils::modifyList(pdflist, params)
+ params <- utils::modifyList(latexengine, params)
+
+ # Render file
+ # Don't use output_dir here,
+ # because that's already included in file name!
+
+ created_file <- rmarkdown::render(
+ input = system.file("rmd", "codebook.Rmd", package = "gmoTree"),
+ output_format = output_format2,
+ output_file = output_file,
+ params = params,
+ quiet = FALSE,
+ output_options = output_options,
+ clean = TRUE # Encoding is ignored here! Always UTF-8
+ )
+
+ # Open
+ created_file <- normalizePath(created_file)
+
+ if (output_open) {
+ utils::browseURL(created_file)
+ }
+ message("File saved in ", created_file)
}
# Message: Variables with no documentation info ####
@@ -1875,14 +2279,14 @@ codebook <- function(path = ".",
}
} else {
- # Check if the element is a character string containing "float"
+ # Add the current path to the list if "float" is found
if (length(codebook) == 1L &&
is.character(codebook) &&
grepl("float(?!Field)",
codebook,
ignore.case = TRUE,
perl = TRUE)) {
- # Add the current path to the list if "float" is found
+
collected_paths <- c(collected_paths, path)
}
}
@@ -1899,41 +2303,64 @@ codebook <- function(path = ".",
env$complexcons <- c(env$complexcons, complex2)
- # Show warning if there is complex code in Constants, Player, Group or settings
+ # Show warning if there is complex code in Constants,
+ # Player, Group or settings
if (length(env$complexcons) > 0L) {
env$warnings <-
c(env$warnings,
- paste0("Some variables or code parts contain code that is too complex for this function. ",
+ paste0("Some variables or code parts contain code that ",
+ "is too complex for this function. ",
"Hence, this function might have overseen ",
"important variables and references to them. ",
- "Check the output carefully! Found in:\n",
+ "Found in:\n",
paste(env$complexcons, collapse = "")))
}
# Return warnings ####
- if (length(env$settingslist) > 0) {
- if (env$settingspy == TRUE) {
+ # Warning message regarding global settings variables
+ if (length(env$settingslist) > 0L &&
+ !is.null(settings_replace) &&
+ settings_replace == "global") {
+
+ if (env$settingspy) {
env$warnings <-
c(env$warnings,
- paste0("The following settings variable/s is/are not in settings and ",
+ paste0("The following settings variable/s is/are ",
+ "not in settings and ",
"cannot be replaced:\n",
- env$settingslist))
+ paste0(env$settingslist, collapse = "")))
} else {
env$warnings <-
c(env$warnings, paste0("There is no settings.py in your path! ",
"The following settings variable/s is/are not in settings and ",
- "cannot be replaced:\n ",
- env$settingslist))
+ "cannot be replaced:\n",
+ paste0(env$settingslist, collapse = "")))
}
}
- if (length(env$warnings) > 0) {
+ # Warning message regarding user settings variables
+ if (length(env$usettingslist) > 0L &&
+ !is.null(settings_replace) &&
+ settings_replace == "user") {
+
+ env$warnings <-
+ c(env$warnings,
+ paste0("The following settings variable/s is/are ",
+ "not in user_settings and ",
+ "cannot be replaced:\n",
+ paste0(env$usettingslist, collapse = "")))
+
+ }
+
+ if (length(env$warnings) > 0L) {
env$warnings <- paste(env$warnings, collapse = "\n\n")
warning(env$warnings)
}
+
# Return list ####
+
if (output == "list" || output == "both") {
return(combined_codebook)
}
diff --git a/R/delete_cases.R b/R/delete_cases.R
index 9e82582..b16d942 100644
--- a/R/delete_cases.R
+++ b/R/delete_cases.R
@@ -138,11 +138,13 @@ delete_cases <- function(oTree,
omit = FALSE,
info = FALSE) {
+
+ env <- new.env(parent = emptyenv())
+ env$messed_message <- character(0L)
+ env$chat_messed <- FALSE
+ env$time_messed <- FALSE
all_deleted <- character(0L)
deletion_frame <- data.frame()
- time_messed <- FALSE
- chat_messed <- FALSE
- messed_message <- character(0L)
# Create list of apps ####
appnames <- names(oTree)
@@ -164,8 +166,8 @@ delete_cases <- function(oTree,
tryCatch({
messy_time(oTree, combine = FALSE)
}, error = function(e) {
- time_messed <<- TRUE
- messed_message <<- paste0("Please run messy_time() with the argument ",
+ env$time_messed <- TRUE
+ env$messed_message <- paste0("Please run messy_time() with the argument ",
"combine=TRUE before running this function.")
})
@@ -173,19 +175,19 @@ delete_cases <- function(oTree,
tryCatch({
messy_chat(oTree, combine = FALSE)
}, error = function(e) {
- chat_messed <<- TRUE
+ env$chat_messed <- TRUE
- if (time_messed) {
+ if (env$time_messed) {
# Combine messy chat message with messy time message
- messed_message <<-
- paste0(messed_message,
+ env$messed_message <-
+ paste0(env$messed_message,
" AND: Please run messy_chat() with the argument ",
"combine=TRUE before running this function.")
} else {
# Make messy chat message
- messed_message <<-
+ env$messed_message <-
paste0("Please run messy_chat() with the argument ",
"combine=TRUE before running this function.")
}
@@ -193,9 +195,9 @@ delete_cases <- function(oTree,
# Stop if messy time and/or chat variables should not be merged
- if (time_messed || chat_messed) {
+ if (env$time_messed || env$chat_messed) {
stop("You combined data from old and new oTree versions. ",
- messed_message)
+ env$messed_message)
}
# Warnings ####
@@ -217,7 +219,7 @@ delete_cases <- function(oTree,
}
if (!(is.null(saved_vars)) &&
- any(!(saved_vars %in% colnames(oTree$all_apps_wide)))) {
+ !all(saved_vars %in% colnames(oTree$all_apps_wide))) {
stop("saved_vars not in \"all_apps_wide\" data frame!")
}
diff --git a/R/delete_sessions.R b/R/delete_sessions.R
index bd050fb..95aafa3 100644
--- a/R/delete_sessions.R
+++ b/R/delete_sessions.R
@@ -113,10 +113,14 @@ delete_sessions <- function(oTree,
messages <- character(0L)
deleted_participants <- character(0L)
deletion_frame <- data.frame()
- time_messed <- FALSE
- chat_messed <- FALSE
- messed_message <- character(0L)
+
+ env <- new.env(parent = emptyenv())
+ env$messed_message <- character(0L)
+ env$time_messed <- FALSE
+ env$chat_messed <- FALSE
+
+
# Create list of apps ####
appnames <- names(oTree)
appnames <- appnames[appnames != "info"]
@@ -137,8 +141,8 @@ delete_sessions <- function(oTree,
tryCatch({
messy_time(oTree, combine = FALSE)
}, error = function(e) {
- time_messed <<- TRUE
- messed_message <<- paste0("Please run messy_time() with the argument ",
+ env$time_messed <- TRUE
+ env$messed_message <- paste0("Please run messy_time() with the argument ",
"combine=TRUE before running this function.")
})
@@ -146,23 +150,23 @@ delete_sessions <- function(oTree,
tryCatch({
messy_chat(oTree, combine = FALSE)
}, error = function(e) {
- chat_messed <<- TRUE
+ env$chat_messed <- TRUE
- if (time_messed) {
- messed_message <<-
- paste0(messed_message,
+ if (env$time_messed) {
+ env$messed_message <-
+ paste0(env$messed_message,
" AND: Please run messy_chat() with the argument ",
"combine=TRUE before running this function.")
} else {
- messed_message <<-
+ env$messed_message <-
paste0("Please run messy_chat() with the argument ",
"combine=TRUE before running this function.")
}
})
- if (time_messed || chat_messed) {
+ if (env$time_messed || env$chat_messed) {
stop("You combined data from old and new oTree versions. ",
- messed_message)
+ env$messed_message)
}
# Set background function: chat function ####
diff --git a/R/extime.R b/R/extime.R
index 6438b88..43384a1 100644
--- a/R/extime.R
+++ b/R/extime.R
@@ -293,15 +293,14 @@ extime <- function(
# Seconds ####
if (seconds) {
- divsec <- 1
+ divsec <- 1L
} else {
- divsec <- 60 # Divide seconds by 60 to get minutes
+ divsec <- 60L # Divide seconds by 60 to get minutes
}
# Transform plabel to pcode identifier ####
if (!is.null(plabel)) {
- if (length(unique(oTree$all_apps_wide$participant.label)) ==
- length(oTree$all_apps_wide$participant.label)) {
+ if (anyDuplicated(oTree$all_apps_wide$participant.label) == 0L) {
pcode <- oTree$all_apps_wide$participant.code[
oTree$all_apps_wide$participant.label == plabel]
diff --git a/R/make_ids.R b/R/make_ids.R
index e43128b..4b565b2 100644
--- a/R/make_ids.R
+++ b/R/make_ids.R
@@ -88,10 +88,11 @@ make_ids <- function(oTree,
emptyrows = NULL,
icw = FALSE) {
- my_warnings <- character(0L)
- time_messed <- FALSE
- chat_messed <- FALSE
- messed_message <- character(0L)
+ env <- new.env(parent = emptyenv())
+ env$time_messed <- FALSE
+ env$chat_messed <- FALSE
+ env$messed_message <- character(0L)
+ env$my_warnings <- character(0L)
# Before start: Error messages ####
if (from_app %in% c("info", "Chats", "Time")) {
@@ -121,13 +122,12 @@ make_ids <- function(oTree,
stop("Please only use from_app (all except all_apps_wide) ",
"or from_var!")
- } else if (from_app == "all_apps_wide") {
- if (is.null(oTree[[from_app]][[from_var]])) {
+ } else if (from_app == "all_apps_wide" && is.null(oTree[[from_app]][[from_var]])) {
stop("from_var \"",
- from_var,
- "\" not found. ",
- "Please select another one.")
- }
+ from_var,
+ "\" not found. ",
+ "Please select another one.")
+
}
# gmake should be automatically TRUE if from_var is set
@@ -147,8 +147,8 @@ make_ids <- function(oTree,
tryCatch({
messy_time(oTree, combine = FALSE)
}, error = function(e) {
- time_messed <<- TRUE
- messed_message <<- paste0("Please run messy_time() with the argument ",
+ env$time_messed <- TRUE
+ env$messed_message <- paste0("Please run messy_time() with the argument ",
"combine=TRUE before running this function.")
})
@@ -156,28 +156,28 @@ make_ids <- function(oTree,
tryCatch({
messy_chat(oTree, combine = FALSE)
}, error = function(e) {
- chat_messed <<- TRUE
+ env$chat_messed <- TRUE
- if (time_messed) {
+ if (env$time_messed) {
# Combine messy chat message with messy time message
- messed_message <<-
- paste0(messed_message,
+ env$messed_message <<-
+ paste0(env$messed_message,
" AND: Run messy_chat() with the argument ",
"combine=TRUE before running this function!")
} else {
# Make messy chat message
- messed_message <<-
+ env$messed_message <<-
paste0("Run messy_chat() with the argument ",
"combine=TRUE before running this function!")
}
})
# Stop if messy time and/or chat variables should not be merged
- if (time_messed || chat_messed) {
+ if (env$time_messed || env$chat_messed) {
stop("You combined data from old and new oTree versions. ",
- messed_message)
+ env$messed_message)
}
# Check for NAs in the relevant variables
@@ -203,26 +203,26 @@ make_ids <- function(oTree,
if (length(oTree[[from_app]]$participant.code) !=
length(unique(oTree[[from_app]]$participant.code))) {
- stop(paste0(
+ stop(
from_app,
": The length of participant codes is not equal the length of ",
"unique participant codes. Please check your data for ",
"duplicates or empty rows! ",
"(Advice: You may use delete_duplicate() to ",
- "remove duplicate rows of all oTree data frames."))
+ "remove duplicate rows of all oTree data frames.")
}
} else {
if (length(unique(oTree[[from_app]]$participant.code)) !=
length(oTree[[from_app]]$participant.code) /
max(oTree[[from_app]]$subsession.round_number)) {
- stop(paste0(
+ stop(
from_app,
": The length of participant codes is not equal the length of ",
"unique participant codes. Please check your data for ",
"duplicates or empty rows! ",
"(Advice: You may use delete_duplicate() to ",
- "remove duplicate rows of all oTree data frames."))
+ "remove duplicate rows of all oTree data frames.")
}
}
@@ -244,25 +244,25 @@ make_ids <- function(oTree,
)) {
if (length(unique(oTree$Chats$participant_code[
- oTree$Chats$session_code == code])) == 1) {
+ oTree$Chats$session_code == code])) == 1L) {
- if (icw == FALSE) {
+ if (!icw) {
stop(messymessage)
}
} else if (length(unique(
oTree$Chats$participant__code[
- oTree$Chats$session__code == code])) == 1) {
+ oTree$Chats$session__code == code])) == 1L) {
- if (icw == FALSE) {
+ if (!icw) {
stop(messymessage) # Can this even happen?
}
} else if (length(unique(
oTree$Chats$participant__code[
- oTree$Chats$participant__session__code == code])) == 1) {
+ oTree$Chats$participant__session__code == code])) == 1L) {
- if (icw == FALSE) {
+ if (!icw) {
stop(messymessage) # Can this even happen?
}
}
@@ -270,19 +270,19 @@ make_ids <- function(oTree,
# Check if group numbers are the same in all variables
# if app and round is not specified
- if (gmake == TRUE &&
+ if (gmake &&
from_app == "all_apps_wide" &&
is.null(from_var)) {
checkdata <- oTree[[from_app]][, endsWith(names(oTree[[from_app]]),
"group.id_in_subsession")]
- if (ncol(checkdata) == 0) {
+ if (ncol(checkdata) == 0L) {
stop("No variable that ends with \"group.id_in_subsession\"")
}
if (inherits(checkdata, "data.frame") &&
- !(all(checkdata == checkdata[, 1]))) {
+ !(all(checkdata == checkdata[, 1L]))) {
# Not all the same
stop(
"group_id can not be calculated. ",
@@ -319,10 +319,10 @@ make_ids <- function(oTree,
data.table::rleidv(oTree[[from_app]]$GroupSessionID)
oTree[[from_app]]$group_id <-
- oTree[[from_app]]$group_id + (gstart - 1)
+ oTree[[from_app]]$group_id + (gstart - 1L)
- if (length(unique(oTree[[from_app]][[from_var]])) == 1) {
- my_warnings <<- c(my_warnings, paste0(
+ if (length(unique(oTree[[from_app]][[from_var]])) == 1L) {
+ env$my_warnings <<- c(env$my_warnings, paste0(
"The group variable values are constant. ",
"Group IDs now correspond to session IDs."))
}
@@ -340,15 +340,15 @@ make_ids <- function(oTree,
all_group_ids <- oTree[[from_app]][, grep("group.id_in_subsession",
colnames(oTree[[from_app]]))]
- if (inherits(all_group_ids, "data.frame") == TRUE &&
- ncol(all_group_ids) > 0) {
+ if (inherits(all_group_ids, "data.frame") &&
+ ncol(all_group_ids) > 0L) {
# Make a helping variable GroupSessionID
- oTree <- group_session_id_df(oTree)
+ oTree <- group_session_id_df(oTree, env = env)
} else {
# Make a helping variable GroupSessionID
- oTree <- group_session_id_vector(oTree)
+ oTree <- group_session_id_vector(oTree, env = env)
}
# 2) Arrange group numbers, too (I took the first occurrence)
@@ -359,12 +359,12 @@ make_ids <- function(oTree,
# 3) Assign session wide group number
oTree[[from_app]]$group_id <-
- data.table::rleidv(oTree[[from_app]]$GroupSessionID) + (gstart - 1)
+ data.table::rleidv(oTree[[from_app]]$GroupSessionID) + (gstart - 1L)
return(oTree)
}
- group_session_id_df <- function(oTree) {
+ group_session_id_df <- function(oTree, env) {
# Here several variables are called group.id_in_subsession.
# Take the first one.
@@ -373,14 +373,14 @@ make_ids <- function(oTree,
paste(
oTree[[from_app]]$session_id,
oTree[[from_app]][, grep("group.id_in_subsession",
- colnames(oTree[[from_app]]))][, 1])
+ colnames(oTree[[from_app]]))][, 1L])
if (length(
unique(oTree[[from_app]][,
grep("group.id_in_subsession",
- colnames(oTree[[from_app]]))][, 1])) == 1) {
+ colnames(oTree[[from_app]]))][, 1L])) == 1L) {
- my_warnings <<- c(my_warnings, paste0(
+ env$my_warnings <<- c(env$my_warnings, paste0(
"The group variable values (of the first group variable) ",
"are constant. ",
"Group IDs now correspond to session IDs."))
@@ -388,7 +388,7 @@ make_ids <- function(oTree,
return(oTree)
}
- group_session_id_vector <- function(oTree) {
+ group_session_id_vector <- function(oTree, env) {
# Here only one variable is called group.id_in_subsession
# Add session ID so there are no group IDs twice
@@ -402,7 +402,7 @@ make_ids <- function(oTree,
unique(oTree[[from_app]][, grep("group.id_in_subsession",
colnames(oTree[[from_app]]))])) == 1L) {
- my_warnings <<- c(my_warnings, paste0(
+ env$my_warnings <<- c(env$my_warnings, paste0(
"The group variable values are constant. ",
"Group IDs now correspond to session IDs."))
}
@@ -550,8 +550,8 @@ make_ids <- function(oTree,
# This part is usually called if session.code is NA
# This does not happen with cleaned data
if (anyNA(oTree[[from_app]]$session.code)) {
- my_warnings <-
- c(my_warnings,
+ env$my_warnings <-
+ c(env$my_warnings,
(paste0("At least one of your session.codes in your from_app is ",
"NA. All session codes that are Na are ",
"handled as being the same ",
@@ -571,7 +571,7 @@ make_ids <- function(oTree,
# Make session_id
oTree[[from_app]]$session_id <-
- data.table::rleid(oTree[[from_app]]$session.code) + (sstart - 1)
+ data.table::rleid(oTree[[from_app]]$session.code) + (sstart - 1L)
# Delete variable again
oTree[[from_app]]$participant.time_started_min <- NULL
@@ -620,7 +620,7 @@ make_ids <- function(oTree,
# Make participant_id
oTree[[from_app]]$participant_id <-
data.table::rleidv(oTree[[from_app]]$participant.code) +
- (pstart - 1)
+ (pstart - 1L)
} else {
stop("There is no participant.code in ",
@@ -631,7 +631,7 @@ make_ids <- function(oTree,
# Step 4: Make info lists ####
listincluded <- c("session_id", "session.code", "participant.code")
- oTree[["info"]][["additional_variables"]] <- c("session_id")
+ oTree[["info"]][["additional_variables"]] <- "session_id"
if (group_size_info) {
@@ -672,7 +672,7 @@ make_ids <- function(oTree,
oTree[[from_app]]$participant.code)])
if (length(participants_more) > 0L) {
- my_warnings <- c(my_warnings,
+ env$my_warnings <- c(env$my_warnings,
paste0("Data frame \"",
names(oTree)[[i]],
"\" has more participants than ",
@@ -692,7 +692,7 @@ make_ids <- function(oTree,
oTree[[from_app]]$participant.code)])
if (length(participants_more) > 0L) {
- my_warnings <- c(my_warnings,
+ env$my_warnings <- c(env$my_warnings,
paste0("Data frame \"",
names(oTree)[[i]],
"\" has more participants than ",
@@ -713,7 +713,7 @@ make_ids <- function(oTree,
participants_more <- unique(participants_more)
if (length(participants_more) > 0L) {
- my_warnings <- c(my_warnings,
+ env$my_warnings <- c(env$my_warnings,
paste0("Data frame \"", names(oTree)[[i]],
"\" has more participants than ",
from_app, ": ",
@@ -724,8 +724,8 @@ make_ids <- function(oTree,
oTree <- ids_in_old_time_apps(oTree, df_group_in_date, i)
} else {
- my_warnings <-
- c(my_warnings,
+ env$my_warnings <-
+ c(env$my_warnings,
paste0("Participant code variable couldn't be found in \"",
name_of_app,
"\"! No IDs are calculated for this data frame."))
@@ -734,10 +734,10 @@ make_ids <- function(oTree,
# Reorder columns ####
j <- 0L
if (pmake) {
- j <- j + 1
+ j <- j + 1L
}
if (group_size_info) {
- j <- j + 1
+ j <- j + 1L
}
oTree[[i]] <-
oTree[[i]][, c(c((ncol(oTree[[i]]) - j):ncol(oTree[[i]])),
@@ -755,8 +755,8 @@ make_ids <- function(oTree,
oTree[[from_app]]$initial_order <- NULL
# Print warnings ####
- if (length(my_warnings > 0)) {
- warning(paste(my_warnings, collapse = "\n"))
+ if (length(env$my_warnings) > 0L) {
+ warning(paste(env$my_warnings, collapse = "\n"))
}
return(oTree)
diff --git a/R/messy_time.R b/R/messy_time.R
index 1d5759f..2c680e9 100644
--- a/R/messy_time.R
+++ b/R/messy_time.R
@@ -12,8 +12,8 @@
#' @param oTree A list of data frames that were created
#' by \code{\link{import_otree}}.
#' @param combine Logical. \code{TRUE} if all variables referring to epoch time
-#' should be merged and/or all variables referring to participant code should be merged
-#' in case data of several versions of oTree are used.
+#' should be merged and/or all variables referring to participant code
+#' should be merged in case data of several versions of oTree are used.
#' @param epoch_time Logical. \code{TRUE} if all variables referring to the time
#' stamp should be checked and merged. Only works if \code{combine = TRUE}.
#' @param participant Logical. \code{TRUE} if all variables referring to the
diff --git a/R/oTree.R b/R/oTree.R
index 9515c79..c01c80a 100644
--- a/R/oTree.R
+++ b/R/oTree.R
@@ -1,4 +1,4 @@
-#' Sample experiment data
+#' Sample experimental data
#'
#' @docType data
#' @format A list of data frames created by import_otree().
diff --git a/R/pagesec.R b/R/pagesec.R
index edcc57a..0a588ab 100644
--- a/R/pagesec.R
+++ b/R/pagesec.R
@@ -118,7 +118,7 @@ pagesec <- function(
# Translate to minutes
if (minutes) {
- oTree$Time$minutes_on_page <- oTree$Time$seconds_on_page2 / 60
+ oTree$Time$minutes_on_page <- oTree$Time$seconds_on_page2 / 60L
if (rounded) {
oTree$Time$minutes_on_page <- round(oTree$Time$minutes_on_page,
diff --git a/R/show_dropouts.R b/R/show_dropouts.R
index 98ebac8..039b572 100644
--- a/R/show_dropouts.R
+++ b/R/show_dropouts.R
@@ -79,8 +79,8 @@ show_dropouts <- function(oTree,
final_pages = NULL,
saved_vars = NULL) {
- keep_these_participants <- c() # Is just here for the inconsistency test
- delete_these_participants <- c() # Not deleted here. Inconsistency check!
+ keep_these_participants <- character() # Just here for the inconsistency test
+ delete_these_participants <- character() # Not deleted here. #Inconsistency
dropout_data <- data.frame()
output <- list()
my_warnings <- list()
@@ -163,7 +163,7 @@ show_dropouts <- function(oTree,
delete_these_participants <- unique(delete_these_participants)
# Test if no one in "keep" is in "delete" ####
- newlist <- c()
+ newlist <- character()
for (element in keep_these_participants) {
if (element %in% delete_these_participants) {
newlist <- append(element, newlist)
diff --git a/build/vignette.rds b/build/vignette.rds
deleted file mode 100644
index 1c03b68..0000000
Binary files a/build/vignette.rds and /dev/null differ
diff --git a/cran-comments.md b/cran-comments.md
index e79e35a..435da6f 100644
--- a/cran-comments.md
+++ b/cran-comments.md
@@ -1,3 +1,7 @@
+# Version 1.3.0
+
+No comments.
+
# Version 1.2.0
```
diff --git a/docs/404.html b/docs/404.html
index 03bdbe6..0b8e823 100644
--- a/docs/404.html
+++ b/docs/404.html
@@ -14,8 +14,8 @@
-
-
+
+
@@ -28,7 +28,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -75,7 +75,7 @@
diff --git a/docs/articles/codebook.html b/docs/articles/codebook.html
index 3e92870..38d7ca6 100644
--- a/docs/articles/codebook.html
+++ b/docs/articles/codebook.html
@@ -14,8 +14,8 @@
-
-
+
+
@@ -27,7 +27,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -68,7 +68,7 @@ Patricia F.
Zauchner
2023-09-21 (updated:
-2024-09-30)
+2024-12-06)
Source: vignettes/codebook.Rmd
codebook.Rmd
@@ -83,9 +83,7 @@ OverviewoTree (Chen et al.,
2016) framework with the function codebook()
. This vignette
-introduces you to the key features and functionalities, including how to
-adjust titles, work with oTree data, and customize output formats for
-your codebooks.
+introduces its key features and functionalities.
Disclaimer: This code has been tested with both custom
implementations and official oTree sample codes.Skip to contents
@@ -7,7 +7,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -52,7 +52,7 @@ All vignettes
diff --git a/docs/articles/otreedata.png b/docs/articles/intro.png
similarity index 100%
rename from docs/articles/otreedata.png
rename to docs/articles/intro.png
diff --git a/docs/articles/intro_to_gmoTree.html b/docs/articles/intro_to_gmoTree.html
index 377de2f..5aef2d1 100644
--- a/docs/articles/intro_to_gmoTree.html
+++ b/docs/articles/intro_to_gmoTree.html
@@ -14,8 +14,8 @@
-
-
+
+
@@ -27,7 +27,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -153,15 +153,15 @@
output_open
-Logical. TRUE
if file output should be opened after creation.
+Logical. TRUE
if file output should
+be opened after creation.
app_doc
-Logical. TRUE
if app documentation should be included in
-output file.
+Logical. TRUE
if app documentation should be
+included in the output file.
app
Character. Name of the included app(s).
Default is to use all apps.
-This argument can not be used simultaneously as the argument app_rm
.
+Cannot be used simultaneously with app_rm
.
app_rm
Character. Name of the excluded app(s).
Default is to exclude no apps.
-This argument can not be used simultaneously as the argument app.
+Cannot be used simultaneously with app
.
doc_info
Logical. TRUE
if a message with information on all
-variables without documentation should also be returned.
+variables without documentation should also be returned. FALSE
if
+this message should be suppressed.
sort
-Character. Vector that specifies the order of
+
Character vector. Vector that specifies the order of
the apps in the codebook.
@@ -154,10 +168,11 @@ Arguments to replace references with the variables
provided in the user_settings
argument.
Use NULL
to leave references to settings variables unchanged.
-Caution: This function does not use variables defined in SESSION_CONFIGS
.
+Caution: This function does not use variables defined
+in SESSION_CONFIGS
.
If you vary settings variables in SESSION_CONFIGS
,
-set settings_replace
to "user"
and manually replace them using the
-user_settings
argument.
+set settings_replace
to "user"
and manually replace
+them using the user_
settings
argument.
user_settings
@@ -200,10 +215,29 @@ Argumentsdate
-Date that is passed to the Rmd file.
+
Character or NULL
. Date that is passed to the Rmd file.
Either "today"
, NULL
, or a user defined date.
Only relevant if argument output "file"
or "both"
if chosen.
+
+splitvarname
+Logical. TRUE
if long variable names should be
+split across multiple lines in the output file tables.
+If FALSE
, table columns should adjust to fit the longest
+variable names.
+
+
+sep_list
+Character. Determines how sub-lists are displayed
+in the file output. Use "newline"
to separate sub-lists with
+newline characters (`\n`), or "vector"
to display them as
+strings in `c(...)` format.
+
+
+initial
+Logical. TRUE
if initial values should be included
+in the output file. FALSE
if they should not be included.
+
@@ -255,7 +292,7 @@
Examples#> $ bertrand :List of 4
#> $ common_value_auction:List of 4
#> $ cournot :List of 4
-#> $ dictator :List of 3
+#> $ dictator :List of 4
#> $ guess_two_thirds :List of 4
#> $ matching_pennies :List of 4
#> $ payment_info :List of 4
@@ -281,7 +318,7 @@ Examples app = "bargaining" ,
doc_info = FALSE )
-# Show the structure of the codebook
+# Show the structure of the codebook
str ( combined_codebook , 1 )
#> List of 2
#> $ settings :List of 10
@@ -301,14 +338,14 @@ Examples app_rm = "bargaining" ,
doc_info = FALSE )
-# Show the structure of the codebook
+# Show the structure of the codebook
str ( combined_codebook , 1 )
#> List of 15
#> $ settings :List of 10
#> $ bertrand :List of 4
#> $ common_value_auction:List of 4
#> $ cournot :List of 4
-#> $ dictator :List of 3
+#> $ dictator :List of 4
#> $ guess_two_thirds :List of 4
#> $ matching_pennies :List of 4
#> $ payment_info :List of 4
@@ -327,13 +364,10 @@ Examples path = system.file ( "extdata/ocode_z" , package = "gmoTree" ) ,
fsource = "model" ,
output = "list" ,
- doc_info = TRUE )
-#> Variables without documentation, label, or verbose name:
-#> > rankaversion$Player$choicenumber
-#> > rankend$Player$done_distribution
-#> Warning: Some variables or code parts contain code that is too complex for this function. Hence, this function might have overseen important variables and references to them. Check the output carefully! Found in:
-#> > App rankaversion(Constants) (read_csv)
-#> > App rankend(Constants) (read_csv)
+ doc_info = FALSE )
+#> Warning: Some variables or code parts contain code that is too complex for this function. Hence, this function might have overseen important variables and references to them. Found in:
+#> > $rankaversion$Constants (read_csv)
+#> > $rankend$Constants (read_csv)
#> > $settings$showupToken (float)
#> > $end$Constants$showupToken (float)
#> > $end$Constants$showupTokenTest (float)
@@ -346,6 +380,30 @@ Examples#> $ rankaversion:List of 4
#> $ rankend :List of 4
+# Show information on missing documentation or complex code
+combined_codebook <- codebook (
+ path = system.file ( "extdata/ocode_new" , package = "gmoTree" ) ,
+ fsource = "init" ,
+ output = "list" ,
+ app_rm = "bargaining" ,
+ doc_info = TRUE )
+#> Variables without documentation, label, or verbose name:
+#> > $bertrand$Group$winning_price
+#> > $bertrand$Player$is_winner
+#> > $common_value_auction$Group$highest_bid
+#> > $cournot$Group$unit_price
+#> > $dictator$Player$gender
+#> > $guess_two_thirds$Group$two_thirds_avg
+#> > $guess_two_thirds$Group$best_guess
+#> > $guess_two_thirds$Group$num_winners
+#> > $guess_two_thirds$Player$is_winner
+#> > $matching_pennies$Player$is_winner
+#> > $public_goods_simple$Group$total_contribution
+#> > $public_goods_simple$Group$individual_share
+#> > $traveler_dilemma$Group$lower_claim
+#> > $traveler_dilemma$Player$adjustment
+#> > $volunteer_dilemma$Group$num_volunteers
+
if ( FALSE ) { # \dontrun{
# Create a codebook PDF with authors' names and todays' date
@@ -392,7 +450,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/delete_cases.html b/docs/reference/delete_cases.html
index e98f9c0..198d509 100644
--- a/docs/reference/delete_cases.html
+++ b/docs/reference/delete_cases.html
@@ -1,5 +1,5 @@
-Delete specific cases — delete_cases • gmoTree Delete specific cases — delete_cases • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -273,7 +273,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/delete_dropouts.html b/docs/reference/delete_dropouts.html
index 18c5e34..a10bf56 100644
--- a/docs/reference/delete_dropouts.html
+++ b/docs/reference/delete_dropouts.html
@@ -1,5 +1,5 @@
-Delete dropouts — delete_dropouts • gmoTree Delete dropouts — delete_dropouts • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -329,7 +329,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/delete_duplicate.html b/docs/reference/delete_duplicate.html
index 4955204..5332a4e 100644
--- a/docs/reference/delete_duplicate.html
+++ b/docs/reference/delete_duplicate.html
@@ -1,5 +1,5 @@
-Delete duplicate data — delete_duplicate • gmoTree Delete duplicate data — delete_duplicate • gmoTree
Skip to contents
@@ -9,7 +9,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -104,7 +104,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/delete_plabels.html b/docs/reference/delete_plabels.html
index 777745c..fe5adec 100644
--- a/docs/reference/delete_plabels.html
+++ b/docs/reference/delete_plabels.html
@@ -1,5 +1,5 @@
-Delete participant labels in all apps — delete_plabels • gmoTree Delete participant labels in all apps — delete_plabels • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -131,7 +131,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/delete_sessions.html b/docs/reference/delete_sessions.html
index b4d5be9..d6769fb 100644
--- a/docs/reference/delete_sessions.html
+++ b/docs/reference/delete_sessions.html
@@ -1,5 +1,5 @@
-Delete all cases of one session — delete_sessions • gmoTree Delete all cases of one session — delete_sessions • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -236,7 +236,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/extime.html b/docs/reference/extime.html
index 558a713..e0272b0 100644
--- a/docs/reference/extime.html
+++ b/docs/reference/extime.html
@@ -1,5 +1,5 @@
-Calculate the time that was spent on the whole experiment — extime • gmoTree Calculate the time that was spent on the whole experiment — extime • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -259,7 +259,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/import_otree.html b/docs/reference/import_otree.html
index 5ab45f8..2b6c2da 100644
--- a/docs/reference/import_otree.html
+++ b/docs/reference/import_otree.html
@@ -1,5 +1,5 @@
-Import oTree data — import_otree • gmoTree Import oTree data — import_otree • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -323,7 +323,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/index.html b/docs/reference/index.html
index 8610067..6f20106 100644
--- a/docs/reference/index.html
+++ b/docs/reference/index.html
@@ -1,5 +1,5 @@
-Package index • gmoTree
+Package index • gmoTree
Skip to contents
@@ -7,7 +7,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -135,7 +135,7 @@ All functionsoTree
- Sample experiment data
+ Sample experimental data
pagesec()
@@ -163,7 +163,7 @@ All functions
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/make_ids.html b/docs/reference/make_ids.html
index c89d38d..8c19d2c 100644
--- a/docs/reference/make_ids.html
+++ b/docs/reference/make_ids.html
@@ -1,5 +1,5 @@
-Make IDs — make_ids • gmoTree Make IDs — make_ids • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -201,7 +201,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/messy_chat.html b/docs/reference/messy_chat.html
index 8ec3d63..c193224 100644
--- a/docs/reference/messy_chat.html
+++ b/docs/reference/messy_chat.html
@@ -1,5 +1,5 @@
-Check if the Chats data frame is messy — messy_chat • gmoTree Check if the Chats data frame is messy — messy_chat • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -153,7 +153,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/messy_time.html b/docs/reference/messy_time.html
index 761403f..419a315 100644
--- a/docs/reference/messy_time.html
+++ b/docs/reference/messy_time.html
@@ -1,5 +1,5 @@
-Check if the Time data frame is messy — messy_time • gmoTree Check if the Time data frame is messy — messy_time • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -81,8 +81,8 @@ Argumentscombine
Logical. TRUE
if all variables referring to epoch time
-should be merged and/or all variables referring to participant code should be merged
-in case data of several versions of oTree are used.
+should be merged and/or all variables referring to participant code
+should be merged in case data of several versions of oTree are used.
epoch_time
@@ -157,7 +157,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/oTree.html b/docs/reference/oTree.html
index 88297a4..4eb3c21 100644
--- a/docs/reference/oTree.html
+++ b/docs/reference/oTree.html
@@ -1,5 +1,5 @@
-Sample experiment data — oTree • gmoTree
+Sample experimental data — oTree • gmoTree
Skip to contents
@@ -7,7 +7,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -32,13 +32,13 @@
-
Sample experiment data
+
Sample experimental data
@@ -67,7 +67,7 @@
Source <
diff --git a/docs/reference/pagesec.html b/docs/reference/pagesec.html
index c88b198..a361f08 100644
--- a/docs/reference/pagesec.html
+++ b/docs/reference/pagesec.html
@@ -1,5 +1,5 @@
-
Calculate the seconds spent on each page — pagesec • gmoTree Calculate the seconds spent on each page — pagesec • gmoTree
Skip to contents
@@ -9,7 +9,7 @@
gmoTree
-
1.2.0
+
1.3.0
@@ -200,7 +200,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/show_constant.html b/docs/reference/show_constant.html
index 4f95792..ebc5b46 100644
--- a/docs/reference/show_constant.html
+++ b/docs/reference/show_constant.html
@@ -1,5 +1,5 @@
-Show constant columns — show_constant • gmoTree Show constant columns — show_constant • gmoTree gmoTree
- 1.2.0
+ 1.3.0
@@ -216,7 +216,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/reference/show_dropouts.html b/docs/reference/show_dropouts.html
index e4ea5bb..d30069f 100644
--- a/docs/reference/show_dropouts.html
+++ b/docs/reference/show_dropouts.html
@@ -1,5 +1,5 @@
-Show participants who did not finish the experiment — show_dropouts • gmoTree Show participants who did not finish the experiment — show_dropouts • gmoTree
Skip to contents
@@ -9,7 +9,7 @@
gmoTree
- 1.2.0
+ 1.3.0
@@ -636,7 +636,7 @@ Examples
- Site built with pkgdown 2.1.0.
+ Site built with pkgdown 2.1.1.
diff --git a/docs/search.json b/docs/search.json
index 324291f..d4327cd 100644
--- a/docs/search.json
+++ b/docs/search.json
@@ -1 +1 @@
-[{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"overview","dir":"Articles","previous_headings":"","what":"Overview","title":"gmoTree Codebooks","text":"gmoTree package provides tools generating codebooks based data oTree (Chen et al., 2016) framework function codebook(). vignette introduces key features functionalities, including adjust titles, work oTree data, customize output formats codebooks. Disclaimer: code tested custom implementations official oTree sample codes.1 However, due complexity oTree setups, may address variations. Please review output carefully, feel free open GitHub issue encounter problems.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"running-the-code","dir":"Articles","previous_headings":"","what":"Running the code","title":"gmoTree Codebooks","text":"simplest form, function requires path oTree code. code reads contents oTree file, saves file containing codebook working directory, returns list named cbook, contains information list format.","code":"cbook <- codebook(system.file(path = \"extdata/ocode_new\", package = \"gmoTree\"))"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"codebook-structure-and-output","dir":"Articles","previous_headings":"","what":"Codebook structure and output","title":"gmoTree Codebooks","text":"output structured clear headings: Heading Level 1: Represents app oTree data. Heading Level 2: Group Player variables, categorized within app. Showing class Constants optional can turned using argument include_cons = FALSE. example showing output cournot app, includes Constants, Group, Player variables. class contains information, heading still appear, along message “Empty class.” default codebook design meet requirements, can either reference previously created cbook list bypass file creation setting output = \"list\". return information list format, can use R Markdown design custom codebook. example section list output cournot app. (argument doc_info = FALSE used omit messages missing variable documentation.)","code":"cbook <- codebook(path = system.file(path = \"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", doc_info = FALSE) print(cbook$cournot) ## $doc ## [1] \"In Cournot competition, firms simultaneously decide the units of products to manufacture. The unit selling price depends on the total units produced. In this implementation, there are 2 firms competing for 1 period.\" ## ## $Constants ## $Constants$NAME_IN_URL ## [1] \"cournot\" ## ## $Constants$PLAYERS_PER_GROUP ## [1] 2 ## ## $Constants$NUM_ROUNDS ## [1] 1 ## ## $Constants$TOTAL_CAPACITY ## [1] 60 ## ## $Constants$MAX_UNITS_PER_PLAYER ## [1] \"int(60 / 2)\" ## ## ## $Group ## $Group$unit_price ## $Group$unit_price$noargs ## [1] \"TRUE\" ## ## $Group$unit_price$field ## [1] \"CurrencyField\" ## ## ## $Group$total_units ## $Group$total_units$noargs ## [1] \"FALSE\" ## ## $Group$total_units$doc ## [1] \"Total units produced by all players\" ## ## $Group$total_units$field ## [1] \"IntegerField\" ## ## ## ## $Player ## $Player$units ## $Player$units$noargs ## [1] \"FALSE\" ## ## $Player$units$min ## [1] \"0\" ## ## $Player$units$max ## [1] \"int(60 / 2)\" ## ## $Player$units$doc ## [1] \"Quantity of units to produce\" ## ## $Player$units$label ## [1] \"How many units will you produce (from 0 to 30)?\" ## ## $Player$units$field ## [1] \"IntegerField\""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"apps","dir":"Articles","previous_headings":"Choosing what to show","what":"Apps","title":"gmoTree Codebooks","text":"generate codebook one app, use app argument. example, generate codebook cournot app: code returns list app-specific information. can also generate codebooks multiple apps specifying app argument. can also choose remove one apps. example removes app prisoner.","code":"cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app = \"cournot\") str(cbook) ## List of 2 ## $ settings:List of 10 ## ..$ variable : num 66 ## ..$ PARTICIPANT_FIELDS : chr \"[]\" ## ..$ SESSION_FIELDS : chr \"[]\" ## ..$ LANGUAGE_CODE : chr \"en\" ## ..$ REAL_WORLD_CURRENCY_CODE: chr \"USD\" ## ..$ USE_POINTS : chr \"True\" ## ..$ ADMIN_USERNAME : chr \"admin\" ## ..$ ADMIN_PASSWORD : chr \"environ.get('OTREE_ADMIN_PASSWORD')\" ## ..$ DEMO_PAGE_INTRO_HTML : chr \"\\\"\\\"\\\"Here are some oTree games.\\\"\\\"\\\"\" ## ..$ SECRET_KEY : chr \"9356668094877\" ## $ cournot :List of 4 ## ..$ doc : chr \"In Cournot competition, firms simultaneously decide the units of products to manufacture. The unit selling pric\"| __truncated__ ## ..$ Constants:List of 5 ## .. ..$ NAME_IN_URL : chr \"cournot\" ## .. ..$ PLAYERS_PER_GROUP : num 2 ## .. ..$ NUM_ROUNDS : num 1 ## .. ..$ TOTAL_CAPACITY : num 60 ## .. ..$ MAX_UNITS_PER_PLAYER: chr \"int(60 / 2)\" ## ..$ Group :List of 2 ## .. ..$ unit_price :List of 2 ## .. .. ..$ noargs: chr \"TRUE\" ## .. .. ..$ field : chr \"CurrencyField\" ## .. ..$ total_units:List of 3 ## .. .. ..$ noargs: chr \"FALSE\" ## .. .. ..$ doc : chr \"Total units produced by all players\" ## .. .. ..$ field : chr \"IntegerField\" ## ..$ Player :List of 1 ## .. ..$ units:List of 6 ## .. .. ..$ noargs: chr \"FALSE\" ## .. .. ..$ min : chr \"0\" ## .. .. ..$ max : chr \"int(60 / 2)\" ## .. .. ..$ doc : chr \"Quantity of units to produce\" ## .. .. ..$ label : chr \"How many units will you produce (from 0 to 30)?\" ## .. .. ..$ field : chr \"IntegerField\" cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app = c(\"cournot\", \"dictator\")) str(cbook, 1) ## List of 3 ## $ settings:List of 10 ## $ cournot :List of 4 ## $ dictator:List of 3 cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app_rm = \"prisoner\") str(cbook, 1) ## List of 15 ## $ settings :List of 10 ## $ bargaining :List of 4 ## $ bertrand :List of 4 ## $ common_value_auction:List of 4 ## $ cournot :List of 4 ## $ dictator :List of 3 ## $ guess_two_thirds :List of 4 ## $ matching_pennies :List of 4 ## $ payment_info :List of 4 ## $ public_goods_simple :List of 3 ## $ survey :List of 3 ## $ traveler_dilemma :List of 4 ## $ trust :List of 3 ## $ trust_simple :List of 3 ## $ volunteer_dilemma :List of 4"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"otree-data-description","dir":"Articles","previous_headings":"Choosing what to show","what":"oTree data description","title":"gmoTree Codebooks","text":"setting preamb = TRUE parameter, predefined description oTree data inserted beginning codebook, explaining experimental data stored oTree.","code":""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"customizing-the-codebook-titles-and-metadata","dir":"Articles","previous_headings":"Customizing how the codebook is shown","what":"Customizing the codebook titles and metadata","title":"gmoTree Codebooks","text":"can easily modify titles, subtitles, dates, author names codebooks using following arguments:","code":"codebook( path = \"YouroTreePath\", # Can be either absolute or releative! title = \"Codebook\", subtitle = \"Example Project\", date = \"today\", params = list(author = c(\"Max Mustermann\", \"John Doe\")) )"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"sorting-the-code","dir":"Articles","previous_headings":"Customizing how the codebook is shown","what":"Sorting the code","title":"gmoTree Codebooks","text":"can sort apps codebook specifying sort argument. example:","code":"cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app = c(\"cournot\", \"dictator\"), sort = c(\"dictator\", \"cournot\")) str(cbook, 1) ## List of 3 ## $ settings:List of 10 ## $ dictator:List of 3 ## $ cournot :List of 4"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"referring-to-settings","dir":"Articles","previous_headings":"Customizing how the codebook is shown","what":"Referring to settings","title":"gmoTree Codebooks","text":"gmoTree package can automatically replace references variables settings.py values settings.py file. However, can also choose replace using settings_replace = NULL: also possible provide list variables replace settings variables:","code":"cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", settings_replace = \"global\", app = \"dictator\") print(cbook$dictator$Constants$Variable) ## [1] 66 cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", settings_replace = NULL, app = \"dictator\") print(cbook$dictator$Constants$Variable) ## [1] \"settings.variable\" cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", settings_replace = \"user\", user_settings = list(variable = \"someValue\"), app = \"dictator\") print(cbook$dictator$Constants$Variable) ## [1] \"someValue\""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"saving-your-codebook","dir":"Articles","previous_headings":"","what":"Saving your codebook","title":"gmoTree Codebooks","text":"choose output = \"file\" output = \"\", codebook saved professional document ready publication sharing. argument output_format allows choose format exported codebook file. Available formats : pdf_document html_document word_document latex_document odt_document rtf_document md_document can choose format best suits needs, formats except PDF offering easy post-generation editing. default, gmoTree codebooks saved working directory default file name codebook. can modify specifying custom file name directory path. example, save codebook different name, use following code: can also include file extension, though optional: can save file subfolder within current directory including absolute relative folder name output_file argument. example: However, can also specify absolute paths, either output_dir argument directly within file name specified output_file. example:","code":"codebook( path = \"C:/Users/username/Nextcloud/oTree\", # Replace! output_file = \"gmoTree_codebook\") codebook( path = \"C:/Users/username/Nextcloud/oTree\", # Replace! output_file = \"gmoTree_codebook.pdf\") codebook( path = \"C:/Users/username/Nextcloud/oTree\", # Replace! output_file = \"codebookfiles/gmoTree_codebook.pdf\") codebook( path = \"C:/Users/username/Nextcloud/oTree\", # Replace! output_dir = \"C:/Users/username/Nextcloud/codebooks\", output_file = \"mycodebook\")"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"summary","dir":"Articles","previous_headings":"","what":"Summary","title":"gmoTree Codebooks","text":"vignette covers customize codebook generated codebook() function, including options selecting content, formatting presentation, exporting various formats. tools enable creation comprehensive tailored documentation experimental data.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"references","dir":"Articles","previous_headings":"","what":"References","title":"gmoTree Codebooks","text":"Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—open-source platform laboratory, online, field experiments. Journal Behavioral Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001","code":""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"background-information-on-the-data-downloaded-by-otree","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"Background information on the data downloaded by oTree","title":"Introduction to gmoTree","text":"oTree experiment structured around one modular units called “apps,” encompass one multiple “pages.” Data generated app can downloaded individually, offering flexibility analyze separate components experiment. -encompassing view experiment, data apps can also downloaded comprehensive file labeled “all_apps_wide.” addition aforementioned app data cumulative all_apps_wide file, oTree generates file time stamps every page. file documenting chat interactions also provided experiment includes one multiple chat rooms. newer oTree versions, also custom data can downloaded. oTree experiment run across different databases, set data files downloaded database. include individual app data files, all_apps_wide file, file time stamps every page, chat log file chat room used experiment. gmoTree package’s functionality lies ability load aggregate files ease.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"import_otree","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"import_otree()","title":"Introduction to gmoTree","text":"can import oTree data combine list data frames using import_otree() function. data frame named according associated app, function generates accompanying info list details essential information regarding imported files, deleted cases. information list updated use functions within package. worth noting even use one all_apps_wide file, still load data import_otree() want access functions within gmoTree package. Alternatively, reproduce structure created function hand. following example shows import oTree data, structure oTree list data frames importing data, information provided oTree$info. Caution: function works oTree data saved using typical oTree file pattern!","code":"# Get path to the package data path <- system.file(\"extdata/exp_data_5.4.0\", package = \"gmoTree\") # Import without specifications # Import all oTree files in this folder and its subfolders otree <- import_otree(path = path) ## Warning in import_otree(path = path): You have stored all_apps_wide globally ## but also room-specific. This function will import both of them. (Globally, the ## files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All ## apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing ## is there twice! (Advice: You may use delete_duplicate() to remove duplicate ## rows of all oTree data frames. # Check the structure of the oTree list of data frames str(otree, 1) ## List of 8 ## $ all_apps_wide:'data.frame': 12 obs. of 60 variables: ## $ info :List of 2 ## $ chatapp :'data.frame': 8 obs. of 24 variables: ## $ dictator :'data.frame': 48 obs. of 25 variables: ## $ start :'data.frame': 8 obs. of 24 variables: ## $ survey :'data.frame': 8 obs. of 29 variables: ## $ Time :'data.frame': 77 obs. of 10 variables: ## $ Chats :'data.frame': 6 obs. of 7 variables: # The initial info list otree$info ## $imported_files ## [1] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/ChatMessages-2023-05-16.csv\" ## [2] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/PageTimes-2023-05-16.csv\" ## [3] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/survey_2023-05-16.csv\" ## [4] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/start_2023-05-16.csv\" ## [5] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/dictator_2023-05-16.csv\" ## [6] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/dictator_2023-05-00.csv\" ## [7] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/chatapp_2023-05-16.csv\" ## [8] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/all_apps_wide_2023-05-16.csv\" ## [9] \"C:/Users/pzauchner/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/all_apps_wide-2023-05-16.csv\" ## ## $initial_n ## [1] 12"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_duplicate","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"delete_duplicate()","title":"Introduction to gmoTree","text":"Sometimes, data imported several times. happen several reasons. First, one data set might part another download temporarily stored data downloading final data frame. Second, room-specific global data imported, data $all_apps_wide data frame two times. Third, data stored several imported folders. function delete_duplicate() deletes duplicate data apps $all_apps_wide. , however, change $Time $Chats data frames. running function, let us first check number participant codes initial count executing delete_duplicate() function. imported $all_apps_wide data frame, 12 participant codes. However, among , 8 unique, indicates presence duplicate data. $info data frame suggests initially 12 entries. remove duplicates, employ delete_duplicate() function: Please note details deleted rows added list deleted cases. list might used analysis, function mainly focuses cleaning untidy data import. However, count $info$initial_n adjusted accordingly. deletion operation, find participant codes unique, count $info$initial_n matches number unique participant codes.","code":"# Initial check before deletion length(otree$all_apps_wide$participant.code) ## [1] 12 length(unique(otree$all_apps_wide$participant.code)) ## [1] 8 otree$info$initial_n ## [1] 12 # Delete duplicate cases otree <- delete_duplicate(otree) # Check participant codes and initial_n after deletion length(otree$all_apps_wide$participant.code) ## [1] 8 length(unique(otree$all_apps_wide$participant.code)) ## [1] 8 otree$info$initial_n ## [1] 8"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"dealing-with-messy-chats-and-time-data-frames","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"Dealing with messy Chats and Time data frames","title":"Introduction to gmoTree","text":"combine data experiments ran different versions oTree, might happen several variables referring attribute $Time $Chats data frames. functions messy_chat() messy_time() integrate corresponding variables used argument combine = TRUE. show example, let us first load data different versions oTree. Now can run functions messy_time() messy_chat(). warning messages part expected output, indicating precisely variables combined. need concern see . However, can also turn using info = FALSE.","code":"# Import data from different oTree versions otree_all <- import_otree( path = system.file(\"extdata\", package = \"gmoTree\")) ## Warning in import_otree(path = system.file(\"extdata\", package = \"gmoTree\")): ## You have stored all_apps_wide globally but also room-specific. This function ## will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" ## Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") ## After importing the data, make sure nothing is there twice! (Advice: You may ## use delete_duplicate() to remove duplicate rows of all oTree data frames. # Check names of Time data frame names(otree_all$Time) ## [1] \"session_code\" \"participant_id_in_session\" ## [3] \"participant_code\" \"page_index\" ## [5] \"app_name\" \"page_name\" ## [7] \"epoch_time_completed\" \"round_number\" ## [9] \"timeout_happened\" \"is_wait_page\" # Check names of Chats data frame names(otree_all$Chats) ## [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" ## [5] \"nickname\" \"body\" \"timestamp\" otree_all <- messy_time(otree_all, combine = TRUE, info = TRUE) otree_all <- messy_chat(otree_all, combine = TRUE, info = TRUE) # Check names of Time data frame again names(otree_all$Time) ## [1] \"session_code\" \"participant_id_in_session\" ## [3] \"participant_code\" \"page_index\" ## [5] \"app_name\" \"page_name\" ## [7] \"epoch_time_completed\" \"round_number\" ## [9] \"timeout_happened\" \"is_wait_page\" # Check names of Chats data frame again names(otree_all$Chats) ## [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" ## [5] \"nickname\" \"body\" \"timestamp\""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"show_dropouts","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"show_dropouts()","title":"Introduction to gmoTree","text":"Sometimes, participants drop experiments. get overview dropouts, can use function show_dropouts(). creates three data frames/tables information participants finish () certain app(s) page(s). First, function show_dropouts() creates data frame $full provides specific information apps pages participants left experiment prematurely. Additionally, data frame indicates apps affected participants dropped . Second, function show_dropouts() also generates smaller data frame $unique includes information person . Third, function show_dropouts() furthermore creates table $all_end, contains information participants ended experiment. columns contain names pages experiment; rows contain names apps.","code":"# Show everyone that has not finished with the app \"survey\" dropout_list <- show_dropouts(otree, \"survey\") head(dropout_list$full) ## participant.code session.code end_app end_page ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 2 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 3 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 4 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 5 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 6 dhgisush 2wlrl5kb dictator Offer ## reason ## 1 Experiment not completed. Noticed at: all_apps_wide ## 2 Experiment not completed. Noticed at: chatapp ## 3 Experiment not completed. Noticed at: dictator ## 4 Experiment not completed. Noticed at: start ## 5 Experiment not completed. Noticed at: survey ## 6 Experiment not completed. Noticed at: all_apps_wide dropout_list$unique ## participant.code session.code end_app end_page ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 6 dhgisush 2wlrl5kb dictator Offer ## 11 j2g9mcaf jk9ekpl0 dictator Introduction ## 16 p6m495xi 2wlrl5kb dictator Introduction ## reason ## 1 Experiment not completed ## 6 Experiment not completed ## 11 Experiment not completed ## 16 Experiment not completed dropout_list$all_end ## ## Demographics Introduction Offer ResultsWaitPage ## dictator 0 2 1 1 ## survey 4 0 0 0"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_dropouts","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"delete_dropouts()","title":"Introduction to gmoTree","text":"function delete_dropouts() removes data related participants prematurely terminated experiment data frames oTree list, exception data info list $Chats data frame. highly recommend manually delete chat data, can occasionally become unintelligible one person’s input removed. Therefore, function delete chat input participants dropped experiment. running example, let us first check row numbers data frames. run function delete_dropouts() check row numbers , see cases deleted data frame $Chats data frame. Just show_dropouts(), delete_dropouts() function also gives detailed information deleted cases. Caution: function delete data original CSV Excel files!","code":"# First, check some row numbers nrow(otree$all_apps_wide) ## [1] 8 nrow(otree$survey) ## [1] 8 nrow(otree$Time) ## [1] 77 nrow(otree$Chats) ## [1] 6 # Delete all cases that didn't end the experiment on the page \"Demographics\" # within the app \"survey\" otree2 <- delete_dropouts(otree, final_apps = \"survey\", final_pages = \"Demographics\", info = TRUE) ## 4 case(s) deleted ## Dropouts are deleted from all data frames. Except: The list of oTree data frames includes a chat. As the interpretation of chat data depends on how participants engage with each other, the data must be deleted with more care than deleting data in other apps. Hence, this function does not delete data in this data frame. Please do this manually if necessary! # Check row numbers again nrow(otree2$all_apps_wide) ## [1] 4 nrow(otree2$survey) ## [1] 4 nrow(otree2$Time) ## [1] 66 nrow(otree2$Chats) ## [1] 6 head(otree2$info$deleted_cases$full) ## participant.code session.code end_app end_page ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 2 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 3 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 4 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 5 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 6 dhgisush 2wlrl5kb dictator Offer ## reason ## 1 ENC. Noticed at: survey ## 2 ENC. Noticed at: start ## 3 ENC. Noticed at: dictator ## 4 ENC. Noticed at: chatapp ## 5 ENC. Noticed at: all_apps_wide ## 6 ENC. Noticed at: survey otree2$info$deleted_cases$unique ## participant.code session.code end_app end_page reason ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ENC ## 6 dhgisush 2wlrl5kb dictator Offer ENC ## 11 j2g9mcaf jk9ekpl0 dictator Introduction ENC ## 16 p6m495xi 2wlrl5kb dictator Introduction ENC otree2$info$deleted_cases$all_end ## ## Demographics Introduction Offer ResultsWaitPage ## dictator 0 2 1 1 ## survey 4 0 0 0"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_cases","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"delete_cases()","title":"Introduction to gmoTree","text":"Sometimes, participants ask data deleted. delete_cases() function can delete person app’s data frame, $all_apps_wide, $Time data frame. , data $Chats data frame must deleted hand. function adds information deleted cases previously created information deleted cases. Caution: function delete data original CSV Excel files!","code":"# First, check some row numbers nrow(otree2$all_apps_wide) ## [1] 4 nrow(otree2$survey) ## [1] 4 nrow(otree2$Time) ## [1] 66 nrow(otree2$Chats) ## [1] 6 # Delete one participant person <- otree2$all_apps_wide$participant.code[1] otree2 <- delete_cases(otree2, pcodes = person, reason = \"requested\", saved_vars = \"participant._index_in_pages\", info = TRUE) ## 1 case(s) deleted. Cases are deleted from all data frames. Except: The list of oTree data frames includes a chat. As the interpretation of chat data depends on how participants engage with each other, the data must be deleted with more care than deleting data in other apps. Hence, this function does not delete data in this data frame. Please do this manually if necessary! # Check row numbers again nrow(otree2$all_apps_wide) ## [1] 3 nrow(otree2$survey) ## [1] 3 nrow(otree2$Time) ## [1] 48 nrow(otree2$Chats) ## [1] 6 # Check for all deleted cases (also dropouts): tail(otree2$info$deleted_cases$full) ## participant.code session.code end_app end_page ## 16 p6m495xi 2wlrl5kb dictator Introduction ## 17 p6m495xi 2wlrl5kb dictator Introduction ## 18 p6m495xi 2wlrl5kb dictator Introduction ## 19 p6m495xi 2wlrl5kb dictator Introduction ## 20 p6m495xi 2wlrl5kb dictator Introduction ## 21 sdh9ar2m ## reason session participant._index_in_pages ## 16 ENC. Noticed at: survey NA ## 17 ENC. Noticed at: start NA ## 18 ENC. Noticed at: dictator NA ## 19 ENC. Noticed at: chatapp NA ## 20 ENC. Noticed at: all_apps_wide NA ## 21 requested jk9ekpl0 18"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_sessions","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"delete_sessions()","title":"Introduction to gmoTree","text":"certainly hope never becomes necessary, may instances entire session needs removed data set due unforeseen issues. However, occurs, can use function delete_sessions(). function removes sessions’ data apps, $all_apps_wide, $Time data frame also sessions’ chat data $Chats data frame chatting usually restricted within session. following, see row numbers deletion, application function, row numbers deletion. Apart functions, sessions’ entries $Chats data frame destroyed since chat data occurs just per session may thus eliminated without impacting comprehensibility chat data.","code":"# First, check some row numbers nrow(otree2$all_apps_wide) ## [1] 3 nrow(otree2$survey) ## [1] 3 nrow(otree2$Time) ## [1] 48 nrow(otree2$Chats) ## [1] 6 # Delete one session otree2 <- delete_sessions(otree, scodes = \"jk9ekpl0\", reason = \"Only tests\", info = TRUE) ## 4 case(s) deleted # Check row numbers again nrow(otree2$all_apps_wide) ## [1] 4 nrow(otree2$survey) ## [1] 4 nrow(otree2$Time) ## [1] 38 nrow(otree2$Chats) ## [1] 3"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_pabels","dir":"Articles","previous_headings":"Deleting sensitive information","what":"delete_pabels()","title":"Introduction to gmoTree","text":"uncommon participant.label variable contain sensitive information like MTurk worker ID. can raise serious privacy concerns. function delete_plabels() automatically removes variable data frames. Additionally, function option delete MTurk-related variables. following, see application delete_plabels() function, preceded information sensitive variables running function followed information sensitive variables running function. Caution: function delete variable original CSV Excel files!","code":"# Check variables head(otree2$all_apps_wide$participant.label) ## [1] \"\" \"\" \"Person1\" \"Person2\" head(otree2$all_apps_wide$participant.mturk_worker_id) ## [1] NA NA NA NA head(otree2$survey$participant.label) ## [1] \"\" \"\" \"Person1\" \"Person2\" # Delete all participant labels otree2 <- delete_plabels(otree2, del_mturk = TRUE) # Check variables head(otree2$all_apps_wide$participant.label) ## NULL head(otree2$all_apps_wide$participant.mturk_worker_id) ## NULL head(otree2$survey$participant.label) ## NULL"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"make_ids","dir":"Articles","previous_headings":"Making IDs","what":"make_ids()","title":"Introduction to gmoTree","text":"working oTree, participant codes, session codes, group IDs used identify cases. However, often, researchers prefer streamlined, consecutive numbering system spans sessions, beginning first participant, session, group concluding last. make_ids() function provides way achieve goal. using function, let us inspect underlying variables first. function returns following variables. prior example, Group IDs calculated group IDs must called specifically. Since group IDs per app data match (groups relevant dictator app), just using group_id = TRUE lead error message. cases group IDs vary among apps, can specified make_ids() app variable used extracting group information. instance, following syntax can used obtain group IDs variable dictator.1.group.id_in_subsession $all_apps_wide.","code":"# Check variables first otree2$all_apps_wide$participant.code ## [1] \"dhgisush\" \"p6m495xi\" \"c9inx5wl\" \"kr8yd7f3\" otree2$all_apps_wide$session.code ## [1] \"2wlrl5kb\" \"2wlrl5kb\" \"mz2r27bk\" \"mz2r27bk\" otree2$all_apps_wide$dictator.1.group.id_in_subsession ## [1] 1 1 1 1 # Make session IDs only otree2 <- make_ids(otree2) # Check variables otree2$all_apps_wide$participant_id ## [1] 1 2 3 4 otree2$all_apps_wide$session_id ## [1] 1 1 2 2 # Get IDs from \"from_variable\" in the data frame \"all_apps_wide\" otree2 <- make_ids(otree2, # gmake = TRUE, # Not necessary if from_var is not NULL from_var = \"dictator.1.group.id_in_subsession\") ## Warning in make_ids(otree2, from_var = \"dictator.1.group.id_in_subsession\"): ## The group variable values are constant. Group IDs now correspond to session ## IDs. # Check variables otree2$all_apps_wide$participant_id ## [1] 1 2 3 4 otree2$all_apps_wide$group_id ## [1] 1 1 2 2 otree2$all_apps_wide$session_id ## [1] 1 1 2 2"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"apptime","dir":"Articles","previous_headings":"Measuring the time","what":"apptime()","title":"Introduction to gmoTree","text":"need determine much time participants spent specific app, apptime() function powerful tool can help. function calculates summary statistics mean, minimum, maximum time spent page, well detailed list durations participant app. following example shows much time participants spent app “survey” minutes. can also get time specific participants . Without specifying applications, get duration applications individually.","code":"# Calculate the time all participants spent on app \"survey\" apptime(otree2, apps = \"survey\", digits = 3) ## $mean_duration ## [1] 0.242 ## ## $min_duration ## [1] 0.233 ## ## $max_duration ## [1] 0.25 ## ## $single_durations ## participant session duration ## 1 c9inx5wl mz2r27bk 0.250 ## 2 kr8yd7f3 mz2r27bk 0.233 ## ## $messages ## [1] \"For some participants, no duration could be calculated. See list in $warnings.\" ## ## $warnings ## [1] \"dhgisush\" \"p6m495xi\" # Calculate the time one participant spent on app \"dictator\" apptime(otree2, pcode = \"c9inx5wl\", digits = 3) ## $chatapp ## [1] 0.267 ## ## $dictator ## [1] 0.5 ## ## $start ## [1] 0.017 ## ## $survey ## [1] 0.25"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"extime","dir":"Articles","previous_headings":"Measuring the time","what":"extime()","title":"Introduction to gmoTree","text":"need determine much time participants spent complete experiment, can use extime() function. function calculates summary statistics mean, minimum, maximum time spent experiment, well detailed list durations participant. (Note min, max, mean values two digits underlying data.) can also get duration just one participant.","code":"# Calculate the time that all participants spent on the experiment extime(otree2, digits = 3) ## $mean_duration ## [1] 0.525 ## ## $min_duration ## [1] 0.05 ## ## $max_duration ## [1] 1.033 ## ## $single_durations ## participant session duration ## 2 p6m495xi 2wlrl5kb 0.050 ## 1 dhgisush 2wlrl5kb 0.117 ## 4 kr8yd7f3 mz2r27bk 0.900 ## 3 c9inx5wl mz2r27bk 1.033 # Calculate the time one participant spent on the experiment extime(otree2, pcode = \"c9inx5wl\", digits = 3) ## [1] 1.033"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"pagesec","dir":"Articles","previous_headings":"Measuring the time","what":"pagesec()","title":"Introduction to gmoTree","text":"older versions oTree included variable called seconds_on_page $Time data frame. Although good reason omit , sometimes want detailed information time spent one page. Therefore, created function pagesec() adds new variable seconds_on_page2 $Time data frame.","code":"# Create two new columns: seconds_on_page2 and minutes_on_page otree2 <- pagesec(otree2, rounded = TRUE, minutes = TRUE) tail(otree2$Time) ## timeout_happened is_wait_page group_id session_id participant_id ## 72 0 0 2 2 3 ## 73 0 0 2 2 4 ## 74 0 0 2 2 4 ## 75 0 0 2 2 3 ## 76 0 0 2 2 4 ## 77 0 0 2 2 3 ## session_code participant_id_in_session participant_code page_index app_name ## 72 mz2r27bk 1 c9inx5wl 15 survey ## 73 mz2r27bk 2 kr8yd7f3 15 survey ## 74 mz2r27bk 2 kr8yd7f3 16 survey ## 75 mz2r27bk 1 c9inx5wl 16 survey ## 76 mz2r27bk 2 kr8yd7f3 17 survey ## 77 mz2r27bk 1 c9inx5wl 17 survey ## page_name epoch_time_completed round_number minutes_on_page ## 72 CognitiveReflectionTest 1684258104 1 0.05 ## 73 CognitiveReflectionTest 1684258108 1 0.13 ## 74 Offer 1684258109 1 0.02 ## 75 Offer 1684258110 1 0.10 ## 76 Demographics 1684258114 1 0.08 ## 77 Demographics 1684258116 1 0.10"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"assignv","dir":"Articles","previous_headings":"Transferring variables between the apps","what":"assignv()","title":"Introduction to gmoTree","text":"function assignv() copies variable $all_apps_wide data frame data frames apps. following example, variable survey.1.player.gender copied $all_apps_wide app data frames; data frames, new variable named gender. also copies variable $all_apps_wide keep degree consistency.","code":"# Assign variable \"survey.1.player.gender\" and name it \"gender\" otree2 <- assignv(oTree = otree2, variable = \"survey.1.player.gender\", newvar = \"gender\") # Control otree2$dictator$gender ## [1] \"\" \"\" \"\" \"\" \"\" \"\" \"Female\" \"Male\" ## [9] \"Female\" \"Male\" \"Female\" \"Male\" otree2$chatapp$gender ## [1] \"\" \"\" \"Female\" \"Male\" # In app \"survey\", the variable is now twice because it is taken from here otree2$survey$gender ## [1] \"\" \"\" \"Female\" \"Male\" otree2$survey$player.gender ## [1] \"\" \"\" \"Female\" \"Male\" # In app \"all_apps_wide,\" the variable is also there twice # (This can be avoided by calling the new variable the same # as the old variable) otree2$all_apps_wide$gender ## [1] \"\" \"\" \"Female\" \"Male\" otree2$all_apps_wide$survey.1.player.gender ## [1] \"\" \"\" \"Female\" \"Male\""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"assignv_to_aaw","dir":"Articles","previous_headings":"Transferring variables between the apps","what":"assignv_to_aaw()","title":"Introduction to gmoTree","text":"function assignv_to_aaw() copies variable one data frames $all_apps_wide data frame. following example, variable $survey data frame copied $all_apps_wide placed directly variable survey.1.player.age.","code":"# Create a new variable otree2$survey$younger30 <- ifelse(otree2$survey$player.age < 30, 1, 0) # Get variable younger30 from survey to all_apps_wide # and put the new variable right behind the old age variable otree2 <- assignv_to_aaw(otree2, app = \"survey\", variable = \"younger30\", newvar = \"younger30\", resafter = \"survey.1.player.age\") # Control otree2$all_apps_wide$survey.1.player.age ## [1] NA NA 66 33 # Check the position of the old age variable and the new variable match(\"survey.1.player.age\", colnames(otree2$all_apps_wide)) ## [1] 52 match(\"younger30\", colnames(otree2$all_apps_wide)) ## [1] 53"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"show_constant","dir":"Articles","previous_headings":"Before running the experiment","what":"show_constant()","title":"Introduction to gmoTree","text":"program experiments, frequently add variables turn useless later. forget remove , especially experiments numerous rounds, data frame becomes unreasonably huge. function show_constant(), may identify variables variation remove experiment. following example, variable named constant created, vary. function show_constant() shows us many variables also unchanging; however, delete oTree internal. Yet, prevent unreasonably large data frame, remove variable constant running experiment.","code":"# Make a constant column (this variable is usually created in oTree) otree2$dictator$constant <- 3 # Show all columns that contain columns containing only one specified value show_constant(oTree = otree2) ## $all_apps_wide ## [1] \"participant._is_bot\" ## [2] \"participant._max_page_index\" ## [3] \"participant.visited\" ## [4] \"session.label\" ## [5] \"session.comment\" ## [6] \"session.config.real_world_currency_per_point\" ## [7] \"session.config.name\" ## [8] \"session.config.participation_fee\" ## [9] \"start.1.player.role\" ## [10] \"start.1.player.payoff\" ## [11] \"start.1.group.id_in_subsession\" ## [12] \"start.1.subsession.round_number\" ## [13] \"dictator.1.player.role\" ## [14] \"dictator.1.group.id_in_subsession\" ## [15] \"dictator.1.subsession.round_number\" ## [16] \"dictator.2.player.role\" ## [17] \"dictator.2.group.id_in_subsession\" ## [18] \"dictator.2.subsession.round_number\" ## [19] \"dictator.3.player.role\" ## [20] \"dictator.3.group.id_in_subsession\" ## [21] \"dictator.3.subsession.round_number\" ## [22] \"chatapp.1.player.role\" ## [23] \"chatapp.1.player.payoff\" ## [24] \"chatapp.1.group.id_in_subsession\" ## [25] \"chatapp.1.subsession.round_number\" ## [26] \"survey.1.player.role\" ## [27] \"survey.1.player.payoff\" ## [28] \"survey.1.group.id_in_subsession\" ## [29] \"survey.1.subsession.round_number\" ## ## $chatapp ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"player.payoff\" ## [7] \"group.id_in_subsession\" \"subsession.round_number\" ## [9] \"session.label\" ## ## $dictator ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"group.id_in_subsession\" ## [7] \"session.label\" \"constant\" ## ## $start ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"player.payoff\" ## [7] \"group.id_in_subsession\" \"subsession.round_number\" ## [9] \"session.label\" ## ## $survey ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"player.payoff\" ## [7] \"group.id_in_subsession\" \"subsession.round_number\" ## [9] \"session.label\" ## ## $Time ## character(0) ## ## $Chats ## [1] \"group_id\" \"session_id\" \"session_code\" \"channel\""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"codebook","dir":"Articles","previous_headings":"Before running the experiment","what":"codebook()","title":"Introduction to gmoTree","text":"Thorough documentation experiment essential. detailed guidance generating codebook oTree code, refer vignette gmoTree Codebooks. recommend creating codebook running experiment, can help identify incomplete documentation potential issues within code.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"references","dir":"Articles","previous_headings":"","what":"References","title":"Introduction to gmoTree","text":"Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—open-source platform laboratory, online, field experiments. Journal Behavioral Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001","code":""},{"path":"https://zauchnerp.github.io/gmoTree/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Patricia F. Zauchner. Author, translator, maintainer, copyright holder. University Bremen","code":""},{"path":"https://zauchnerp.github.io/gmoTree/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Zauchner, Patricia F. (2024). gmoTree: oTree Data Manipulation Tool. R package version 1.2.0, .","code":"@Manual{, title = {gmoTree: oTree Data Manipulation Tool}, author = {Patricia F. Zauchner}, year = {2024}, note = {R package version 1.2.0}, url = {https://CRAN.R-project.org/package=gmoTree}, }"},{"path":"https://zauchnerp.github.io/gmoTree/impressum.html","id":null,"dir":"","previous_headings":"","what":"Site notice","title":"Site notice","text":"website published Patricia Zauchner Universität Bremen SOCIUM Forschungszentrum Ungleichheit und Sozialpolitik Unicom-Gebäude Raum: 7.4460 Mary-Somerville-Straße 7 28359 Bremen Deutschland Telephone: +49 421 218-58555 E-Mail: patricia.zauchner [] uni-bremen.de Patricia Zauchner also responsible content accordance 55 Abs. 2 RStV.","code":""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/impressum.html","id":"accountability-for-content","dir":"","previous_headings":"Disclaimer","what":"Accountability for content","title":"Site notice","text":"contents pages created utmost care. However, guarantee contents’ accuracy, completeness topicality. According statutory provisions, furthermore responsible content web pages. context, please note accordingly obliged monitor merely transmitted saved information third parties, investigate circumstances pointing illegal activity. obligations remove block use information generally applicable laws remain unaffected per §§ 8 10 Telemedia Act (TMG).","code":""},{"path":"https://zauchnerp.github.io/gmoTree/impressum.html","id":"accountability-for-links","dir":"","previous_headings":"Disclaimer","what":"Accountability for links","title":"Site notice","text":"Responsibility content external links (web pages third parties) lies solely operators linked pages. violations evident time linking. legal infringement become known us, remove respective link immediately.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"gmotree--get-and-modify-otree-data","dir":"","previous_headings":"","what":"Get and Modify oTree Data","title":"Get and Modify oTree Data","text":"gmoTree R package developed importing, merging, efficiently managing data obtained running oTree (Chen et al., 2016) experiments. ’s particularly valuable dealing complex experimental designs span multiple sessions generate large number files need integrated.1","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Get and Modify oTree Data","text":"install CRAN version package, use following command: install.packages(\"gmoTree\") install development version: devtools::install_github(\"ZauchnerP/gmoTree\")","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"list-of-all-functions","dir":"","previous_headings":"","what":"List of all functions","title":"Get and Modify oTree Data","text":"See page Introduction gmoTree detailed overview functions. details package whole, visit gmoTree website.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"importing-data","dir":"","previous_headings":"","what":"Importing data","title":"Get and Modify oTree Data","text":"import_otree(): Imports oTree data combines list data frames.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"cleaning-up-data","dir":"","previous_headings":"","what":"Cleaning up data","title":"Get and Modify oTree Data","text":"messy_chat(): Checks messy Chats data frame combines variables refer concept. messy_chat(): Checks messy Time data frame combines variables refer concept. delete_duplicate(): Deletes duplicate rows data frames oTree list.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"dealing-with-dropouts-and-deleting-cases","dir":"","previous_headings":"","what":"Dealing with dropouts and deleting cases","title":"Get and Modify oTree Data","text":"show_dropouts(): Shows participant codes people finish () certain app(s) page(s). delete_dropouts(): Deletes data participants finish () certain app(s) page(s). function deletes participants’ data data frames oTree list. Caution: delete cases original CSV Excel files! delete_cases(): Deletes data specified participants data frames oTree list. Caution: function delete data original CSV Excel files! delete_sessions(): Deletes data specified sessions data frames oTree list. Caution: function delete data original CSV Excel files!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"deleting-sensitive-information","dir":"","previous_headings":"","what":"Deleting sensitive information","title":"Get and Modify oTree Data","text":"delete_plabels(): Deletes variable participant.label every app might contain identifiable information participants, MTurk ID. Caution: function delete variable original CSV Excel files!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"making-ids","dir":"","previous_headings":"","what":"Making IDs","title":"Get and Modify oTree Data","text":"make_ids(): Makes participant, group, session IDs across apps.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"measuring-time","dir":"","previous_headings":"","what":"Measuring time","title":"Get and Modify oTree Data","text":"apptime(): Calculates time spent specific app. extime(): Calculates time spent experiment. pagesec(): Calculates time spent page.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"transferring-variables-between-the-apps","dir":"","previous_headings":"","what":"Transferring variables between the apps","title":"Get and Modify oTree Data","text":"assignv(): Copies variable all_apps_wide data frame data frames apps. assignv_to_aaw(): Copies variable one data frames all_apps_wide data frame.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"before-running-the-experiment","dir":"","previous_headings":"","what":"Before running the experiment","title":"Get and Modify oTree Data","text":"show_constant(): Shows constant variables. codebook(): Creates codebook based oTree code. See also vignette “gmoTree Codebooks.”","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"references","dir":"","previous_headings":"","what":"References","title":"Get and Modify oTree Data","text":"Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—open-source platform laboratory, online, field experiments. Journal Behavioral Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the time that was spent on an app — apptime","title":"Calculate the time that was spent on an app — apptime","text":"Calculate time spent one app several apps.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the time that was spent on an app — apptime","text":"","code":"apptime( oTree, apps = NULL, pcode = NULL, plabel = NULL, group_id = NULL, seconds = FALSE, rounded = TRUE, digits = 2, sinfo = \"session_code\", combine = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the time that was spent on an app — apptime","text":"oTree list data frames created import_otree apps Character. Name(s) app(s) time calculated. pcode Character. value participant.code variable time calculated one specified participant. plabel Character. value participant.label variable time calculated one specified participant. group_id Integer. value group_id variable time calculated one specified group. group_id variable can created make_ids. seconds Logical. TRUE output seconds instead minutes. rounded Logical. TRUE output rounded. digits Integer. number digits output rounded. parameter effect unless rounded = TRUE. sinfo Character. \"session_id\" use session ID additional information data frame single durations, \"session_code\" use session codes, NULL session column shown. combine Logical. TRUE variables relating epoch time merged, variables relating participant code merged data multiple versions oTree used.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the time that was spent on an app — apptime","text":"function returns list app containing information mean, minimum, maximum time participants spent app, data frame information time participant spent app, eventually, vectors relevant background information numbers. experiment's duration calculated one participant, output returns NA (per app) person make app(s).","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the time that was spent on an app — apptime","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show how much time all participants spent on app \"survey\" apptime(oTree, apps = \"survey\") #> $mean_duration #> [1] 0.28 #> #> $min_duration #> [1] 0.08 #> #> $max_duration #> [1] 1.13 #> #> $single_durations #> participant session duration #> 1 46kxib6w 7bfqtokx 1.13 #> 2 iay3dhkn 7bfqtokx 0.22 #> 3 4zhzdmzo 7bfqtokx 0.15 #> 4 3ttf7yix 7bfqtokx 0.42 #> 5 2d72mfgh 7bfqtokx 0.13 #> 6 rvce7958 7bfqtokx 0.22 #> 7 lsl3vbij 7bfqtokx 0.13 #> 8 xx78b3x0 vd1h01iv 0.17 #> 9 xmxl46rm vd1h01iv 0.15 #> 10 iagvtslv t0rog7nz 0.15 #> 11 jxh15obl t0rog7nz 0.08 #> 12 a7dppel1 t0rog7nz 0.23 #> 13 wk247s9w t0rog7nz 0.73 #> 14 xkobdvuh t0rog7nz 0.40 #> 15 1l5kal0r t0rog7nz 0.13 #> 16 7l0hmpcq qyu3qg0q 0.15 #> 17 ia9rnfvc qyu3qg0q 0.15 #> #> $messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $warnings #> [1] \"164r1hs4\" \"ktjz5jli\" \"vbhvhozv\" \"2scvem7a\" \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" #> [8] \"d4sq7zio\" #> # Show how much time the participant \"a7dppel1\" spent on # the app \"survey\" apptime(oTree, pcode = \"a7dppel1\", apps = \"survey\") #> [1] 0.23 # Show how much time the participants in group 4 spent on # the app \"survey\" oTree <- make_ids(oTree, gmake = TRUE, from_var = \"dictator.1.group.id_in_subsession\" ) apptime(oTree, group_id = 4, apps = \"survey\") #> $mean_duration #> [1] 0.13 #> #> $min_duration #> [1] 0.13 #> #> $max_duration #> [1] 0.13 #> #> $single_durations #> participant session duration #> 1 lsl3vbij 7bfqtokx 0.13 #> #> $messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $warnings #> [1] \"164r1hs4\" #> # Show how much time all participants spent on all apps apptime(oTree) #> $chatapp #> $chatapp$mean_duration #> [1] 0.65 #> #> $chatapp$min_duration #> [1] 0.02 #> #> $chatapp$max_duration #> [1] 1.87 #> #> $chatapp$single_durations #> participant session duration #> 10 iagvtslv t0rog7nz 0.02 #> 11 jxh15obl t0rog7nz 0.07 #> 8 xx78b3x0 vd1h01iv 0.20 #> 16 7l0hmpcq qyu3qg0q 0.20 #> 9 xmxl46rm vd1h01iv 0.45 #> 17 ia9rnfvc qyu3qg0q 0.55 #> 4 3ttf7yix 7bfqtokx 0.57 #> 13 wk247s9w t0rog7nz 0.57 #> 12 a7dppel1 t0rog7nz 0.58 #> 7 lsl3vbij 7bfqtokx 0.60 #> 1 46kxib6w 7bfqtokx 0.62 #> 3 4zhzdmzo 7bfqtokx 0.77 #> 5 2d72mfgh 7bfqtokx 0.77 #> 14 xkobdvuh t0rog7nz 1.07 #> 6 rvce7958 7bfqtokx 1.08 #> 15 1l5kal0r t0rog7nz 1.10 #> 2 iay3dhkn 7bfqtokx 1.87 #> #> $chatapp$messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $chatapp$warnings #> [1] \"164r1hs4\" \"ktjz5jli\" \"vbhvhozv\" \"2scvem7a\" \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" #> [8] \"d4sq7zio\" #> #> #> $dictator #> $dictator$mean_duration #> [1] 2.05 #> #> $dictator$min_duration #> [1] 0.4 #> #> $dictator$max_duration #> [1] 5.95 #> #> $dictator$single_durations #> participant session duration #> 12 vbhvhozv vd1h01iv 0.40 #> 13 2scvem7a vd1h01iv 0.43 #> 20 7l0hmpcq qyu3qg0q 0.43 #> 2 iay3dhkn 7bfqtokx 0.47 #> 21 ia9rnfvc qyu3qg0q 0.50 #> 1 46kxib6w 7bfqtokx 0.57 #> 11 xmxl46rm vd1h01iv 0.65 #> 10 xx78b3x0 vd1h01iv 0.72 #> 18 xkobdvuh t0rog7nz 0.90 #> 19 1l5kal0r t0rog7nz 0.95 #> 16 a7dppel1 t0rog7nz 1.17 #> 17 wk247s9w t0rog7nz 1.20 #> 15 jxh15obl t0rog7nz 1.58 #> 14 iagvtslv t0rog7nz 2.65 #> 9 ktjz5jli 7bfqtokx 2.88 #> 8 lsl3vbij 7bfqtokx 3.45 #> 7 164r1hs4 7bfqtokx 3.53 #> 6 rvce7958 7bfqtokx 4.37 #> 5 2d72mfgh 7bfqtokx 4.48 #> 3 4zhzdmzo 7bfqtokx 5.87 #> 4 3ttf7yix 7bfqtokx 5.95 #> #> $dictator$messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $dictator$warnings #> [1] \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" \"d4sq7zio\" #> #> #> $survey #> $survey$mean_duration #> [1] 0.28 #> #> $survey$min_duration #> [1] 0.08 #> #> $survey$max_duration #> [1] 1.13 #> #> $survey$single_durations #> participant session duration #> 11 jxh15obl t0rog7nz 0.08 #> 5 2d72mfgh 7bfqtokx 0.13 #> 7 lsl3vbij 7bfqtokx 0.13 #> 15 1l5kal0r t0rog7nz 0.13 #> 3 4zhzdmzo 7bfqtokx 0.15 #> 9 xmxl46rm vd1h01iv 0.15 #> 10 iagvtslv t0rog7nz 0.15 #> 16 7l0hmpcq qyu3qg0q 0.15 #> 17 ia9rnfvc qyu3qg0q 0.15 #> 8 xx78b3x0 vd1h01iv 0.17 #> 2 iay3dhkn 7bfqtokx 0.22 #> 6 rvce7958 7bfqtokx 0.22 #> 12 a7dppel1 t0rog7nz 0.23 #> 14 xkobdvuh t0rog7nz 0.40 #> 4 3ttf7yix 7bfqtokx 0.42 #> 13 wk247s9w t0rog7nz 0.73 #> 1 46kxib6w 7bfqtokx 1.13 #> #> $survey$messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $survey$warnings #> [1] \"164r1hs4\" \"ktjz5jli\" \"vbhvhozv\" \"2scvem7a\" \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" #> [8] \"d4sq7zio\" #> #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":null,"dir":"Reference","previous_headings":"","what":"Assign a variable from all_apps_wide — assignv","title":"Assign a variable from all_apps_wide — assignv","text":"Assign variable $all_apps_wide app data frames.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Assign a variable from all_apps_wide — assignv","text":"","code":"assignv(oTree, variable, newvar)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Assign a variable from all_apps_wide — assignv","text":"oTree list data frames created import_otree variable Character. variable $all_apps_wide data frame assigned apps. newvar Character. name newly created variable.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Assign a variable from all_apps_wide — assignv","text":"function returns duplicate original oTree list data frames additional column data frames. additional column contains data specified variable found $all_apps_wide.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Assign a variable from all_apps_wide — assignv","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Assign variable \"survey.1.player.gender\" and name it \"gender\" oTree <- assignv(oTree = oTree, variable = \"survey.1.player.gender\", newvar = \"gender\") # Show the new variable in some of the other app data frames oTree$dictator$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" #> [17] \"Male\" \"\" \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" #> [25] \"\" \"Male\" \"\" \"Female\" \"Female\" \"\" \"\" \"Female\" #> [33] \"Female\" \"\" \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" #> [41] \"\" \"Female\" \"Female\" \"Female\" \"Male\" \"Male\" \"\" \"Female\" #> [49] \"Female\" \"Female\" \"Male\" \"Male\" \"\" \"Female\" \"Female\" \"Female\" #> [57] \"Male\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" #> [65] \"\" \"\" \"\" \"\" \"\" \"Female\" \"Female\" \"Female\" #> [73] \"Female\" \"Female\" \"Female\" oTree$chatapp$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" # The variable is now duplicated in app \"survey\" because it is obtained from # there (This can be avoided by naming the new variable the same as the old # variable) oTree$survey$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" oTree$survey$player.gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" # In app \"all_apps_wide,\" the variable is also there twice (This can be # avoided by naming the new variable the same as the old variable) oTree$all_apps_wide$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" \"Female\" \"Female\" \"Female\" \"Male\" oTree$all_apps_wide$survey.1.player.gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" \"Female\" \"Female\" \"Female\" \"Male\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":null,"dir":"Reference","previous_headings":"","what":"Assign a variable to all_apps_wide — assignv_to_aaw","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"Assign variable one app data frames $all_apps_wide.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"","code":"assignv_to_aaw(oTree, app, variable, newvar, resafter = NULL)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"oTree list data frames created import_otree. app Character. data frame variable taken. variable Character. name variable assigned $all_apps_wide. newvar Character. name newly created variable $all_apps_wide data frame. resafter Character. name variable precedes new variable. NULL, new variable placed end data frame.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"function returns duplicate original oTree list data frames additional column $all_apps_wide data frame contains variable question.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Check out the old variable oTree$survey$player.age #> [1] 22 22 23 23 33 45 NA 44 NA 33 23 NA NA 23 NA 44 21 23 23 NA NA NA NA 34 20 # Create a new variable oTree$survey$younger30 <- ifelse(oTree$survey$player.age < 30, 1, 0) # Assign the variable younger30 to all_apps_wide oTree2 <- assignv_to_aaw( oTree = oTree, app = \"survey\", variable = \"younger30\", newvar = \"younger30\") #> Warning: New variable is created. However, there is an unequal number of participants in \"all_apps_wide\" (29) and app \"survey\" (25). Did you forget to delete dropouts and empty cases or did you forget to import app data? Sometimes, this can happen if you import data from within a session or room where you can only import \"all_apps_wide\" but not the separate app data, time data or chat data. # Show the new variable in the all_apps_wide data frame oTree2$all_apps_wide$younger30 #> [1] 1 1 1 1 0 0 NA 0 NA 0 1 NA NA 1 NA 0 1 1 1 NA NA NA NA 0 1 #> [26] NA NA NA NA # Check the position of the new variable match(\"younger30\",names(oTree2$all_apps_wide)) #> [1] 56 # Place the new variable immediately after the \"survey.1.player.age\" variable oTree2 <- assignv_to_aaw(oTree, app = \"survey\", variable = \"younger30\", newvar = \"younger30\", resafter = \"survey.1.player.age\") #> Warning: New variable is created. However, there is an unequal number of participants in \"all_apps_wide\" (29) and app \"survey\" (25). Did you forget to delete dropouts and empty cases or did you forget to import app data? Sometimes, this can happen if you import data from within a session or room where you can only import \"all_apps_wide\" but not the separate app data, time data or chat data. # Show the new variable in the all_apps_wide data frame oTree2$all_apps_wide$younger30 #> [1] 1 1 1 1 0 0 NA 0 NA 0 1 NA NA 1 NA 0 1 1 1 NA NA NA NA 0 1 #> [26] NA NA NA NA # Show the position of the new variable match(\"younger30\", names(oTree2$all_apps_wide)) #> [1] 50"},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a codebook for the oTree code — codebook","title":"Create a codebook for the oTree code — codebook","text":"Create codebook oTree code automatically scanning project folder retrieving variables' information.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a codebook for the oTree code — codebook","text":"","code":"codebook( path = \".\", fsource = \"init\", output = \"both\", output_dir = getwd(), output_file = \"codebook\", output_format = \"pdf_document\", output_open = TRUE, app_doc = TRUE, app = NULL, app_rm = NULL, doc_info = TRUE, sort = NULL, settings_replace = \"global\", user_settings = NULL, include_cons = TRUE, preamb = FALSE, encoding = \"UTF-8\", title = \"Codebook\", subtitle = \"created with gmoTree\", params = NULL, date = \"today\" )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a codebook for the oTree code — codebook","text":"path Character. Path oTree experiment. fsource Character. \"init\" information taken init.py files (newer oTree code 5.x format). \"models\" (\"model\") information taken models.py files (older oTree code 3.x format). output Character. \"list\" output contain list variables information. \"file\" output file Word PDF file. \"\" output contain file list. output_dir Character. absolute path function's output saved. absolute paths allowed parameter. Relative paths can specified output_file parameter. output_file Character. name output file generated function. file name can provided without extension. Relative paths also allowed file name. output_format Character. Format file output. format passed output_format argument rmarkdown::render. must use either \"pdf_document\", \"html_document\", \"word_document\", \"odt_document\", \"rtf_document\", \"md_document\", \"latex_document\". output_open Logical. TRUE file output opened creation. app_doc Logical. TRUE app documentation included output file. app Character. Name included app(s). Default use apps. argument can used simultaneously argument app_rm. app_rm Character. Name excluded app(s). Default exclude apps. argument can used simultaneously argument app. doc_info Logical. TRUE message information variables without documentation also returned. sort Character. Vector specifies order apps codebook. settings_replace Character NULL. Specifies handle references settings variables. Use \"global\" replace references global settings variables defined settings.py. Use \"user\" replace references variables provided user_settings argument. Use NULL leave references settings variables unchanged. Caution: function use variables defined SESSION_CONFIGS. vary settings variables SESSION_CONFIGS, set settings_replace \"user\" manually replace using user_settings argument. user_settings List. List variables settings.py file used replace setting variable references. used settings_replace = \"user\" used setting variables defined within SESSION_CONFIGS. include_cons Logical. TRUE section constants codebook. preamb Logical. TRUE preamble printed explains oTree saves variables. encoding Character. Encoding created Markdown file. knitr::knit, argument always assumed UTF-8 ignored. title Character. Title output file. subtitle Character. Subtitle output file. params List. List variable name value pairs passed RmD file. relevant argument output \"file\" \"\" chosen. date Date passed Rmd file. Either \"today\", NULL, user defined date. relevant argument output \"file\" \"\" chosen.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create a codebook for the oTree code — codebook","text":"function returns two main types outputs: () list variables along information (b) file containing codebook experiment doc_info TRUE also returns message containing names variables documentation.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Create a codebook for the oTree code — codebook","text":"code works dictionaries used (example session configurations settings.py). Caution 1: Multiline comments ignored, meaning variables commented manner nevertheless included codebook. contrast, variables commented line comments appear codebook. Caution 2: commas value strings, might used split text. Please manually insert backslash symbol front commas avoid . E.g. \"Yes, \" -> \"Yes\\, \". Caution 3: code interpret variables imported files (example CSV files) special formatting included (e.g., special string formatting Python float(1.4) represent float number). Caution 4: code developed tested basic oTree codes verified compatibility oTree versions later 5.4.0. experience issues newer versions complex code structures, please open issue GitHub.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create a codebook for the oTree code — codebook","text":"","code":"# The examples use a slightly modified version of the official oTree sample codes. # Make a codebook and resort the apps combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", fsource = \"init\", doc_info = FALSE) # Show the structure of the codebook str(combined_codebook, 1) #> List of 16 #> $ settings :List of 10 #> $ bargaining :List of 4 #> $ bertrand :List of 4 #> $ common_value_auction:List of 4 #> $ cournot :List of 4 #> $ dictator :List of 3 #> $ guess_two_thirds :List of 4 #> $ matching_pennies :List of 4 #> $ payment_info :List of 4 #> $ prisoner :List of 4 #> $ public_goods_simple :List of 3 #> $ survey :List of 3 #> $ traveler_dilemma :List of 4 #> $ trust :List of 3 #> $ trust_simple :List of 3 #> $ volunteer_dilemma :List of 4 str(combined_codebook$bargaining$Player, 1) #> List of 4 #> $ request:List of 6 #> $ level2 :List of 3 #> $ level3 :List of 3 #> $ level :List of 3 # Make a codebook with only the \"bargaining\" app combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", fsource = \"init\", app = \"bargaining\", doc_info = FALSE) # Show the structure of the codebook str(combined_codebook, 1) #> List of 2 #> $ settings :List of 10 #> $ bargaining:List of 4 str(combined_codebook$bargaining$Player, 1) #> List of 4 #> $ request:List of 6 #> $ level2 :List of 3 #> $ level3 :List of 3 #> $ level :List of 3 # Make a codebook with all but the \"bargaining\" app combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", fsource = \"init\", app_rm = \"bargaining\", doc_info = FALSE) # Show the structure of the codebook str(combined_codebook, 1) #> List of 15 #> $ settings :List of 10 #> $ bertrand :List of 4 #> $ common_value_auction:List of 4 #> $ cournot :List of 4 #> $ dictator :List of 3 #> $ guess_two_thirds :List of 4 #> $ matching_pennies :List of 4 #> $ payment_info :List of 4 #> $ prisoner :List of 4 #> $ public_goods_simple :List of 3 #> $ survey :List of 3 #> $ traveler_dilemma :List of 4 #> $ trust :List of 3 #> $ trust_simple :List of 3 #> $ volunteer_dilemma :List of 4 str(combined_codebook$bargaining$Player, 1) #> NULL # Use oTree code in 3.x format combined_codebook <- codebook( path = system.file(\"extdata/ocode_z\", package = \"gmoTree\"), fsource = \"model\", output = \"list\", doc_info = TRUE) #> Variables without documentation, label, or verbose name: #> > rankaversion$Player$choicenumber #> > rankend$Player$done_distribution #> Warning: Some variables or code parts contain code that is too complex for this function. Hence, this function might have overseen important variables and references to them. Check the output carefully! Found in: #> > App rankaversion(Constants) (read_csv) #> > App rankend(Constants) (read_csv) #> > $settings$showupToken (float) #> > $end$Constants$showupToken (float) #> > $end$Constants$showupTokenTest (float) # Show the structure of the codebook str(combined_codebook, 1) #> List of 4 #> $ settings :List of 20 #> $ end :List of 4 #> $ rankaversion:List of 4 #> $ rankend :List of 4 if (FALSE) { # \\dontrun{ # Create a codebook PDF with authors' names and todays' date codebook( path = system.file(\"extdata/ocode_z\", package = \"gmoTree\"), fsource = \"init\", doc_info = FALSE, output = \"file\", output_format = \"pdf_document\", date = \"today\", title = \"My Codebook\", subtitle = \"codebook created with gmoTree\", params = list(author = c(\"Max Mustermann\", \"John Doe\")) ) # Create a codebook PDF and save it in a subfolder of the # current folder: # \"C:/Users/pzauchner/Nextcloud/R_analyses/cb/cb.pdf\" getwd() # \"C:/Users/pzauchner/Nextcloud/R_analyses\" dir.create(\"cb\") combined_codebook <- gmoTree::codebook( path = \"C:/Users/pzauchner/Nextcloud/R_analyses/oTree\", fsource = \"models\", output = \"both\", output_file = \"cb/cb.pdf\", output_format = \"pdf_document\") # You can also omit *.pdf after the file name combined_codebook <- gmoTree::codebook( path = \"C:/Users/pzauchner/Nextcloud/R_analyses/oTree\", fsource = \"models\", output = \"both\", output_file = \"cb/cb\", output_format = \"pdf_document\") } # }"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete specific cases — delete_cases","title":"Delete specific cases — delete_cases","text":"Delete specific cases data frames oTree list. Caution 1: function delete cases original CSV Excel files! Caution 2: function delete cases custom exports custom data frames data frames variable named participant.code! Caution 3: function delete data $Chats data frame! (interpretation chat data depends participants engage , data must deleted care deleting data apps. Hence, function delete data data frame. Please manually necessary!)","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete specific cases — delete_cases","text":"","code":"delete_cases( oTree, pcodes = NULL, plabels = NULL, saved_vars = NULL, reason, omit = FALSE, info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete specific cases — delete_cases","text":"oTree list data frames created import_otree. pcodes Character. value(s) participant.code variable participants whose data removed. plabels Character. value(s) participant.label variable participants whose data removed. saved_vars Character. name(s) variable(s) need(s) stored list information deleted cases $info$deleted_cases. reason Character. reason deletion stored list information deleted cases $info$deleted_cases. omit Logical. TRUE deleted cases added information deleted cases $info$deleted_cases. info Logical. TRUE brief information case deletion process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete specific cases — delete_cases","text":"function returns duplicate original oTree list data frames include deleted cases. adds information deleted cases $info$deleted_cases. (list also filled functions.) list, can find following information: - $codes = vector participant codes deleted cases. - $count = number participants $codes. - $full $unique = data frames $full $unique contain information deleted participant reason deleted. entries $full $unique data frames . Columns \"end_app\" \"end_page\" left empty intentionally filled delete_dropouts function.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete specific cases — delete_cases","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Delete only one case oTree2 <- delete_cases(oTree, pcodes = \"xmxl46rm\", reason = \"requested\") # Show changes in row numbers print(paste(\"Row numbers before deletion: \", nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"Row numbers before deletion: 29 25 289 35\" print(paste(\"Row numbers after deletion: \", nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"Row numbers after deletion: 28 24 275 35\" # Delete several cases deletionlist <- c(\"4zhzdmzo\", \"xmxl46rm\") oTree2 <- delete_cases(oTree, pcodes = deletionlist, reason = \"requested\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"27 23 258 35\" # Show information on all deleted cases (also dropouts): oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason #> 3 4zhzdmzo 7bfqtokx requested #> 12 xmxl46rm vd1h01iv requested # Save one variable oTree2 <- delete_cases(oTree, pcodes = deletionlist, reason = \"requested\", saved_vars = \"participant._index_in_pages\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"27 23 258 35\" # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason #> 3 4zhzdmzo 7bfqtokx requested #> 12 xmxl46rm vd1h01iv requested #> participant._index_in_pages #> 3 17 #> 12 17 # Save some variables oTree2 <- delete_cases(oTree, pcodes = deletionlist, reason = \"requested\", saved_vars = c( \"participant._index_in_pages\", \"participant._max_page_index\")) # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"27 23 258 35\" # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason #> 3 4zhzdmzo 7bfqtokx requested #> 12 xmxl46rm vd1h01iv requested #> participant._index_in_pages participant._max_page_index #> 3 17 16 #> 12 17 16 # Get a list of all deleted cases # (If there is already a list, the new list is added to it) oTree2$info$deleted_cases$codes #> [1] \"4zhzdmzo\" \"xmxl46rm\" # Show number of all deleted cases length(oTree2$info$deleted_cases$codes) #> [1] 2 oTree2$info$deleted_cases$count #> [1] 2 # Delete a session and delete a single case from another session oTree2 <- delete_sessions(oTree, scodes = c(\"vd1h01iv\"), reason = \"Server Crash\", saved_vars = \"dictator.1.group.id_in_subsession\") oTree2 <- delete_cases(oTree2, pcodes = \"4zhzdmzo\", reason = \"requested\") # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session.code dictator.1.group.id_in_subsession end_app #> 1 xx78b3x0 vd1h01iv 1 #> 2 xmxl46rm vd1h01iv 1 #> 3 vbhvhozv vd1h01iv 2 #> 4 2scvem7a vd1h01iv 2 #> 5 4zhzdmzo NA #> end_page reason session #> 1 Server Crash #> 2 Server Crash #> 3 Server Crash #> 4 Server Crash #> 5 requested 7bfqtokx # See codes of deleted variables oTree2$info$deleted_cases$codes #> [1] \"4zhzdmzo\" \"xx78b3x0\" \"xmxl46rm\" \"vbhvhozv\" \"2scvem7a\" # See number of deleted variables oTree2$info$deleted_cases$count #> [1] 5"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete dropouts — delete_dropouts","title":"Delete dropouts — delete_dropouts","text":"Delete data participants end experiment () certain page(s) /app(s). Caution 1: function delete cases original CSV Excel files! Caution 2: function delete cases custom exports custom exports variable named participant.code variable named session.code! Caution 3: function delete data $Chats data frame! (interpretation chat data depends participants engage , data must deleted care deleting data apps. Hence, function delete data data frame. Please manually necessary!)","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete dropouts — delete_dropouts","text":"","code":"delete_dropouts( oTree, final_apps = NULL, final_pages = NULL, saved_vars = NULL, inconsistent = NULL, reason = \"ENC\", info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete dropouts — delete_dropouts","text":"oTree list data frames created import_otree final_apps Character. name(s) app(s) participants finish experiment. final_pages Character. name(s) page(s) participants finish experiment. saved_vars Character. name(s) variable(s) need(s) stored list information deleted cases $info$deleted_cases. inconsistent Character. function continue stopped least one participant inconsistent end_pages, inconsistent end_apps, ? continue, type \"yes\", stop function, type \"\". reason Character. reason deletion stored list information deleted cases $info$deleted_cases. info Logical. TRUE brief information dropout deletion process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete dropouts — delete_dropouts","text":"function returns duplicate original oTree list data frames without deleted cases. adds information deleted cases $info$deleted_cases. (list also filled functions.) list, can find following information: - $full = data frame contains information participants finish study; shows participant codes, names apps left experiment, names pages left experiment, names app data frames information found, dropout reason (\"ENC\", experiment completed, combined name data frame dropout observed). participants usually appear multiple app data frames, $info$deleted_cases$full data frame may contain several entries person. - $unique = data frame contains similar information $full data frame one row per participant information data frame dropout observed. - $all_end = table provides information app page combinations participants ended experiment. table also includes information participants drop experiment. $all_end table shown $all_apps_wide data frame exists. - $codes = vector containing participant codes deleted participants. - $count = number deleted participants. important note argument final_pages set, function distinguish page names reoccur different apps. columns end_app end_page output empty, variables saved oTree specific participants. empty rows deleted. can done using argument del_empty = TRUE using import_otree.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete dropouts — delete_dropouts","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # First, show some row numbers print(paste(nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"29 25 289 35\" # Delete all cases that didn't end the experiment on the page \"Demographics\" # within the app \"survey\" oTree2 <- delete_dropouts(oTree, final_apps = c(\"survey\"), final_pages = c(\"Demographics\")) # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"20 16 248 35\" # Delete all cases that didn't end the experiment on the page \"Demographics\" # This page can be in any app oTree2 <- delete_dropouts(oTree, final_pages = \"Demographics\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"20 16 248 35\" # Delete all cases that didn't end the experiment on # any page in the app \"survey\" oTree <- delete_dropouts(oTree, final_apps = \"survey\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"20 16 248 35\" # Get list of information on all deleted cases # (If there is already a list, the new list is added to it!) oTree2$info$deleted_cases #> $full #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 2 164r1hs4 7bfqtokx chatapp chat #> 3 164r1hs4 7bfqtokx chatapp chat #> 4 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 6 2scvem7a vd1h01iv dictator ResultsWaitPage #> 7 2scvem7a vd1h01iv dictator ResultsWaitPage #> 8 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 10 7wa8kk3d l8ecm1uh dictator Introduction #> 11 7wa8kk3d l8ecm1uh dictator Introduction #> 12 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 14 ao9kqvqn l8ecm1uh dictator Introduction #> 15 ao9kqvqn l8ecm1uh dictator Introduction #> 16 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 18 d4sq7zio l8ecm1uh dictator Introduction #> 19 d4sq7zio l8ecm1uh dictator Introduction #> 20 d4sq7zio l8ecm1uh dictator Introduction #> 21 jxh15obl t0rog7nz survey Offer #> 22 jxh15obl t0rog7nz survey Offer #> 23 jxh15obl t0rog7nz survey Offer #> 24 jxh15obl t0rog7nz survey Offer #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 26 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 27 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 28 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 30 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 31 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 32 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 33 znri6myc l8ecm1uh dictator Introduction #> 34 znri6myc l8ecm1uh dictator Introduction #> 35 znri6myc l8ecm1uh dictator Introduction #> 36 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 ENC. Noticed at: survey #> 2 ENC. Noticed at: all_apps_wide #> 3 ENC. Noticed at: chatapp #> 4 ENC. Noticed at: dictator #> 5 ENC. Noticed at: all_apps_wide #> 6 ENC. Noticed at: chatapp #> 7 ENC. Noticed at: dictator #> 8 ENC. Noticed at: survey #> 9 ENC. Noticed at: all_apps_wide #> 10 ENC. Noticed at: chatapp #> 11 ENC. Noticed at: dictator #> 12 ENC. Noticed at: survey #> 13 ENC. Noticed at: all_apps_wide #> 14 ENC. Noticed at: chatapp #> 15 ENC. Noticed at: dictator #> 16 ENC. Noticed at: survey #> 17 ENC. Noticed at: chatapp #> 18 ENC. Noticed at: dictator #> 19 ENC. Noticed at: survey #> 20 ENC. Noticed at: all_apps_wide #> 21 ENC. Noticed at: dictator #> 22 ENC. Noticed at: survey #> 23 ENC. Noticed at: all_apps_wide #> 24 ENC. Noticed at: chatapp #> 25 ENC. Noticed at: all_apps_wide #> 26 ENC. Noticed at: chatapp #> 27 ENC. Noticed at: dictator #> 28 ENC. Noticed at: survey #> 29 ENC. Noticed at: all_apps_wide #> 30 ENC. Noticed at: chatapp #> 31 ENC. Noticed at: dictator #> 32 ENC. Noticed at: survey #> 33 ENC. Noticed at: all_apps_wide #> 34 ENC. Noticed at: chatapp #> 35 ENC. Noticed at: dictator #> 36 ENC. Noticed at: survey #> #> $unique #> participant.code session.code end_app end_page reason #> 1 164r1hs4 7bfqtokx chatapp chat ENC #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage ENC #> 9 7wa8kk3d l8ecm1uh dictator Introduction ENC #> 13 ao9kqvqn l8ecm1uh dictator Introduction ENC #> 17 d4sq7zio l8ecm1uh dictator Introduction ENC #> 21 jxh15obl t0rog7nz survey Offer ENC #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage ENC #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage ENC #> 33 znri6myc l8ecm1uh dictator Introduction ENC #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"164r1hs4\" \"2scvem7a\" \"7wa8kk3d\" \"ao9kqvqn\" \"d4sq7zio\" \"jxh15obl\" \"ktjz5jli\" #> [8] \"vbhvhozv\" \"znri6myc\" #> #> $count #> [1] 9 #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete duplicate data — delete_duplicate","title":"Delete duplicate data — delete_duplicate","text":"Delete duplicate rows oTree app data frames $all_apps_wide.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete duplicate data — delete_duplicate","text":"","code":"delete_duplicate(oTree)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete duplicate data — delete_duplicate","text":"oTree list data frames created import_otree.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete duplicate data — delete_duplicate","text":"function returns duplicate original oTree list data frames without duplicate rows app data frames $all_apps_wide. function effect data frames $Time $Chats. function add information $info$deleted_cases, delete important information cleans messy data import. However, function adjusts $info$initial_n, $all_apps_wide data frame exists.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete duplicate data — delete_duplicate","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. # First, show some row numbers print(paste(nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"41 33 366 41\" # Delete duplicate rows oTree <- delete_duplicate(oTree) # Show row numbers again print(paste(nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"37 33 366 41\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete participant labels in all apps — delete_plabels","title":"Delete participant labels in all apps — delete_plabels","text":"work MTurk, MTurk IDs stored participant labels variable. function deletes variable $all_apps_wide every app data frame list data frames created import_otree /variables referring MTurk, participant.mturk_worker_id. Caution: function delete variables original CSV Excel files!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete participant labels in all apps — delete_plabels","text":"","code":"delete_plabels(oTree, del_plabel = TRUE, del_mturk = TRUE)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete participant labels in all apps — delete_plabels","text":"oTree list data frames created import_otree. del_plabel Logical. TRUE participant labels deleted. del_mturk Logical. TRUE MTurk variables deleted.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete participant labels in all apps — delete_plabels","text":"function returns duplicate original oTree list data frames include participant labels /MTurk variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete participant labels in all apps — delete_plabels","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show participant labels oTree$all_apps_wide$participant.label #> [1] \"Person1\" \"Person2\" \"Person4\" \"Person5\" \"Person6\" \"Person7\" #> [7] \"Person8\" \"Person9\" \"Person10\" \"Person1\" \"Person2\" \"Person3\" #> [13] \"Person4\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person5\" #> [19] \"Person6\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person2\" #> [25] \"Person3\" NA NA NA NA oTree$survey$participant.label #> [1] \"Person1\" \"Person2\" \"Person4\" \"Person5\" \"Person6\" \"Person7\" #> [7] \"Person8\" \"Person9\" \"Person10\" \"Person1\" \"Person2\" \"Person3\" #> [13] \"Person4\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person5\" #> [19] \"Person6\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person2\" #> [25] \"Person3\" # Delete all participant labels oTree2 <- delete_plabels(oTree) # Show participant labels again oTree2$all_apps_wide$participant.label #> NULL oTree2$survey$participant.label #> NULL"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete all cases of one session — delete_sessions","title":"Delete all cases of one session — delete_sessions","text":"Delete cases specific sessions data frames oTree list data frames. Caution 1: function delete cases original CSV Excel files! Caution 2: function delete cases custom exports custom exports variable named participant.code variable named session.code!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete all cases of one session — delete_sessions","text":"","code":"delete_sessions(oTree, scodes, saved_vars = NULL, reason, info = FALSE)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete all cases of one session — delete_sessions","text":"oTree list data frames created import_otree. scodes Character. session.code(s) session(s) whose data removed. saved_vars Character. name(s) variable(s) need(s) stored list information deleted cases $info$deleted_cases. reason Character. reason deletion stored list information deleted cases $info$deleted_cases. info Logical. TRUE brief information session deletion process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete all cases of one session — delete_sessions","text":"function returns duplicate original oTree list data frames include deleted sessions. adds information deleted cases $info$deleted_cases. (list also filled functions.) list, can find following information: - $full $unique = data frames $full $unique contain information participants whose data deleted. entries $full $unique data frames list . Columns end_app end_page left empty intentionally filled delete_dropouts function. Columns participant.code reason filled. - $codes = vector containing participant codes deleted participants. - $count = number deleted participants.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete all cases of one session — delete_sessions","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Delete one session oTree2 <- delete_sessions(oTree, scodes = \"7bfqtokx\", reason = \"Only tests\") # Show changes in row numbers print(paste(\"Row numbers before deletion: \", nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"Row numbers before deletion: 29 25 289 35\" print(paste(\"Row numbers after deletion: \", nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"Row numbers after deletion: 20 16 166 14\" # Delete two sessions and show deletion message oTree2 <- delete_sessions(oTree, scodes = c(\"7bfqtokx\", \"vd1h01iv\"), reason = \"Only tests\", info = TRUE) #> 13 case(s) deleted # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"16 12 126 10\" # Delete session and save variable to the info list oTree2 <- delete_sessions(oTree, scodes = c(\"7bfqtokx\", \"vd1h01iv\"), reason = \"Server Crash\", saved_vars = \"dictator.1.group.id_in_subsession\") # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session.code dictator.1.group.id_in_subsession end_app #> 1 46kxib6w 7bfqtokx 1 #> 2 iay3dhkn 7bfqtokx 1 #> 3 4zhzdmzo 7bfqtokx 2 #> 4 3ttf7yix 7bfqtokx 2 #> 5 2d72mfgh 7bfqtokx 3 #> 6 rvce7958 7bfqtokx 3 #> 7 164r1hs4 7bfqtokx 4 #> 8 lsl3vbij 7bfqtokx 4 #> 9 ktjz5jli 7bfqtokx 5 #> 11 xx78b3x0 vd1h01iv 1 #> 12 xmxl46rm vd1h01iv 1 #> 13 vbhvhozv vd1h01iv 2 #> 14 2scvem7a vd1h01iv 2 #> end_page reason #> 1 Server Crash #> 2 Server Crash #> 3 Server Crash #> 4 Server Crash #> 5 Server Crash #> 6 Server Crash #> 7 Server Crash #> 8 Server Crash #> 9 Server Crash #> 11 Server Crash #> 12 Server Crash #> 13 Server Crash #> 14 Server Crash # See codes of deleted variables oTree2$info$deleted_cases$codes #> [1] \"46kxib6w\" \"iay3dhkn\" \"4zhzdmzo\" \"3ttf7yix\" \"2d72mfgh\" \"rvce7958\" #> [7] \"164r1hs4\" \"lsl3vbij\" \"ktjz5jli\" \"xx78b3x0\" \"xmxl46rm\" \"vbhvhozv\" #> [13] \"2scvem7a\" # See number of deleted variables oTree2$info$deleted_cases$count #> [1] 13 # Delete a single case and then delete a session oTree2 <- delete_cases(oTree, pcodes = \"4zhzdmzo\", reason = \"requested\") oTree2 <- delete_sessions(oTree2, scodes = c(\"vd1h01iv\"), reason = \"Server Crash\", saved_vars = \"dictator.1.group.id_in_subsession\") # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason session.code #> 1 4zhzdmzo 7bfqtokx requested #> 2 xx78b3x0 Server Crash vd1h01iv #> 3 xmxl46rm Server Crash vd1h01iv #> 4 vbhvhozv Server Crash vd1h01iv #> 5 2scvem7a Server Crash vd1h01iv #> dictator.1.group.id_in_subsession #> 1 NA #> 2 1 #> 3 1 #> 4 2 #> 5 2 # See codes of deleted variables oTree2$info$deleted_cases$codes #> [1] \"xx78b3x0\" \"xmxl46rm\" \"vbhvhozv\" \"2scvem7a\" \"4zhzdmzo\" # See number of deleted variables oTree2$info$deleted_cases$count #> [1] 5"},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the time that was spent on the whole experiment — extime","title":"Calculate the time that was spent on the whole experiment — extime","text":"Calculate time spent experiment. stated otherwise, calculation starts end first page!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the time that was spent on the whole experiment — extime","text":"","code":"extime( oTree, pcode = NULL, plabel = NULL, group_id = NULL, seconds = FALSE, rounded = TRUE, digits = 2L, startat = 1L, tz = \"UTC\", sinfo = \"session_code\", combine = TRUE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the time that was spent on the whole experiment — extime","text":"oTree list data frames created import_otree. pcode Character. value participant.code variable time calculated one specified participant. plabel Character. value participant.label variable time calculated one specified participant. group_id Integer. value group_id variable time calculated one specified group. group_id variable can created make_ids. seconds Logical. TRUE output seconds instead minutes. rounded Logical. TRUE output rounded. digits Integer. number digits output rounded. parameter effect unless rounded = TRUE. startat Integer character string \"real\" Whether start experiment taken time certain index person's vector page_indexes $Time data frame time_started variable $all_apps_wide (\"real\"). Important: integer, represents position within page index sequence, numeric value page_index variable. tz Character. Time zone. sinfo Character. \"session_id\" use session ID additional information data frame single durations, \"session_code\" use session codes, NULL session column shown. combine Logical. TRUE variables referring epoch time merged, variables referring participant code merged case data several versions oTree used. FALSE, function returns error several oTree versions' data present.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the time that was spent on the whole experiment — extime","text":"function returns either single value data one person calculated list information time several participants spent experiment. list, can find following information: - $mean_duration = experiment's average duration. - $min_duration = experiment's minimum duration. - $max_duration = experiment's maximum duration. - $single_durations = data frame durations used calculating min, max, mean duration. - $messages = important notes calculations. - $only_one_page = vector individuals one time stamp.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Calculate the time that was spent on the whole experiment — extime","text":"functions calculates time spent experiment using variable refers time stamp. variable present, function alternatively uses seconds_on_page2, can created pagesec function.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the time that was spent on the whole experiment — extime","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show time for one participant extime(oTree, pcode = \"wk247s9w\") #> [1] 2.5 # Make a data frame of durations extime(oTree) #> $mean_duration #> [1] 2.81 #> #> $min_duration #> [1] 0.4 #> #> $max_duration #> [1] 6.93 #> #> $single_durations #> participant session duration #> 12 vbhvhozv vd1h01iv 0.40 #> 13 2scvem7a vd1h01iv 0.43 #> 20 7l0hmpcq qyu3qg0q 0.78 #> 10 xx78b3x0 vd1h01iv 1.08 #> 21 ia9rnfvc qyu3qg0q 1.20 #> 11 xmxl46rm vd1h01iv 1.25 #> 15 jxh15obl t0rog7nz 1.73 #> 16 a7dppel1 t0rog7nz 1.98 #> 19 1l5kal0r t0rog7nz 2.18 #> 1 46kxib6w 7bfqtokx 2.32 #> 18 xkobdvuh t0rog7nz 2.37 #> 17 wk247s9w t0rog7nz 2.50 #> 2 iay3dhkn 7bfqtokx 2.55 #> 14 iagvtslv t0rog7nz 2.82 #> 9 ktjz5jli 7bfqtokx 2.88 #> 7 164r1hs4 7bfqtokx 3.53 #> 8 lsl3vbij 7bfqtokx 4.18 #> 5 2d72mfgh 7bfqtokx 5.38 #> 6 rvce7958 7bfqtokx 5.67 #> 3 4zhzdmzo 7bfqtokx 6.78 #> 4 3ttf7yix 7bfqtokx 6.93 #> #> $messages #> [1] \"Warning: For at least one participant, the experiment only has one page. I.e., the indices for the first and the last page are the same. See $only_one_page for information on this participant/these participants! Participants in this list are not included in the output.\" #> #> $only_one_page #> [1] \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" \"d4sq7zio\" #> # Make a data frame of durations (beginning from the end of the second page) extime(oTree, startat = 2) #> $mean_duration #> [1] 1.88 #> #> $min_duration #> [1] 0.03 #> #> $max_duration #> [1] 6.08 #> #> $single_durations #> participant session duration #> 13 2scvem7a vd1h01iv 0.03 #> 9 ktjz5jli 7bfqtokx 0.05 #> 12 vbhvhozv vd1h01iv 0.15 #> 20 7l0hmpcq qyu3qg0q 0.63 #> 7 164r1hs4 7bfqtokx 0.82 #> 10 xx78b3x0 vd1h01iv 1.03 #> 11 xmxl46rm vd1h01iv 1.08 #> 21 ia9rnfvc qyu3qg0q 1.08 #> 8 lsl3vbij 7bfqtokx 1.40 #> 15 jxh15obl t0rog7nz 1.53 #> 16 a7dppel1 t0rog7nz 1.78 #> 19 1l5kal0r t0rog7nz 1.98 #> 18 xkobdvuh t0rog7nz 2.17 #> 1 46kxib6w 7bfqtokx 2.20 #> 17 wk247s9w t0rog7nz 2.32 #> 2 iay3dhkn 7bfqtokx 2.37 #> 14 iagvtslv t0rog7nz 2.70 #> 5 2d72mfgh 7bfqtokx 2.73 #> 6 rvce7958 7bfqtokx 2.97 #> 4 3ttf7yix 7bfqtokx 4.35 #> 3 4zhzdmzo 7bfqtokx 6.08 #> #> $messages #> [1] \"Warning: For at least one participant, the experiment only has one page. I.e., the indices for the first and the last page are the same. See $only_one_page for information on this participant/these participants! Participants in this list are not included in the output.\" #> #> $only_one_page #> [1] \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" \"d4sq7zio\" #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":null,"dir":"Reference","previous_headings":"","what":"Import oTree data — import_otree","title":"Import oTree data — import_otree","text":"Import data files created oTree. files containing pattern YYYY-MM-DD end file names considered oTree files. Bot outputs saved oTree without date included. Hence, import bot data, must either rename original bot files using YYYY-MM-DD format use argument onlybots = TRUE. using second option, data bot files imported. Caution! Data can downloaded within session globally time. files downloaded, can lead $all_apps_wide data twice! can remove duplicate data using delete_duplicate. Caution! importing Excel files, function check erroneous data structures combine data frames file name patterns. using CSV = FALSE argument, clean data appropriately.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Import oTree data — import_otree","text":"","code":"import_otree( path = \".\", file_names = NULL, final_apps = NULL, final_pages = NULL, recursive = TRUE, csv = TRUE, onlybots = FALSE, del_empty = TRUE, info = FALSE, encoding = \"UTF-8\" )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Import oTree data — import_otree","text":"path Character. path files (default working directory). file_names Character. name(s) file(s) imported. specified, files path subfolders imported. final_apps Character. name(s) app(s) participants finish experiment. argument final_apps left empty, can still call deleting participants finish experiment delete_dropouts. final_pages Character. name(s) page(s) participants finish experiment. argument final_pages left empty, can still call deleting participants finish experiment delete_dropouts. recursive Logical. TRUE files path's subfolders also imported. csv Logical. TRUE CSV files imported. FALSE Excel files imported. onlybots Logical. TRUE bot-created files imported. del_empty Logical. TRUE empty cases deleted $all_apps_wide normal app data frames (Time Chats). info Logical. TRUE brief information data import printed. encoding Character. Encoding CSV files imported. Default \"UTF-8\".","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Import oTree data — import_otree","text":"Returns list data frames (one data frame app $all_apps_wide) list information list data frames $info. See detailed information imported files $info$imported_files. $all_apps_wide imported, see number imported cases $info$initial_n. number, empty rows already considered. , empty rows deleted del_empty=TRUE, initial_n counts rows empty. Cases deleted participants make last page /app subtracted number. Information: Empty rows rows without participant._current_app_name variable set. Empty rows deleted app data frames $all_apps_wide using del_empty = TRUE. Empty rows $Chats $Time data frames deleted. old new oTree versions combined, $Time data frame contains variables called participant_code participant__code (difference underscores). Caution! unusual amount NAs, check everything got imported correctly. Sometimes, CSV Excel file may corrupted, information found one column.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Import oTree data — import_otree","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() # Show the structure of the import str(oTree, max.level = 1) # Show the names of all imported files oTree$info$imported_files # Delete empty cases and delete every case of a person # who didn't end the experiment in the app \"survey\" oTree <- import_otree( del_empty = TRUE, final_apps = \"survey\", info = TRUE) # Show the structure of the import str(oTree, max.level = 1) # Import bot files import_otree( path = \"./bot_data\", onlybots = TRUE, csv = TRUE, info = TRUE) # Show the structure of the import str(oTree, max.level = 1) # Import with file names (path separately) oTree2 <- import_otree( del_empty = TRUE, path = \"./exp_data\", file_names = c(\"all_apps_wide-2023-03-27.csv\", \"ChatMessages-2023-03-27.csv\", \"PageTimes-2023-03-27.csv\"), onlybots = FALSE, csv = TRUE, info = TRUE) # Show the structure of the import str(oTree, max.level = 1) # Import with file names (without path separately) oTree2 <- import_otree( del_empty = TRUE, file_names = c(\"exp_data/all_apps_wide-2023-03-27.csv\", \"exp_data/ChatMessages-2023-03-27.csv\", \"exp_data/PageTimes-2023-03-27.csv\"), onlybots = FALSE, csv = TRUE, info = TRUE) # Show the structure of the import str(oTree, max.level = 1) }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. #> List of 8 #> $ all_apps_wide:'data.frame':\t41 obs. of 60 variables: #> $ info :List of 2 #> $ chatapp :'data.frame':\t33 obs. of 24 variables: #> $ dictator :'data.frame':\t123 obs. of 25 variables: #> $ survey :'data.frame':\t33 obs. of 29 variables: #> $ start :'data.frame':\t8 obs. of 24 variables: #> $ Time :'data.frame':\t366 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. #> Imported: 5 app(s) and/or all_apps_wide #> Imported: Time file(s) #> Imported: Chat file(s) #> 12 case(s) deleted #> Dropouts are deleted from all data frames. Except: The list of oTree data frames includes a chat. As the interpretation of chat data depends on how participants engage with each other, the data must be deleted with more care than deleting data in other apps. Hence, this function does not delete data in this data frame. Please do this manually if necessary! #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Imported: 4 app(s) and/or all_apps_wide #> No Time files available #> No chat files available #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Imported: 1 app(s) and/or all_apps_wide #> Imported: Time file(s) #> Imported: Chat file(s) #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Imported: 1 app(s) and/or all_apps_wide #> Imported: Time file(s) #> Imported: Chat file(s) #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables:"},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":null,"dir":"Reference","previous_headings":"","what":"Make IDs — make_ids","title":"Make IDs — make_ids","text":"Make session IDs , optionally, group IDs participant IDs span across data frames created import_otree. Information IDs taken $all_apps_wide can defined otherwise. Note: Older versions oTree may already contain variable called session_id $Time data frames. variable overwritten function! Important: Combine duplicate data running function!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Make IDs — make_ids","text":"","code":"make_ids( oTree, gmake = FALSE, pmake = TRUE, from_app = \"all_apps_wide\", from_var = NULL, sstart = 1L, gstart = 1L, pstart = 1L, emptyrows = NULL, icw = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Make IDs — make_ids","text":"oTree list data frames created import_otree. gmake Logical. TRUE variable called group_id made. from_var NULL, gmake automatically set TRUE. pmake Logical. TRUE variable called participant_id made. from_app Character. Name data frame session, group, participant information taken. normal app data frames $all_apps_wide allowed. from_var Character. Name variable group information taken. argument relevant $all_apps_wide used from_app group information contradicts . sstart Integer. number serves starting point session IDs. gstart Integer. number serves starting point group IDs. pstart Integer. number serves starting point participant IDs. emptyrows Character. \"\" function stop empty rows from_app. \"yes\" function continue make IDs. icw Logical. TRUE warning message ignored states IDs made oTree bug.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Make IDs — make_ids","text":"ID variables made $all_apps_wide, app data frames, $Time data frame, $Chats data frame. See list additional ID variables $info$additional_variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Make IDs — make_ids","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Make session IDs only oTree2 <- make_ids(oTree) # Show new variables oTree2$all_apps_wide$session_id #> [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5 6 6 6 6 # Make session IDs and group IDs # Not working with this data set because group ID is not the same in all apps if (FALSE) { # \\dontrun{ oTree2 <- make_ids(oTree, gmake = TRUE) # Show new variables oTree2$all_apps_wide$session_id oTree2$all_apps_wide$group_id } # } # Get IDs from variable \"dictator.1.group.id_in_subsession\" # in the data frame \"all_apps_wide\" oTree2 <- make_ids(oTree, gmake = TRUE, from_var = \"dictator.1.group.id_in_subsession\") # Show new variables oTree2$all_apps_wide$session_id #> [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5 6 6 6 6 oTree2$all_apps_wide$group_id #> [1] 1 1 2 2 3 3 4 4 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 #> [26] 14 14 15 15 # Get IDs from another app than all_apps_wide oTree2 <- make_ids(oTree, gmake = TRUE, from_app = \"dictator\") #> Warning: Data frame \"all_apps_wide\" has more participants than dictator: 6cim3a5i, 1mn1kzs7, zdki96d6, byxco6zo # Show new variables oTree2$all_apps_wide$session_id #> [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5 #> [26] NA NA NA NA oTree2$all_apps_wide$group_id #> [1] 1 1 2 2 3 3 4 4 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 #> [26] NA NA NA NA"},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":null,"dir":"Reference","previous_headings":"","what":"Check if the Chats data frame is messy — messy_chat","title":"Check if the Chats data frame is messy — messy_chat","text":"Check $Chats data frame includes session-related variables participant-related variables appear multiple times. may occur data different oTree versions, use different variable names, combined. desired, function can merge variables, storing data using newer oTree version's variable names removing outdated variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check if the Chats data frame is messy — messy_chat","text":"","code":"messy_chat( oTree, combine = FALSE, session = TRUE, participant = TRUE, info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check if the Chats data frame is messy — messy_chat","text":"oTree list data frames created import_otree. combine Logical. TRUE variables referring session code merged /variables referring participant code merged case data several versions oTree used. session Logical. TRUE variables referring session code checked merged. Merging works combine = TRUE. participant Logical. TRUE variables referring participant code checked merged. Merging works combine = TRUE. info Logical. TRUE brief information process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check if the Chats data frame is messy — messy_chat","text":"function searches multiple variables related session code participant code $Chats data frame. can occur data old new oTree versions used. combine = FALSE, function throw error variables found. combine = TRUE, function throw error variables found. Instead, automatically combines variables new variables adds original $Chats data frame. function returns duplicate original oTree list $Chats data frame modified. new variables called participant_code session_code.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check if the Chats data frame is messy — messy_chat","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. # Show all Chats column names print(colnames(oTree$Chats)) #> [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" #> [5] \"nickname\" \"body\" \"timestamp\" # Run function oTree <- messy_chat(oTree, combine = TRUE) # Show all Chats column names again print(colnames(oTree$Chats)) #> [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" #> [5] \"nickname\" \"body\" \"timestamp\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":null,"dir":"Reference","previous_headings":"","what":"Check if the Time data frame is messy — messy_time","title":"Check if the Time data frame is messy — messy_time","text":"Checks Time data frame includes participant-related variables time stamp variables appear multiple times. may occur data different oTree versions, use different variable names, combined. desired, function can merge variables, storing data using newer oTree version's variable names removing outdated variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check if the Time data frame is messy — messy_time","text":"","code":"messy_time( oTree, combine = FALSE, epoch_time = TRUE, participant = TRUE, info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check if the Time data frame is messy — messy_time","text":"oTree list data frames created import_otree. combine Logical. TRUE variables referring epoch time merged /variables referring participant code merged case data several versions oTree used. epoch_time Logical. TRUE variables referring time stamp checked merged. works combine = TRUE. participant Logical. TRUE variables referring participant code checked merged. works combine = TRUE. info Logical. TRUE brief information process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check if the Time data frame is messy — messy_time","text":"function searches multiple variables related time stamp participant code $Time data frame, can occur data old new oTree versions used. combine = FALSE, function throw error variables found. combine = TRUE, function throw error variables found. Instead, automatically combines variables new variables adds original $Time data frame. function returns duplicate original oTree list $Time data frame modified. new variables called epoch_time_completed participant_code.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check if the Time data frame is messy — messy_time","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. # Show all Time column names print(colnames(oTree$Time)) #> [1] \"session_code\" \"participant_id_in_session\" #> [3] \"participant_code\" \"page_index\" #> [5] \"app_name\" \"page_name\" #> [7] \"epoch_time_completed\" \"round_number\" #> [9] \"timeout_happened\" \"is_wait_page\" # Run function oTree <- messy_time(oTree, combine = TRUE) # Show all Time column names again print(colnames(oTree$Time)) #> [1] \"session_code\" \"participant_id_in_session\" #> [3] \"participant_code\" \"page_index\" #> [5] \"app_name\" \"page_name\" #> [7] \"epoch_time_completed\" \"round_number\" #> [9] \"timeout_happened\" \"is_wait_page\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":null,"dir":"Reference","previous_headings":"","what":"Sample experiment data — oTree","title":"Sample experiment data — oTree","text":"Sample experiment data","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Sample experiment data — oTree","text":"","code":"oTree"},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Sample experiment data — oTree","text":"list data frames created import_otree().","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":"source","dir":"Reference","previous_headings":"","what":"Source","title":"Sample experiment data — oTree","text":"data set created using modified versions official oTree sample experiments can downloaded installing oTree. detail, following apps used: \"start,\" \"dictator,\" \"chatapp,\" \"survey.\"","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the seconds spent on each page — pagesec","title":"Calculate the seconds spent on each page — pagesec","text":"Create new variable $Time data frame contains time spent page.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the seconds spent on each page — pagesec","text":"","code":"pagesec(oTree, rounded = TRUE, digits = 2, minutes = FALSE, combine = FALSE)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the seconds spent on each page — pagesec","text":"oTree list data frames created import_otree. rounded Logical. TRUE output rounded. digits Integer. number digits output rounded. parameter effect unless rounded = TRUE. minutes Logical. TRUE output minutes instead seconds. combine Logical. TRUE variables referring epoch time merged, variables referring participant code merged case data several versions oTree used.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the seconds spent on each page — pagesec","text":"function returns duplicate original oTree list data frames also contains column $Time data frame named seconds_on_page2 minutes_on_page.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the seconds spent on each page — pagesec","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Create two new columns: seconds_on_page2 and minutes_on_page oTree <- pagesec(oTree, rounded = TRUE, minutes = TRUE) # Show the Time data frame head(oTree$Time, n = 30) #> session_code participant_id_in_session participant_code page_index app_name #> 1 7bfqtokx 1 46kxib6w 0 #> 2 7bfqtokx 2 iay3dhkn 0 #> 3 7bfqtokx 3 4zhzdmzo 0 #> 4 7bfqtokx 4 3ttf7yix 0 #> 5 7bfqtokx 5 2d72mfgh 0 #> 6 7bfqtokx 6 rvce7958 0 #> 7 7bfqtokx 7 164r1hs4 0 #> 8 7bfqtokx 8 lsl3vbij 0 #> 9 7bfqtokx 9 ktjz5jli 0 #> 10 7bfqtokx 1 46kxib6w 1 dictator #> 11 7bfqtokx 1 46kxib6w 2 dictator #> 12 7bfqtokx 2 iay3dhkn 1 dictator #> 13 7bfqtokx 1 46kxib6w 3 dictator #> 14 7bfqtokx 2 iay3dhkn 3 dictator #> 15 7bfqtokx 2 iay3dhkn 4 dictator #> 16 7bfqtokx 2 iay3dhkn 5 dictator #> 17 7bfqtokx 1 46kxib6w 4 dictator #> 18 7bfqtokx 1 46kxib6w 5 dictator #> 19 7bfqtokx 1 46kxib6w 6 dictator #> 20 7bfqtokx 1 46kxib6w 7 dictator #> 21 7bfqtokx 2 iay3dhkn 7 dictator #> 22 7bfqtokx 1 46kxib6w 8 dictator #> 23 7bfqtokx 1 46kxib6w 9 dictator #> 24 7bfqtokx 1 46kxib6w 10 dictator #> 25 7bfqtokx 2 iay3dhkn 8 dictator #> 26 7bfqtokx 2 iay3dhkn 9 dictator #> 27 7bfqtokx 1 46kxib6w 11 dictator #> 28 7bfqtokx 2 iay3dhkn 11 dictator #> 29 7bfqtokx 2 iay3dhkn 12 dictator #> 30 7bfqtokx 1 46kxib6w 12 dictator #> page_name epoch_time_completed round_number timeout_happened #> 1 InitializeParticipant 1679926144 1 0 #> 2 InitializeParticipant 1679926145 1 0 #> 3 InitializeParticipant 1679926146 1 0 #> 4 InitializeParticipant 1679926146 1 0 #> 5 InitializeParticipant 1679926147 1 0 #> 6 InitializeParticipant 1679926147 1 0 #> 7 InitializeParticipant 1679926148 1 0 #> 8 InitializeParticipant 1679926148 1 0 #> 9 InitializeParticipant 1679926149 1 0 #> 10 Introduction 1679926151 1 0 #> 11 Offer 1679926154 1 0 #> 12 Introduction 1679926156 1 0 #> 13 ResultsWaitPage 1679926156 1 0 #> 14 ResultsWaitPage 1679926156 1 0 #> 15 Results 1679926157 1 0 #> 16 Introduction 1679926158 2 0 #> 17 Results 1679926160 1 0 #> 18 Introduction 1679926162 2 0 #> 19 Offer 1679926165 2 0 #> 20 ResultsWaitPage 1679926165 2 0 #> 21 ResultsWaitPage 1679926165 2 0 #> 22 Results 1679926166 2 0 #> 23 Introduction 1679926167 3 0 #> 24 Offer 1679926169 3 0 #> 25 Results 1679926171 2 0 #> 26 Introduction 1679926172 3 0 #> 27 ResultsWaitPage 1679926172 3 0 #> 28 ResultsWaitPage 1679926172 3 0 #> 29 Results 1679926173 3 0 #> 30 Results 1679926178 3 0 #> is_wait_page minutes_on_page #> 1 0 NA #> 2 0 NA #> 3 0 NA #> 4 0 NA #> 5 0 NA #> 6 0 NA #> 7 0 NA #> 8 0 NA #> 9 0 NA #> 10 0 0.12 #> 11 0 0.05 #> 12 0 0.18 #> 13 1 0.03 #> 14 1 0.00 #> 15 0 0.02 #> 16 0 0.02 #> 17 0 0.07 #> 18 0 0.03 #> 19 0 0.05 #> 20 1 0.00 #> 21 1 0.12 #> 22 0 0.02 #> 23 0 0.02 #> 24 0 0.03 #> 25 0 0.10 #> 26 0 0.02 #> 27 1 0.05 #> 28 1 0.00 #> 29 0 0.02 #> 30 0 0.10"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":null,"dir":"Reference","previous_headings":"","what":"Show constant columns — show_constant","title":"Show constant columns — show_constant","text":"Show columns variation values data frame oTree list data frames (except ones info list). function helpful running experiment check unnecessary variables. can check columns unchanging possible value columns containing specific value.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show constant columns — show_constant","text":"","code":"show_constant(oTree, value = \"any\")"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show constant columns — show_constant","text":"oTree list data frames created import_otree. value value controlled within column. value set \"\", function checks columns possible values identical.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show constant columns — show_constant","text":"function returns list vectors, one app, $all_apps_wide, $Time /$Chats data frame. vector contains names variables constant values. variables constant values, vector empty.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show constant columns — show_constant","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show all columns that contain only NAs show_constant(oTree = oTree) #> $all_apps_wide #> [1] \"participant._is_bot\" #> [2] \"participant._max_page_index\" #> [3] \"participant.visited\" #> [4] \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" #> [6] \"session.label\" #> [7] \"session.mturk_HITId\" #> [8] \"session.mturk_HITGroupId\" #> [9] \"session.comment\" #> [10] \"session.is_demo\" #> [11] \"session.config.name\" #> [12] \"session.config.real_world_currency_per_point\" #> [13] \"session.config.participation_fee\" #> [14] \"dictator.1.player.role\" #> [15] \"dictator.1.subsession.round_number\" #> [16] \"dictator.2.player.role\" #> [17] \"dictator.2.subsession.round_number\" #> [18] \"dictator.3.player.role\" #> [19] \"dictator.3.subsession.round_number\" #> [20] \"chatapp.1.player.role\" #> [21] \"chatapp.1.player.payoff\" #> [22] \"chatapp.1.subsession.round_number\" #> [23] \"survey.1.player.role\" #> [24] \"survey.1.player.payoff\" #> [25] \"survey.1.group.id_in_subsession\" #> [26] \"survey.1.subsession.round_number\" #> #> $chatapp #> [1] \"participant._is_bot\" \"participant._max_page_index\" #> [3] \"participant.visited\" \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" \"player.role\" #> [7] \"player.payoff\" \"subsession.round_number\" #> [9] \"session.label\" \"session.mturk_HITId\" #> [11] \"session.mturk_HITGroupId\" \"session.comment\" #> [13] \"session.is_demo\" #> #> $dictator #> [1] \"participant._is_bot\" \"participant._max_page_index\" #> [3] \"participant.visited\" \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" \"player.role\" #> [7] \"session.label\" \"session.mturk_HITId\" #> [9] \"session.mturk_HITGroupId\" \"session.comment\" #> [11] \"session.is_demo\" #> #> $survey #> [1] \"participant._is_bot\" \"participant._max_page_index\" #> [3] \"participant.visited\" \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" \"player.role\" #> [7] \"player.payoff\" \"group.id_in_subsession\" #> [9] \"subsession.round_number\" \"session.label\" #> [11] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [13] \"session.comment\" \"session.is_demo\" #> #> $Time #> [1] \"timeout_happened\" #> #> $Chats #> character(0) #> show_constant(oTree = oTree, value = NA) #> $all_apps_wide #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"session.label\" \"session.mturk_HITId\" #> [5] \"session.mturk_HITGroupId\" \"session.comment\" #> [7] \"dictator.1.player.role\" \"dictator.2.player.role\" #> [9] \"dictator.3.player.role\" \"chatapp.1.player.role\" #> [11] \"survey.1.player.role\" #> #> $chatapp #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"player.role\" \"session.label\" #> [5] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [7] \"session.comment\" #> #> $dictator #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"player.role\" \"session.label\" #> [5] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [7] \"session.comment\" #> #> $survey #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"player.role\" \"session.label\" #> [5] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [7] \"session.comment\" #> #> $Time #> character(0) #> #> $Chats #> character(0) #> # Show all columns that contain only -99 show_constant(oTree = oTree, value = -99) #> $all_apps_wide #> character(0) #> #> $chatapp #> character(0) #> #> $dictator #> character(0) #> #> $survey #> character(0) #> #> $Time #> character(0) #> #> $Chats #> character(0) #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":null,"dir":"Reference","previous_headings":"","what":"Show participants who did not finish the experiment — show_dropouts","title":"Show participants who did not finish the experiment — show_dropouts","text":"Show information people finish experiment () certain page(s) /app(s).","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show participants who did not finish the experiment — show_dropouts","text":"","code":"show_dropouts(oTree, final_apps = NULL, final_pages = NULL, saved_vars = NULL)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show participants who did not finish the experiment — show_dropouts","text":"oTree list data frames created import_otree. final_apps Character. name(s) app(s) participants finish experiment. final_pages Character. name(s) page(s) participants finish experiment. saved_vars name(s) variable(s) need(s) shown list information dropout cases.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show participants who did not finish the experiment — show_dropouts","text":"function returns list information participants finish experiment. list, can find following information: - $full = data frame contains information participants finish study; shows participant codes, names apps left experiment, names pages left experiment, names app data frames information found, dropout reason (\"ENC\", experiment completed, combined name data frame dropout observed). participants usually appear multiple app data frames, $full data frame may contain several entries person. - $unique = data frame contains similar information $full data frame one row per participant information data frame dropout observed. - $all_end = table provides information app page combinations participants ended experiment. table also includes information participants drop experiment. $all_end table shown $all_apps_wide data frame exists. - $codes = vector containing participant codes participants finish experiment. - $count = number participants finish experiment. important note argument final_pages set, function distinguish page names reoccur different apps. columns end_app end_page output empty, variables saved oTree specific participants. empty rows deleted. can done using argument del_empty = TRUE\" using import_otree.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show participants who did not finish the experiment — show_dropouts","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show everyone who did not finish with the app \"survey\" show_dropouts(oTree, final_apps = \"survey\") #> $full #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 2 164r1hs4 7bfqtokx chatapp chat #> 3 164r1hs4 7bfqtokx chatapp chat #> 4 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 6 2scvem7a vd1h01iv dictator ResultsWaitPage #> 7 2scvem7a vd1h01iv dictator ResultsWaitPage #> 8 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 10 7wa8kk3d l8ecm1uh dictator Introduction #> 11 7wa8kk3d l8ecm1uh dictator Introduction #> 12 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 14 ao9kqvqn l8ecm1uh dictator Introduction #> 15 ao9kqvqn l8ecm1uh dictator Introduction #> 16 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 18 d4sq7zio l8ecm1uh dictator Introduction #> 19 d4sq7zio l8ecm1uh dictator Introduction #> 20 d4sq7zio l8ecm1uh dictator Introduction #> 21 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 22 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 23 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 24 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 25 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 26 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 27 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 28 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 29 znri6myc l8ecm1uh dictator Introduction #> 30 znri6myc l8ecm1uh dictator Introduction #> 31 znri6myc l8ecm1uh dictator Introduction #> 32 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed. Noticed at: all_apps_wide #> 2 Experiment not completed. Noticed at: chatapp #> 3 Experiment not completed. Noticed at: dictator #> 4 Experiment not completed. Noticed at: survey #> 5 Experiment not completed. Noticed at: all_apps_wide #> 6 Experiment not completed. Noticed at: chatapp #> 7 Experiment not completed. Noticed at: dictator #> 8 Experiment not completed. Noticed at: survey #> 9 Experiment not completed. Noticed at: all_apps_wide #> 10 Experiment not completed. Noticed at: chatapp #> 11 Experiment not completed. Noticed at: dictator #> 12 Experiment not completed. Noticed at: survey #> 13 Experiment not completed. Noticed at: all_apps_wide #> 14 Experiment not completed. Noticed at: chatapp #> 15 Experiment not completed. Noticed at: dictator #> 16 Experiment not completed. Noticed at: survey #> 17 Experiment not completed. Noticed at: all_apps_wide #> 18 Experiment not completed. Noticed at: chatapp #> 19 Experiment not completed. Noticed at: dictator #> 20 Experiment not completed. Noticed at: survey #> 21 Experiment not completed. Noticed at: all_apps_wide #> 22 Experiment not completed. Noticed at: chatapp #> 23 Experiment not completed. Noticed at: dictator #> 24 Experiment not completed. Noticed at: survey #> 25 Experiment not completed. Noticed at: all_apps_wide #> 26 Experiment not completed. Noticed at: chatapp #> 27 Experiment not completed. Noticed at: dictator #> 28 Experiment not completed. Noticed at: survey #> 29 Experiment not completed. Noticed at: all_apps_wide #> 30 Experiment not completed. Noticed at: chatapp #> 31 Experiment not completed. Noticed at: dictator #> 32 Experiment not completed. Noticed at: survey #> #> $unique #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 21 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 25 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 29 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed #> 5 Experiment not completed #> 9 Experiment not completed #> 13 Experiment not completed #> 17 Experiment not completed #> 21 Experiment not completed #> 25 Experiment not completed #> 29 Experiment not completed #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"164r1hs4\" \"2scvem7a\" \"7wa8kk3d\" \"ao9kqvqn\" \"d4sq7zio\" \"ktjz5jli\" \"vbhvhozv\" #> [8] \"znri6myc\" #> #> $count #> [1] 8 #> # Show everyone who did not finish with the page \"Demographics\" show_dropouts(oTree, final_pages = \"Demographics\") #> $full #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 2 164r1hs4 7bfqtokx chatapp chat #> 3 164r1hs4 7bfqtokx chatapp chat #> 4 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 6 2scvem7a vd1h01iv dictator ResultsWaitPage #> 7 2scvem7a vd1h01iv dictator ResultsWaitPage #> 8 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 10 7wa8kk3d l8ecm1uh dictator Introduction #> 11 7wa8kk3d l8ecm1uh dictator Introduction #> 12 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 14 ao9kqvqn l8ecm1uh dictator Introduction #> 15 ao9kqvqn l8ecm1uh dictator Introduction #> 16 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 18 d4sq7zio l8ecm1uh dictator Introduction #> 19 d4sq7zio l8ecm1uh dictator Introduction #> 20 d4sq7zio l8ecm1uh dictator Introduction #> 21 jxh15obl t0rog7nz survey Offer #> 22 jxh15obl t0rog7nz survey Offer #> 23 jxh15obl t0rog7nz survey Offer #> 24 jxh15obl t0rog7nz survey Offer #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 26 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 27 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 28 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 30 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 31 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 32 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 33 znri6myc l8ecm1uh dictator Introduction #> 34 znri6myc l8ecm1uh dictator Introduction #> 35 znri6myc l8ecm1uh dictator Introduction #> 36 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed. Noticed at: all_apps_wide #> 2 Experiment not completed. Noticed at: survey #> 3 Experiment not completed. Noticed at: dictator #> 4 Experiment not completed. Noticed at: chatapp #> 5 Experiment not completed. Noticed at: survey #> 6 Experiment not completed. Noticed at: dictator #> 7 Experiment not completed. Noticed at: chatapp #> 8 Experiment not completed. Noticed at: all_apps_wide #> 9 Experiment not completed. Noticed at: survey #> 10 Experiment not completed. Noticed at: dictator #> 11 Experiment not completed. Noticed at: chatapp #> 12 Experiment not completed. Noticed at: all_apps_wide #> 13 Experiment not completed. Noticed at: survey #> 14 Experiment not completed. Noticed at: dictator #> 15 Experiment not completed. Noticed at: chatapp #> 16 Experiment not completed. Noticed at: all_apps_wide #> 17 Experiment not completed. Noticed at: dictator #> 18 Experiment not completed. Noticed at: chatapp #> 19 Experiment not completed. Noticed at: all_apps_wide #> 20 Experiment not completed. Noticed at: survey #> 21 Experiment not completed. Noticed at: chatapp #> 22 Experiment not completed. Noticed at: all_apps_wide #> 23 Experiment not completed. Noticed at: survey #> 24 Experiment not completed. Noticed at: dictator #> 25 Experiment not completed. Noticed at: survey #> 26 Experiment not completed. Noticed at: dictator #> 27 Experiment not completed. Noticed at: chatapp #> 28 Experiment not completed. Noticed at: all_apps_wide #> 29 Experiment not completed. Noticed at: survey #> 30 Experiment not completed. Noticed at: dictator #> 31 Experiment not completed. Noticed at: chatapp #> 32 Experiment not completed. Noticed at: all_apps_wide #> 33 Experiment not completed. Noticed at: survey #> 34 Experiment not completed. Noticed at: dictator #> 35 Experiment not completed. Noticed at: chatapp #> 36 Experiment not completed. Noticed at: all_apps_wide #> #> $unique #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 21 jxh15obl t0rog7nz survey Offer #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 33 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed #> 5 Experiment not completed #> 9 Experiment not completed #> 13 Experiment not completed #> 17 Experiment not completed #> 21 Experiment not completed #> 25 Experiment not completed #> 29 Experiment not completed #> 33 Experiment not completed #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"164r1hs4\" \"2scvem7a\" \"7wa8kk3d\" \"ao9kqvqn\" \"d4sq7zio\" \"jxh15obl\" \"ktjz5jli\" #> [8] \"vbhvhozv\" \"znri6myc\" #> #> $count #> [1] 9 #> # Show everyone who finished with the following apps: \"survey,\" \"dictator\" final_apps <- unique(oTree$all_apps_wide$participant._current_app_name) final_apps <- final_apps[final_apps != \"survey\"] final_apps <- final_apps[final_apps != \"dictator\"] show_dropouts(oTree, final_apps = final_apps) #> $full #> participant.code session.code end_app end_page #> 1 1l5kal0r t0rog7nz survey Demographics #> 2 1l5kal0r t0rog7nz survey Demographics #> 3 1l5kal0r t0rog7nz survey Demographics #> 4 1l5kal0r t0rog7nz survey Demographics #> 5 1mn1kzs7 gii59rga survey Demographics #> 6 2d72mfgh 7bfqtokx survey Demographics #> 7 2d72mfgh 7bfqtokx survey Demographics #> 8 2d72mfgh 7bfqtokx survey Demographics #> 9 2d72mfgh 7bfqtokx survey Demographics #> 10 2scvem7a vd1h01iv dictator ResultsWaitPage #> 11 2scvem7a vd1h01iv dictator ResultsWaitPage #> 12 2scvem7a vd1h01iv dictator ResultsWaitPage #> 13 2scvem7a vd1h01iv dictator ResultsWaitPage #> 14 3ttf7yix 7bfqtokx survey Demographics #> 15 3ttf7yix 7bfqtokx survey Demographics #> 16 3ttf7yix 7bfqtokx survey Demographics #> 17 3ttf7yix 7bfqtokx survey Demographics #> 18 46kxib6w 7bfqtokx survey Demographics #> 19 46kxib6w 7bfqtokx survey Demographics #> 20 46kxib6w 7bfqtokx survey Demographics #> 21 46kxib6w 7bfqtokx survey Demographics #> 22 4zhzdmzo 7bfqtokx survey Demographics #> 23 4zhzdmzo 7bfqtokx survey Demographics #> 24 4zhzdmzo 7bfqtokx survey Demographics #> 25 4zhzdmzo 7bfqtokx survey Demographics #> 26 6cim3a5i gii59rga survey Demographics #> 27 7l0hmpcq qyu3qg0q survey Demographics #> 28 7l0hmpcq qyu3qg0q survey Demographics #> 29 7l0hmpcq qyu3qg0q survey Demographics #> 30 7l0hmpcq qyu3qg0q survey Demographics #> 31 7wa8kk3d l8ecm1uh dictator Introduction #> 32 7wa8kk3d l8ecm1uh dictator Introduction #> 33 7wa8kk3d l8ecm1uh dictator Introduction #> 34 7wa8kk3d l8ecm1uh dictator Introduction #> 35 a7dppel1 t0rog7nz survey Demographics #> 36 a7dppel1 t0rog7nz survey Demographics #> 37 a7dppel1 t0rog7nz survey Demographics #> 38 a7dppel1 t0rog7nz survey Demographics #> 39 ao9kqvqn l8ecm1uh dictator Introduction #> 40 ao9kqvqn l8ecm1uh dictator Introduction #> 41 ao9kqvqn l8ecm1uh dictator Introduction #> 42 ao9kqvqn l8ecm1uh dictator Introduction #> 43 byxco6zo gii59rga survey Demographics #> 44 d4sq7zio l8ecm1uh dictator Introduction #> 45 d4sq7zio l8ecm1uh dictator Introduction #> 46 d4sq7zio l8ecm1uh dictator Introduction #> 47 d4sq7zio l8ecm1uh dictator Introduction #> 48 ia9rnfvc qyu3qg0q survey Demographics #> 49 ia9rnfvc qyu3qg0q survey Demographics #> 50 ia9rnfvc qyu3qg0q survey Demographics #> 51 ia9rnfvc qyu3qg0q survey Demographics #> 52 iagvtslv t0rog7nz survey Demographics #> 53 iagvtslv t0rog7nz survey Demographics #> 54 iagvtslv t0rog7nz survey Demographics #> 55 iagvtslv t0rog7nz survey Demographics #> 56 iay3dhkn 7bfqtokx survey Demographics #> 57 iay3dhkn 7bfqtokx survey Demographics #> 58 iay3dhkn 7bfqtokx survey Demographics #> 59 iay3dhkn 7bfqtokx survey Demographics #> 60 jxh15obl t0rog7nz survey Offer #> 61 jxh15obl t0rog7nz survey Offer #> 62 jxh15obl t0rog7nz survey Offer #> 63 jxh15obl t0rog7nz survey Offer #> 64 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 65 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 66 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 67 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 68 lsl3vbij 7bfqtokx survey Demographics #> 69 lsl3vbij 7bfqtokx survey Demographics #> 70 lsl3vbij 7bfqtokx survey Demographics #> 71 lsl3vbij 7bfqtokx survey Demographics #> 72 rvce7958 7bfqtokx survey Demographics #> 73 rvce7958 7bfqtokx survey Demographics #> 74 rvce7958 7bfqtokx survey Demographics #> 75 rvce7958 7bfqtokx survey Demographics #> 76 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 77 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 78 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 79 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 80 wk247s9w t0rog7nz survey Demographics #> 81 wk247s9w t0rog7nz survey Demographics #> 82 wk247s9w t0rog7nz survey Demographics #> 83 wk247s9w t0rog7nz survey Demographics #> 84 xkobdvuh t0rog7nz survey Demographics #> 85 xkobdvuh t0rog7nz survey Demographics #> 86 xkobdvuh t0rog7nz survey Demographics #> 87 xkobdvuh t0rog7nz survey Demographics #> 88 xmxl46rm vd1h01iv survey Demographics #> 89 xmxl46rm vd1h01iv survey Demographics #> 90 xmxl46rm vd1h01iv survey Demographics #> 91 xmxl46rm vd1h01iv survey Demographics #> 92 xx78b3x0 vd1h01iv survey Demographics #> 93 xx78b3x0 vd1h01iv survey Demographics #> 94 xx78b3x0 vd1h01iv survey Demographics #> 95 xx78b3x0 vd1h01iv survey Demographics #> 96 zdki96d6 gii59rga survey Demographics #> 97 znri6myc l8ecm1uh dictator Introduction #> 98 znri6myc l8ecm1uh dictator Introduction #> 99 znri6myc l8ecm1uh dictator Introduction #> 100 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed. Noticed at: chatapp #> 2 Experiment not completed. Noticed at: all_apps_wide #> 3 Experiment not completed. Noticed at: dictator #> 4 Experiment not completed. Noticed at: survey #> 5 Experiment not completed. Noticed at: all_apps_wide #> 6 Experiment not completed. Noticed at: chatapp #> 7 Experiment not completed. Noticed at: all_apps_wide #> 8 Experiment not completed. Noticed at: dictator #> 9 Experiment not completed. Noticed at: survey #> 10 Experiment not completed. Noticed at: survey #> 11 Experiment not completed. Noticed at: all_apps_wide #> 12 Experiment not completed. Noticed at: dictator #> 13 Experiment not completed. Noticed at: chatapp #> 14 Experiment not completed. Noticed at: chatapp #> 15 Experiment not completed. Noticed at: dictator #> 16 Experiment not completed. Noticed at: survey #> 17 Experiment not completed. Noticed at: all_apps_wide #> 18 Experiment not completed. Noticed at: all_apps_wide #> 19 Experiment not completed. Noticed at: dictator #> 20 Experiment not completed. Noticed at: chatapp #> 21 Experiment not completed. Noticed at: survey #> 22 Experiment not completed. Noticed at: chatapp #> 23 Experiment not completed. Noticed at: survey #> 24 Experiment not completed. Noticed at: all_apps_wide #> 25 Experiment not completed. Noticed at: dictator #> 26 Experiment not completed. Noticed at: all_apps_wide #> 27 Experiment not completed. Noticed at: dictator #> 28 Experiment not completed. Noticed at: chatapp #> 29 Experiment not completed. Noticed at: all_apps_wide #> 30 Experiment not completed. Noticed at: survey #> 31 Experiment not completed. Noticed at: chatapp #> 32 Experiment not completed. Noticed at: all_apps_wide #> 33 Experiment not completed. Noticed at: dictator #> 34 Experiment not completed. Noticed at: survey #> 35 Experiment not completed. Noticed at: survey #> 36 Experiment not completed. Noticed at: all_apps_wide #> 37 Experiment not completed. Noticed at: dictator #> 38 Experiment not completed. Noticed at: chatapp #> 39 Experiment not completed. Noticed at: chatapp #> 40 Experiment not completed. Noticed at: all_apps_wide #> 41 Experiment not completed. Noticed at: dictator #> 42 Experiment not completed. Noticed at: survey #> 43 Experiment not completed. Noticed at: all_apps_wide #> 44 Experiment not completed. Noticed at: chatapp #> 45 Experiment not completed. Noticed at: all_apps_wide #> 46 Experiment not completed. Noticed at: dictator #> 47 Experiment not completed. Noticed at: survey #> 48 Experiment not completed. Noticed at: all_apps_wide #> 49 Experiment not completed. Noticed at: dictator #> 50 Experiment not completed. Noticed at: chatapp #> 51 Experiment not completed. Noticed at: survey #> 52 Experiment not completed. Noticed at: chatapp #> 53 Experiment not completed. Noticed at: survey #> 54 Experiment not completed. Noticed at: all_apps_wide #> 55 Experiment not completed. Noticed at: dictator #> 56 Experiment not completed. Noticed at: survey #> 57 Experiment not completed. Noticed at: all_apps_wide #> 58 Experiment not completed. Noticed at: dictator #> 59 Experiment not completed. Noticed at: chatapp #> 60 Experiment not completed. Noticed at: all_apps_wide #> 61 Experiment not completed. Noticed at: dictator #> 62 Experiment not completed. Noticed at: chatapp #> 63 Experiment not completed. Noticed at: survey #> 64 Experiment not completed. Noticed at: chatapp #> 65 Experiment not completed. Noticed at: all_apps_wide #> 66 Experiment not completed. Noticed at: dictator #> 67 Experiment not completed. Noticed at: survey #> 68 Experiment not completed. Noticed at: chatapp #> 69 Experiment not completed. Noticed at: dictator #> 70 Experiment not completed. Noticed at: all_apps_wide #> 71 Experiment not completed. Noticed at: survey #> 72 Experiment not completed. Noticed at: chatapp #> 73 Experiment not completed. Noticed at: all_apps_wide #> 74 Experiment not completed. Noticed at: dictator #> 75 Experiment not completed. Noticed at: survey #> 76 Experiment not completed. Noticed at: all_apps_wide #> 77 Experiment not completed. Noticed at: dictator #> 78 Experiment not completed. Noticed at: chatapp #> 79 Experiment not completed. Noticed at: survey #> 80 Experiment not completed. Noticed at: chatapp #> 81 Experiment not completed. Noticed at: survey #> 82 Experiment not completed. Noticed at: all_apps_wide #> 83 Experiment not completed. Noticed at: dictator #> 84 Experiment not completed. Noticed at: chatapp #> 85 Experiment not completed. Noticed at: dictator #> 86 Experiment not completed. Noticed at: survey #> 87 Experiment not completed. Noticed at: all_apps_wide #> 88 Experiment not completed. Noticed at: dictator #> 89 Experiment not completed. Noticed at: chatapp #> 90 Experiment not completed. Noticed at: all_apps_wide #> 91 Experiment not completed. Noticed at: survey #> 92 Experiment not completed. Noticed at: chatapp #> 93 Experiment not completed. Noticed at: all_apps_wide #> 94 Experiment not completed. Noticed at: dictator #> 95 Experiment not completed. Noticed at: survey #> 96 Experiment not completed. Noticed at: all_apps_wide #> 97 Experiment not completed. Noticed at: chatapp #> 98 Experiment not completed. Noticed at: dictator #> 99 Experiment not completed. Noticed at: all_apps_wide #> 100 Experiment not completed. Noticed at: survey #> #> $unique #> participant.code session.code end_app end_page #> 1 1l5kal0r t0rog7nz survey Demographics #> 5 1mn1kzs7 gii59rga survey Demographics #> 6 2d72mfgh 7bfqtokx survey Demographics #> 10 2scvem7a vd1h01iv dictator ResultsWaitPage #> 14 3ttf7yix 7bfqtokx survey Demographics #> 18 46kxib6w 7bfqtokx survey Demographics #> 22 4zhzdmzo 7bfqtokx survey Demographics #> 26 6cim3a5i gii59rga survey Demographics #> 27 7l0hmpcq qyu3qg0q survey Demographics #> 31 7wa8kk3d l8ecm1uh dictator Introduction #> 35 a7dppel1 t0rog7nz survey Demographics #> 39 ao9kqvqn l8ecm1uh dictator Introduction #> 43 byxco6zo gii59rga survey Demographics #> 44 d4sq7zio l8ecm1uh dictator Introduction #> 48 ia9rnfvc qyu3qg0q survey Demographics #> 52 iagvtslv t0rog7nz survey Demographics #> 56 iay3dhkn 7bfqtokx survey Demographics #> 60 jxh15obl t0rog7nz survey Offer #> 64 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 68 lsl3vbij 7bfqtokx survey Demographics #> 72 rvce7958 7bfqtokx survey Demographics #> 76 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 80 wk247s9w t0rog7nz survey Demographics #> 84 xkobdvuh t0rog7nz survey Demographics #> 88 xmxl46rm vd1h01iv survey Demographics #> 92 xx78b3x0 vd1h01iv survey Demographics #> 96 zdki96d6 gii59rga survey Demographics #> 97 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed #> 5 Experiment not completed #> 6 Experiment not completed #> 10 Experiment not completed #> 14 Experiment not completed #> 18 Experiment not completed #> 22 Experiment not completed #> 26 Experiment not completed #> 27 Experiment not completed #> 31 Experiment not completed #> 35 Experiment not completed #> 39 Experiment not completed #> 43 Experiment not completed #> 44 Experiment not completed #> 48 Experiment not completed #> 52 Experiment not completed #> 56 Experiment not completed #> 60 Experiment not completed #> 64 Experiment not completed #> 68 Experiment not completed #> 72 Experiment not completed #> 76 Experiment not completed #> 80 Experiment not completed #> 84 Experiment not completed #> 88 Experiment not completed #> 92 Experiment not completed #> 96 Experiment not completed #> 97 Experiment not completed #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"1l5kal0r\" \"1mn1kzs7\" \"2d72mfgh\" \"2scvem7a\" \"3ttf7yix\" \"46kxib6w\" #> [7] \"4zhzdmzo\" \"6cim3a5i\" \"7l0hmpcq\" \"7wa8kk3d\" \"a7dppel1\" \"ao9kqvqn\" #> [13] \"byxco6zo\" \"d4sq7zio\" \"ia9rnfvc\" \"iagvtslv\" \"iay3dhkn\" \"jxh15obl\" #> [19] \"ktjz5jli\" \"lsl3vbij\" \"rvce7958\" \"vbhvhozv\" \"wk247s9w\" \"xkobdvuh\" #> [25] \"xmxl46rm\" \"xx78b3x0\" \"zdki96d6\" \"znri6myc\" #> #> $count #> [1] 28 #>"},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-120","dir":"Changelog","previous_headings":"","what":"gmoTree 1.2.0","title":"gmoTree 1.2.0","text":"codebook(): Create codebook oTree code Linted code (readable) Minor changes warning messages tests examples","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-110","dir":"Changelog","previous_headings":"","what":"gmoTree 1.1.0","title":"gmoTree 1.1.0","text":"CRAN release: 2024-07-04 extime(): Enhanced efficiency extended functionality: Introduced capability perform calculations using ‘seconds_on_page2’ variable. apptime(): Enhanced efficiency extended functionality: Introduced capability perform calculations using ‘seconds_on_page2’ variable. Linted code (efficient & readable) Minor changes tests.R Minor changes website, new logo","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-101","dir":"Changelog","previous_headings":"","what":"gmoTree 1.0.1","title":"gmoTree 1.0.1","text":"CRAN release: 2023-10-25 Minor changes examples DESCRIPTION file. Changes functions: NONE","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-100","dir":"Changelog","previous_headings":"","what":"gmoTree 1.0.0","title":"gmoTree 1.0.0","text":"File names examples now portable. import_otree(): Minor changes. Can also import portable file names now.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-003","dir":"Changelog","previous_headings":"","what":"gmoTree 0.0.3","title":"gmoTree 0.0.3","text":"Minor improvement documentation & website. Changes functions: NONE","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-002","dir":"Changelog","previous_headings":"","what":"gmoTree 0.0.2","title":"gmoTree 0.0.2","text":"Minor improvement documentation & website. (Sent CRAN omitted .) Changes functions: NONE","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-001","dir":"Changelog","previous_headings":"","what":"gmoTree 0.0.1","title":"gmoTree 0.0.1","text":"Beta version gmoTree published (formerly known “ioTree”).","code":""}]
+[{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"overview","dir":"Articles","previous_headings":"","what":"Overview","title":"gmoTree Codebooks","text":"gmoTree package provides tools generating codebooks based data oTree (Chen et al., 2016) framework function codebook(). vignette introduces key features functionalities. Disclaimer: code tested custom implementations official oTree sample codes.1 However, due complexity oTree setups, may address variations. Please review output carefully, feel free open GitHub issue encounter problems.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"running-the-code","dir":"Articles","previous_headings":"","what":"Running the code","title":"gmoTree Codebooks","text":"simplest form, function requires path oTree code. following code reads contents oTree file, saves file containing codebook working directory, returns list named cbook, containing extracted information.","code":"cbook <- codebook(\"D:/pathtoyourproject/oTree_codes\")"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"codebook-structure-and-output","dir":"Articles","previous_headings":"","what":"Codebook structure and output","title":"gmoTree Codebooks","text":"output structured clear headings: Heading Level 1: Represents app oTree data. Heading Level 2: Group Player variables, categorized within app. Showing class Constants optional can turned using argument include_cons = FALSE. example shows output cournot app, includes Constants, Group, Player variables. class contains information, heading still appear, along message “Empty class.” Use output = \"list\" bypass file creation. option returns information list format, can used R Markdown design custom codebook. example list output looks like. (argument doc_info = FALSE suppresses messages missing variable documentation.)","code":"# Create the codebook list cbook <- codebook(path = system.file(path = \"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", doc_info = FALSE) str(cbook, 1) # Show all apps ## List of 16 ## $ settings :List of 10 ## $ bargaining :List of 4 ## $ bertrand :List of 4 ## $ common_value_auction:List of 4 ## $ cournot :List of 4 ## $ dictator :List of 4 ## $ guess_two_thirds :List of 4 ## $ matching_pennies :List of 4 ## $ payment_info :List of 4 ## $ prisoner :List of 4 ## $ public_goods_simple :List of 3 ## $ survey :List of 3 ## $ traveler_dilemma :List of 4 ## $ trust :List of 3 ## $ trust_simple :List of 3 ## $ volunteer_dilemma :List of 4 print(cbook$cournot) # Only show cournot app ## $doc ## [1] \"In Cournot competition, firms simultaneously decide the units of products to manufacture. The unit selling price depends on the total units produced. In this implementation, there are 2 firms competing for 1 period.\" ## ## $Constants ## $Constants$NAME_IN_URL ## [1] \"cournot\" ## ## $Constants$PLAYERS_PER_GROUP ## [1] 2 ## ## $Constants$NUM_ROUNDS ## [1] 1 ## ## $Constants$TOTAL_CAPACITY ## [1] 60 ## ## $Constants$MAX_UNITS_PER_PLAYER ## [1] \"int(60 / 2)\" ## ## ## $Group ## $Group$unit_price ## $Group$unit_price$noargs ## [1] TRUE ## ## $Group$unit_price$field ## [1] \"CurrencyField\" ## ## ## $Group$total_units ## $Group$total_units$noargs ## [1] FALSE ## ## $Group$total_units$doc ## [1] \"Total units produced by all players\" ## ## $Group$total_units$field ## [1] \"IntegerField\" ## ## ## ## $Player ## $Player$units ## $Player$units$noargs ## [1] \"FALSE\" ## ## $Player$units$min ## [1] \"0\" ## ## $Player$units$max ## [1] \"int(60 / 2)\" ## ## $Player$units$doc ## [1] \"Quantity of units to produce\" ## ## $Player$units$label ## [1] \"How many units will you produce (from 0 to 30)?\" ## ## $Player$units$field ## [1] \"IntegerField\""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"apps","dir":"Articles","previous_headings":"Choosing what to show","what":"Apps","title":"gmoTree Codebooks","text":"Per default, apps included codebook. generate codebook one app, use app argument. example, generate codebook cournot app: code returns list app-specific information. can also generate codebooks multiple apps specifying app argument. can also choose remove one apps. example removes app prisoner:","code":"cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app = \"cournot\") str(cbook) ## List of 2 ## $ settings:List of 10 ## ..$ variable : num 66 ## ..$ PARTICIPANT_FIELDS : list() ## ..$ SESSION_FIELDS : list() ## ..$ LANGUAGE_CODE : chr \"en\" ## ..$ REAL_WORLD_CURRENCY_CODE: chr \"USD\" ## ..$ USE_POINTS : chr \"True\" ## ..$ ADMIN_USERNAME : chr \"admin\" ## ..$ ADMIN_PASSWORD : chr \"environ.get('OTREE_ADMIN_PASSWORD')\" ## ..$ DEMO_PAGE_INTRO_HTML : chr \"Here are some oTree games.\" ## ..$ SECRET_KEY : chr \"9356668094877\" ## $ cournot :List of 4 ## ..$ doc : chr \"In Cournot competition, firms simultaneously decide the units of products to manufacture. The unit selling pric\"| __truncated__ ## ..$ Constants:List of 5 ## .. ..$ NAME_IN_URL : chr \"cournot\" ## .. ..$ PLAYERS_PER_GROUP : num 2 ## .. ..$ NUM_ROUNDS : num 1 ## .. ..$ TOTAL_CAPACITY : num 60 ## .. ..$ MAX_UNITS_PER_PLAYER: chr \"int(60 / 2)\" ## ..$ Group :List of 2 ## .. ..$ unit_price :List of 2 ## .. .. ..$ noargs: logi TRUE ## .. .. ..$ field : chr \"CurrencyField\" ## .. ..$ total_units:List of 3 ## .. .. ..$ noargs: logi FALSE ## .. .. ..$ doc : chr \"Total units produced by all players\" ## .. .. ..$ field : chr \"IntegerField\" ## ..$ Player :List of 1 ## .. ..$ units:List of 6 ## .. .. ..$ noargs: chr \"FALSE\" ## .. .. ..$ min : chr \"0\" ## .. .. ..$ max : chr \"int(60 / 2)\" ## .. .. ..$ doc : chr \"Quantity of units to produce\" ## .. .. ..$ label : chr \"How many units will you produce (from 0 to 30)?\" ## .. .. ..$ field : chr \"IntegerField\" cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app = c(\"cournot\", \"dictator\")) str(cbook, 1) ## List of 3 ## $ settings:List of 10 ## $ cournot :List of 4 ## $ dictator:List of 4 cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app_rm = \"prisoner\") str(cbook, 1) ## List of 15 ## $ settings :List of 10 ## $ bargaining :List of 4 ## $ bertrand :List of 4 ## $ common_value_auction:List of 4 ## $ cournot :List of 4 ## $ dictator :List of 4 ## $ guess_two_thirds :List of 4 ## $ matching_pennies :List of 4 ## $ payment_info :List of 4 ## $ public_goods_simple :List of 3 ## $ survey :List of 3 ## $ traveler_dilemma :List of 4 ## $ trust :List of 3 ## $ trust_simple :List of 3 ## $ volunteer_dilemma :List of 4"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"otree-data-description","dir":"Articles","previous_headings":"Choosing what to show","what":"oTree data description","title":"gmoTree Codebooks","text":"setting preamb = TRUE parameter, predefined description oTree data inserted beginning codebook, explaining experimental data stored oTree.","code":""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"customizing-the-codebook-titles-and-metadata","dir":"Articles","previous_headings":"Customizing how the codebook is shown","what":"Customizing the codebook titles and metadata","title":"gmoTree Codebooks","text":"can easily modify titles, subtitles, dates, author names codebooks using following arguments:","code":"codebook( path = \"YouroTreePath\", # Can be either absolute or relative! title = \"Codebook\", subtitle = \"Example Project\", date = \"today\", params = list(author = c(\"Max Mustermann\", \"John Doe\")) )"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"sorting-the-code","dir":"Articles","previous_headings":"Customizing how the codebook is shown","what":"Sorting the code","title":"gmoTree Codebooks","text":"can sort apps codebook specifying sort argument. example:","code":"cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", doc_info = FALSE, app = c(\"cournot\", \"dictator\"), sort = c(\"dictator\", \"cournot\")) str(cbook, 1) ## List of 3 ## $ settings:List of 10 ## $ dictator:List of 4 ## $ cournot :List of 4"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"referring-to-settings","dir":"Articles","previous_headings":"Customizing how the codebook is shown","what":"Referring to settings","title":"gmoTree Codebooks","text":"gmoTree package can automatically replace references variables settings.py values settings.py file. enable , set settings_replace = \"global\". can also choose replace references settings variables using settings_replace = NULL. also possible provide list variables replace settings variables argument user_settings. example:","code":"cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", settings_replace = \"global\", app = \"dictator\") ## Variables without documentation, label, or verbose name: ## > $dictator$Player$gender print(cbook$dictator$Constants$Variable) ## [1] 66 cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", settings_replace = NULL, app = \"dictator\") ## Variables without documentation, label, or verbose name: ## > $dictator$Player$gender print(cbook$dictator$Constants$Variable) ## [1] \"settings.variable\" cbook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", settings_replace = \"user\", user_settings = list(variable = \"someValue\"), app = \"dictator\") ## Variables without documentation, label, or verbose name: ## > $dictator$Player$gender print(cbook$dictator$Constants$Variable) ## [1] \"someValue\""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"saving-your-codebook","dir":"Articles","previous_headings":"","what":"Saving your codebook","title":"gmoTree Codebooks","text":"choose output = \"file\" output = \"\", codebook saved professional document ready publication sharing.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"output-formats","dir":"Articles","previous_headings":"Saving your codebook","what":"Output formats","title":"gmoTree Codebooks","text":"argument output_format allows choose format exported codebook file. Available formats : html_document word_document latex_document odt_document rtf_document md_document pdf_document pdf_document_simple can choose format best suits needs, formats except PDF allowing easy post-generation editing. knitting PDF, make sure LaTex installed! recommended use output_format = pdf_document_simple. However, many non-Latin characters (e.g., Chinese characters) may work format. cases, can choose output_format = pdf_document, set use xelatex. Please note using xelatex gmoTree limitations: example, gmoTree currently handle long variable values result excessively long table cells. can cause PDF display improperly certain viewers, Nitro. address , carefully review file. necessary, consider using output_format = latex_document. Alternatively, open file PDF viewer can handle cases, save ensure displays correctly PDF viewers.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"output-files","dir":"Articles","previous_headings":"Saving your codebook","what":"Output files","title":"gmoTree Codebooks","text":"default, gmoTree codebooks saved working directory default file name codebook. can modify specifying custom file name directory path. example, save codebook different name, use following code: can also include file extension, although optional: can save file subfolder within current directory including absolute relative folder name output_file argument. example: can also specify absolute paths, either output_dir argument directly within file name specified output_file. example:","code":"codebook( path = \"C:/Users/username/folder/oTree\", # Replace! output_file = \"gmoTree_codebook\") codebook( path = \"C:/Users/username/folder/oTree\", # Replace! output_file = \"gmoTree_codebook.pdf\") codebook( path = \"C:/Users/username/folder/oTree\", # Replace! output_file = \"codebookfiles/gmoTree_codebook.pdf\") codebook( path = \"C:/Users/username/folder/oTree\", # Replace! output_dir = \"C:/Users/username/folder/codebooks\", output_file = \"mycodebook\")"},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"summary","dir":"Articles","previous_headings":"","what":"Summary","title":"gmoTree Codebooks","text":"vignette documents customize codebook generated codebook() function, including options content selection, formatting, exporting various formats. tools enable creation comprehensive tailored documentation experimental data.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/codebook.html","id":"references","dir":"Articles","previous_headings":"","what":"References","title":"gmoTree Codebooks","text":"Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—open-source platform laboratory, online, field experiments. Journal Behavioral Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001","code":""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"background-information-on-the-data-downloaded-by-otree","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"Background information on the data downloaded by oTree","title":"Introduction to gmoTree","text":"oTree experiment structured around one modular units called “apps,” encompass one multiple “pages.” Data generated app can downloaded individually, offering flexibility analyze separate components experiment. -encompassing view experiment, data apps can also downloaded comprehensive file labeled “all_apps_wide.” addition aforementioned app data cumulative all_apps_wide file, oTree generates file time stamps every page. file documenting chat interactions also provided experiment includes one multiple chat rooms. newer oTree versions, also custom data can downloaded. oTree experiment run across different databases, set data files downloaded database. include individual app data files, all_apps_wide file, file time stamps every page, chat log file chat room used experiment. gmoTree package’s functionality lies ability load aggregate files ease.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"import_otree","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"import_otree()","title":"Introduction to gmoTree","text":"can import oTree data combine list data frames using import_otree() function. data frame named according associated app, function generates accompanying info list details essential information regarding imported files, deleted cases. information list updated use functions within package. worth noting even use one all_apps_wide file, still load data import_otree() want access functions within gmoTree package. Alternatively, reproduce structure created function hand. following example shows import oTree data, structure oTree list data frames importing data, information provided oTree$info. Caution: function works oTree data saved using typical oTree file pattern!","code":"# Get path to the package data path <- system.file(\"extdata/exp_data_5.4.0\", package = \"gmoTree\") # Import without specifications # Import all oTree files in this folder and its subfolders otree <- import_otree(path = path) ## Warning in import_otree(path = path): You have stored all_apps_wide globally ## but also room-specific. This function will import both of them. (Globally, the ## files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All ## apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing ## is there twice! (Advice: You may use delete_duplicate() to remove duplicate ## rows of all oTree data frames. # Check the structure of the oTree list of data frames str(otree, 1) ## List of 8 ## $ all_apps_wide:'data.frame': 12 obs. of 60 variables: ## $ info :List of 2 ## $ chatapp :'data.frame': 8 obs. of 24 variables: ## $ dictator :'data.frame': 48 obs. of 25 variables: ## $ start :'data.frame': 8 obs. of 24 variables: ## $ survey :'data.frame': 8 obs. of 29 variables: ## $ Time :'data.frame': 77 obs. of 10 variables: ## $ Chats :'data.frame': 6 obs. of 7 variables: # The initial info list otree$info ## $imported_files ## [1] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/ChatMessages-2023-05-16.csv\" ## [2] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/PageTimes-2023-05-16.csv\" ## [3] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/survey_2023-05-16.csv\" ## [4] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/start_2023-05-16.csv\" ## [5] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/dictator_2023-05-16.csv\" ## [6] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/dictator_2023-05-00.csv\" ## [7] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/chatapp_2023-05-16.csv\" ## [8] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/all_apps_wide_2023-05-16.csv\" ## [9] \"C:/Users/Lenovo/AppData/Local/R/win-library/4.4/gmoTree/extdata/exp_data_5.4.0/all_apps_wide-2023-05-16.csv\" ## ## $initial_n ## [1] 12"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_duplicate","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"delete_duplicate()","title":"Introduction to gmoTree","text":"Sometimes, data imported several times. happen several reasons. First, one data set might part another download temporarily stored data downloading final data frame. Second, room-specific global data imported, data $all_apps_wide data frame two times. Third, data stored several imported folders. function delete_duplicate() deletes duplicate data apps $all_apps_wide. , however, change $Time $Chats data frames. running function, let us first check number participant codes initial count executing delete_duplicate() function. imported $all_apps_wide data frame, 12 participant codes. However, among , 8 unique, indicates presence duplicate data. $info data frame suggests initially 12 entries. remove duplicates, employ delete_duplicate() function: Please note details deleted rows added list deleted cases. list might used analysis, function mainly focuses cleaning untidy data import. However, count $info$initial_n adjusted accordingly. deletion operation, find participant codes unique, count $info$initial_n matches number unique participant codes.","code":"# Initial check before deletion length(otree$all_apps_wide$participant.code) ## [1] 12 length(unique(otree$all_apps_wide$participant.code)) ## [1] 8 otree$info$initial_n ## [1] 12 # Delete duplicate cases otree <- delete_duplicate(otree) # Check participant codes and initial_n after deletion length(otree$all_apps_wide$participant.code) ## [1] 8 length(unique(otree$all_apps_wide$participant.code)) ## [1] 8 otree$info$initial_n ## [1] 8"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"dealing-with-messy-chats-and-time-data-frames","dir":"Articles","previous_headings":"Importing and cleaning up data","what":"Dealing with messy Chats and Time data frames","title":"Introduction to gmoTree","text":"combine data experiments ran different versions oTree, might happen several variables referring attribute $Time $Chats data frames. functions messy_chat() messy_time() integrate corresponding variables used argument combine = TRUE. show example, let us first load data different versions oTree. Now can run functions messy_time() messy_chat(). warning messages part expected output, indicating precisely variables combined. need concern see . However, can also turn using info = FALSE.","code":"# Import data from different oTree versions otree_all <- import_otree( path = system.file(\"extdata\", package = \"gmoTree\")) ## Warning in import_otree(path = system.file(\"extdata\", package = \"gmoTree\")): ## You have stored all_apps_wide globally but also room-specific. This function ## will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" ## Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") ## After importing the data, make sure nothing is there twice! (Advice: You may ## use delete_duplicate() to remove duplicate rows of all oTree data frames. # Check names of Time data frame names(otree_all$Time) ## [1] \"session_code\" \"participant_id_in_session\" ## [3] \"participant_code\" \"page_index\" ## [5] \"app_name\" \"page_name\" ## [7] \"epoch_time_completed\" \"round_number\" ## [9] \"timeout_happened\" \"is_wait_page\" # Check names of Chats data frame names(otree_all$Chats) ## [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" ## [5] \"nickname\" \"body\" \"timestamp\" otree_all <- messy_time(otree_all, combine = TRUE, info = TRUE) otree_all <- messy_chat(otree_all, combine = TRUE, info = TRUE) # Check names of Time data frame again names(otree_all$Time) ## [1] \"session_code\" \"participant_id_in_session\" ## [3] \"participant_code\" \"page_index\" ## [5] \"app_name\" \"page_name\" ## [7] \"epoch_time_completed\" \"round_number\" ## [9] \"timeout_happened\" \"is_wait_page\" # Check names of Chats data frame again names(otree_all$Chats) ## [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" ## [5] \"nickname\" \"body\" \"timestamp\""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"show_dropouts","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"show_dropouts()","title":"Introduction to gmoTree","text":"Sometimes, participants drop experiments. get overview dropouts, can use function show_dropouts(). creates three data frames/tables information participants finish () certain app(s) page(s). First, function show_dropouts() creates data frame $full provides specific information apps pages participants left experiment prematurely. Additionally, data frame indicates apps affected participants dropped . Second, function show_dropouts() also generates smaller data frame $unique includes information person . Third, function show_dropouts() furthermore creates table $all_end, contains information participants ended experiment. columns contain names pages experiment; rows contain names apps.","code":"# Show everyone that has not finished with the app \"survey\" dropout_list <- show_dropouts(otree, \"survey\") head(dropout_list$full) ## participant.code session.code end_app end_page ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 2 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 3 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 4 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 5 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 6 dhgisush 2wlrl5kb dictator Offer ## reason ## 1 Experiment not completed. Noticed at: all_apps_wide ## 2 Experiment not completed. Noticed at: chatapp ## 3 Experiment not completed. Noticed at: dictator ## 4 Experiment not completed. Noticed at: start ## 5 Experiment not completed. Noticed at: survey ## 6 Experiment not completed. Noticed at: all_apps_wide dropout_list$unique ## participant.code session.code end_app end_page ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 6 dhgisush 2wlrl5kb dictator Offer ## 11 j2g9mcaf jk9ekpl0 dictator Introduction ## 16 p6m495xi 2wlrl5kb dictator Introduction ## reason ## 1 Experiment not completed ## 6 Experiment not completed ## 11 Experiment not completed ## 16 Experiment not completed dropout_list$all_end ## ## Demographics Introduction Offer ResultsWaitPage ## dictator 0 2 1 1 ## survey 4 0 0 0"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_dropouts","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"delete_dropouts()","title":"Introduction to gmoTree","text":"function delete_dropouts() removes data related participants prematurely terminated experiment data frames oTree list, exception data info list $Chats data frame. highly recommend manually delete chat data, can occasionally become unintelligible one person’s input removed. Therefore, function delete chat input participants dropped experiment. running example, let us first check row numbers data frames. run function delete_dropouts() check row numbers , see cases deleted data frame $Chats data frame. Just show_dropouts(), delete_dropouts() function also gives detailed information deleted cases. Caution: function delete data original CSV Excel files!","code":"# First, check some row numbers nrow(otree$all_apps_wide) ## [1] 8 nrow(otree$survey) ## [1] 8 nrow(otree$Time) ## [1] 77 nrow(otree$Chats) ## [1] 6 # Delete all cases that didn't end the experiment on the page \"Demographics\" # within the app \"survey\" otree2 <- delete_dropouts(otree, final_apps = \"survey\", final_pages = \"Demographics\", info = TRUE) ## 4 case(s) deleted ## Dropouts are deleted from all data frames. Except: The list of oTree data frames includes a chat. As the interpretation of chat data depends on how participants engage with each other, the data must be deleted with more care than deleting data in other apps. Hence, this function does not delete data in this data frame. Please do this manually if necessary! # Check row numbers again nrow(otree2$all_apps_wide) ## [1] 4 nrow(otree2$survey) ## [1] 4 nrow(otree2$Time) ## [1] 66 nrow(otree2$Chats) ## [1] 6 head(otree2$info$deleted_cases$full) ## participant.code session.code end_app end_page ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 2 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 3 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 4 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 5 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ## 6 dhgisush 2wlrl5kb dictator Offer ## reason ## 1 ENC. Noticed at: survey ## 2 ENC. Noticed at: start ## 3 ENC. Noticed at: dictator ## 4 ENC. Noticed at: chatapp ## 5 ENC. Noticed at: all_apps_wide ## 6 ENC. Noticed at: survey otree2$info$deleted_cases$unique ## participant.code session.code end_app end_page reason ## 1 1k58kgm7 jk9ekpl0 dictator ResultsWaitPage ENC ## 6 dhgisush 2wlrl5kb dictator Offer ENC ## 11 j2g9mcaf jk9ekpl0 dictator Introduction ENC ## 16 p6m495xi 2wlrl5kb dictator Introduction ENC otree2$info$deleted_cases$all_end ## ## Demographics Introduction Offer ResultsWaitPage ## dictator 0 2 1 1 ## survey 4 0 0 0"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_cases","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"delete_cases()","title":"Introduction to gmoTree","text":"Sometimes, participants ask data deleted. delete_cases() function can delete person app’s data frame, $all_apps_wide, $Time data frame. , data $Chats data frame must deleted hand. function adds information deleted cases previously created information deleted cases. Caution: function delete data original CSV Excel files!","code":"# First, check some row numbers nrow(otree2$all_apps_wide) ## [1] 4 nrow(otree2$survey) ## [1] 4 nrow(otree2$Time) ## [1] 66 nrow(otree2$Chats) ## [1] 6 # Delete one participant person <- otree2$all_apps_wide$participant.code[1] otree2 <- delete_cases(otree2, pcodes = person, reason = \"requested\", saved_vars = \"participant._index_in_pages\", info = TRUE) ## 1 case(s) deleted. Cases are deleted from all data frames. Except: The list of oTree data frames includes a chat. As the interpretation of chat data depends on how participants engage with each other, the data must be deleted with more care than deleting data in other apps. Hence, this function does not delete data in this data frame. Please do this manually if necessary! # Check row numbers again nrow(otree2$all_apps_wide) ## [1] 3 nrow(otree2$survey) ## [1] 3 nrow(otree2$Time) ## [1] 48 nrow(otree2$Chats) ## [1] 6 # Check for all deleted cases (also dropouts): tail(otree2$info$deleted_cases$full) ## participant.code session.code end_app end_page ## 16 p6m495xi 2wlrl5kb dictator Introduction ## 17 p6m495xi 2wlrl5kb dictator Introduction ## 18 p6m495xi 2wlrl5kb dictator Introduction ## 19 p6m495xi 2wlrl5kb dictator Introduction ## 20 p6m495xi 2wlrl5kb dictator Introduction ## 21 sdh9ar2m ## reason session participant._index_in_pages ## 16 ENC. Noticed at: survey NA ## 17 ENC. Noticed at: start NA ## 18 ENC. Noticed at: dictator NA ## 19 ENC. Noticed at: chatapp NA ## 20 ENC. Noticed at: all_apps_wide NA ## 21 requested jk9ekpl0 18"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_sessions","dir":"Articles","previous_headings":"Dealing with dropouts and deleting cases","what":"delete_sessions()","title":"Introduction to gmoTree","text":"certainly hope never becomes necessary, may instances entire session needs removed data set due unforeseen issues. However, occurs, can use function delete_sessions(). function removes sessions’ data apps, $all_apps_wide, $Time data frame also sessions’ chat data $Chats data frame chatting usually restricted within session. following, see row numbers deletion, application function, row numbers deletion. Apart functions, sessions’ entries $Chats data frame destroyed since chat data occurs just per session may thus eliminated without impacting comprehensibility chat data.","code":"# First, check some row numbers nrow(otree2$all_apps_wide) ## [1] 3 nrow(otree2$survey) ## [1] 3 nrow(otree2$Time) ## [1] 48 nrow(otree2$Chats) ## [1] 6 # Delete one session otree2 <- delete_sessions(otree, scodes = \"jk9ekpl0\", reason = \"Only tests\", info = TRUE) ## 4 case(s) deleted # Check row numbers again nrow(otree2$all_apps_wide) ## [1] 4 nrow(otree2$survey) ## [1] 4 nrow(otree2$Time) ## [1] 38 nrow(otree2$Chats) ## [1] 3"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"delete_pabels","dir":"Articles","previous_headings":"Deleting sensitive information","what":"delete_pabels()","title":"Introduction to gmoTree","text":"uncommon participant.label variable contain sensitive information like MTurk worker ID. can raise serious privacy concerns. function delete_plabels() automatically removes variable data frames. Additionally, function option delete MTurk-related variables. following, see application delete_plabels() function, preceded information sensitive variables running function followed information sensitive variables running function. Caution: function delete variable original CSV Excel files!","code":"# Check variables head(otree2$all_apps_wide$participant.label) ## [1] \"\" \"\" \"Person1\" \"Person2\" head(otree2$all_apps_wide$participant.mturk_worker_id) ## [1] NA NA NA NA head(otree2$survey$participant.label) ## [1] \"\" \"\" \"Person1\" \"Person2\" # Delete all participant labels otree2 <- delete_plabels(otree2, del_mturk = TRUE) # Check variables head(otree2$all_apps_wide$participant.label) ## NULL head(otree2$all_apps_wide$participant.mturk_worker_id) ## NULL head(otree2$survey$participant.label) ## NULL"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"make_ids","dir":"Articles","previous_headings":"Making IDs","what":"make_ids()","title":"Introduction to gmoTree","text":"working oTree, participant codes, session codes, group IDs used identify cases. However, often, researchers prefer streamlined, consecutive numbering system spans sessions, beginning first participant, session, group concluding last. make_ids() function provides way achieve goal. using function, let us inspect underlying variables first. function returns following variables. prior example, Group IDs calculated group IDs must called specifically. Since group IDs per app data match (groups relevant dictator app), just using group_id = TRUE lead error message. cases group IDs vary among apps, can specified make_ids() app variable used extracting group information. instance, following syntax can used obtain group IDs variable dictator.1.group.id_in_subsession $all_apps_wide.","code":"# Check variables first otree2$all_apps_wide$participant.code ## [1] \"dhgisush\" \"p6m495xi\" \"c9inx5wl\" \"kr8yd7f3\" otree2$all_apps_wide$session.code ## [1] \"2wlrl5kb\" \"2wlrl5kb\" \"mz2r27bk\" \"mz2r27bk\" otree2$all_apps_wide$dictator.1.group.id_in_subsession ## [1] 1 1 1 1 # Make session IDs only otree2 <- make_ids(otree2) # Check variables otree2$all_apps_wide$participant_id ## [1] 1 2 3 4 otree2$all_apps_wide$session_id ## [1] 1 1 2 2 # Get IDs from \"from_variable\" in the data frame \"all_apps_wide\" otree2 <- make_ids(otree2, # gmake = TRUE, # Not necessary if from_var is not NULL from_var = \"dictator.1.group.id_in_subsession\") ## Warning in make_ids(otree2, from_var = \"dictator.1.group.id_in_subsession\"): ## The group variable values are constant. Group IDs now correspond to session ## IDs. # Check variables otree2$all_apps_wide$participant_id ## [1] 1 2 3 4 otree2$all_apps_wide$group_id ## [1] 1 1 2 2 otree2$all_apps_wide$session_id ## [1] 1 1 2 2"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"apptime","dir":"Articles","previous_headings":"Measuring the time","what":"apptime()","title":"Introduction to gmoTree","text":"need determine much time participants spent specific app, apptime() function powerful tool can help. function calculates summary statistics mean, minimum, maximum time spent page, well detailed list durations participant app. following example shows much time participants spent app “survey” minutes. can also get time specific participants . Without specifying applications, get duration applications individually.","code":"# Calculate the time all participants spent on app \"survey\" apptime(otree2, apps = \"survey\", digits = 3) ## $mean_duration ## [1] 0.242 ## ## $min_duration ## [1] 0.233 ## ## $max_duration ## [1] 0.25 ## ## $single_durations ## participant session duration ## 1 c9inx5wl mz2r27bk 0.250 ## 2 kr8yd7f3 mz2r27bk 0.233 ## ## $messages ## [1] \"For some participants, no duration could be calculated. See list in $warnings.\" ## ## $warnings ## [1] \"dhgisush\" \"p6m495xi\" # Calculate the time one participant spent on app \"dictator\" apptime(otree2, pcode = \"c9inx5wl\", digits = 3) ## $chatapp ## [1] 0.267 ## ## $dictator ## [1] 0.5 ## ## $start ## [1] 0.017 ## ## $survey ## [1] 0.25"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"extime","dir":"Articles","previous_headings":"Measuring the time","what":"extime()","title":"Introduction to gmoTree","text":"need determine much time participants spent complete experiment, can use extime() function. function calculates summary statistics mean, minimum, maximum time spent experiment, well detailed list durations participant. (Note min, max, mean values two digits underlying data.) can also get duration just one participant.","code":"# Calculate the time that all participants spent on the experiment extime(otree2, digits = 3) ## $mean_duration ## [1] 0.525 ## ## $min_duration ## [1] 0.05 ## ## $max_duration ## [1] 1.033 ## ## $single_durations ## participant session duration ## 2 p6m495xi 2wlrl5kb 0.050 ## 1 dhgisush 2wlrl5kb 0.117 ## 4 kr8yd7f3 mz2r27bk 0.900 ## 3 c9inx5wl mz2r27bk 1.033 # Calculate the time one participant spent on the experiment extime(otree2, pcode = \"c9inx5wl\", digits = 3) ## [1] 1.033"},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"pagesec","dir":"Articles","previous_headings":"Measuring the time","what":"pagesec()","title":"Introduction to gmoTree","text":"older versions oTree included variable called seconds_on_page $Time data frame. Although good reason omit , sometimes want detailed information time spent one page. Therefore, created function pagesec() adds new variable seconds_on_page2 $Time data frame.","code":"# Create two new columns: seconds_on_page2 and minutes_on_page otree2 <- pagesec(otree2, rounded = TRUE, minutes = TRUE) tail(otree2$Time) ## timeout_happened is_wait_page group_id session_id participant_id ## 72 0 0 2 2 3 ## 73 0 0 2 2 4 ## 74 0 0 2 2 4 ## 75 0 0 2 2 3 ## 76 0 0 2 2 4 ## 77 0 0 2 2 3 ## session_code participant_id_in_session participant_code page_index app_name ## 72 mz2r27bk 1 c9inx5wl 15 survey ## 73 mz2r27bk 2 kr8yd7f3 15 survey ## 74 mz2r27bk 2 kr8yd7f3 16 survey ## 75 mz2r27bk 1 c9inx5wl 16 survey ## 76 mz2r27bk 2 kr8yd7f3 17 survey ## 77 mz2r27bk 1 c9inx5wl 17 survey ## page_name epoch_time_completed round_number minutes_on_page ## 72 CognitiveReflectionTest 1684258104 1 0.05 ## 73 CognitiveReflectionTest 1684258108 1 0.13 ## 74 Offer 1684258109 1 0.02 ## 75 Offer 1684258110 1 0.10 ## 76 Demographics 1684258114 1 0.08 ## 77 Demographics 1684258116 1 0.10"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"assignv","dir":"Articles","previous_headings":"Transferring variables between the apps","what":"assignv()","title":"Introduction to gmoTree","text":"function assignv() copies variable $all_apps_wide data frame data frames apps. following example, variable survey.1.player.gender copied $all_apps_wide app data frames; data frames, new variable named gender. also copies variable $all_apps_wide keep degree consistency.","code":"# Assign variable \"survey.1.player.gender\" and name it \"gender\" otree2 <- assignv(oTree = otree2, variable = \"survey.1.player.gender\", newvar = \"gender\") # Control otree2$dictator$gender ## [1] \"\" \"\" \"\" \"\" \"\" \"\" \"Female\" \"Male\" ## [9] \"Female\" \"Male\" \"Female\" \"Male\" otree2$chatapp$gender ## [1] \"\" \"\" \"Female\" \"Male\" # In app \"survey\", the variable is now twice because it is taken from here otree2$survey$gender ## [1] \"\" \"\" \"Female\" \"Male\" otree2$survey$player.gender ## [1] \"\" \"\" \"Female\" \"Male\" # In app \"all_apps_wide,\" the variable is also there twice # (This can be avoided by calling the new variable the same # as the old variable) otree2$all_apps_wide$gender ## [1] \"\" \"\" \"Female\" \"Male\" otree2$all_apps_wide$survey.1.player.gender ## [1] \"\" \"\" \"Female\" \"Male\""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"assignv_to_aaw","dir":"Articles","previous_headings":"Transferring variables between the apps","what":"assignv_to_aaw()","title":"Introduction to gmoTree","text":"function assignv_to_aaw() copies variable one data frames $all_apps_wide data frame. following example, variable $survey data frame copied $all_apps_wide placed directly variable survey.1.player.age.","code":"# Create a new variable otree2$survey$younger30 <- ifelse(otree2$survey$player.age < 30, 1, 0) # Get variable younger30 from survey to all_apps_wide # and put the new variable right behind the old age variable otree2 <- assignv_to_aaw(otree2, app = \"survey\", variable = \"younger30\", newvar = \"younger30\", resafter = \"survey.1.player.age\") # Control otree2$all_apps_wide$survey.1.player.age ## [1] NA NA 66 33 # Check the position of the old age variable and the new variable match(\"survey.1.player.age\", colnames(otree2$all_apps_wide)) ## [1] 52 match(\"younger30\", colnames(otree2$all_apps_wide)) ## [1] 53"},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"show_constant","dir":"Articles","previous_headings":"Before running the experiment","what":"show_constant()","title":"Introduction to gmoTree","text":"program experiments, frequently add variables turn useless later. forget remove , especially experiments numerous rounds, data frame becomes unreasonably huge. function show_constant(), may identify variables variation remove experiment. following example, variable named constant created, vary. function show_constant() shows us many variables also unchanging; however, delete oTree internal. Yet, prevent unreasonably large data frame, remove variable constant running experiment.","code":"# Make a constant column (this variable is usually created in oTree) otree2$dictator$constant <- 3 # Show all columns that contain columns containing only one specified value show_constant(oTree = otree2) ## $all_apps_wide ## [1] \"participant._is_bot\" ## [2] \"participant._max_page_index\" ## [3] \"participant.visited\" ## [4] \"session.label\" ## [5] \"session.comment\" ## [6] \"session.config.real_world_currency_per_point\" ## [7] \"session.config.name\" ## [8] \"session.config.participation_fee\" ## [9] \"start.1.player.role\" ## [10] \"start.1.player.payoff\" ## [11] \"start.1.group.id_in_subsession\" ## [12] \"start.1.subsession.round_number\" ## [13] \"dictator.1.player.role\" ## [14] \"dictator.1.group.id_in_subsession\" ## [15] \"dictator.1.subsession.round_number\" ## [16] \"dictator.2.player.role\" ## [17] \"dictator.2.group.id_in_subsession\" ## [18] \"dictator.2.subsession.round_number\" ## [19] \"dictator.3.player.role\" ## [20] \"dictator.3.group.id_in_subsession\" ## [21] \"dictator.3.subsession.round_number\" ## [22] \"chatapp.1.player.role\" ## [23] \"chatapp.1.player.payoff\" ## [24] \"chatapp.1.group.id_in_subsession\" ## [25] \"chatapp.1.subsession.round_number\" ## [26] \"survey.1.player.role\" ## [27] \"survey.1.player.payoff\" ## [28] \"survey.1.group.id_in_subsession\" ## [29] \"survey.1.subsession.round_number\" ## ## $chatapp ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"player.payoff\" ## [7] \"group.id_in_subsession\" \"subsession.round_number\" ## [9] \"session.label\" ## ## $dictator ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"group.id_in_subsession\" ## [7] \"session.label\" \"constant\" ## ## $start ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"player.payoff\" ## [7] \"group.id_in_subsession\" \"subsession.round_number\" ## [9] \"session.label\" ## ## $survey ## [1] \"session.comment\" \"participant._is_bot\" ## [3] \"participant._max_page_index\" \"participant.visited\" ## [5] \"player.role\" \"player.payoff\" ## [7] \"group.id_in_subsession\" \"subsession.round_number\" ## [9] \"session.label\" ## ## $Time ## character(0) ## ## $Chats ## [1] \"group_id\" \"session_id\" \"session_code\" \"channel\""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"codebook","dir":"Articles","previous_headings":"Before running the experiment","what":"codebook()","title":"Introduction to gmoTree","text":"Thorough documentation experiment essential. detailed guidance generating codebook oTree code, refer vignette gmoTree Codebooks. recommend creating codebook running experiment, can help identify incomplete documentation potential issues within code.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/articles/intro_to_gmoTree.html","id":"references","dir":"Articles","previous_headings":"","what":"References","title":"Introduction to gmoTree","text":"Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—open-source platform laboratory, online, field experiments. Journal Behavioral Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001","code":""},{"path":"https://zauchnerp.github.io/gmoTree/authors.html","id":null,"dir":"","previous_headings":"","what":"Authors","title":"Authors and Citation","text":"Patricia F. Zauchner. Author, translator, maintainer, copyright holder. University Bremen","code":""},{"path":"https://zauchnerp.github.io/gmoTree/authors.html","id":"citation","dir":"","previous_headings":"","what":"Citation","title":"Authors and Citation","text":"Zauchner, Patricia F. (2024). gmoTree: oTree Data Manipulation Tool. R package version 1.3.0, .","code":"@Manual{, title = {gmoTree: oTree Data Manipulation Tool}, author = {Patricia F. Zauchner}, year = {2024}, note = {R package version 1.3.0}, url = {https://CRAN.R-project.org/package=gmoTree}, }"},{"path":"https://zauchnerp.github.io/gmoTree/impressum.html","id":null,"dir":"","previous_headings":"","what":"Site notice","title":"Site notice","text":"website published Patricia Zauchner Universität Bremen SOCIUM Forschungszentrum Ungleichheit und Sozialpolitik Unicom-Gebäude Raum: 7.4460 Mary-Somerville-Straße 7 28359 Bremen Deutschland Telephone: +49 421 218-58555 E-Mail: patricia.zauchner [] uni-bremen.de Patricia Zauchner also responsible content accordance 55 Abs. 2 RStV.","code":""},{"path":[]},{"path":"https://zauchnerp.github.io/gmoTree/impressum.html","id":"accountability-for-content","dir":"","previous_headings":"Disclaimer","what":"Accountability for content","title":"Site notice","text":"contents pages created utmost care. However, guarantee contents’ accuracy, completeness topicality. According statutory provisions, furthermore responsible content web pages. context, please note accordingly obliged monitor merely transmitted saved information third parties, investigate circumstances pointing illegal activity. obligations remove block use information generally applicable laws remain unaffected per §§ 8 10 Telemedia Act (TMG).","code":""},{"path":"https://zauchnerp.github.io/gmoTree/impressum.html","id":"accountability-for-links","dir":"","previous_headings":"Disclaimer","what":"Accountability for links","title":"Site notice","text":"Responsibility content external links (web pages third parties) lies solely operators linked pages. violations evident time linking. legal infringement become known us, remove respective link immediately.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"gmotree--get-and-modify-otree-data","dir":"","previous_headings":"","what":"Get and Modify oTree Data","title":"Get and Modify oTree Data","text":"gmoTree R package developed importing, merging, efficiently managing data obtained running oTree (Chen et al., 2016) experiments. ’s particularly valuable dealing complex experimental designs span multiple sessions generate large number files need integrated.1","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"installation","dir":"","previous_headings":"","what":"Installation","title":"Get and Modify oTree Data","text":"install CRAN version package, use following command: install.packages(\"gmoTree\") install development version: devtools::install_github(\"ZauchnerP/gmoTree\")","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"list-of-all-functions","dir":"","previous_headings":"","what":"List of all functions","title":"Get and Modify oTree Data","text":"See page Introduction gmoTree detailed overview functions. details package whole, visit gmoTree website.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"importing-data","dir":"","previous_headings":"","what":"Importing data","title":"Get and Modify oTree Data","text":"import_otree(): Imports oTree data combines list data frames.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"cleaning-up-data","dir":"","previous_headings":"","what":"Cleaning up data","title":"Get and Modify oTree Data","text":"messy_chat(): Checks messy Chats data frame combines variables refer concept. messy_chat(): Checks messy Time data frame combines variables refer concept. delete_duplicate(): Deletes duplicate rows data frames oTree list.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"dealing-with-dropouts-and-deleting-cases","dir":"","previous_headings":"","what":"Dealing with dropouts and deleting cases","title":"Get and Modify oTree Data","text":"show_dropouts(): Shows participant codes people finish () certain app(s) page(s). delete_dropouts(): Deletes data participants finish () certain app(s) page(s). function deletes participants’ data data frames oTree list. Caution: delete cases original CSV Excel files! delete_cases(): Deletes data specified participants data frames oTree list. Caution: function delete data original CSV Excel files! delete_sessions(): Deletes data specified sessions data frames oTree list. Caution: function delete data original CSV Excel files!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"deleting-sensitive-information","dir":"","previous_headings":"","what":"Deleting sensitive information","title":"Get and Modify oTree Data","text":"delete_plabels(): Deletes variable participant.label every app might contain identifiable information participants, MTurk ID. Caution: function delete variable original CSV Excel files!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"making-ids","dir":"","previous_headings":"","what":"Making IDs","title":"Get and Modify oTree Data","text":"make_ids(): Makes participant, group, session IDs across apps.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"measuring-time","dir":"","previous_headings":"","what":"Measuring time","title":"Get and Modify oTree Data","text":"apptime(): Calculates time spent specific app. extime(): Calculates time spent experiment. pagesec(): Calculates time spent page.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"transferring-variables-between-the-apps","dir":"","previous_headings":"","what":"Transferring variables between the apps","title":"Get and Modify oTree Data","text":"assignv(): Copies variable all_apps_wide data frame data frames apps. assignv_to_aaw(): Copies variable one data frames all_apps_wide data frame.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"before-running-the-experiment","dir":"","previous_headings":"","what":"Before running the experiment","title":"Get and Modify oTree Data","text":"show_constant(): Shows constant variables. codebook(): Creates codebook based oTree code. See also vignette “gmoTree Codebooks.”","code":""},{"path":"https://zauchnerp.github.io/gmoTree/index.html","id":"references","dir":"","previous_headings":"","what":"References","title":"Get and Modify oTree Data","text":"Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—open-source platform laboratory, online, field experiments. Journal Behavioral Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the time that was spent on an app — apptime","title":"Calculate the time that was spent on an app — apptime","text":"Calculate time spent one app several apps.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the time that was spent on an app — apptime","text":"","code":"apptime( oTree, apps = NULL, pcode = NULL, plabel = NULL, group_id = NULL, seconds = FALSE, rounded = TRUE, digits = 2, sinfo = \"session_code\", combine = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the time that was spent on an app — apptime","text":"oTree list data frames created import_otree apps Character. Name(s) app(s) time calculated. pcode Character. value participant.code variable time calculated one specified participant. plabel Character. value participant.label variable time calculated one specified participant. group_id Integer. value group_id variable time calculated one specified group. group_id variable can created make_ids. seconds Logical. TRUE output seconds instead minutes. rounded Logical. TRUE output rounded. digits Integer. number digits output rounded. parameter effect unless rounded = TRUE. sinfo Character. \"session_id\" use session ID additional information data frame single durations, \"session_code\" use session codes, NULL session column shown. combine Logical. TRUE variables relating epoch time merged, variables relating participant code merged data multiple versions oTree used.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the time that was spent on an app — apptime","text":"function returns list app containing information mean, minimum, maximum time participants spent app, data frame information time participant spent app, eventually, vectors relevant background information numbers. experiment's duration calculated one participant, output returns NA (per app) person make app(s).","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/apptime.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the time that was spent on an app — apptime","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show how much time all participants spent on app \"survey\" apptime(oTree, apps = \"survey\") #> $mean_duration #> [1] 0.28 #> #> $min_duration #> [1] 0.08 #> #> $max_duration #> [1] 1.13 #> #> $single_durations #> participant session duration #> 1 46kxib6w 7bfqtokx 1.13 #> 2 iay3dhkn 7bfqtokx 0.22 #> 3 4zhzdmzo 7bfqtokx 0.15 #> 4 3ttf7yix 7bfqtokx 0.42 #> 5 2d72mfgh 7bfqtokx 0.13 #> 6 rvce7958 7bfqtokx 0.22 #> 7 lsl3vbij 7bfqtokx 0.13 #> 8 xx78b3x0 vd1h01iv 0.17 #> 9 xmxl46rm vd1h01iv 0.15 #> 10 iagvtslv t0rog7nz 0.15 #> 11 jxh15obl t0rog7nz 0.08 #> 12 a7dppel1 t0rog7nz 0.23 #> 13 wk247s9w t0rog7nz 0.73 #> 14 xkobdvuh t0rog7nz 0.40 #> 15 1l5kal0r t0rog7nz 0.13 #> 16 7l0hmpcq qyu3qg0q 0.15 #> 17 ia9rnfvc qyu3qg0q 0.15 #> #> $messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $warnings #> [1] \"164r1hs4\" \"ktjz5jli\" \"vbhvhozv\" \"2scvem7a\" \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" #> [8] \"d4sq7zio\" #> # Show how much time the participant \"a7dppel1\" spent on # the app \"survey\" apptime(oTree, pcode = \"a7dppel1\", apps = \"survey\") #> [1] 0.23 # Show how much time the participants in group 4 spent on # the app \"survey\" oTree <- make_ids(oTree, gmake = TRUE, from_var = \"dictator.1.group.id_in_subsession\" ) apptime(oTree, group_id = 4, apps = \"survey\") #> $mean_duration #> [1] 0.13 #> #> $min_duration #> [1] 0.13 #> #> $max_duration #> [1] 0.13 #> #> $single_durations #> participant session duration #> 1 lsl3vbij 7bfqtokx 0.13 #> #> $messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $warnings #> [1] \"164r1hs4\" #> # Show how much time all participants spent on all apps apptime(oTree) #> $chatapp #> $chatapp$mean_duration #> [1] 0.65 #> #> $chatapp$min_duration #> [1] 0.02 #> #> $chatapp$max_duration #> [1] 1.87 #> #> $chatapp$single_durations #> participant session duration #> 10 iagvtslv t0rog7nz 0.02 #> 11 jxh15obl t0rog7nz 0.07 #> 8 xx78b3x0 vd1h01iv 0.20 #> 16 7l0hmpcq qyu3qg0q 0.20 #> 9 xmxl46rm vd1h01iv 0.45 #> 17 ia9rnfvc qyu3qg0q 0.55 #> 4 3ttf7yix 7bfqtokx 0.57 #> 13 wk247s9w t0rog7nz 0.57 #> 12 a7dppel1 t0rog7nz 0.58 #> 7 lsl3vbij 7bfqtokx 0.60 #> 1 46kxib6w 7bfqtokx 0.62 #> 3 4zhzdmzo 7bfqtokx 0.77 #> 5 2d72mfgh 7bfqtokx 0.77 #> 14 xkobdvuh t0rog7nz 1.07 #> 6 rvce7958 7bfqtokx 1.08 #> 15 1l5kal0r t0rog7nz 1.10 #> 2 iay3dhkn 7bfqtokx 1.87 #> #> $chatapp$messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $chatapp$warnings #> [1] \"164r1hs4\" \"ktjz5jli\" \"vbhvhozv\" \"2scvem7a\" \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" #> [8] \"d4sq7zio\" #> #> #> $dictator #> $dictator$mean_duration #> [1] 2.05 #> #> $dictator$min_duration #> [1] 0.4 #> #> $dictator$max_duration #> [1] 5.95 #> #> $dictator$single_durations #> participant session duration #> 12 vbhvhozv vd1h01iv 0.40 #> 13 2scvem7a vd1h01iv 0.43 #> 20 7l0hmpcq qyu3qg0q 0.43 #> 2 iay3dhkn 7bfqtokx 0.47 #> 21 ia9rnfvc qyu3qg0q 0.50 #> 1 46kxib6w 7bfqtokx 0.57 #> 11 xmxl46rm vd1h01iv 0.65 #> 10 xx78b3x0 vd1h01iv 0.72 #> 18 xkobdvuh t0rog7nz 0.90 #> 19 1l5kal0r t0rog7nz 0.95 #> 16 a7dppel1 t0rog7nz 1.17 #> 17 wk247s9w t0rog7nz 1.20 #> 15 jxh15obl t0rog7nz 1.58 #> 14 iagvtslv t0rog7nz 2.65 #> 9 ktjz5jli 7bfqtokx 2.88 #> 8 lsl3vbij 7bfqtokx 3.45 #> 7 164r1hs4 7bfqtokx 3.53 #> 6 rvce7958 7bfqtokx 4.37 #> 5 2d72mfgh 7bfqtokx 4.48 #> 3 4zhzdmzo 7bfqtokx 5.87 #> 4 3ttf7yix 7bfqtokx 5.95 #> #> $dictator$messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $dictator$warnings #> [1] \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" \"d4sq7zio\" #> #> #> $survey #> $survey$mean_duration #> [1] 0.28 #> #> $survey$min_duration #> [1] 0.08 #> #> $survey$max_duration #> [1] 1.13 #> #> $survey$single_durations #> participant session duration #> 11 jxh15obl t0rog7nz 0.08 #> 5 2d72mfgh 7bfqtokx 0.13 #> 7 lsl3vbij 7bfqtokx 0.13 #> 15 1l5kal0r t0rog7nz 0.13 #> 3 4zhzdmzo 7bfqtokx 0.15 #> 9 xmxl46rm vd1h01iv 0.15 #> 10 iagvtslv t0rog7nz 0.15 #> 16 7l0hmpcq qyu3qg0q 0.15 #> 17 ia9rnfvc qyu3qg0q 0.15 #> 8 xx78b3x0 vd1h01iv 0.17 #> 2 iay3dhkn 7bfqtokx 0.22 #> 6 rvce7958 7bfqtokx 0.22 #> 12 a7dppel1 t0rog7nz 0.23 #> 14 xkobdvuh t0rog7nz 0.40 #> 4 3ttf7yix 7bfqtokx 0.42 #> 13 wk247s9w t0rog7nz 0.73 #> 1 46kxib6w 7bfqtokx 1.13 #> #> $survey$messages #> [1] \"For some participants, no duration could be calculated. See list in $warnings.\" #> #> $survey$warnings #> [1] \"164r1hs4\" \"ktjz5jli\" \"vbhvhozv\" \"2scvem7a\" \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" #> [8] \"d4sq7zio\" #> #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":null,"dir":"Reference","previous_headings":"","what":"Assign a variable from all_apps_wide — assignv","title":"Assign a variable from all_apps_wide — assignv","text":"Assign variable $all_apps_wide app data frames.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Assign a variable from all_apps_wide — assignv","text":"","code":"assignv(oTree, variable, newvar)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Assign a variable from all_apps_wide — assignv","text":"oTree list data frames created import_otree variable Character. variable $all_apps_wide data frame assigned apps. newvar Character. name newly created variable.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Assign a variable from all_apps_wide — assignv","text":"function returns duplicate original oTree list data frames additional column data frames. additional column contains data specified variable found $all_apps_wide.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Assign a variable from all_apps_wide — assignv","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Assign variable \"survey.1.player.gender\" and name it \"gender\" oTree <- assignv(oTree = oTree, variable = \"survey.1.player.gender\", newvar = \"gender\") # Show the new variable in some of the other app data frames oTree$dictator$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" #> [17] \"Male\" \"\" \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" #> [25] \"\" \"Male\" \"\" \"Female\" \"Female\" \"\" \"\" \"Female\" #> [33] \"Female\" \"\" \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" #> [41] \"\" \"Female\" \"Female\" \"Female\" \"Male\" \"Male\" \"\" \"Female\" #> [49] \"Female\" \"Female\" \"Male\" \"Male\" \"\" \"Female\" \"Female\" \"Female\" #> [57] \"Male\" \"\" \"\" \"\" \"\" \"\" \"\" \"\" #> [65] \"\" \"\" \"\" \"\" \"\" \"Female\" \"Female\" \"Female\" #> [73] \"Female\" \"Female\" \"Female\" oTree$chatapp$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" # The variable is now duplicated in app \"survey\" because it is obtained from # there (This can be avoided by naming the new variable the same as the old # variable) oTree$survey$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" oTree$survey$player.gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" # In app \"all_apps_wide,\" the variable is also there twice (This can be # avoided by naming the new variable the same as the old variable) oTree$all_apps_wide$gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" \"Female\" \"Female\" \"Female\" \"Male\" oTree$all_apps_wide$survey.1.player.gender #> [1] \"Male\" \"Female\" \"Male\" \"Female\" \"Female\" \"Male\" \"\" \"Male\" #> [9] \"\" \"Female\" \"Female\" \"\" \"\" \"Male\" \"\" \"Female\" #> [17] \"Female\" \"Female\" \"Male\" \"\" \"\" \"\" \"\" \"Female\" #> [25] \"Female\" \"Female\" \"Female\" \"Female\" \"Male\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":null,"dir":"Reference","previous_headings":"","what":"Assign a variable to all_apps_wide — assignv_to_aaw","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"Assign variable one app data frames $all_apps_wide.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"","code":"assignv_to_aaw(oTree, app, variable, newvar, resafter = NULL)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"oTree list data frames created import_otree. app Character. data frame variable taken. variable Character. name variable assigned $all_apps_wide. newvar Character. name newly created variable $all_apps_wide data frame. resafter Character. name variable precedes new variable. NULL, new variable placed end data frame.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"function returns duplicate original oTree list data frames additional column $all_apps_wide data frame contains variable question.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/assignv_to_aaw.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Assign a variable to all_apps_wide — assignv_to_aaw","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Check out the old variable oTree$survey$player.age #> [1] 22 22 23 23 33 45 NA 44 NA 33 23 NA NA 23 NA 44 21 23 23 NA NA NA NA 34 20 # Create a new variable oTree$survey$younger30 <- ifelse(oTree$survey$player.age < 30, 1, 0) # Assign the variable younger30 to all_apps_wide oTree2 <- assignv_to_aaw( oTree = oTree, app = \"survey\", variable = \"younger30\", newvar = \"younger30\") #> Warning: New variable is created. However, there is an unequal number of participants in \"all_apps_wide\" (29) and app \"survey\" (25). Did you forget to delete dropouts and empty cases or did you forget to import app data? Sometimes, this can happen if you import data from within a session or room where you can only import \"all_apps_wide\" but not the separate app data, time data or chat data. # Show the new variable in the all_apps_wide data frame oTree2$all_apps_wide$younger30 #> [1] 1 1 1 1 0 0 NA 0 NA 0 1 NA NA 1 NA 0 1 1 1 NA NA NA NA 0 1 #> [26] NA NA NA NA # Check the position of the new variable match(\"younger30\",names(oTree2$all_apps_wide)) #> [1] 56 # Place the new variable immediately after the \"survey.1.player.age\" variable oTree2 <- assignv_to_aaw(oTree, app = \"survey\", variable = \"younger30\", newvar = \"younger30\", resafter = \"survey.1.player.age\") #> Warning: New variable is created. However, there is an unequal number of participants in \"all_apps_wide\" (29) and app \"survey\" (25). Did you forget to delete dropouts and empty cases or did you forget to import app data? Sometimes, this can happen if you import data from within a session or room where you can only import \"all_apps_wide\" but not the separate app data, time data or chat data. # Show the new variable in the all_apps_wide data frame oTree2$all_apps_wide$younger30 #> [1] 1 1 1 1 0 0 NA 0 NA 0 1 NA NA 1 NA 0 1 1 1 NA NA NA NA 0 1 #> [26] NA NA NA NA # Show the position of the new variable match(\"younger30\", names(oTree2$all_apps_wide)) #> [1] 50"},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":null,"dir":"Reference","previous_headings":"","what":"Create a codebook for the oTree code — codebook","title":"Create a codebook for the oTree code — codebook","text":"Create codebook oTree code automatically scanning project folder retrieving variables' information.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Create a codebook for the oTree code — codebook","text":"","code":"codebook( path = \".\", fsource = \"init\", output = \"both\", output_dir = NULL, output_file = \"codebook\", output_format = \"pdf_document_simple\", output_open = TRUE, app_doc = TRUE, app = NULL, app_rm = NULL, doc_info = TRUE, sort = NULL, settings_replace = \"global\", user_settings = NULL, include_cons = TRUE, preamb = FALSE, encoding = \"UTF-8\", title = \"Codebook\", subtitle = \"created with gmoTree\", params = NULL, date = \"today\", splitvarname = FALSE, sep_list = \"newline\", initial = TRUE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Create a codebook for the oTree code — codebook","text":"path Character. Path oTree experiment. fsource Character. \"init\" information taken init.py files (newer oTree code 5.x format). \"models\" (\"model\") information taken models.py files (older oTree code 3.x format). output Character. \"list\" output contain list variables information. \"file\" output file Word PDF file. \"\" output contain file list. output_dir Character. absolute path function's output saved. absolute paths allowed parameter. Relative paths can specified output_file parameter. output_file Character. name output file generated function. file name can provided without extension. Relative paths also allowed file name. output_format Character. Specifies format file output. value passed output_format argument rmarkdown::render. Allowed options : \"html_document\", \"word_document\", \"odt_document\", \"rtf_document\", \"md_document\", \"latex_document\", \"pdf_document\", \"pdf_document_simple\", short forms \"html\", \"word\", \"odt\", \"rtf\", \"md\", \"latex\", \"pdf\", \"pdf_simple\". Important: \"pdf_document\" format uses xelatex PDF generation. document require advanced LaTeX features, recommended use \"pdf_document_simple\". output_open Logical. TRUE file output opened creation. app_doc Logical. TRUE app documentation included output file. app Character. Name included app(s). Default use apps. used simultaneously app_rm. app_rm Character. Name excluded app(s). Default exclude apps. used simultaneously app. doc_info Logical. TRUE message information variables without documentation also returned. FALSE message suppressed. sort Character vector. Vector specifies order apps codebook. settings_replace Character NULL. Specifies handle references settings variables. Use \"global\" replace references global settings variables defined settings.py. Use \"user\" replace references variables provided user_settings argument. Use NULL leave references settings variables unchanged. Caution: function use variables defined SESSION_CONFIGS. vary settings variables SESSION_CONFIGS, set settings_replace \"user\" manually replace using user_settings argument. user_settings List. List variables settings.py file used replace setting variable references. used settings_replace = \"user\" used setting variables defined within SESSION_CONFIGS. include_cons Logical. TRUE section constants codebook. preamb Logical. TRUE preamble printed explains oTree saves variables. encoding Character. Encoding created Markdown file. knitr::knit, argument always assumed UTF-8 ignored. title Character. Title output file. subtitle Character. Subtitle output file. params List. List variable name value pairs passed RmD file. relevant argument output \"file\" \"\" chosen. date Character NULL. Date passed Rmd file. Either \"today\", NULL, user defined date. relevant argument output \"file\" \"\" chosen. splitvarname Logical. TRUE long variable names split across multiple lines output file tables. FALSE, table columns adjust fit longest variable names. sep_list Character. Determines sub-lists displayed file output. Use \"newline\" separate sub-lists newline characters (`\\n`), \"vector\" display strings `c(...)` format. initial Logical. TRUE initial values included output file. FALSE included.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Create a codebook for the oTree code — codebook","text":"function returns two main types outputs: () list variables along information (b) file containing codebook experiment doc_info TRUE also returns message containing names variables documentation.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Create a codebook for the oTree code — codebook","text":"code works dictionaries used (example session configurations settings.py). Caution 1: Multiline comments ignored, meaning variables commented manner nevertheless included codebook. contrast, variables commented line comments appear codebook. Caution 2: commas value strings, might used split text. Please manually insert backslash symbol front commas avoid (.e., escape ). E.g. \"Yes, \" -> \"Yes\\, \". Caution 3: code interpret variables imported files (example CSV files) special formatting included (e.g., special string formatting Python float(1.4) represent float number). Caution 4: code developed tested basic oTree codes verified compatibility oTree versions later 5.4.0. experience issues newer versions complex code structures, please open issue GitHub. Caution 5: Custom exports part codebook. info: None values presented \"None\" (.e. string) list codebook.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/codebook.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Create a codebook for the oTree code — codebook","text":"","code":"# The examples use a slightly modified version of the official oTree sample codes. # Make a codebook and resort the apps combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", fsource = \"init\", doc_info = FALSE) # Show the structure of the codebook str(combined_codebook, 1) #> List of 16 #> $ settings :List of 10 #> $ bargaining :List of 4 #> $ bertrand :List of 4 #> $ common_value_auction:List of 4 #> $ cournot :List of 4 #> $ dictator :List of 4 #> $ guess_two_thirds :List of 4 #> $ matching_pennies :List of 4 #> $ payment_info :List of 4 #> $ prisoner :List of 4 #> $ public_goods_simple :List of 3 #> $ survey :List of 3 #> $ traveler_dilemma :List of 4 #> $ trust :List of 3 #> $ trust_simple :List of 3 #> $ volunteer_dilemma :List of 4 str(combined_codebook$bargaining$Player, 1) #> List of 4 #> $ request:List of 6 #> $ level2 :List of 3 #> $ level3 :List of 3 #> $ level :List of 3 # Make a codebook with only the \"bargaining\" app combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", fsource = \"init\", app = \"bargaining\", doc_info = FALSE) # Show the structure of the codebook str(combined_codebook, 1) #> List of 2 #> $ settings :List of 10 #> $ bargaining:List of 4 str(combined_codebook$bargaining$Player, 1) #> List of 4 #> $ request:List of 6 #> $ level2 :List of 3 #> $ level3 :List of 3 #> $ level :List of 3 # Make a codebook with all but the \"bargaining\" app combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), output = \"list\", fsource = \"init\", app_rm = \"bargaining\", doc_info = FALSE) # Show the structure of the codebook str(combined_codebook, 1) #> List of 15 #> $ settings :List of 10 #> $ bertrand :List of 4 #> $ common_value_auction:List of 4 #> $ cournot :List of 4 #> $ dictator :List of 4 #> $ guess_two_thirds :List of 4 #> $ matching_pennies :List of 4 #> $ payment_info :List of 4 #> $ prisoner :List of 4 #> $ public_goods_simple :List of 3 #> $ survey :List of 3 #> $ traveler_dilemma :List of 4 #> $ trust :List of 3 #> $ trust_simple :List of 3 #> $ volunteer_dilemma :List of 4 str(combined_codebook$bargaining$Player, 1) #> NULL # Use oTree code in 3.x format combined_codebook <- codebook( path = system.file(\"extdata/ocode_z\", package = \"gmoTree\"), fsource = \"model\", output = \"list\", doc_info = FALSE) #> Warning: Some variables or code parts contain code that is too complex for this function. Hence, this function might have overseen important variables and references to them. Found in: #> > $rankaversion$Constants (read_csv) #> > $rankend$Constants (read_csv) #> > $settings$showupToken (float) #> > $end$Constants$showupToken (float) #> > $end$Constants$showupTokenTest (float) # Show the structure of the codebook str(combined_codebook, 1) #> List of 4 #> $ settings :List of 20 #> $ end :List of 4 #> $ rankaversion:List of 4 #> $ rankend :List of 4 # Show information on missing documentation or complex code combined_codebook <- codebook( path = system.file(\"extdata/ocode_new\", package = \"gmoTree\"), fsource = \"init\", output = \"list\", app_rm = \"bargaining\", doc_info = TRUE) #> Variables without documentation, label, or verbose name: #> > $bertrand$Group$winning_price #> > $bertrand$Player$is_winner #> > $common_value_auction$Group$highest_bid #> > $cournot$Group$unit_price #> > $dictator$Player$gender #> > $guess_two_thirds$Group$two_thirds_avg #> > $guess_two_thirds$Group$best_guess #> > $guess_two_thirds$Group$num_winners #> > $guess_two_thirds$Player$is_winner #> > $matching_pennies$Player$is_winner #> > $public_goods_simple$Group$total_contribution #> > $public_goods_simple$Group$individual_share #> > $traveler_dilemma$Group$lower_claim #> > $traveler_dilemma$Player$adjustment #> > $volunteer_dilemma$Group$num_volunteers if (FALSE) { # \\dontrun{ # Create a codebook PDF with authors' names and todays' date codebook( path = system.file(\"extdata/ocode_z\", package = \"gmoTree\"), fsource = \"init\", doc_info = FALSE, output = \"file\", output_format = \"pdf_document\", date = \"today\", title = \"My Codebook\", subtitle = \"codebook created with gmoTree\", params = list(author = c(\"Max Mustermann\", \"John Doe\")) ) # Create a codebook PDF and save it in a subfolder of the # current folder: # \"C:/Users/pzauchner/Nextcloud/R_analyses/cb/cb.pdf\" getwd() # \"C:/Users/pzauchner/Nextcloud/R_analyses\" dir.create(\"cb\") combined_codebook <- gmoTree::codebook( path = \"C:/Users/pzauchner/Nextcloud/R_analyses/oTree\", fsource = \"models\", output = \"both\", output_file = \"cb/cb.pdf\", output_format = \"pdf_document\") # You can also omit *.pdf after the file name combined_codebook <- gmoTree::codebook( path = \"C:/Users/pzauchner/Nextcloud/R_analyses/oTree\", fsource = \"models\", output = \"both\", output_file = \"cb/cb\", output_format = \"pdf_document\") } # }"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete specific cases — delete_cases","title":"Delete specific cases — delete_cases","text":"Delete specific cases data frames oTree list. Caution 1: function delete cases original CSV Excel files! Caution 2: function delete cases custom exports custom data frames data frames variable named participant.code! Caution 3: function delete data $Chats data frame! (interpretation chat data depends participants engage , data must deleted care deleting data apps. Hence, function delete data data frame. Please manually necessary!)","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete specific cases — delete_cases","text":"","code":"delete_cases( oTree, pcodes = NULL, plabels = NULL, saved_vars = NULL, reason, omit = FALSE, info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete specific cases — delete_cases","text":"oTree list data frames created import_otree. pcodes Character. value(s) participant.code variable participants whose data removed. plabels Character. value(s) participant.label variable participants whose data removed. saved_vars Character. name(s) variable(s) need(s) stored list information deleted cases $info$deleted_cases. reason Character. reason deletion stored list information deleted cases $info$deleted_cases. omit Logical. TRUE deleted cases added information deleted cases $info$deleted_cases. info Logical. TRUE brief information case deletion process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete specific cases — delete_cases","text":"function returns duplicate original oTree list data frames include deleted cases. adds information deleted cases $info$deleted_cases. (list also filled functions.) list, can find following information: - $codes = vector participant codes deleted cases. - $count = number participants $codes. - $full $unique = data frames $full $unique contain information deleted participant reason deleted. entries $full $unique data frames . Columns \"end_app\" \"end_page\" left empty intentionally filled delete_dropouts function.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_cases.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete specific cases — delete_cases","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Delete only one case oTree2 <- delete_cases(oTree, pcodes = \"xmxl46rm\", reason = \"requested\") # Show changes in row numbers print(paste(\"Row numbers before deletion: \", nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"Row numbers before deletion: 29 25 289 35\" print(paste(\"Row numbers after deletion: \", nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"Row numbers after deletion: 28 24 275 35\" # Delete several cases deletionlist <- c(\"4zhzdmzo\", \"xmxl46rm\") oTree2 <- delete_cases(oTree, pcodes = deletionlist, reason = \"requested\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"27 23 258 35\" # Show information on all deleted cases (also dropouts): oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason #> 3 4zhzdmzo 7bfqtokx requested #> 12 xmxl46rm vd1h01iv requested # Save one variable oTree2 <- delete_cases(oTree, pcodes = deletionlist, reason = \"requested\", saved_vars = \"participant._index_in_pages\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"27 23 258 35\" # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason #> 3 4zhzdmzo 7bfqtokx requested #> 12 xmxl46rm vd1h01iv requested #> participant._index_in_pages #> 3 17 #> 12 17 # Save some variables oTree2 <- delete_cases(oTree, pcodes = deletionlist, reason = \"requested\", saved_vars = c( \"participant._index_in_pages\", \"participant._max_page_index\")) # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"27 23 258 35\" # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason #> 3 4zhzdmzo 7bfqtokx requested #> 12 xmxl46rm vd1h01iv requested #> participant._index_in_pages participant._max_page_index #> 3 17 16 #> 12 17 16 # Get a list of all deleted cases # (If there is already a list, the new list is added to it) oTree2$info$deleted_cases$codes #> [1] \"4zhzdmzo\" \"xmxl46rm\" # Show number of all deleted cases length(oTree2$info$deleted_cases$codes) #> [1] 2 oTree2$info$deleted_cases$count #> [1] 2 # Delete a session and delete a single case from another session oTree2 <- delete_sessions(oTree, scodes = c(\"vd1h01iv\"), reason = \"Server Crash\", saved_vars = \"dictator.1.group.id_in_subsession\") oTree2 <- delete_cases(oTree2, pcodes = \"4zhzdmzo\", reason = \"requested\") # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session.code dictator.1.group.id_in_subsession end_app #> 1 xx78b3x0 vd1h01iv 1 #> 2 xmxl46rm vd1h01iv 1 #> 3 vbhvhozv vd1h01iv 2 #> 4 2scvem7a vd1h01iv 2 #> 5 4zhzdmzo NA #> end_page reason session #> 1 Server Crash #> 2 Server Crash #> 3 Server Crash #> 4 Server Crash #> 5 requested 7bfqtokx # See codes of deleted variables oTree2$info$deleted_cases$codes #> [1] \"4zhzdmzo\" \"xx78b3x0\" \"xmxl46rm\" \"vbhvhozv\" \"2scvem7a\" # See number of deleted variables oTree2$info$deleted_cases$count #> [1] 5"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete dropouts — delete_dropouts","title":"Delete dropouts — delete_dropouts","text":"Delete data participants end experiment () certain page(s) /app(s). Caution 1: function delete cases original CSV Excel files! Caution 2: function delete cases custom exports custom exports variable named participant.code variable named session.code! Caution 3: function delete data $Chats data frame! (interpretation chat data depends participants engage , data must deleted care deleting data apps. Hence, function delete data data frame. Please manually necessary!)","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete dropouts — delete_dropouts","text":"","code":"delete_dropouts( oTree, final_apps = NULL, final_pages = NULL, saved_vars = NULL, inconsistent = NULL, reason = \"ENC\", info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete dropouts — delete_dropouts","text":"oTree list data frames created import_otree final_apps Character. name(s) app(s) participants finish experiment. final_pages Character. name(s) page(s) participants finish experiment. saved_vars Character. name(s) variable(s) need(s) stored list information deleted cases $info$deleted_cases. inconsistent Character. function continue stopped least one participant inconsistent end_pages, inconsistent end_apps, ? continue, type \"yes\", stop function, type \"\". reason Character. reason deletion stored list information deleted cases $info$deleted_cases. info Logical. TRUE brief information dropout deletion process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete dropouts — delete_dropouts","text":"function returns duplicate original oTree list data frames without deleted cases. adds information deleted cases $info$deleted_cases. (list also filled functions.) list, can find following information: - $full = data frame contains information participants finish study; shows participant codes, names apps left experiment, names pages left experiment, names app data frames information found, dropout reason (\"ENC\", experiment completed, combined name data frame dropout observed). participants usually appear multiple app data frames, $info$deleted_cases$full data frame may contain several entries person. - $unique = data frame contains similar information $full data frame one row per participant information data frame dropout observed. - $all_end = table provides information app page combinations participants ended experiment. table also includes information participants drop experiment. $all_end table shown $all_apps_wide data frame exists. - $codes = vector containing participant codes deleted participants. - $count = number deleted participants. important note argument final_pages set, function distinguish page names reoccur different apps. columns end_app end_page output empty, variables saved oTree specific participants. empty rows deleted. can done using argument del_empty = TRUE using import_otree.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_dropouts.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete dropouts — delete_dropouts","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # First, show some row numbers print(paste(nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"29 25 289 35\" # Delete all cases that didn't end the experiment on the page \"Demographics\" # within the app \"survey\" oTree2 <- delete_dropouts(oTree, final_apps = c(\"survey\"), final_pages = c(\"Demographics\")) # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"20 16 248 35\" # Delete all cases that didn't end the experiment on the page \"Demographics\" # This page can be in any app oTree2 <- delete_dropouts(oTree, final_pages = \"Demographics\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"20 16 248 35\" # Delete all cases that didn't end the experiment on # any page in the app \"survey\" oTree <- delete_dropouts(oTree, final_apps = \"survey\") # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"20 16 248 35\" # Get list of information on all deleted cases # (If there is already a list, the new list is added to it!) oTree2$info$deleted_cases #> $full #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 2 164r1hs4 7bfqtokx chatapp chat #> 3 164r1hs4 7bfqtokx chatapp chat #> 4 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 6 2scvem7a vd1h01iv dictator ResultsWaitPage #> 7 2scvem7a vd1h01iv dictator ResultsWaitPage #> 8 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 10 7wa8kk3d l8ecm1uh dictator Introduction #> 11 7wa8kk3d l8ecm1uh dictator Introduction #> 12 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 14 ao9kqvqn l8ecm1uh dictator Introduction #> 15 ao9kqvqn l8ecm1uh dictator Introduction #> 16 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 18 d4sq7zio l8ecm1uh dictator Introduction #> 19 d4sq7zio l8ecm1uh dictator Introduction #> 20 d4sq7zio l8ecm1uh dictator Introduction #> 21 jxh15obl t0rog7nz survey Offer #> 22 jxh15obl t0rog7nz survey Offer #> 23 jxh15obl t0rog7nz survey Offer #> 24 jxh15obl t0rog7nz survey Offer #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 26 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 27 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 28 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 30 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 31 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 32 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 33 znri6myc l8ecm1uh dictator Introduction #> 34 znri6myc l8ecm1uh dictator Introduction #> 35 znri6myc l8ecm1uh dictator Introduction #> 36 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 ENC. Noticed at: survey #> 2 ENC. Noticed at: all_apps_wide #> 3 ENC. Noticed at: chatapp #> 4 ENC. Noticed at: dictator #> 5 ENC. Noticed at: all_apps_wide #> 6 ENC. Noticed at: chatapp #> 7 ENC. Noticed at: dictator #> 8 ENC. Noticed at: survey #> 9 ENC. Noticed at: all_apps_wide #> 10 ENC. Noticed at: chatapp #> 11 ENC. Noticed at: dictator #> 12 ENC. Noticed at: survey #> 13 ENC. Noticed at: all_apps_wide #> 14 ENC. Noticed at: chatapp #> 15 ENC. Noticed at: dictator #> 16 ENC. Noticed at: survey #> 17 ENC. Noticed at: chatapp #> 18 ENC. Noticed at: dictator #> 19 ENC. Noticed at: survey #> 20 ENC. Noticed at: all_apps_wide #> 21 ENC. Noticed at: dictator #> 22 ENC. Noticed at: survey #> 23 ENC. Noticed at: all_apps_wide #> 24 ENC. Noticed at: chatapp #> 25 ENC. Noticed at: all_apps_wide #> 26 ENC. Noticed at: chatapp #> 27 ENC. Noticed at: dictator #> 28 ENC. Noticed at: survey #> 29 ENC. Noticed at: all_apps_wide #> 30 ENC. Noticed at: chatapp #> 31 ENC. Noticed at: dictator #> 32 ENC. Noticed at: survey #> 33 ENC. Noticed at: all_apps_wide #> 34 ENC. Noticed at: chatapp #> 35 ENC. Noticed at: dictator #> 36 ENC. Noticed at: survey #> #> $unique #> participant.code session.code end_app end_page reason #> 1 164r1hs4 7bfqtokx chatapp chat ENC #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage ENC #> 9 7wa8kk3d l8ecm1uh dictator Introduction ENC #> 13 ao9kqvqn l8ecm1uh dictator Introduction ENC #> 17 d4sq7zio l8ecm1uh dictator Introduction ENC #> 21 jxh15obl t0rog7nz survey Offer ENC #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage ENC #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage ENC #> 33 znri6myc l8ecm1uh dictator Introduction ENC #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"164r1hs4\" \"2scvem7a\" \"7wa8kk3d\" \"ao9kqvqn\" \"d4sq7zio\" \"jxh15obl\" \"ktjz5jli\" #> [8] \"vbhvhozv\" \"znri6myc\" #> #> $count #> [1] 9 #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete duplicate data — delete_duplicate","title":"Delete duplicate data — delete_duplicate","text":"Delete duplicate rows oTree app data frames $all_apps_wide.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete duplicate data — delete_duplicate","text":"","code":"delete_duplicate(oTree)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete duplicate data — delete_duplicate","text":"oTree list data frames created import_otree.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete duplicate data — delete_duplicate","text":"function returns duplicate original oTree list data frames without duplicate rows app data frames $all_apps_wide. function effect data frames $Time $Chats. function add information $info$deleted_cases, delete important information cleans messy data import. However, function adjusts $info$initial_n, $all_apps_wide data frame exists.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_duplicate.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete duplicate data — delete_duplicate","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. # First, show some row numbers print(paste(nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"41 33 366 41\" # Delete duplicate rows oTree <- delete_duplicate(oTree) # Show row numbers again print(paste(nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"37 33 366 41\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete participant labels in all apps — delete_plabels","title":"Delete participant labels in all apps — delete_plabels","text":"work MTurk, MTurk IDs stored participant labels variable. function deletes variable $all_apps_wide every app data frame list data frames created import_otree /variables referring MTurk, participant.mturk_worker_id. Caution: function delete variables original CSV Excel files!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete participant labels in all apps — delete_plabels","text":"","code":"delete_plabels(oTree, del_plabel = TRUE, del_mturk = TRUE)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete participant labels in all apps — delete_plabels","text":"oTree list data frames created import_otree. del_plabel Logical. TRUE participant labels deleted. del_mturk Logical. TRUE MTurk variables deleted.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete participant labels in all apps — delete_plabels","text":"function returns duplicate original oTree list data frames include participant labels /MTurk variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_plabels.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete participant labels in all apps — delete_plabels","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show participant labels oTree$all_apps_wide$participant.label #> [1] \"Person1\" \"Person2\" \"Person4\" \"Person5\" \"Person6\" \"Person7\" #> [7] \"Person8\" \"Person9\" \"Person10\" \"Person1\" \"Person2\" \"Person3\" #> [13] \"Person4\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person5\" #> [19] \"Person6\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person2\" #> [25] \"Person3\" NA NA NA NA oTree$survey$participant.label #> [1] \"Person1\" \"Person2\" \"Person4\" \"Person5\" \"Person6\" \"Person7\" #> [7] \"Person8\" \"Person9\" \"Person10\" \"Person1\" \"Person2\" \"Person3\" #> [13] \"Person4\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person5\" #> [19] \"Person6\" \"Person1\" \"Person2\" \"Person3\" \"Person4\" \"Person2\" #> [25] \"Person3\" # Delete all participant labels oTree2 <- delete_plabels(oTree) # Show participant labels again oTree2$all_apps_wide$participant.label #> NULL oTree2$survey$participant.label #> NULL"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":null,"dir":"Reference","previous_headings":"","what":"Delete all cases of one session — delete_sessions","title":"Delete all cases of one session — delete_sessions","text":"Delete cases specific sessions data frames oTree list data frames. Caution 1: function delete cases original CSV Excel files! Caution 2: function delete cases custom exports custom exports variable named participant.code variable named session.code!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Delete all cases of one session — delete_sessions","text":"","code":"delete_sessions(oTree, scodes, saved_vars = NULL, reason, info = FALSE)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Delete all cases of one session — delete_sessions","text":"oTree list data frames created import_otree. scodes Character. session.code(s) session(s) whose data removed. saved_vars Character. name(s) variable(s) need(s) stored list information deleted cases $info$deleted_cases. reason Character. reason deletion stored list information deleted cases $info$deleted_cases. info Logical. TRUE brief information session deletion process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Delete all cases of one session — delete_sessions","text":"function returns duplicate original oTree list data frames include deleted sessions. adds information deleted cases $info$deleted_cases. (list also filled functions.) list, can find following information: - $full $unique = data frames $full $unique contain information participants whose data deleted. entries $full $unique data frames list . Columns end_app end_page left empty intentionally filled delete_dropouts function. Columns participant.code reason filled. - $codes = vector containing participant codes deleted participants. - $count = number deleted participants.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/delete_sessions.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Delete all cases of one session — delete_sessions","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Delete one session oTree2 <- delete_sessions(oTree, scodes = \"7bfqtokx\", reason = \"Only tests\") # Show changes in row numbers print(paste(\"Row numbers before deletion: \", nrow(oTree$all_apps_wide), nrow(oTree$survey), nrow(oTree$Time), nrow(oTree$Chats))) #> [1] \"Row numbers before deletion: 29 25 289 35\" print(paste(\"Row numbers after deletion: \", nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"Row numbers after deletion: 20 16 166 14\" # Delete two sessions and show deletion message oTree2 <- delete_sessions(oTree, scodes = c(\"7bfqtokx\", \"vd1h01iv\"), reason = \"Only tests\", info = TRUE) #> 13 case(s) deleted # Show row numbers again print(paste(nrow(oTree2$all_apps_wide), nrow(oTree2$survey), nrow(oTree2$Time), nrow(oTree2$Chats))) #> [1] \"16 12 126 10\" # Delete session and save variable to the info list oTree2 <- delete_sessions(oTree, scodes = c(\"7bfqtokx\", \"vd1h01iv\"), reason = \"Server Crash\", saved_vars = \"dictator.1.group.id_in_subsession\") # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session.code dictator.1.group.id_in_subsession end_app #> 1 46kxib6w 7bfqtokx 1 #> 2 iay3dhkn 7bfqtokx 1 #> 3 4zhzdmzo 7bfqtokx 2 #> 4 3ttf7yix 7bfqtokx 2 #> 5 2d72mfgh 7bfqtokx 3 #> 6 rvce7958 7bfqtokx 3 #> 7 164r1hs4 7bfqtokx 4 #> 8 lsl3vbij 7bfqtokx 4 #> 9 ktjz5jli 7bfqtokx 5 #> 11 xx78b3x0 vd1h01iv 1 #> 12 xmxl46rm vd1h01iv 1 #> 13 vbhvhozv vd1h01iv 2 #> 14 2scvem7a vd1h01iv 2 #> end_page reason #> 1 Server Crash #> 2 Server Crash #> 3 Server Crash #> 4 Server Crash #> 5 Server Crash #> 6 Server Crash #> 7 Server Crash #> 8 Server Crash #> 9 Server Crash #> 11 Server Crash #> 12 Server Crash #> 13 Server Crash #> 14 Server Crash # See codes of deleted variables oTree2$info$deleted_cases$codes #> [1] \"46kxib6w\" \"iay3dhkn\" \"4zhzdmzo\" \"3ttf7yix\" \"2d72mfgh\" \"rvce7958\" #> [7] \"164r1hs4\" \"lsl3vbij\" \"ktjz5jli\" \"xx78b3x0\" \"xmxl46rm\" \"vbhvhozv\" #> [13] \"2scvem7a\" # See number of deleted variables oTree2$info$deleted_cases$count #> [1] 13 # Delete a single case and then delete a session oTree2 <- delete_cases(oTree, pcodes = \"4zhzdmzo\", reason = \"requested\") oTree2 <- delete_sessions(oTree2, scodes = c(\"vd1h01iv\"), reason = \"Server Crash\", saved_vars = \"dictator.1.group.id_in_subsession\") # Check the \"full\" deletion information oTree2$info$deleted_cases$full #> participant.code session end_app end_page reason session.code #> 1 4zhzdmzo 7bfqtokx requested #> 2 xx78b3x0 Server Crash vd1h01iv #> 3 xmxl46rm Server Crash vd1h01iv #> 4 vbhvhozv Server Crash vd1h01iv #> 5 2scvem7a Server Crash vd1h01iv #> dictator.1.group.id_in_subsession #> 1 NA #> 2 1 #> 3 1 #> 4 2 #> 5 2 # See codes of deleted variables oTree2$info$deleted_cases$codes #> [1] \"xx78b3x0\" \"xmxl46rm\" \"vbhvhozv\" \"2scvem7a\" \"4zhzdmzo\" # See number of deleted variables oTree2$info$deleted_cases$count #> [1] 5"},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the time that was spent on the whole experiment — extime","title":"Calculate the time that was spent on the whole experiment — extime","text":"Calculate time spent experiment. stated otherwise, calculation starts end first page!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the time that was spent on the whole experiment — extime","text":"","code":"extime( oTree, pcode = NULL, plabel = NULL, group_id = NULL, seconds = FALSE, rounded = TRUE, digits = 2L, startat = 1L, tz = \"UTC\", sinfo = \"session_code\", combine = TRUE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the time that was spent on the whole experiment — extime","text":"oTree list data frames created import_otree. pcode Character. value participant.code variable time calculated one specified participant. plabel Character. value participant.label variable time calculated one specified participant. group_id Integer. value group_id variable time calculated one specified group. group_id variable can created make_ids. seconds Logical. TRUE output seconds instead minutes. rounded Logical. TRUE output rounded. digits Integer. number digits output rounded. parameter effect unless rounded = TRUE. startat Integer character string \"real\" Whether start experiment taken time certain index person's vector page_indexes $Time data frame time_started variable $all_apps_wide (\"real\"). Important: integer, represents position within page index sequence, numeric value page_index variable. tz Character. Time zone. sinfo Character. \"session_id\" use session ID additional information data frame single durations, \"session_code\" use session codes, NULL session column shown. combine Logical. TRUE variables referring epoch time merged, variables referring participant code merged case data several versions oTree used. FALSE, function returns error several oTree versions' data present.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the time that was spent on the whole experiment — extime","text":"function returns either single value data one person calculated list information time several participants spent experiment. list, can find following information: - $mean_duration = experiment's average duration. - $min_duration = experiment's minimum duration. - $max_duration = experiment's maximum duration. - $single_durations = data frame durations used calculating min, max, mean duration. - $messages = important notes calculations. - $only_one_page = vector individuals one time stamp.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"details","dir":"Reference","previous_headings":"","what":"Details","title":"Calculate the time that was spent on the whole experiment — extime","text":"functions calculates time spent experiment using variable refers time stamp. variable present, function alternatively uses seconds_on_page2, can created pagesec function.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/extime.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the time that was spent on the whole experiment — extime","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show time for one participant extime(oTree, pcode = \"wk247s9w\") #> [1] 2.5 # Make a data frame of durations extime(oTree) #> $mean_duration #> [1] 2.81 #> #> $min_duration #> [1] 0.4 #> #> $max_duration #> [1] 6.93 #> #> $single_durations #> participant session duration #> 12 vbhvhozv vd1h01iv 0.40 #> 13 2scvem7a vd1h01iv 0.43 #> 20 7l0hmpcq qyu3qg0q 0.78 #> 10 xx78b3x0 vd1h01iv 1.08 #> 21 ia9rnfvc qyu3qg0q 1.20 #> 11 xmxl46rm vd1h01iv 1.25 #> 15 jxh15obl t0rog7nz 1.73 #> 16 a7dppel1 t0rog7nz 1.98 #> 19 1l5kal0r t0rog7nz 2.18 #> 1 46kxib6w 7bfqtokx 2.32 #> 18 xkobdvuh t0rog7nz 2.37 #> 17 wk247s9w t0rog7nz 2.50 #> 2 iay3dhkn 7bfqtokx 2.55 #> 14 iagvtslv t0rog7nz 2.82 #> 9 ktjz5jli 7bfqtokx 2.88 #> 7 164r1hs4 7bfqtokx 3.53 #> 8 lsl3vbij 7bfqtokx 4.18 #> 5 2d72mfgh 7bfqtokx 5.38 #> 6 rvce7958 7bfqtokx 5.67 #> 3 4zhzdmzo 7bfqtokx 6.78 #> 4 3ttf7yix 7bfqtokx 6.93 #> #> $messages #> [1] \"Warning: For at least one participant, the experiment only has one page. I.e., the indices for the first and the last page are the same. See $only_one_page for information on this participant/these participants! Participants in this list are not included in the output.\" #> #> $only_one_page #> [1] \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" \"d4sq7zio\" #> # Make a data frame of durations (beginning from the end of the second page) extime(oTree, startat = 2) #> $mean_duration #> [1] 1.88 #> #> $min_duration #> [1] 0.03 #> #> $max_duration #> [1] 6.08 #> #> $single_durations #> participant session duration #> 13 2scvem7a vd1h01iv 0.03 #> 9 ktjz5jli 7bfqtokx 0.05 #> 12 vbhvhozv vd1h01iv 0.15 #> 20 7l0hmpcq qyu3qg0q 0.63 #> 7 164r1hs4 7bfqtokx 0.82 #> 10 xx78b3x0 vd1h01iv 1.03 #> 11 xmxl46rm vd1h01iv 1.08 #> 21 ia9rnfvc qyu3qg0q 1.08 #> 8 lsl3vbij 7bfqtokx 1.40 #> 15 jxh15obl t0rog7nz 1.53 #> 16 a7dppel1 t0rog7nz 1.78 #> 19 1l5kal0r t0rog7nz 1.98 #> 18 xkobdvuh t0rog7nz 2.17 #> 1 46kxib6w 7bfqtokx 2.20 #> 17 wk247s9w t0rog7nz 2.32 #> 2 iay3dhkn 7bfqtokx 2.37 #> 14 iagvtslv t0rog7nz 2.70 #> 5 2d72mfgh 7bfqtokx 2.73 #> 6 rvce7958 7bfqtokx 2.97 #> 4 3ttf7yix 7bfqtokx 4.35 #> 3 4zhzdmzo 7bfqtokx 6.08 #> #> $messages #> [1] \"Warning: For at least one participant, the experiment only has one page. I.e., the indices for the first and the last page are the same. See $only_one_page for information on this participant/these participants! Participants in this list are not included in the output.\" #> #> $only_one_page #> [1] \"7wa8kk3d\" \"znri6myc\" \"ao9kqvqn\" \"d4sq7zio\" #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":null,"dir":"Reference","previous_headings":"","what":"Import oTree data — import_otree","title":"Import oTree data — import_otree","text":"Import data files created oTree. files containing pattern YYYY-MM-DD end file names considered oTree files. Bot outputs saved oTree without date included. Hence, import bot data, must either rename original bot files using YYYY-MM-DD format use argument onlybots = TRUE. using second option, data bot files imported. Caution! Data can downloaded within session globally time. files downloaded, can lead $all_apps_wide data twice! can remove duplicate data using delete_duplicate. Caution! importing Excel files, function check erroneous data structures combine data frames file name patterns. using CSV = FALSE argument, clean data appropriately.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Import oTree data — import_otree","text":"","code":"import_otree( path = \".\", file_names = NULL, final_apps = NULL, final_pages = NULL, recursive = TRUE, csv = TRUE, onlybots = FALSE, del_empty = TRUE, info = FALSE, encoding = \"UTF-8\" )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Import oTree data — import_otree","text":"path Character. path files (default working directory). file_names Character. name(s) file(s) imported. specified, files path subfolders imported. final_apps Character. name(s) app(s) participants finish experiment. argument final_apps left empty, can still call deleting participants finish experiment delete_dropouts. final_pages Character. name(s) page(s) participants finish experiment. argument final_pages left empty, can still call deleting participants finish experiment delete_dropouts. recursive Logical. TRUE files path's subfolders also imported. csv Logical. TRUE CSV files imported. FALSE Excel files imported. onlybots Logical. TRUE bot-created files imported. del_empty Logical. TRUE empty cases deleted $all_apps_wide normal app data frames (Time Chats). info Logical. TRUE brief information data import printed. encoding Character. Encoding CSV files imported. Default \"UTF-8\".","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Import oTree data — import_otree","text":"Returns list data frames (one data frame app $all_apps_wide) list information list data frames $info. See detailed information imported files $info$imported_files. $all_apps_wide imported, see number imported cases $info$initial_n. number, empty rows already considered. , empty rows deleted del_empty=TRUE, initial_n counts rows empty. Cases deleted participants make last page /app subtracted number. Information: Empty rows rows without participant._current_app_name variable set. Empty rows deleted app data frames $all_apps_wide using del_empty = TRUE. Empty rows $Chats $Time data frames deleted. old new oTree versions combined, $Time data frame contains variables called participant_code participant__code (difference underscores). Caution! unusual amount NAs, check everything got imported correctly. Sometimes, CSV Excel file may corrupted, information found one column.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/import_otree.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Import oTree data — import_otree","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() # Show the structure of the import str(oTree, max.level = 1) # Show the names of all imported files oTree$info$imported_files # Delete empty cases and delete every case of a person # who didn't end the experiment in the app \"survey\" oTree <- import_otree( del_empty = TRUE, final_apps = \"survey\", info = TRUE) # Show the structure of the import str(oTree, max.level = 1) # Import bot files import_otree( path = \"./bot_data\", onlybots = TRUE, csv = TRUE, info = TRUE) # Show the structure of the import str(oTree, max.level = 1) # Import with file names (path separately) oTree2 <- import_otree( del_empty = TRUE, path = \"./exp_data\", file_names = c(\"all_apps_wide-2023-03-27.csv\", \"ChatMessages-2023-03-27.csv\", \"PageTimes-2023-03-27.csv\"), onlybots = FALSE, csv = TRUE, info = TRUE) # Show the structure of the import str(oTree, max.level = 1) # Import with file names (without path separately) oTree2 <- import_otree( del_empty = TRUE, file_names = c(\"exp_data/all_apps_wide-2023-03-27.csv\", \"exp_data/ChatMessages-2023-03-27.csv\", \"exp_data/PageTimes-2023-03-27.csv\"), onlybots = FALSE, csv = TRUE, info = TRUE) # Show the structure of the import str(oTree, max.level = 1) }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. #> List of 8 #> $ all_apps_wide:'data.frame':\t41 obs. of 60 variables: #> $ info :List of 2 #> $ chatapp :'data.frame':\t33 obs. of 24 variables: #> $ dictator :'data.frame':\t123 obs. of 25 variables: #> $ survey :'data.frame':\t33 obs. of 29 variables: #> $ start :'data.frame':\t8 obs. of 24 variables: #> $ Time :'data.frame':\t366 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. #> Imported: 5 app(s) and/or all_apps_wide #> Imported: Time file(s) #> Imported: Chat file(s) #> 12 case(s) deleted #> Dropouts are deleted from all data frames. Except: The list of oTree data frames includes a chat. As the interpretation of chat data depends on how participants engage with each other, the data must be deleted with more care than deleting data in other apps. Hence, this function does not delete data in this data frame. Please do this manually if necessary! #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Imported: 4 app(s) and/or all_apps_wide #> No Time files available #> No chat files available #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Imported: 1 app(s) and/or all_apps_wide #> Imported: Time file(s) #> Imported: Chat file(s) #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables: #> Imported: 1 app(s) and/or all_apps_wide #> Imported: Time file(s) #> Imported: Chat file(s) #> List of 8 #> $ all_apps_wide:'data.frame':\t27 obs. of 60 variables: #> $ info :List of 3 #> $ chatapp :'data.frame':\t21 obs. of 24 variables: #> $ dictator :'data.frame':\t75 obs. of 25 variables: #> $ survey :'data.frame':\t21 obs. of 29 variables: #> $ start :'data.frame':\t4 obs. of 24 variables: #> $ Time :'data.frame':\t326 obs. of 10 variables: #> $ Chats :'data.frame':\t41 obs. of 7 variables:"},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":null,"dir":"Reference","previous_headings":"","what":"Make IDs — make_ids","title":"Make IDs — make_ids","text":"Make session IDs , optionally, group IDs participant IDs span across data frames created import_otree. Information IDs taken $all_apps_wide can defined otherwise. Note: Older versions oTree may already contain variable called session_id $Time data frames. variable overwritten function! Important: Combine duplicate data running function!","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Make IDs — make_ids","text":"","code":"make_ids( oTree, gmake = FALSE, pmake = TRUE, from_app = \"all_apps_wide\", from_var = NULL, sstart = 1L, gstart = 1L, pstart = 1L, emptyrows = NULL, icw = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Make IDs — make_ids","text":"oTree list data frames created import_otree. gmake Logical. TRUE variable called group_id made. from_var NULL, gmake automatically set TRUE. pmake Logical. TRUE variable called participant_id made. from_app Character. Name data frame session, group, participant information taken. normal app data frames $all_apps_wide allowed. from_var Character. Name variable group information taken. argument relevant $all_apps_wide used from_app group information contradicts . sstart Integer. number serves starting point session IDs. gstart Integer. number serves starting point group IDs. pstart Integer. number serves starting point participant IDs. emptyrows Character. \"\" function stop empty rows from_app. \"yes\" function continue make IDs. icw Logical. TRUE warning message ignored states IDs made oTree bug.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Make IDs — make_ids","text":"ID variables made $all_apps_wide, app data frames, $Time data frame, $Chats data frame. See list additional ID variables $info$additional_variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/make_ids.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Make IDs — make_ids","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Make session IDs only oTree2 <- make_ids(oTree) # Show new variables oTree2$all_apps_wide$session_id #> [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5 6 6 6 6 # Make session IDs and group IDs # Not working with this data set because group ID is not the same in all apps if (FALSE) { # \\dontrun{ oTree2 <- make_ids(oTree, gmake = TRUE) # Show new variables oTree2$all_apps_wide$session_id oTree2$all_apps_wide$group_id } # } # Get IDs from variable \"dictator.1.group.id_in_subsession\" # in the data frame \"all_apps_wide\" oTree2 <- make_ids(oTree, gmake = TRUE, from_var = \"dictator.1.group.id_in_subsession\") # Show new variables oTree2$all_apps_wide$session_id #> [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5 6 6 6 6 oTree2$all_apps_wide$group_id #> [1] 1 1 2 2 3 3 4 4 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 #> [26] 14 14 15 15 # Get IDs from another app than all_apps_wide oTree2 <- make_ids(oTree, gmake = TRUE, from_app = \"dictator\") #> Warning: Data frame \"all_apps_wide\" has more participants than dictator: 6cim3a5i, 1mn1kzs7, zdki96d6, byxco6zo # Show new variables oTree2$all_apps_wide$session_id #> [1] 1 1 1 1 1 1 1 1 1 2 2 2 2 3 3 3 3 3 3 4 4 4 4 5 5 #> [26] NA NA NA NA oTree2$all_apps_wide$group_id #> [1] 1 1 2 2 3 3 4 4 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 #> [26] NA NA NA NA"},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":null,"dir":"Reference","previous_headings":"","what":"Check if the Chats data frame is messy — messy_chat","title":"Check if the Chats data frame is messy — messy_chat","text":"Check $Chats data frame includes session-related variables participant-related variables appear multiple times. may occur data different oTree versions, use different variable names, combined. desired, function can merge variables, storing data using newer oTree version's variable names removing outdated variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check if the Chats data frame is messy — messy_chat","text":"","code":"messy_chat( oTree, combine = FALSE, session = TRUE, participant = TRUE, info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check if the Chats data frame is messy — messy_chat","text":"oTree list data frames created import_otree. combine Logical. TRUE variables referring session code merged /variables referring participant code merged case data several versions oTree used. session Logical. TRUE variables referring session code checked merged. Merging works combine = TRUE. participant Logical. TRUE variables referring participant code checked merged. Merging works combine = TRUE. info Logical. TRUE brief information process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check if the Chats data frame is messy — messy_chat","text":"function searches multiple variables related session code participant code $Chats data frame. can occur data old new oTree versions used. combine = FALSE, function throw error variables found. combine = TRUE, function throw error variables found. Instead, automatically combines variables new variables adds original $Chats data frame. function returns duplicate original oTree list $Chats data frame modified. new variables called participant_code session_code.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_chat.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check if the Chats data frame is messy — messy_chat","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. # Show all Chats column names print(colnames(oTree$Chats)) #> [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" #> [5] \"nickname\" \"body\" \"timestamp\" # Run function oTree <- messy_chat(oTree, combine = TRUE) # Show all Chats column names again print(colnames(oTree$Chats)) #> [1] \"session_code\" \"id_in_session\" \"participant_code\" \"channel\" #> [5] \"nickname\" \"body\" \"timestamp\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":null,"dir":"Reference","previous_headings":"","what":"Check if the Time data frame is messy — messy_time","title":"Check if the Time data frame is messy — messy_time","text":"Checks Time data frame includes participant-related variables time stamp variables appear multiple times. may occur data different oTree versions, use different variable names, combined. desired, function can merge variables, storing data using newer oTree version's variable names removing outdated variables.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Check if the Time data frame is messy — messy_time","text":"","code":"messy_time( oTree, combine = FALSE, epoch_time = TRUE, participant = TRUE, info = FALSE )"},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Check if the Time data frame is messy — messy_time","text":"oTree list data frames created import_otree. combine Logical. TRUE variables referring epoch time merged /variables referring participant code merged case data several versions oTree used. epoch_time Logical. TRUE variables referring time stamp checked merged. works combine = TRUE. participant Logical. TRUE variables referring participant code checked merged. works combine = TRUE. info Logical. TRUE brief information process printed.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Check if the Time data frame is messy — messy_time","text":"function searches multiple variables related time stamp participant code $Time data frame, can occur data old new oTree versions used. combine = FALSE, function throw error variables found. combine = TRUE, function throw error variables found. Instead, automatically combines variables new variables adds original $Time data frame. function returns duplicate original oTree list $Time data frame modified. new variables called epoch_time_completed participant_code.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/messy_time.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Check if the Time data frame is messy — messy_time","text":"","code":"# Set data folder first withr::with_dir(system.file(\"extdata\", package = \"gmoTree\"), { # Import all oTree files in this folder and its subfolders oTree <- import_otree() }) #> Warning: You have stored all_apps_wide globally but also room-specific. This function will import both of them. (Globally, the files are saved as \"all_apps_wide_.\" Room-specific, the files are saved as \"All apps - wide-\" or \"all_apps_wide-.\") After importing the data, make sure nothing is there twice! (Advice: You may use delete_duplicate() to remove duplicate rows of all oTree data frames. # Show all Time column names print(colnames(oTree$Time)) #> [1] \"session_code\" \"participant_id_in_session\" #> [3] \"participant_code\" \"page_index\" #> [5] \"app_name\" \"page_name\" #> [7] \"epoch_time_completed\" \"round_number\" #> [9] \"timeout_happened\" \"is_wait_page\" # Run function oTree <- messy_time(oTree, combine = TRUE) # Show all Time column names again print(colnames(oTree$Time)) #> [1] \"session_code\" \"participant_id_in_session\" #> [3] \"participant_code\" \"page_index\" #> [5] \"app_name\" \"page_name\" #> [7] \"epoch_time_completed\" \"round_number\" #> [9] \"timeout_happened\" \"is_wait_page\""},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":null,"dir":"Reference","previous_headings":"","what":"Sample experimental data — oTree","title":"Sample experimental data — oTree","text":"Sample experimental data","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Sample experimental data — oTree","text":"","code":"oTree"},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":"format","dir":"Reference","previous_headings":"","what":"Format","title":"Sample experimental data — oTree","text":"list data frames created import_otree().","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/oTree.html","id":"source","dir":"Reference","previous_headings":"","what":"Source","title":"Sample experimental data — oTree","text":"data set created using modified versions official oTree sample experiments can downloaded installing oTree. detail, following apps used: \"start,\" \"dictator,\" \"chatapp,\" \"survey.\"","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":null,"dir":"Reference","previous_headings":"","what":"Calculate the seconds spent on each page — pagesec","title":"Calculate the seconds spent on each page — pagesec","text":"Create new variable $Time data frame contains time spent page.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Calculate the seconds spent on each page — pagesec","text":"","code":"pagesec(oTree, rounded = TRUE, digits = 2, minutes = FALSE, combine = FALSE)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Calculate the seconds spent on each page — pagesec","text":"oTree list data frames created import_otree. rounded Logical. TRUE output rounded. digits Integer. number digits output rounded. parameter effect unless rounded = TRUE. minutes Logical. TRUE output minutes instead seconds. combine Logical. TRUE variables referring epoch time merged, variables referring participant code merged case data several versions oTree used.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Calculate the seconds spent on each page — pagesec","text":"function returns duplicate original oTree list data frames also contains column $Time data frame named seconds_on_page2 minutes_on_page.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/pagesec.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Calculate the seconds spent on each page — pagesec","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Create two new columns: seconds_on_page2 and minutes_on_page oTree <- pagesec(oTree, rounded = TRUE, minutes = TRUE) # Show the Time data frame head(oTree$Time, n = 30) #> session_code participant_id_in_session participant_code page_index app_name #> 1 7bfqtokx 1 46kxib6w 0 #> 2 7bfqtokx 2 iay3dhkn 0 #> 3 7bfqtokx 3 4zhzdmzo 0 #> 4 7bfqtokx 4 3ttf7yix 0 #> 5 7bfqtokx 5 2d72mfgh 0 #> 6 7bfqtokx 6 rvce7958 0 #> 7 7bfqtokx 7 164r1hs4 0 #> 8 7bfqtokx 8 lsl3vbij 0 #> 9 7bfqtokx 9 ktjz5jli 0 #> 10 7bfqtokx 1 46kxib6w 1 dictator #> 11 7bfqtokx 1 46kxib6w 2 dictator #> 12 7bfqtokx 2 iay3dhkn 1 dictator #> 13 7bfqtokx 1 46kxib6w 3 dictator #> 14 7bfqtokx 2 iay3dhkn 3 dictator #> 15 7bfqtokx 2 iay3dhkn 4 dictator #> 16 7bfqtokx 2 iay3dhkn 5 dictator #> 17 7bfqtokx 1 46kxib6w 4 dictator #> 18 7bfqtokx 1 46kxib6w 5 dictator #> 19 7bfqtokx 1 46kxib6w 6 dictator #> 20 7bfqtokx 1 46kxib6w 7 dictator #> 21 7bfqtokx 2 iay3dhkn 7 dictator #> 22 7bfqtokx 1 46kxib6w 8 dictator #> 23 7bfqtokx 1 46kxib6w 9 dictator #> 24 7bfqtokx 1 46kxib6w 10 dictator #> 25 7bfqtokx 2 iay3dhkn 8 dictator #> 26 7bfqtokx 2 iay3dhkn 9 dictator #> 27 7bfqtokx 1 46kxib6w 11 dictator #> 28 7bfqtokx 2 iay3dhkn 11 dictator #> 29 7bfqtokx 2 iay3dhkn 12 dictator #> 30 7bfqtokx 1 46kxib6w 12 dictator #> page_name epoch_time_completed round_number timeout_happened #> 1 InitializeParticipant 1679926144 1 0 #> 2 InitializeParticipant 1679926145 1 0 #> 3 InitializeParticipant 1679926146 1 0 #> 4 InitializeParticipant 1679926146 1 0 #> 5 InitializeParticipant 1679926147 1 0 #> 6 InitializeParticipant 1679926147 1 0 #> 7 InitializeParticipant 1679926148 1 0 #> 8 InitializeParticipant 1679926148 1 0 #> 9 InitializeParticipant 1679926149 1 0 #> 10 Introduction 1679926151 1 0 #> 11 Offer 1679926154 1 0 #> 12 Introduction 1679926156 1 0 #> 13 ResultsWaitPage 1679926156 1 0 #> 14 ResultsWaitPage 1679926156 1 0 #> 15 Results 1679926157 1 0 #> 16 Introduction 1679926158 2 0 #> 17 Results 1679926160 1 0 #> 18 Introduction 1679926162 2 0 #> 19 Offer 1679926165 2 0 #> 20 ResultsWaitPage 1679926165 2 0 #> 21 ResultsWaitPage 1679926165 2 0 #> 22 Results 1679926166 2 0 #> 23 Introduction 1679926167 3 0 #> 24 Offer 1679926169 3 0 #> 25 Results 1679926171 2 0 #> 26 Introduction 1679926172 3 0 #> 27 ResultsWaitPage 1679926172 3 0 #> 28 ResultsWaitPage 1679926172 3 0 #> 29 Results 1679926173 3 0 #> 30 Results 1679926178 3 0 #> is_wait_page minutes_on_page #> 1 0 NA #> 2 0 NA #> 3 0 NA #> 4 0 NA #> 5 0 NA #> 6 0 NA #> 7 0 NA #> 8 0 NA #> 9 0 NA #> 10 0 0.12 #> 11 0 0.05 #> 12 0 0.18 #> 13 1 0.03 #> 14 1 0.00 #> 15 0 0.02 #> 16 0 0.02 #> 17 0 0.07 #> 18 0 0.03 #> 19 0 0.05 #> 20 1 0.00 #> 21 1 0.12 #> 22 0 0.02 #> 23 0 0.02 #> 24 0 0.03 #> 25 0 0.10 #> 26 0 0.02 #> 27 1 0.05 #> 28 1 0.00 #> 29 0 0.02 #> 30 0 0.10"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":null,"dir":"Reference","previous_headings":"","what":"Show constant columns — show_constant","title":"Show constant columns — show_constant","text":"Show columns variation values data frame oTree list data frames (except ones info list). function helpful running experiment check unnecessary variables. can check columns unchanging possible value columns containing specific value.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show constant columns — show_constant","text":"","code":"show_constant(oTree, value = \"any\")"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show constant columns — show_constant","text":"oTree list data frames created import_otree. value value controlled within column. value set \"\", function checks columns possible values identical.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show constant columns — show_constant","text":"function returns list vectors, one app, $all_apps_wide, $Time /$Chats data frame. vector contains names variables constant values. variables constant values, vector empty.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_constant.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show constant columns — show_constant","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show all columns that contain only NAs show_constant(oTree = oTree) #> $all_apps_wide #> [1] \"participant._is_bot\" #> [2] \"participant._max_page_index\" #> [3] \"participant.visited\" #> [4] \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" #> [6] \"session.label\" #> [7] \"session.mturk_HITId\" #> [8] \"session.mturk_HITGroupId\" #> [9] \"session.comment\" #> [10] \"session.is_demo\" #> [11] \"session.config.name\" #> [12] \"session.config.real_world_currency_per_point\" #> [13] \"session.config.participation_fee\" #> [14] \"dictator.1.player.role\" #> [15] \"dictator.1.subsession.round_number\" #> [16] \"dictator.2.player.role\" #> [17] \"dictator.2.subsession.round_number\" #> [18] \"dictator.3.player.role\" #> [19] \"dictator.3.subsession.round_number\" #> [20] \"chatapp.1.player.role\" #> [21] \"chatapp.1.player.payoff\" #> [22] \"chatapp.1.subsession.round_number\" #> [23] \"survey.1.player.role\" #> [24] \"survey.1.player.payoff\" #> [25] \"survey.1.group.id_in_subsession\" #> [26] \"survey.1.subsession.round_number\" #> #> $chatapp #> [1] \"participant._is_bot\" \"participant._max_page_index\" #> [3] \"participant.visited\" \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" \"player.role\" #> [7] \"player.payoff\" \"subsession.round_number\" #> [9] \"session.label\" \"session.mturk_HITId\" #> [11] \"session.mturk_HITGroupId\" \"session.comment\" #> [13] \"session.is_demo\" #> #> $dictator #> [1] \"participant._is_bot\" \"participant._max_page_index\" #> [3] \"participant.visited\" \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" \"player.role\" #> [7] \"session.label\" \"session.mturk_HITId\" #> [9] \"session.mturk_HITGroupId\" \"session.comment\" #> [11] \"session.is_demo\" #> #> $survey #> [1] \"participant._is_bot\" \"participant._max_page_index\" #> [3] \"participant.visited\" \"participant.mturk_worker_id\" #> [5] \"participant.mturk_assignment_id\" \"player.role\" #> [7] \"player.payoff\" \"group.id_in_subsession\" #> [9] \"subsession.round_number\" \"session.label\" #> [11] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [13] \"session.comment\" \"session.is_demo\" #> #> $Time #> [1] \"timeout_happened\" #> #> $Chats #> character(0) #> show_constant(oTree = oTree, value = NA) #> $all_apps_wide #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"session.label\" \"session.mturk_HITId\" #> [5] \"session.mturk_HITGroupId\" \"session.comment\" #> [7] \"dictator.1.player.role\" \"dictator.2.player.role\" #> [9] \"dictator.3.player.role\" \"chatapp.1.player.role\" #> [11] \"survey.1.player.role\" #> #> $chatapp #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"player.role\" \"session.label\" #> [5] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [7] \"session.comment\" #> #> $dictator #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"player.role\" \"session.label\" #> [5] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [7] \"session.comment\" #> #> $survey #> [1] \"participant.mturk_worker_id\" \"participant.mturk_assignment_id\" #> [3] \"player.role\" \"session.label\" #> [5] \"session.mturk_HITId\" \"session.mturk_HITGroupId\" #> [7] \"session.comment\" #> #> $Time #> character(0) #> #> $Chats #> character(0) #> # Show all columns that contain only -99 show_constant(oTree = oTree, value = -99) #> $all_apps_wide #> character(0) #> #> $chatapp #> character(0) #> #> $dictator #> character(0) #> #> $survey #> character(0) #> #> $Time #> character(0) #> #> $Chats #> character(0) #>"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":null,"dir":"Reference","previous_headings":"","what":"Show participants who did not finish the experiment — show_dropouts","title":"Show participants who did not finish the experiment — show_dropouts","text":"Show information people finish experiment () certain page(s) /app(s).","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"ref-usage","dir":"Reference","previous_headings":"","what":"Usage","title":"Show participants who did not finish the experiment — show_dropouts","text":"","code":"show_dropouts(oTree, final_apps = NULL, final_pages = NULL, saved_vars = NULL)"},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"arguments","dir":"Reference","previous_headings":"","what":"Arguments","title":"Show participants who did not finish the experiment — show_dropouts","text":"oTree list data frames created import_otree. final_apps Character. name(s) app(s) participants finish experiment. final_pages Character. name(s) page(s) participants finish experiment. saved_vars name(s) variable(s) need(s) shown list information dropout cases.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"value","dir":"Reference","previous_headings":"","what":"Value","title":"Show participants who did not finish the experiment — show_dropouts","text":"function returns list information participants finish experiment. list, can find following information: - $full = data frame contains information participants finish study; shows participant codes, names apps left experiment, names pages left experiment, names app data frames information found, dropout reason (\"ENC\", experiment completed, combined name data frame dropout observed). participants usually appear multiple app data frames, $full data frame may contain several entries person. - $unique = data frame contains similar information $full data frame one row per participant information data frame dropout observed. - $all_end = table provides information app page combinations participants ended experiment. table also includes information participants drop experiment. $all_end table shown $all_apps_wide data frame exists. - $codes = vector containing participant codes participants finish experiment. - $count = number participants finish experiment. important note argument final_pages set, function distinguish page names reoccur different apps. columns end_app end_page output empty, variables saved oTree specific participants. empty rows deleted. can done using argument del_empty = TRUE\" using import_otree.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/reference/show_dropouts.html","id":"ref-examples","dir":"Reference","previous_headings":"","what":"Examples","title":"Show participants who did not finish the experiment — show_dropouts","text":"","code":"# Use package-internal list of oTree data frames oTree <- gmoTree::oTree # Show everyone who did not finish with the app \"survey\" show_dropouts(oTree, final_apps = \"survey\") #> $full #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 2 164r1hs4 7bfqtokx chatapp chat #> 3 164r1hs4 7bfqtokx chatapp chat #> 4 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 6 2scvem7a vd1h01iv dictator ResultsWaitPage #> 7 2scvem7a vd1h01iv dictator ResultsWaitPage #> 8 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 10 7wa8kk3d l8ecm1uh dictator Introduction #> 11 7wa8kk3d l8ecm1uh dictator Introduction #> 12 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 14 ao9kqvqn l8ecm1uh dictator Introduction #> 15 ao9kqvqn l8ecm1uh dictator Introduction #> 16 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 18 d4sq7zio l8ecm1uh dictator Introduction #> 19 d4sq7zio l8ecm1uh dictator Introduction #> 20 d4sq7zio l8ecm1uh dictator Introduction #> 21 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 22 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 23 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 24 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 25 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 26 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 27 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 28 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 29 znri6myc l8ecm1uh dictator Introduction #> 30 znri6myc l8ecm1uh dictator Introduction #> 31 znri6myc l8ecm1uh dictator Introduction #> 32 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed. Noticed at: all_apps_wide #> 2 Experiment not completed. Noticed at: chatapp #> 3 Experiment not completed. Noticed at: dictator #> 4 Experiment not completed. Noticed at: survey #> 5 Experiment not completed. Noticed at: all_apps_wide #> 6 Experiment not completed. Noticed at: chatapp #> 7 Experiment not completed. Noticed at: dictator #> 8 Experiment not completed. Noticed at: survey #> 9 Experiment not completed. Noticed at: all_apps_wide #> 10 Experiment not completed. Noticed at: chatapp #> 11 Experiment not completed. Noticed at: dictator #> 12 Experiment not completed. Noticed at: survey #> 13 Experiment not completed. Noticed at: all_apps_wide #> 14 Experiment not completed. Noticed at: chatapp #> 15 Experiment not completed. Noticed at: dictator #> 16 Experiment not completed. Noticed at: survey #> 17 Experiment not completed. Noticed at: all_apps_wide #> 18 Experiment not completed. Noticed at: chatapp #> 19 Experiment not completed. Noticed at: dictator #> 20 Experiment not completed. Noticed at: survey #> 21 Experiment not completed. Noticed at: all_apps_wide #> 22 Experiment not completed. Noticed at: chatapp #> 23 Experiment not completed. Noticed at: dictator #> 24 Experiment not completed. Noticed at: survey #> 25 Experiment not completed. Noticed at: all_apps_wide #> 26 Experiment not completed. Noticed at: chatapp #> 27 Experiment not completed. Noticed at: dictator #> 28 Experiment not completed. Noticed at: survey #> 29 Experiment not completed. Noticed at: all_apps_wide #> 30 Experiment not completed. Noticed at: chatapp #> 31 Experiment not completed. Noticed at: dictator #> 32 Experiment not completed. Noticed at: survey #> #> $unique #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 21 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 25 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 29 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed #> 5 Experiment not completed #> 9 Experiment not completed #> 13 Experiment not completed #> 17 Experiment not completed #> 21 Experiment not completed #> 25 Experiment not completed #> 29 Experiment not completed #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"164r1hs4\" \"2scvem7a\" \"7wa8kk3d\" \"ao9kqvqn\" \"d4sq7zio\" \"ktjz5jli\" \"vbhvhozv\" #> [8] \"znri6myc\" #> #> $count #> [1] 8 #> # Show everyone who did not finish with the page \"Demographics\" show_dropouts(oTree, final_pages = \"Demographics\") #> $full #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 2 164r1hs4 7bfqtokx chatapp chat #> 3 164r1hs4 7bfqtokx chatapp chat #> 4 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 6 2scvem7a vd1h01iv dictator ResultsWaitPage #> 7 2scvem7a vd1h01iv dictator ResultsWaitPage #> 8 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 10 7wa8kk3d l8ecm1uh dictator Introduction #> 11 7wa8kk3d l8ecm1uh dictator Introduction #> 12 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 14 ao9kqvqn l8ecm1uh dictator Introduction #> 15 ao9kqvqn l8ecm1uh dictator Introduction #> 16 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 18 d4sq7zio l8ecm1uh dictator Introduction #> 19 d4sq7zio l8ecm1uh dictator Introduction #> 20 d4sq7zio l8ecm1uh dictator Introduction #> 21 jxh15obl t0rog7nz survey Offer #> 22 jxh15obl t0rog7nz survey Offer #> 23 jxh15obl t0rog7nz survey Offer #> 24 jxh15obl t0rog7nz survey Offer #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 26 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 27 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 28 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 30 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 31 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 32 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 33 znri6myc l8ecm1uh dictator Introduction #> 34 znri6myc l8ecm1uh dictator Introduction #> 35 znri6myc l8ecm1uh dictator Introduction #> 36 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed. Noticed at: all_apps_wide #> 2 Experiment not completed. Noticed at: survey #> 3 Experiment not completed. Noticed at: dictator #> 4 Experiment not completed. Noticed at: chatapp #> 5 Experiment not completed. Noticed at: survey #> 6 Experiment not completed. Noticed at: dictator #> 7 Experiment not completed. Noticed at: chatapp #> 8 Experiment not completed. Noticed at: all_apps_wide #> 9 Experiment not completed. Noticed at: survey #> 10 Experiment not completed. Noticed at: dictator #> 11 Experiment not completed. Noticed at: chatapp #> 12 Experiment not completed. Noticed at: all_apps_wide #> 13 Experiment not completed. Noticed at: survey #> 14 Experiment not completed. Noticed at: dictator #> 15 Experiment not completed. Noticed at: chatapp #> 16 Experiment not completed. Noticed at: all_apps_wide #> 17 Experiment not completed. Noticed at: dictator #> 18 Experiment not completed. Noticed at: chatapp #> 19 Experiment not completed. Noticed at: all_apps_wide #> 20 Experiment not completed. Noticed at: survey #> 21 Experiment not completed. Noticed at: chatapp #> 22 Experiment not completed. Noticed at: all_apps_wide #> 23 Experiment not completed. Noticed at: survey #> 24 Experiment not completed. Noticed at: dictator #> 25 Experiment not completed. Noticed at: survey #> 26 Experiment not completed. Noticed at: dictator #> 27 Experiment not completed. Noticed at: chatapp #> 28 Experiment not completed. Noticed at: all_apps_wide #> 29 Experiment not completed. Noticed at: survey #> 30 Experiment not completed. Noticed at: dictator #> 31 Experiment not completed. Noticed at: chatapp #> 32 Experiment not completed. Noticed at: all_apps_wide #> 33 Experiment not completed. Noticed at: survey #> 34 Experiment not completed. Noticed at: dictator #> 35 Experiment not completed. Noticed at: chatapp #> 36 Experiment not completed. Noticed at: all_apps_wide #> #> $unique #> participant.code session.code end_app end_page #> 1 164r1hs4 7bfqtokx chatapp chat #> 5 2scvem7a vd1h01iv dictator ResultsWaitPage #> 9 7wa8kk3d l8ecm1uh dictator Introduction #> 13 ao9kqvqn l8ecm1uh dictator Introduction #> 17 d4sq7zio l8ecm1uh dictator Introduction #> 21 jxh15obl t0rog7nz survey Offer #> 25 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 29 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 33 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed #> 5 Experiment not completed #> 9 Experiment not completed #> 13 Experiment not completed #> 17 Experiment not completed #> 21 Experiment not completed #> 25 Experiment not completed #> 29 Experiment not completed #> 33 Experiment not completed #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"164r1hs4\" \"2scvem7a\" \"7wa8kk3d\" \"ao9kqvqn\" \"d4sq7zio\" \"jxh15obl\" \"ktjz5jli\" #> [8] \"vbhvhozv\" \"znri6myc\" #> #> $count #> [1] 9 #> # Show everyone who finished with the following apps: \"survey,\" \"dictator\" final_apps <- unique(oTree$all_apps_wide$participant._current_app_name) final_apps <- final_apps[final_apps != \"survey\"] final_apps <- final_apps[final_apps != \"dictator\"] show_dropouts(oTree, final_apps = final_apps) #> $full #> participant.code session.code end_app end_page #> 1 1l5kal0r t0rog7nz survey Demographics #> 2 1l5kal0r t0rog7nz survey Demographics #> 3 1l5kal0r t0rog7nz survey Demographics #> 4 1l5kal0r t0rog7nz survey Demographics #> 5 1mn1kzs7 gii59rga survey Demographics #> 6 2d72mfgh 7bfqtokx survey Demographics #> 7 2d72mfgh 7bfqtokx survey Demographics #> 8 2d72mfgh 7bfqtokx survey Demographics #> 9 2d72mfgh 7bfqtokx survey Demographics #> 10 2scvem7a vd1h01iv dictator ResultsWaitPage #> 11 2scvem7a vd1h01iv dictator ResultsWaitPage #> 12 2scvem7a vd1h01iv dictator ResultsWaitPage #> 13 2scvem7a vd1h01iv dictator ResultsWaitPage #> 14 3ttf7yix 7bfqtokx survey Demographics #> 15 3ttf7yix 7bfqtokx survey Demographics #> 16 3ttf7yix 7bfqtokx survey Demographics #> 17 3ttf7yix 7bfqtokx survey Demographics #> 18 46kxib6w 7bfqtokx survey Demographics #> 19 46kxib6w 7bfqtokx survey Demographics #> 20 46kxib6w 7bfqtokx survey Demographics #> 21 46kxib6w 7bfqtokx survey Demographics #> 22 4zhzdmzo 7bfqtokx survey Demographics #> 23 4zhzdmzo 7bfqtokx survey Demographics #> 24 4zhzdmzo 7bfqtokx survey Demographics #> 25 4zhzdmzo 7bfqtokx survey Demographics #> 26 6cim3a5i gii59rga survey Demographics #> 27 7l0hmpcq qyu3qg0q survey Demographics #> 28 7l0hmpcq qyu3qg0q survey Demographics #> 29 7l0hmpcq qyu3qg0q survey Demographics #> 30 7l0hmpcq qyu3qg0q survey Demographics #> 31 7wa8kk3d l8ecm1uh dictator Introduction #> 32 7wa8kk3d l8ecm1uh dictator Introduction #> 33 7wa8kk3d l8ecm1uh dictator Introduction #> 34 7wa8kk3d l8ecm1uh dictator Introduction #> 35 a7dppel1 t0rog7nz survey Demographics #> 36 a7dppel1 t0rog7nz survey Demographics #> 37 a7dppel1 t0rog7nz survey Demographics #> 38 a7dppel1 t0rog7nz survey Demographics #> 39 ao9kqvqn l8ecm1uh dictator Introduction #> 40 ao9kqvqn l8ecm1uh dictator Introduction #> 41 ao9kqvqn l8ecm1uh dictator Introduction #> 42 ao9kqvqn l8ecm1uh dictator Introduction #> 43 byxco6zo gii59rga survey Demographics #> 44 d4sq7zio l8ecm1uh dictator Introduction #> 45 d4sq7zio l8ecm1uh dictator Introduction #> 46 d4sq7zio l8ecm1uh dictator Introduction #> 47 d4sq7zio l8ecm1uh dictator Introduction #> 48 ia9rnfvc qyu3qg0q survey Demographics #> 49 ia9rnfvc qyu3qg0q survey Demographics #> 50 ia9rnfvc qyu3qg0q survey Demographics #> 51 ia9rnfvc qyu3qg0q survey Demographics #> 52 iagvtslv t0rog7nz survey Demographics #> 53 iagvtslv t0rog7nz survey Demographics #> 54 iagvtslv t0rog7nz survey Demographics #> 55 iagvtslv t0rog7nz survey Demographics #> 56 iay3dhkn 7bfqtokx survey Demographics #> 57 iay3dhkn 7bfqtokx survey Demographics #> 58 iay3dhkn 7bfqtokx survey Demographics #> 59 iay3dhkn 7bfqtokx survey Demographics #> 60 jxh15obl t0rog7nz survey Offer #> 61 jxh15obl t0rog7nz survey Offer #> 62 jxh15obl t0rog7nz survey Offer #> 63 jxh15obl t0rog7nz survey Offer #> 64 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 65 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 66 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 67 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 68 lsl3vbij 7bfqtokx survey Demographics #> 69 lsl3vbij 7bfqtokx survey Demographics #> 70 lsl3vbij 7bfqtokx survey Demographics #> 71 lsl3vbij 7bfqtokx survey Demographics #> 72 rvce7958 7bfqtokx survey Demographics #> 73 rvce7958 7bfqtokx survey Demographics #> 74 rvce7958 7bfqtokx survey Demographics #> 75 rvce7958 7bfqtokx survey Demographics #> 76 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 77 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 78 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 79 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 80 wk247s9w t0rog7nz survey Demographics #> 81 wk247s9w t0rog7nz survey Demographics #> 82 wk247s9w t0rog7nz survey Demographics #> 83 wk247s9w t0rog7nz survey Demographics #> 84 xkobdvuh t0rog7nz survey Demographics #> 85 xkobdvuh t0rog7nz survey Demographics #> 86 xkobdvuh t0rog7nz survey Demographics #> 87 xkobdvuh t0rog7nz survey Demographics #> 88 xmxl46rm vd1h01iv survey Demographics #> 89 xmxl46rm vd1h01iv survey Demographics #> 90 xmxl46rm vd1h01iv survey Demographics #> 91 xmxl46rm vd1h01iv survey Demographics #> 92 xx78b3x0 vd1h01iv survey Demographics #> 93 xx78b3x0 vd1h01iv survey Demographics #> 94 xx78b3x0 vd1h01iv survey Demographics #> 95 xx78b3x0 vd1h01iv survey Demographics #> 96 zdki96d6 gii59rga survey Demographics #> 97 znri6myc l8ecm1uh dictator Introduction #> 98 znri6myc l8ecm1uh dictator Introduction #> 99 znri6myc l8ecm1uh dictator Introduction #> 100 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed. Noticed at: chatapp #> 2 Experiment not completed. Noticed at: all_apps_wide #> 3 Experiment not completed. Noticed at: dictator #> 4 Experiment not completed. Noticed at: survey #> 5 Experiment not completed. Noticed at: all_apps_wide #> 6 Experiment not completed. Noticed at: chatapp #> 7 Experiment not completed. Noticed at: all_apps_wide #> 8 Experiment not completed. Noticed at: dictator #> 9 Experiment not completed. Noticed at: survey #> 10 Experiment not completed. Noticed at: survey #> 11 Experiment not completed. Noticed at: all_apps_wide #> 12 Experiment not completed. Noticed at: dictator #> 13 Experiment not completed. Noticed at: chatapp #> 14 Experiment not completed. Noticed at: chatapp #> 15 Experiment not completed. Noticed at: dictator #> 16 Experiment not completed. Noticed at: survey #> 17 Experiment not completed. Noticed at: all_apps_wide #> 18 Experiment not completed. Noticed at: all_apps_wide #> 19 Experiment not completed. Noticed at: dictator #> 20 Experiment not completed. Noticed at: chatapp #> 21 Experiment not completed. Noticed at: survey #> 22 Experiment not completed. Noticed at: chatapp #> 23 Experiment not completed. Noticed at: survey #> 24 Experiment not completed. Noticed at: all_apps_wide #> 25 Experiment not completed. Noticed at: dictator #> 26 Experiment not completed. Noticed at: all_apps_wide #> 27 Experiment not completed. Noticed at: dictator #> 28 Experiment not completed. Noticed at: chatapp #> 29 Experiment not completed. Noticed at: all_apps_wide #> 30 Experiment not completed. Noticed at: survey #> 31 Experiment not completed. Noticed at: chatapp #> 32 Experiment not completed. Noticed at: all_apps_wide #> 33 Experiment not completed. Noticed at: dictator #> 34 Experiment not completed. Noticed at: survey #> 35 Experiment not completed. Noticed at: survey #> 36 Experiment not completed. Noticed at: all_apps_wide #> 37 Experiment not completed. Noticed at: dictator #> 38 Experiment not completed. Noticed at: chatapp #> 39 Experiment not completed. Noticed at: chatapp #> 40 Experiment not completed. Noticed at: all_apps_wide #> 41 Experiment not completed. Noticed at: dictator #> 42 Experiment not completed. Noticed at: survey #> 43 Experiment not completed. Noticed at: all_apps_wide #> 44 Experiment not completed. Noticed at: chatapp #> 45 Experiment not completed. Noticed at: all_apps_wide #> 46 Experiment not completed. Noticed at: dictator #> 47 Experiment not completed. Noticed at: survey #> 48 Experiment not completed. Noticed at: all_apps_wide #> 49 Experiment not completed. Noticed at: dictator #> 50 Experiment not completed. Noticed at: chatapp #> 51 Experiment not completed. Noticed at: survey #> 52 Experiment not completed. Noticed at: chatapp #> 53 Experiment not completed. Noticed at: survey #> 54 Experiment not completed. Noticed at: all_apps_wide #> 55 Experiment not completed. Noticed at: dictator #> 56 Experiment not completed. Noticed at: survey #> 57 Experiment not completed. Noticed at: all_apps_wide #> 58 Experiment not completed. Noticed at: dictator #> 59 Experiment not completed. Noticed at: chatapp #> 60 Experiment not completed. Noticed at: all_apps_wide #> 61 Experiment not completed. Noticed at: dictator #> 62 Experiment not completed. Noticed at: chatapp #> 63 Experiment not completed. Noticed at: survey #> 64 Experiment not completed. Noticed at: chatapp #> 65 Experiment not completed. Noticed at: all_apps_wide #> 66 Experiment not completed. Noticed at: dictator #> 67 Experiment not completed. Noticed at: survey #> 68 Experiment not completed. Noticed at: chatapp #> 69 Experiment not completed. Noticed at: dictator #> 70 Experiment not completed. Noticed at: all_apps_wide #> 71 Experiment not completed. Noticed at: survey #> 72 Experiment not completed. Noticed at: chatapp #> 73 Experiment not completed. Noticed at: all_apps_wide #> 74 Experiment not completed. Noticed at: dictator #> 75 Experiment not completed. Noticed at: survey #> 76 Experiment not completed. Noticed at: all_apps_wide #> 77 Experiment not completed. Noticed at: dictator #> 78 Experiment not completed. Noticed at: chatapp #> 79 Experiment not completed. Noticed at: survey #> 80 Experiment not completed. Noticed at: chatapp #> 81 Experiment not completed. Noticed at: survey #> 82 Experiment not completed. Noticed at: all_apps_wide #> 83 Experiment not completed. Noticed at: dictator #> 84 Experiment not completed. Noticed at: chatapp #> 85 Experiment not completed. Noticed at: dictator #> 86 Experiment not completed. Noticed at: survey #> 87 Experiment not completed. Noticed at: all_apps_wide #> 88 Experiment not completed. Noticed at: dictator #> 89 Experiment not completed. Noticed at: chatapp #> 90 Experiment not completed. Noticed at: all_apps_wide #> 91 Experiment not completed. Noticed at: survey #> 92 Experiment not completed. Noticed at: chatapp #> 93 Experiment not completed. Noticed at: all_apps_wide #> 94 Experiment not completed. Noticed at: dictator #> 95 Experiment not completed. Noticed at: survey #> 96 Experiment not completed. Noticed at: all_apps_wide #> 97 Experiment not completed. Noticed at: chatapp #> 98 Experiment not completed. Noticed at: dictator #> 99 Experiment not completed. Noticed at: all_apps_wide #> 100 Experiment not completed. Noticed at: survey #> #> $unique #> participant.code session.code end_app end_page #> 1 1l5kal0r t0rog7nz survey Demographics #> 5 1mn1kzs7 gii59rga survey Demographics #> 6 2d72mfgh 7bfqtokx survey Demographics #> 10 2scvem7a vd1h01iv dictator ResultsWaitPage #> 14 3ttf7yix 7bfqtokx survey Demographics #> 18 46kxib6w 7bfqtokx survey Demographics #> 22 4zhzdmzo 7bfqtokx survey Demographics #> 26 6cim3a5i gii59rga survey Demographics #> 27 7l0hmpcq qyu3qg0q survey Demographics #> 31 7wa8kk3d l8ecm1uh dictator Introduction #> 35 a7dppel1 t0rog7nz survey Demographics #> 39 ao9kqvqn l8ecm1uh dictator Introduction #> 43 byxco6zo gii59rga survey Demographics #> 44 d4sq7zio l8ecm1uh dictator Introduction #> 48 ia9rnfvc qyu3qg0q survey Demographics #> 52 iagvtslv t0rog7nz survey Demographics #> 56 iay3dhkn 7bfqtokx survey Demographics #> 60 jxh15obl t0rog7nz survey Offer #> 64 ktjz5jli 7bfqtokx dictator ResultsWaitPage #> 68 lsl3vbij 7bfqtokx survey Demographics #> 72 rvce7958 7bfqtokx survey Demographics #> 76 vbhvhozv vd1h01iv dictator ResultsWaitPage #> 80 wk247s9w t0rog7nz survey Demographics #> 84 xkobdvuh t0rog7nz survey Demographics #> 88 xmxl46rm vd1h01iv survey Demographics #> 92 xx78b3x0 vd1h01iv survey Demographics #> 96 zdki96d6 gii59rga survey Demographics #> 97 znri6myc l8ecm1uh dictator Introduction #> reason #> 1 Experiment not completed #> 5 Experiment not completed #> 6 Experiment not completed #> 10 Experiment not completed #> 14 Experiment not completed #> 18 Experiment not completed #> 22 Experiment not completed #> 26 Experiment not completed #> 27 Experiment not completed #> 31 Experiment not completed #> 35 Experiment not completed #> 39 Experiment not completed #> 43 Experiment not completed #> 44 Experiment not completed #> 48 Experiment not completed #> 52 Experiment not completed #> 56 Experiment not completed #> 60 Experiment not completed #> 64 Experiment not completed #> 68 Experiment not completed #> 72 Experiment not completed #> 76 Experiment not completed #> 80 Experiment not completed #> 84 Experiment not completed #> 88 Experiment not completed #> 92 Experiment not completed #> 96 Experiment not completed #> 97 Experiment not completed #> #> $all_end #> #> Demographics Introduction Offer ResultsWaitPage chat #> chatapp 0 0 0 0 1 #> dictator 0 4 0 3 0 #> survey 20 0 1 0 0 #> #> $codes #> [1] \"1l5kal0r\" \"1mn1kzs7\" \"2d72mfgh\" \"2scvem7a\" \"3ttf7yix\" \"46kxib6w\" #> [7] \"4zhzdmzo\" \"6cim3a5i\" \"7l0hmpcq\" \"7wa8kk3d\" \"a7dppel1\" \"ao9kqvqn\" #> [13] \"byxco6zo\" \"d4sq7zio\" \"ia9rnfvc\" \"iagvtslv\" \"iay3dhkn\" \"jxh15obl\" #> [19] \"ktjz5jli\" \"lsl3vbij\" \"rvce7958\" \"vbhvhozv\" \"wk247s9w\" \"xkobdvuh\" #> [25] \"xmxl46rm\" \"xx78b3x0\" \"zdki96d6\" \"znri6myc\" #> #> $count #> [1] 28 #>"},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-130","dir":"Changelog","previous_headings":"","what":"gmoTree 1.3.0","title":"gmoTree 1.3.0","text":"Resolved issue Constants vector presentations output files Fixed incorrect handling equal signs (=) documentation choices. splitvarname deal long variable names. Caveat: cases, columns may still overlap. Control output carefully. sep_list decide list presentation newline presentation output file initial include initial values codebook New preamble text Expanded input possibilities greater flexibility Changed default output_format pdf_document_simple Better presentations quotations inside strings Quotation marks now presented straight smart form Removed non-escaped quotation marks output Values now saved list format vectors Types variables now correspond better types original variables Improved list presentation output files better readability Enhanced error warning messages function can now better deal better empty arguments oTree code Linted older functions (readable) Website changes","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-121","dir":"Changelog","previous_headings":"","what":"gmoTree 1.2.1","title":"gmoTree 1.2.1","text":"codebook(): Create codebook oTree code Linted code (readable) Minor changes warning messages tests examples","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-110","dir":"Changelog","previous_headings":"","what":"gmoTree 1.1.0","title":"gmoTree 1.1.0","text":"CRAN release: 2024-07-04 extime(): Enhanced efficiency extended functionality: Introduced capability perform calculations using ‘seconds_on_page2’ variable. apptime(): Enhanced efficiency extended functionality: Introduced capability perform calculations using ‘seconds_on_page2’ variable. Linted code (efficient & readable) Minor changes tests.R Minor changes website, new logo","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-101","dir":"Changelog","previous_headings":"","what":"gmoTree 1.0.1","title":"gmoTree 1.0.1","text":"CRAN release: 2023-10-25 Minor changes examples DESCRIPTION file. Changes functions: NONE","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-100","dir":"Changelog","previous_headings":"","what":"gmoTree 1.0.0","title":"gmoTree 1.0.0","text":"File names examples now portable. import_otree(): Minor changes. Can also import portable file names now.","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-003","dir":"Changelog","previous_headings":"","what":"gmoTree 0.0.3","title":"gmoTree 0.0.3","text":"Minor improvement documentation & website. Changes functions: NONE","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-002","dir":"Changelog","previous_headings":"","what":"gmoTree 0.0.2","title":"gmoTree 0.0.2","text":"Minor improvement documentation & website. (Sent CRAN omitted .) Changes functions: NONE","code":""},{"path":"https://zauchnerp.github.io/gmoTree/news/index.html","id":"gmotree-001","dir":"Changelog","previous_headings":"","what":"gmoTree 0.0.1","title":"gmoTree 0.0.1","text":"Beta version gmoTree published (formerly known “ioTree”).","code":""}]
diff --git a/inst/CITATION b/inst/CITATION
index 878c8b3..0d42fa0 100644
--- a/inst/CITATION
+++ b/inst/CITATION
@@ -3,7 +3,7 @@ bibentry(
title = "gmoTree: oTree Data Manipulation Tool",
author = "Patricia F. Zauchner",
year = "2024",
- note = "R package version 1.2.0",
+ note = "R package version 1.3.0",
url = "https://CRAN.R-project.org/package=gmoTree",
- textVersion = "Zauchner, Patricia F. (2024). gmoTree: oTree Data Manipulation Tool. R package version 1.2.0, ."
+ textVersion = "Zauchner, Patricia F. (2024). gmoTree: oTree Data Manipulation Tool. R package version 1.3.0, ."
)
diff --git a/inst/extdata/ocode_new/bargaining/__init__.py b/inst/extdata/ocode_new/bargaining/__init__.py
index a41f451..065a3b7 100644
--- a/inst/extdata/ocode_new/bargaining/__init__.py
+++ b/inst/extdata/ocode_new/bargaining/__init__.py
@@ -36,7 +36,7 @@ class Player(BasePlayer):
label="Please enter an amount from 0 to 100",
)
level2 = models.IntegerField(
- choices=["No\, I won't", "yes\, I will", "Maybe I'll do"], # TODO choices were changed to test the code
+ choices=["No\, I won't", "yes\, I will", "Maybe I'll do"],
)
level3 = models.IntegerField(max = 10)
diff --git a/inst/extdata/ocode_new/dictator/__init__.py b/inst/extdata/ocode_new/dictator/__init__.py
index 5d6274f..28b1db7 100644
--- a/inst/extdata/ocode_new/dictator/__init__.py
+++ b/inst/extdata/ocode_new/dictator/__init__.py
@@ -3,6 +3,7 @@
# This code was adjusted to be used by gmotree to make it a bit more messy
class C(BaseConstants):
+ print("test that")
NAME_IN_URL = 'dictator'
PLAYERS_PER_GROUP = 2
NUM_ROUNDS = 1
@@ -29,12 +30,12 @@ class Group(BaseGroup):
doc="""Amount dictator decided to keep for himself""",
min=0,
max=C.ENDOWMENT,
- label="I will keep",
+ label="I will keep"
)
class Player(BasePlayer):
- pass
+ gender = models.IntegerField()
# FUNCTIONS
@@ -80,4 +81,4 @@ def vars_for_template(player: Player):
and the assumptions of economics." Journal of business (1986):
S285-S300.
-This code was adjusted to be used by gmotree to make it a bit more messy """
\ No newline at end of file
+This code was adjusted to be used by gmotree to make it a bit more messy """
diff --git a/inst/extdata/ocode_z/rankaversion/models.py b/inst/extdata/ocode_z/rankaversion/models.py
index 750faee..dd91199 100644
--- a/inst/extdata/ocode_z/rankaversion/models.py
+++ b/inst/extdata/ocode_z/rankaversion/models.py
@@ -164,8 +164,6 @@ def creating_session(self):
random.shuffle(listofpart)
# Select data and set it to a variable
- # TODO: Caution. If there is a warning message "single positional indexer is out-of-bounds",
- # TODO: then the number of participants is higher than the cases in the csv!
for p in self.get_players():
#
diff --git a/inst/extdata/ocode_z/rankaversion/pages.py b/inst/extdata/ocode_z/rankaversion/pages.py
index ca2a63f..bd7612d 100644
--- a/inst/extdata/ocode_z/rankaversion/pages.py
+++ b/inst/extdata/ocode_z/rankaversion/pages.py
@@ -101,7 +101,6 @@ def before_next_page(self):
#
-# Todo: Delete html and all of it at last
class TaskForPresentationReasons(Page):
# Type 1
diff --git a/inst/extdata/ocode_z/rankend/pages.py b/inst/extdata/ocode_z/rankend/pages.py
index a2bea5a..5c6b7a1 100644
--- a/inst/extdata/ocode_z/rankend/pages.py
+++ b/inst/extdata/ocode_z/rankend/pages.py
@@ -76,9 +76,9 @@ def is_displayed(self):
def vars_for_template(self):
self.player.motivation = "Player is not dictator and must not answer this question."
- # Todo: Change if there is an open question
- # # todo hier weitermachen
+
+ #
# Pretest
if "assignedRole" not in self.participant.vars: # if not already assigned in the prior app (pretest)
listofpart = [x for x in range(0, self.session.num_participants, 1)]
diff --git a/inst/extdata/ocode_z/settings.py b/inst/extdata/ocode_z/settings.py
index 3adaeed..5b53799 100644
--- a/inst/extdata/ocode_z/settings.py
+++ b/inst/extdata/ocode_z/settings.py
@@ -29,7 +29,7 @@
ADMIN_USERNAME = 'admin'
# ADMIN_PASSWORD = "admin"
-ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD') # Todo: Change Password
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
SESSION_CONFIG_DEFAULTS = {
@@ -82,4 +82,4 @@
]
POINTS_DECIMAL_PLACES = 2
-REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
\ No newline at end of file
+REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/inst/rmd/codebook.Rmd b/inst/rmd/codebook.Rmd
index 432bcb4..d9d0c64 100644
--- a/inst/rmd/codebook.Rmd
+++ b/inst/rmd/codebook.Rmd
@@ -3,11 +3,15 @@ title: "`r params$title`"
subtitle: "`r params$subtitle`"
date: "`r params$date`"
author: "`r params$author`"
-institute: "`r unlist(lapply(params$authors, function(x) x$inst))`"
+institute: "`r paste(unlist(lapply(params$authors, function(x) x$inst)), collapse = ', ')`"
header-includes:
- \usepackage[margins=raggedright]{floatrow}
+- \usepackage{longtable,booktabs,array}
+- \catcode`\"=\active
+- \def"{\textquotedbl}
---
+
```{r options, include = FALSE}
# Global options ####
knitr::opts_chunk$set(echo = FALSE,
@@ -18,60 +22,223 @@ header-includes:
dpi = 300L,
st_options = "rmarkdown")
+knitr::opts_chunk$set(smart = FALSE)
+
# Pander ####
- pander::panderOptions("knitr.auto.asis", FALSE)
- pander::panderOptions("table.split.table", Inf)
- pander::panderOptions("table.alignment.rownames", "left")
- pander::panderOptions("table.split.cells", 80L)
- pander::panderOptions("table.alignment.default", "left")
- pander::panderOptions("table.style", "multiline")
- pander::panderOptions("keep.line.breaks", TRUE)
+ pander::panderOptions("knitr.auto.asis", FALSE)
+ pander::panderOptions("table.alignment.rownames", "left")
+ pander::panderOptions("table.alignment.default", "left")
+ pander::panderOptions("table.style", "multiline")
+ pander::panderOptions("keep.line.breaks", TRUE)
+ pander::panderOptions("table.split.table", Inf)
+```
+
+```{r}
+data <- params$combined_codebook
```
```{r preamb}
-if (preamb) {
+if (!is.null(params$preamb) && params$preamb) {
cat("# Introduction to oTree data\n\n")
+
+
cat(sep = "", "In an oTree list of data frames, each application (app) is represented by its own data frame. Additionally, there is an `all_apps_wide` data frame that aggregates information from all apps.
-\n\n
-Variables within the `all_apps_wide` data frame follow the naming convention: \n\n",
-"`oTree$all_apps_wide$appname.1.player.variablename`\n\n",
-"The naming convention shows how the data is structured hierarchically, like a tree. In this case, the variable `variablename` is part of the class `Player`, which occurs in round `1,` of app `appname`, which is in the data frame `all_apps_wide` which is part of the list `oTree`.
-\n\n
-There are three different types of classes.\n",
+\n\n",
+
+# All apps wide ####
+ "The `all_apps_wide` data frame is in a wide format, where each participant is represented by a single row. ",
+
+ "Variables within the `all_apps_wide` data frame follow the naming convention: \n\n",
+ "`oTree$all_apps_wide$appname.1.player.variablename`\n\n",
+
+ "This convention reflects the hierarchical organization of the data, resembling a tree: ",
+
+ "the variable `variablename` belongs to the class `Player`, which occurs in round `1` of the app `appname`, and is located in the data frame `all_apps_wide`, which is part of the list `oTree`.
+ \n\n",
+
+# Classes ####
+ "In oTree, there are three types of classes: `Player`, `Group`, and `Participant`. ",
+
+
+"`Player` and `Group` variables are specific to each app, with values that may change across rounds. `Player` variables are unique to individual participants, whereas `Group` variables are shared among all members of a group. ",
+
+"`Participant` variables are individual-specific; however, unlike `Player` variables, they persist across apps. They can be accessed and updated within any app, with only their most recent value retained. ",
+
+ "`Participant` variables are not included in this codebook. ",
+
+ "For more detailed information on these concepts, refer to https://otree.readthedocs.io/en/latest/conceptual_overview.html.",
-"Player variables are individual-specific but may vary across apps and rounds, such as points earned in an effort task. Group variables are common to all members of a group and may also vary. Participant variables are individual-specific and although they can be accessed and manipulated in all apps, only their last value is saved in this global variable. Participant variables are not reported in this codebook. ",
+# App data ####
-"See https://otree.readthedocs.io/en/latest/conceptual_overview.html for more information on the concepts in oTree. ",
+ "\n\nIn contrast to `all_apps_wide`, the individual app data frames store data in a long format, where each row represents a single participant's data for a specific round. Variables in these app data frames follow this convention: ",
+
+ "`oTree$app$player.variablename`. ",
+
+ "Since the round number is saved in a separate variable and the app name is the name of the sublist, the last part only includes the variable name and its associated class.",
-"\n\nIn `all_apps_wide`, the data is stored in a wide format, meaning that there is one row of data for every participant. Conversely, the app data frames contain variables with the following format: `oTree$app$player.variablename`.
-They don't have a round number in their name since the data is stored in a long format.
-Thus, there is one row for each participant in each round. Additionally, it shows the class (Participant, Player, or Group) in which the variables are saved.
-\n\n
-Although the variables in `all_apps_wide` contain information on the app, the class, and the round, the subsequent presentation of that information is organized in a distinct manner through the use of headings and tables. The headings on the first level contain information on the apps. The following heading level denotes the class. ",
+"\n\n",
+
+# This codebook ####
+
+ "The subsequent presentation of the variables' information is organized through the use of headings and tables. ",
+ "The first-level headings correspond to the apps, the second-level headings indicate the class, and the tables at the final level contain the names and values of the variables as defined in the oTree code.",
-"On the last level, a table contains the variable names as they were given in the oTree code and their values. Round numbers are self-explanatory and won't be discussed for each variable. ")
-if (params$include_cons) {
- cat(sep = "", "How often an app is played can be seen in the Constants variable `num_rounds`.")
+ "\n\nStandard oTree variables, such as `player.payoff`, are not reported in this codebook.",
+
+ " Especially round numbers are considered self-explanatory and are not elaborated on for each variable. ")
+
+ if (params$include_cons) {
+ cat(sep = "", "The number of times an app is played can be found in the `Constants` variable `num_rounds`.")
+ }
+
}
+```
-cat(sep = "",
-"\n\nThe standard oTree variables, such as `player.payoff`, are not reported in this codebook."
-)
+```{r background functions}
+split_var_text <- function(text, limit = 30L) {
+ #' Split variable name if it is too long at the underscores
+ #' Is needed because sometimes the variable names are too long
+
+ if (nchar(text) <= limit) {
+ return(text)
+ }
+
+ # Locate all positions of `_`
+ underscore_positions <- gregexpr("_", text)[[1L]]
+
+ # Find the last underscore position before the limit
+ split_position <- max(underscore_positions[underscore_positions < limit])
+
+ # Split the text at the found position and insert a line break
+ if (split_position > 0L) {
+ text <- paste0(
+ substr(text, 1L, split_position), "\\\n",
+ substr(text, split_position + 1L, nchar(text))
+ )
+ }
+
+ return(text)
+}
+
+panderwithsplit <- function(table, splitvarname) {
+ #' Run split_var_text at set longest varname if splitvarname == TRUE
+ #' Is needed because sometimes the variable names are too long
+
+ table_copy <- table
+ spaces <- 0L
+ padding <- 4L
+
+ if (splitvarname) {
+ # Split text and set default split.cells
+ table_copy$Variable <- unlist(lapply(table_copy$Variable,
+ split_var_text))
+
+ maxvarname <- 30 - padding # Keep default
+
+ } else {
+ # Length of the longest variable name used to set split.cells
+ # (It is usually dynamic by default, however,
+ # not if there are underscores
+ # in the variable names)
+ maxvarname <- nchar(max(table_copy$Variable))
+
+ if (maxvarname < 30L) {
+ spaces <- 30L - maxvarname
+ }
+ }
+
+ out <- list()
+ out$table <- table_copy
+
+ # Compute cell width
+ n_uppercase <- sum(sapply(gregexpr("[A-Z]", maxvarname)[[1L]],
+ function(x) x > 0L))
+ n_lowercase <- maxvarname - n_uppercase
+
+ out$col1_length <- (n_lowercase +
+ n_uppercase * 1.142857 + # n_uppercases are wider than lowercases
+ spaces * 0.98 + # spaces are smaller than letters
+ padding)
+ out$col1_length <- round(out$col1_length)
+ out$col2_length <- 90L - out$col1_length
+
+ return(out)
+}
+
+list_to_string <- function(x) {
+ # If x is a vector or list, convert it to a string representation
+ if (is.vector(x)) {
+
+ listvec <- "cfuck("
+ if (is.list(x)) {
+ listvec <- "list("
+ }
+
+ # Use lapply to recursively apply the function to any nested vectors
+ elements <- lapply(x, function(e) {
+ if (is.vector(e) && !is.atomic(e)) {
+ # If element is a vector, call the function recursively
+ return(list_to_string(e))
+ } else {
+ # Otherwise, just return the element as a string
+ return(deparse(e))
+ }
+ })
+ # Create a string
+ return(paste(listvec, paste(elements, collapse = ", "), ")", sep = ""))
+ }
+ return(deparse(x))
+}
+
+makechunks <- function(variable, varval_i, chunk_size = 4L) {
+ # Each chunk should only be 4 rows long
+
+ chunks <- list()
+ cj <- 1L
+
+ # Iterate over the input and assign to chunks
+ for (i in seq_along(varval_i)) {
+
+ varval_sub <- paste(varval_i[[i]], collapse = ", ")
+
+ if (i == 1L) {
+ chunks[[cj]] <- varval_sub
+
+ } else if ((i - 1L) %% chunk_size == 0L) {
+
+ # Start a new chunk
+ cj <- cj + 1L
+ chunks[[cj]] <- varval_sub
+
+ } else if ((i - 1L) %% chunk_size != 0L) {
+ # Append to the current chunk
+ chunks[[cj]] <- paste(chunks[[cj]], varval_sub, sep = "\\\n")
+ }
+ }
+
+ # Create output table variables and values
+ table_variables <- rep("", length(chunks))
+ table_variables[1L] <- variable # Assign the variable name to the first chunk
+ table_values <- chunks # The chunks are the valuesf
+
+ # Return the list of variables and values
+ return(list(var = table_variables, val = table_values))
}
```
-```{r get app info}
+```{r get app info function}
get_app <- function(params,
data, folder) {
+ #' Print app heading and app documentation text
output <- paste0("\n\n# App: ", folder, "\n\n")
if (!is.null(params$app_doc) &&
params$app_doc &&
- !is.null(data[[folder]]$doc)) {
-
+ !is.null(data[[folder]]$doc) &&
+ data[[folder]]$doc != "") {
# Replace \\ with \n
data[[folder]]$doc <- gsub("\\\\",
@@ -85,14 +252,17 @@ get_app <- function(params,
}
```
-```{r group player}
+```{r group player function}
values_group_player <- function(subdata, variable) {
# Values ####
varval <- ""
# Doc
- if ("doc" %in% names(subdata[[variable]])) {
+ if ("doc" %in% names(subdata[[variable]]) &&
+ subdata[[variable]][["doc"]] != ""
+ ) {
+
varval <-
paste0(varval,
" Doc: ", subdata[[variable]][["doc"]],
@@ -140,6 +310,7 @@ values_group_player <- function(subdata, variable) {
subdata[[variable]][["choices"]][["value"]],
collapse = "\\\n"),
"\\\n")
+
} else if ("value" %in% names(subdata[[variable]][["choices"]])) {
varval <- paste0(varval, " Options:\\\n")
varval <- paste0(varval,
@@ -149,6 +320,7 @@ values_group_player <- function(subdata, variable) {
function(x) paste0(" ", x)),
collapse = "\\\n"),
"\\\n")
+
} else {
varval <- paste0(varval, " Options:\\\n")
varval <- paste0(varval,
@@ -161,7 +333,7 @@ values_group_player <- function(subdata, variable) {
}
}
- # Max length
+ # Max length of variable name
if ("max_length" %in% names(subdata[[variable]])) {
varval <- paste0(varval,
" Maximal length: ",
@@ -182,6 +354,14 @@ values_group_player <- function(subdata, variable) {
" Maximum: ",
subdata[[variable]]$max, "\\\n")
}
+
+ # Initial
+ if (params$initial &&
+ "initial" %in% names(subdata[[variable]])) {
+ varval <- paste0(varval,
+ " Initial: ",
+ subdata[[variable]]$initial, "\\\n")
+ }
# Remove last carriage return ####
sub("\\\\\\n$", "", varval)
@@ -189,63 +369,103 @@ values_group_player <- function(subdata, variable) {
# Return ####
return(varval)
}
-
```
-```{r constants}
-values_constants <- function(subdata, variable) {
- if (is.null(subdata)) {
-
- stop("subdata not there")
- }
- if (!is.list(subdata)) {
- stop("Subdata not list")
- }
- if (is.null(variable)) {
- stop("Variable is not there!")
- }
-
- # Values
- varval <- ""
+```{r constants function}
+values_constants <- function(subdata,
+ class,
+ folder) {
- if (!is.null(subdata) && !is.null(variable) && variable %in% names(subdata)) {
-
+ # Initialize lists
+ table_variables <- vector("character", length = 0L)
+ table_values <- vector("character", length = 0L)
+
+ # Loop through variable names
+ for (variable in names(subdata)) {
+
+ # Error messages (TODO do I even need them?) ####
+ if (is.null(subdata)) {
+ stop("Data of class ", class, " in app ", folder, " is not there!")
+ }
+
+ if (!is.list(subdata)) {
+ stop("Data of class ", class, " in app ", folder, " is not a list!")
+ }
+
+ if (is.null(variable)) {
+ stop("Variable ", variable,
+ " in class ", class,
+ " in app ", folder,
+ " is not there!")
+ }
+
+ # Make table values ####
if (length(subdata[[variable]]) == 1L) {
- varval <- subdata[[variable]][[1L]]
-
+ table_variables <- c(table_variables, variable)
+ table_values <- c(table_values, subdata[[variable]][[1L]])
+
} else if (length(subdata[[variable]]) > 1L) {
- for (i in seq_along(subdata[[variable]])) {
+ varval_i <- ""
+
+ if (params$sep_list == "newline") {
+ if (all(lengths(subdata[[variable]]) == 1)) {
+ # If each sublist only contains one element treat it as vector
+
+ varval_i <- paste(subdata[[variable]],
+ collapse = ", ")
+
+ } else {
+
+ if (params$pdf) {
+ chunkparts <- makechunks(variable = variable,
+ varval_i = subdata[[variable]])
+ variable <- unlist(chunkparts$var)
+ varval_i <- unlist(chunkparts$val)
+
+ } else {
+ # Iterate over each element in the sublist
+ for (i in seq_along(subdata[[variable]])) {
+ x <- unlist(subdata[[variable]][i])
+ varval_sub <- paste(x, collapse = ", ")
+ varval_i <- ifelse(varval_i == "",
+ varval_sub,
+ paste(varval_i,
+ varval_sub,
+ sep = "\\\n"))
+
+ }
+ }
+ }
+
+ table_variables <- c(table_variables, variable)
+ table_values <- c(table_values, varval_i)
- if (i == 1L) {
- varval <- paste(subdata[[variable]][[i]],
- collapse = ", ")
-
- } else {
- varval <- paste(varval,
- sep = ", ", # Or new line: "\\\n"
- paste(subdata[[variable]][[i]],
- collapse = ", "), collapse = ", ")
- } # check again for lists
- }
- }
-
+ } else if (params$sep_list == "vector") {
+ table_variables <- c(table_variables, variable)
+ table_values <- c(table_values,
+ list_to_string(subdata[[variable]]))
+ }
+ }
}
- return(varval)
-
+
+ # Construct the final data frame
+ table <- data.frame(Variable = table_variables,
+ Value = table_values,
+ stringsAsFactors = FALSE)
+
+ return(table)
}
```
```{r run functions}
-# Codebook data
-data <- combined_codebook
data$settings <- NULL
-# Data
for (folder in names(data)) {
- if (folder != "settings") { # Unnecessary but important for later code changes
+
+ if (folder != "settings" && folder != "user_settings") {
# App documentation and header
cat(get_app(params, data, folder))
@@ -266,10 +486,12 @@ for (folder in names(data)) {
# If pass
if (is.null(names(subdata))) {
cat("\n\nEmpty class\n")
+
} else {
# For variables
table_var <- data.frame(Variable = names(subdata))
+
table_var$Value <-
sapply(table_var$Variable,
FUN = function(x) values_group_player(subdata, x))
@@ -280,8 +502,17 @@ for (folder in names(data)) {
replacement = "",
x = table_var[nrow(table_var), ])
- # Show table
- pander::pander(table_var)
+ # Splitvariablename
+ xx <- panderwithsplit(table_var,
+ params$splitvarname
+ )
+
+ # Show app table
+ pander::pander(xx$table,
+ split.cells = c(xx$col1_length,
+ xx$col2_length))
+
+
cat("\n\n")
}
} else {
@@ -290,32 +521,38 @@ for (folder in names(data)) {
} else if (class == "Constants" &&
params$include_cons) {
- cat("\n\n## Class: ", class, "\n\n")
-
- if (length(subdata) != 0L) {
- # If pass
- if (is.null(names(subdata))) {
- cat("\n\nEmpty class\n\n")
- } else {
-
- # For variables
- table_var <- data.frame(Variable = names(subdata))
+ cat("\n\n## Class: ", class, "\n\n")
- table_var$Value <-
- sapply(X = table_var$Variable,
- FUN = function(x) values_constants(subdata, x))
+ if (length(subdata) != 0L) {
+
+ # If pass
+ if (is.null(names(subdata))) {
+ cat("\n\nEmpty class\n\n")
+
+ } else {
- pander::pander(table_var)
- cat("\n\n")
+ # Make table
+ table_var <- values_constants(subdata = subdata,
+ class = class,
+ folder = folder)
+
+
+ # Split variable name
+ xx <- panderwithsplit(table_var,
+ params$splitvarname
+ )
+
+
+ # Show Constants table
+ pander::pander(xx$table,
+ split.cells = c(xx$col1_length, xx$col2_length))
+
+ cat("\n\n")
- }
}
+ }
}
}
}
}
```
-
-
-
-
diff --git a/man/codebook.Rd b/man/codebook.Rd
index 3dad521..2f15942 100644
--- a/man/codebook.Rd
+++ b/man/codebook.Rd
@@ -8,9 +8,9 @@ codebook(
path = ".",
fsource = "init",
output = "both",
- output_dir = getwd(),
+ output_dir = NULL,
output_file = "codebook",
- output_format = "pdf_document",
+ output_format = "pdf_document_simple",
output_open = TRUE,
app_doc = TRUE,
app = NULL,
@@ -25,7 +25,10 @@ codebook(
title = "Codebook",
subtitle = "created with gmoTree",
params = NULL,
- date = "today"
+ date = "today",
+ splitvarname = FALSE,
+ sep_list = "newline",
+ initial = TRUE
)
}
\arguments{
@@ -48,32 +51,43 @@ the function's output will be saved.
Only absolute paths are allowed for this parameter.
Relative paths can be specified in the \code{output_file} parameter.}
-\item{output_file}{Character. The name of the output file generated by the function.
+\item{output_file}{Character.
+The name of the output file generated by the function.
The file name can be provided with or without an extension.
Relative paths are also allowed in the file name.}
-\item{output_format}{Character. Format of the file output.
-This is the format that is passed to the \code{output_format}
+\item{output_format}{Character. Specifies the format of the file output.
+This value is passed to the \code{output_format}
argument of \link[rmarkdown:render]{rmarkdown::render}.
-You must use either \code{"pdf_document"}, \code{"html_document"}, \code{"word_document"}, \code{"odt_document"}, \code{"rtf_document"}, \code{"md_document"}, or \code{"latex_document"}.}
-
-\item{output_open}{Logical. \code{TRUE} if file output should be opened after creation.}
-
-\item{app_doc}{Logical. \code{TRUE} if app documentation should be included in
-output file.}
+Allowed options are: \code{"html_document"}, \code{"word_document"}, \code{
+"odt_document"}, \code{"rtf_document"}, \code{"md_document"}, \code{
+"latex_document"}, \code{"pdf_document"}, \code{"pdf_document_simple"},
+or their short forms \code{"html"}, \code{"word"}, \code{"odt"}, \code{
+"rtf"}, \code{"md"}, \code{"latex"}, \code{"pdf"}, \code{"pdf_simple"}.
+Important: The \code{"pdf_document"} format uses \code{xelatex} for
+PDF generation.
+If your document does not require advanced LaTeX features,
+it is recommended to use \code{"pdf_document_simple"}.}
+
+\item{output_open}{Logical. \code{TRUE} if file output should
+be opened after creation.}
+
+\item{app_doc}{Logical. \code{TRUE} if app documentation should be
+included in the output file.}
\item{app}{Character. Name of the included app(s).
Default is to use all apps.
-This argument can not be used simultaneously as the argument \code{app_rm}.}
+Cannot be used simultaneously with \code{app_rm}.}
\item{app_rm}{Character. Name of the excluded app(s).
Default is to exclude no apps.
-This argument can not be used simultaneously as the argument app.}
+Cannot be used simultaneously with \code{app}.}
\item{doc_info}{Logical. \code{TRUE} if a message with information on all
-variables without documentation should also be returned.}
+variables without documentation should also be returned. \code{FALSE} if
+this message should be suppressed.}
-\item{sort}{Character. Vector that specifies the order of
+\item{sort}{Character vector. Vector that specifies the order of
the apps in the codebook.}
\item{settings_replace}{Character or \code{NULL}.
@@ -83,10 +97,11 @@ defined in \code{settings.py}.
Use \code{"user"} to replace references with the variables
provided in the \code{user_settings} argument.
Use \code{NULL} to leave references to settings variables unchanged.
-Caution: This function does not use variables defined in \code{SESSION_CONFIGS}.
+Caution: This function does not use variables defined
+in \code{SESSION_CONFIGS}.
If you vary settings variables in \code{SESSION_CONFIGS},
-set \code{settings_replace} to \code{"user"} and manually replace them using the
-\code{user_settings} argument.}
+set \code{settings_replace} to \code{"user"} and manually replace
+them using the \code{user_}\code{settings} argument.}
\item{user_settings}{List. List of variables in the \code{settings.py} file
that are used to replace setting variable references.
@@ -113,9 +128,22 @@ and ignored.}
List of variable name and value pairs to be passed to the RmD file.
Only relevant if argument output \code{"file"} or \code{"both"} if chosen.}
-\item{date}{Date that is passed to the Rmd file.
+\item{date}{Character or \code{NULL}. Date that is passed to the Rmd file.
Either \code{"today"}, \code{NULL}, or a user defined date.
Only relevant if argument output \code{"file"} or \code{"both"} if chosen.}
+
+\item{splitvarname}{Logical. \code{TRUE} if long variable names should be
+split across multiple lines in the output file tables.
+If \code{FALSE}, table columns should adjust to fit the longest
+variable names.}
+
+\item{sep_list}{Character. Determines how sub-lists are displayed
+in the file output. Use \code{"newline"} to separate sub-lists with
+newline characters (`\\n`), or \code{"vector"} to display them as
+strings in `c(...)` format.}
+
+\item{initial}{Logical. \code{TRUE} if initial values should be included
+in the output file. \code{FALSE} if they should not be included.}
}
\value{
The function returns two main types of outputs:
@@ -142,7 +170,7 @@ appear in the codebook.
Caution 2: If there are commas in the value strings, they might be
used to split the text. Please manually insert a backslash symbol
-in front of the commas to avoid that.
+in front of the commas to avoid that (i.e., escape them).
E.g. \code{"Yes, I will"} -> \code{"Yes\, I will"}.
Caution 3: This code cannot interpret variables that were imported from other
@@ -155,6 +183,11 @@ and has not been verified for compatibility with oTree versions
later than 5.4.0.
If you experience issues with newer versions or more complex code structures,
please open an issue on GitHub.
+
+Caution 5: Custom exports are not part of the codebook.
+
+Further info: \code{None} values are presented as "None" (i.e. as a string)
+in the list and in the codebook.
}
\examples{
\dontshow{if (rlang::is_installed("withr")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
@@ -179,7 +212,7 @@ combined_codebook <- codebook(
app = "bargaining",
doc_info = FALSE)
-# Show the structure of the codebook
+# Show the structure of the codebook
str(combined_codebook, 1)
str(combined_codebook$bargaining$Player, 1)
@@ -191,7 +224,7 @@ combined_codebook <- codebook(
app_rm = "bargaining",
doc_info = FALSE)
-# Show the structure of the codebook
+# Show the structure of the codebook
str(combined_codebook, 1)
str(combined_codebook$bargaining$Player, 1)
@@ -200,11 +233,19 @@ combined_codebook <- codebook(
path = system.file("extdata/ocode_z", package = "gmoTree"),
fsource = "model",
output = "list",
- doc_info = TRUE)
+ doc_info = FALSE)
# Show the structure of the codebook
str(combined_codebook, 1)
+# Show information on missing documentation or complex code
+combined_codebook <- codebook(
+ path = system.file("extdata/ocode_new", package = "gmoTree"),
+ fsource = "init",
+ output = "list",
+ app_rm = "bargaining",
+ doc_info = TRUE)
+
\dontrun{
# Create a codebook PDF with authors' names and todays' date
diff --git a/man/messy_time.Rd b/man/messy_time.Rd
index 3d4a4d7..c4a03d6 100644
--- a/man/messy_time.Rd
+++ b/man/messy_time.Rd
@@ -17,8 +17,8 @@ messy_time(
by \code{\link{import_otree}}.}
\item{combine}{Logical. \code{TRUE} if all variables referring to epoch time
-should be merged and/or all variables referring to participant code should be merged
-in case data of several versions of oTree are used.}
+should be merged and/or all variables referring to participant code
+should be merged in case data of several versions of oTree are used.}
\item{epoch_time}{Logical. \code{TRUE} if all variables referring to the time
stamp should be checked and merged. Only works if \code{combine = TRUE}.}
diff --git a/man/oTree.Rd b/man/oTree.Rd
index 0582939..1dc264b 100644
--- a/man/oTree.Rd
+++ b/man/oTree.Rd
@@ -3,7 +3,7 @@
\docType{data}
\name{oTree}
\alias{oTree}
-\title{Sample experiment data}
+\title{Sample experimental data}
\format{
A list of data frames created by import_otree().
}
@@ -17,6 +17,6 @@ In detail, the following apps were used:
oTree
}
\description{
-Sample experiment data
+Sample experimental data
}
\keyword{datasets}
diff --git a/tests/testthat/tests.R b/tests/testthat/tessts.R
similarity index 99%
rename from tests/testthat/tests.R
rename to tests/testthat/tessts.R
index a96963e..3cf9648 100644
--- a/tests/testthat/tests.R
+++ b/tests/testthat/tessts.R
@@ -6927,7 +6927,6 @@ if (rlang::is_installed(c("withr", "testthat"))) {
test3 <- !is.null(output$max_duration) & !is.na(output$max_duration)
test4 <- exists("single_durations", output)
testthat::expect_true(all(c(test1, test2, test3, test4)))
-
})
testthat::test_that("App time - one app:
@@ -7188,7 +7187,6 @@ if (rlang::is_installed(c("withr", "testthat"))) {
# Run function
output <- apptime(otree2)
-
# Test
test <- grepl("Durations not calculated", output$survey)
testthat::expect_true(test) # Die überall schön machen
@@ -8027,8 +8025,8 @@ if (rlang::is_installed(c("withr", "testthat"))) {
# Run function and test
testthat::expect_error(
assignv(oTree = otree2,
- variable = c("survey.1.player.gender", "asdfasfd"),
- newvar = c("gender", "asfasdf")),
+ variable = c("survey.1.player.gender", "somevar"),
+ newvar = c("gender", "somenewvar")),
"Plase enter only one variable name")
})
@@ -8039,8 +8037,8 @@ if (rlang::is_installed(c("withr", "testthat"))) {
# Run function and test
testthat::expect_error(
assignv(oTree = otree2,
- variable = "asdfasfd",
- newvar = c("gender", "asfasdf")),
+ variable = "somevar",
+ newvar = c("gender", "somenewvar")),
"Plase enter only one new variable name")
})
@@ -8152,9 +8150,9 @@ if (rlang::is_installed(c("withr", "testthat"))) {
# Prepare data
otree2 <- otree_5_4_0
- # Create new variable
+ # Create new variable (delete first row)
person <- otree2$survey$participant.code[1L]
- otree2$survey <- otree2$survey[2L:nrow(otree2$survey), ] # Delete first row
+ otree2$survey <- otree2$survey[2L:nrow(otree2$survey), ]
otree2$survey$younger30 <- as.integer(otree2$survey$player.age < 30L)
# Run function
@@ -8195,7 +8193,7 @@ if (rlang::is_installed(c("withr", "testthat"))) {
testthat::expect_error(
assignv_to_aaw(otree2,
app = "survey",
- variable = c("younger30", "asdfsadf"),
+ variable = c("younger30", "wrongvarname"),
newvar = "younger30"),
"Plase enter only one variable name!")
})
@@ -8210,8 +8208,8 @@ if (rlang::is_installed(c("withr", "testthat"))) {
testthat::expect_error(
assignv_to_aaw(otree2,
app = "survey",
- variable = c("younger30", "asdfsadf"),
- newvar = c("younger30", "asdfasdf")),
+ variable = c("younger30", "wrongvarname"),
+ newvar = c("younger30", "wrongnewname")),
"Plase enter only one variable name!")
})
@@ -8225,7 +8223,7 @@ if (rlang::is_installed(c("withr", "testthat"))) {
assignv_to_aaw(otree2,
app = "survey",
variable = "younger30",
- newvar = c("younger30", "asdfasdf")),
+ newvar = c("younger30", "toomanynames")),
"Plase enter only one new variable name!")
})
diff --git a/tests/testthat/testdata/ocode_count/__init__.py b/tests/testthat/testdata/ocode_count/__init__.py
new file mode 100644
index 0000000..91ddebc
--- /dev/null
+++ b/tests/testthat/testdata/ocode_count/__init__.py
@@ -0,0 +1,63 @@
+from otree.api import *
+import settings
+import time
+
+
+author = 'Patricia Zauchner (zauchner@uni-bremen.de)'
+
+doc = """
+Effort task: Count letters in a sentence.
+"""
+
+
+# Models
+def get_unique_chars(string_to_guess: str) -> list:
+ """
+ Create a sorted list of the unique characters in the string whose letters the participants have to count.
+ The use of the set function in the creation process ensures that only one instance of each letter is returned
+ after filtering out all non-alphabetic characters.
+ :param string_to_guess: The string whose characters shall be counted
+ :return: A sorted list of the unique characters in the input string
+ """
+ return sorted(set(filter(str.isalpha, list(string_to_guess.lower()))))
+
+
+def get_char_counts(string_to_guess: str) -> list:
+ """
+ Maps the alphabetic characters within a given string to their number of occurrences in that string.
+ The return format -- forming a list of lists -- is the following:
+
+ [["X_1/x_1", c_1], ["X_2/x_2", c_2], ... , ["X_n/x_n", c_n]]
+
+ where X_i and x_i are the uppercase and lowercase variants of the i-th alphabetic character, while c_i is the
+ respective count within the given string. As not all characters are necessarily contained within an input string
+ there might be characters of the alphabet missing from the list. Note also that special latin characters like
+ "ä" or "ö" only appear after all ASCII characters (i. e. a, b, c, ..., z).
+ :param string_to_guess: The string whose characters shall be counted
+ :return: A list of lists containing the unique characters of the string and their count.
+ """
+ unique_chars = get_unique_chars(string_to_guess)
+
+ return [[f'{y.upper()}/{y}', sum(map(lambda x: 1 if y in x else 0, string_to_guess.lower()))] for y in unique_chars]
+
+
+class C(BaseConstants):
+ NAME_IN_URL = 'effort_counting'
+ # Not really necessary in effort tasks. But so it looks better in the data
+ PLAYERS_PER_GROUP = 5
+
+ STRING_TO_GUESS = "Die ältesten bekannten kieferlosen Fischartigen (z. B. die Pteraspidomorphi) stammen aus dem " \
+ "frühen Ordovizium vor rund 450–470 Millionen Jahren."
+
+ SOLUTION = get_char_counts(STRING_TO_GUESS)
+
+class Subsession(BaseSubsession):
+ pass
+
+
+class Group(BaseGroup):
+ pass
+
+
+class Player(BasePlayer):
+ pass
diff --git a/tests/testthat/testdata/ocode_f1/MIG1/models.py b/tests/testthat/testdata/ocode_f1/MIG1/models.py
new file mode 100644
index 0000000..6b47aa3
--- /dev/null
+++ b/tests/testthat/testdata/ocode_f1/MIG1/models.py
@@ -0,0 +1,1213 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+from scipy.stats import rankdata
+import math
+
+
+author = 'Patricia Zauchner'
+
+doc = """
+Migration Game.
+Run only on Chrome. Never on IE!
+In IE, the dialogue windows won't work.
+"""
+
+class Constants(BaseConstants):
+ name_in_url = 'MIG1'
+ players_per_group = 5
+ num_rounds = 1 # Wie oft das Experiment durchläuft
+ ShowUpFeeEuro = 12
+ ExchangeEuro = 1
+ ExchangeToken = 1
+ ExchangeRate = ExchangeToken / ExchangeEuro
+
+ ShowUpFeeToken = ShowUpFeeEuro * ExchangeRate
+ P1_Needs = 16 # Formerly known as "Bedarf".
+ UsualConsumption = 0.9 # 90% of the income will be consumed
+ Rounds = 5
+ time_for_args = 0.2
+ time_for_argsSek = time_for_args * 60
+ #
+ P1_GesamtZusatzToken = 30
+ P1_TokenAdd_Equal = [30 / 5, 30 / 5, 30 / 5, 30 / 5, 30 / 5] # Zusatztoken bei Gleichverteilung
+ #
+ P1_StartToken_0 = [0, 14, 19, 26, 41] # StartToken --> Netto After Taxes
+ P1_Taxes_0 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_0 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_0.append(P1_StartToken_0[i] + P1_Taxes_0[i])
+ P1_TokenAddWeakerFirst_0 = [21, 7, 2, 0, 0]
+ P1_TokenAddMixed_0 = [16, 2, 3, 4, 5] # so besprochen am 31.3.
+
+ #
+ #
+ P1_StartToken_9 = [9, 14, 19, 26, 41]
+ P1_Taxes_9 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_9 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_9.append(P1_StartToken_9[i] + P1_Taxes_9[i])
+ P1_TokenAddWeakerFirst_9 = [11, 6, 3, 0, 0]
+ P1_TokenAddMixed_9 = [6.5, 1.5, 1, 4, 7]
+
+ #
+ #
+ #
+ ArgCharMax = 250
+ P1_Rej_ArgBestToken = 2
+ P1_BVote_ArgBestToken = 2
+ P1_AVote_ArgBestToken = 2
+ P1_Acc_ArgBestToken = 2
+ #
+ #
+ ChatTime_Ack = 6 # Todo: Check if time is correct. Should be 6 minutes.
+ ChatTime_Ack_Sec = ChatTime_Ack * 60
+ ChatTime_Distribution = 5 # Formerly known as ChatTime_Verteilung #Todo: Check if time is correct. Should be 5 minutes.
+ ChatTime_DistributionCorr = 1 # Formerly known as ChatTime_VerteilungKorr #Todo: Check if time is correct. Should be 1 minute.
+ ChatTime_DistributionCorrSek = ChatTime_DistributionCorr * 60 # Formerly known as ChatTime_VerteilungKorrSek
+ #
+
+ MinArgumentLength = 10
+ MaxArgumentLength = 250
+
+ # Grafiken
+ TickInterval = 5
+ LineWidth = 5
+ ArgumentChatHeight = 600
+
+
+class Session:
+ pass
+
+
+class Subsession(BaseSubsession):
+ def creating_session(self):
+ """"
+ create ID, StartToken, Wealth, and Treatments;
+ """
+ #
+ # Copy the group and player id structure of the first app
+ if "id_matrix" in self.session.vars:
+ self.set_group_matrix(self.session.vars['id_matrix'])
+ else:
+ self.group_randomly()
+ #
+ #
+ # Assign Treatments: Economic participation
+ if "session_treatment_ec" in self.session.config: # if treatment was already assigned in session config
+ for g in self.get_groups():
+ g.treatment_ec = self.session.config['session_treatment_ec']
+ else:
+ for g in self.get_groups():
+ g.treatment_ec = 0 # Todo: Here you can enter the treatment manually.
+ # Assign Treatments: Political participation
+ if "session_treatment_pol" in self.session.config: # if treatment was already assigned in session config
+ for g in self.get_groups():
+ g.treatment_pol = self.session.config['session_treatment_pol']
+ else:
+ for g in self.get_groups():
+ g.treatment_pol = 1 # Todo: Here you can enter the treatment manually.
+ #
+ #
+ for p in self.get_players(): # Exclusion of player 1 in effort task:
+ if "Economically_Excluded" in p.participant.vars:
+ p.Economically_Excluded = p.participant.vars['Economically_Excluded']
+ else:
+ if p.group.treatment_ec == 0 and p.id_in_group == 1:
+ p.participant.vars['Economically_Excluded'] = 1
+ p.Economically_Excluded = 1
+ else:
+ p.participant.vars['Economically_Excluded'] = 0
+ p.Economically_Excluded = 0
+ for p in self.get_players(): # Exclusion of player 1 in deliberation:
+ if "Politically_Excluded" in p.participant.vars:
+ p.Politically_Excluded = p.participant.vars['Politically_Excluded']
+ else:
+ if p.group.treatment_pol == 0 and p.id_in_group == 1:
+ p.participant.vars['Politically_Excluded'] = 1
+ p.Politically_Excluded = 1
+ else:
+ p.participant.vars['Politically_Excluded'] = 0
+ p.Politically_Excluded = 0
+ #
+ # Assign number of eligible voters:
+ for g in self.get_groups():
+ g.defineEligibleVoters()
+
+ #
+ def vars_for_admin_report(self):
+ #Background-Info to Participants
+ list_of_groupmembership = []
+ for p in self.get_players():
+ group = "Group: " + str(p.group.id_in_subsession)
+ name = " - Participant: "+str(p.participant.label)
+ effpoints = " - Effort Points: "+str(p.Effort_points)
+ rank = " - Rank:"+ str(p.GroupRank)
+ list_of_groupmembership.append(group+name+rank+effpoints)
+ list_of_groupmembership = sorted(list_of_groupmembership)
+ #Decisions and Treatments in Game
+ listofgroupack = []
+ polpart_treatmentlist = []
+ ecpart_treatmentlist = []
+ listP1_NeueVerteilungErreicht = []
+ groupnumberlist = []
+ for g in self.get_groups():
+ groupnumberlist.append(g)
+ polpart_treatmentlist.append(g.treatment_pol)
+ ecpart_treatmentlist.append(g.treatment_ec)
+ listofgroupack.append(g.P1_GroupAcknowledgement)
+ listP1_NeueVerteilungErreicht.append(g.P1_NeueVerteilungErreicht)
+ return {
+ "participantsinlist": list_of_groupmembership,
+ "Political_Participation_Treatment": polpart_treatmentlist,
+ "Economic_Participation_Treatment": ecpart_treatmentlist,
+ "groupnumberlist": groupnumberlist,
+ "groupAcknowledgement": listofgroupack,
+ "P1_NeueVerteilungErreicht": listP1_NeueVerteilungErreicht
+ }
+
+ #
+
+
+class Group(BaseGroup):
+ #
+ REDIS = models.IntegerField(initial=1) # 0 = DIS, 1 = REDIS ---> From now on always redis
+ Effort = models.IntegerField(
+ initial=1) # 0 = Lottery, 1 = Effort ---> From now on always effort for core group members
+
+ treatment_ec = models.IntegerField(
+ doc="""Economic Participation Treatment""",
+ choices=[
+ [0, "0 Anfangssausstattung"], # Person not allowed to participate in effort task
+ [1, "9 Anfangsausstattung"] # Person allowed to participate in effort task
+ ])
+ treatment_pol = models.IntegerField(
+ doc="""Political Participation Treatment""",
+ choices=[
+ [0, "No participation in the decision"],
+ [1, "Participation in the decision"]
+ ])
+
+ #
+ #
+ def randomGroupRank(self):
+ """
+ If Effort = 0, the individuals in the group are assigned random IDs.
+ This method is called by the Intro-WaitPage.
+ I won't need this for the experiment, but it's good for pretesting.
+ """
+ randomnumber = random.sample(list(range(1, 6)), 5)
+ for p in self.get_players():
+ p.GroupRank = randomnumber[p.id_in_group - 1]
+
+ def effortGroupRank(self):
+ """
+ If Effort = 1, the individuals in the group are assigned IDs according to their effort.
+ This method is called by the intro-WaitPage.
+ """
+ if self.treatment_ec == 0:
+ all_group_effort_new = []
+ for p in self.get_players():
+ all_group_effort_new.append(p.Effort_points - (p.Minus_points * 0.0001) - (p.id_in_group * 0.000001))
+ rankgroupeffort = rankdata(all_group_effort_new)
+ else:
+ all_group_effort_new = []
+ for p in self.get_players():
+ if p.id_in_group != 1:
+ all_group_effort_new.append(
+ p.Effort_points - (p.Minus_points * 0.0001) - (p.id_in_group * 0.000001))
+ if p.id_in_group == 1:
+ all_group_effort_new.append(0)
+ rankgroupeffort = rankdata(all_group_effort_new)
+
+ for p in self.get_players():
+ p.GroupRank = int(rankgroupeffort[p.id_in_group - 1])
+
+ def P1_Define_StartToken(self):
+ if self.treatment_ec == 0:
+ for p in self.get_players():
+ # For specific positions
+ p.P1_StartToken = Constants.P1_StartToken_0[p.GroupRank - 1]
+ p.P1_StartTokenPT = Constants.P1_StartTokenPT_0[p.GroupRank - 1]
+ p.P1_Taxes = Constants.P1_Taxes_0[p.GroupRank - 1]
+ p.P1_TokenAddEqual = Constants.P1_TokenAdd_Equal[p.GroupRank - 1]
+ p.P1_TokenAddWeakerFirst = Constants.P1_TokenAddWeakerFirst_0[p.GroupRank - 1]
+ p.P1_TokenAddMixed = Constants.P1_TokenAddMixed_0[p.GroupRank - 1]
+ # For all
+ p.P1_SumRoundIncomeEqual = p.P1_StartToken + p.P1_TokenAddEqual
+ p.P1_SumRoundIncomeWeakerFirst = p.P1_StartToken + p.P1_TokenAddWeakerFirst
+ p.P1_SumRoundIncomeMixed = p.P1_StartToken + p.P1_TokenAddMixed
+ if self.treatment_ec == 1:
+ for p in self.get_players():
+ # For specific positions
+ p.P1_StartToken = Constants.P1_StartToken_9[p.GroupRank - 1]
+ p.P1_StartTokenPT = Constants.P1_StartTokenPT_9[p.GroupRank - 1]
+ p.P1_Taxes = Constants.P1_Taxes_9[p.GroupRank - 1]
+ p.P1_TokenAddEqual = Constants.P1_TokenAdd_Equal[p.GroupRank - 1]
+ p.P1_TokenAddWeakerFirst = Constants.P1_TokenAddWeakerFirst_9[p.GroupRank - 1]
+ p.P1_TokenAddMixed = Constants.P1_TokenAddMixed_9[p.GroupRank - 1]
+ # For all
+ p.P1_SumRoundIncomeEqual = p.P1_StartToken + p.P1_TokenAddEqual
+ p.P1_SumRoundIncomeWeakerFirst = p.P1_StartToken + p.P1_TokenAddWeakerFirst
+ p.P1_SumRoundIncomeMixed = p.P1_StartToken + p.P1_TokenAddMixed
+
+ # Chat Channels
+ Channel_DisProcedure = models.TextField(
+ initial=-99)
+ Channel_DisProcedureKorr = models.TextField(
+ initial=-99)
+ Channel_Ack = models.TextField(
+ initial=-99)
+
+ def Nickname(self):
+ self.Channel_Ack = str(self.id_in_subsession) + "_Ack"
+ self.Channel_DisProcedure = str(self.id_in_subsession) + "_DisProc"
+ self.Channel_DisProcedureKorr = str(self.id_in_subsession) + "_DisProcKorr"
+ for p in self.get_players():
+ p.Nickname = "Player " + str(p.GroupRank)
+
+ #
+ #
+ def P1_calc_wealthD0(self): # Keine Grafiken, nur Zahlen
+ for p in self.get_players():
+ #
+ if (p.P1_StartTokenPT * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionNoDis = Constants.P1_Needs
+ p.P1_WealthNoDis_1R = p.P1_StartTokenPT - Constants.P1_Needs
+ else:
+ p.P1_ConsumptionNoDis = p.P1_StartTokenPT * 0.9
+ p.P1_WealthNoDis_1R = p.P1_StartTokenPT * 0.1
+ p.P1_WealthNoDis_5R = p.P1_WealthNoDis_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddEqual) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionEqual = Constants.P1_Needs
+ p.P1_WealthEqual_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddEqual
+ else:
+ p.P1_ConsumptionEqual = (p.P1_StartToken + p.P1_TokenAddEqual) * 0.9
+ p.P1_WealthEqual_1R = (p.P1_StartToken + p.P1_TokenAddEqual) * 0.1
+ p.P1_WealthEqual_5R = p.P1_WealthEqual_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionWeakerFirst = Constants.P1_Needs
+ p.P1_WealthWeakerFirst_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddWeakerFirst
+ else:
+ p.P1_ConsumptionWeakerFirst = (p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.9
+ p.P1_WealthWeakerFirst_1R = (p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.1
+ p.P1_WealthWeakerFirst_5R = p.P1_WealthWeakerFirst_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddMixed) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionMixed = Constants.P1_Needs
+ p.P1_WealthMixed_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddMixed
+ else:
+ p.P1_ConsumptionMixed = (p.P1_StartToken + p.P1_TokenAddMixed) * 0.9
+ p.P1_WealthMixed_1R = (p.P1_StartToken + p.P1_TokenAddMixed) * 0.1
+ p.P1_WealthMixed_5R = p.P1_WealthMixed_1R * 5
+ #
+
+
+ def P1_ResultsGraphEqual(self):
+ """ Wird in Pages - class P1_Rej_9_Rounds(Page) aufgerufen"""
+ series_Start_PT = []
+ series_Start = []
+ series_Taxes = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start_PT.append(p.P1_StartTokenPT)
+ series_Start.append(p.P1_StartToken)
+ series_Taxes.append(p.P1_Taxes)
+ series_TokenAdd.append(p.P1_TokenAddEqual)
+ cumulativedata = [0,
+ p.P1_WealthEqual_1R * 1,
+ p.P1_WealthEqual_1R * 2,
+ p.P1_WealthEqual_1R * 3,
+ p.P1_WealthEqual_1R * 4,
+ p.P1_WealthEqual_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthEqual_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddEqual)
+ return {
+ "series_StartToken_PT": series_Start_PT,
+ "StartToken": series_Start,
+ "Taxes": series_Taxes,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def P1_info3graph(self):
+ series = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ playerdata = [0,
+ p.P1_WealthNoDis_1R * 1,
+ p.P1_WealthNoDis_1R * 2,
+ p.P1_WealthNoDis_1R * 3,
+ p.P1_WealthNoDis_1R * 4,
+ p.P1_WealthNoDis_1R * 5]
+ series.append({
+ "name": p.GroupRank,
+ "data": playerdata})
+ series_highest_lowest.append(p.P1_WealthNoDis_5R)
+ return {
+ 'highcharts_series': series,
+ "MinValue": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue": self.MinMaxGraph(series_highest_lowest)[1]
+ }
+
+ def P1_ResultsGraphWeakerFirst(self):
+ """ Wird aufgerufen bei Acceptance - Weaker First"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAddWeakerFirst)
+ cumulativedata = [0,
+ p.P1_WealthWeakerFirst_1R * 1,
+ p.P1_WealthWeakerFirst_1R * 2,
+ p.P1_WealthWeakerFirst_1R * 3,
+ p.P1_WealthWeakerFirst_1R * 4,
+ p.P1_WealthWeakerFirst_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthWeakerFirst_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddWeakerFirst)
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def P1_ResultsGraphMixed(self):
+ """ Wird aufgerufen bei Acceptance - Weaker First"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAddMixed)
+ cumulativedata = [0,
+ p.P1_WealthMixed_1R * 1,
+ p.P1_WealthMixed_1R * 2,
+ p.P1_WealthMixed_1R * 3,
+ p.P1_WealthMixed_1R * 4,
+ p.P1_WealthMixed_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthMixed_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddMixed)
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ #
+
+ # Wahlen
+ P1_NumElegibleToVoteForAck = models.IntegerField(initial=-99)
+ P1_NumElegibleToVoteNewDis = models.IntegerField(initial=-99)
+
+ def defineEligibleVoters(self):
+ if self.treatment_pol == 1:
+ self.P1_NumElegibleToVoteForAck = Constants.players_per_group
+ self.P1_NumElegibleToVoteNewDis = Constants.players_per_group
+ elif self.treatment_pol == 0:
+ self.P1_NumElegibleToVoteForAck = Constants.players_per_group - 1
+ self.P1_NumElegibleToVoteNewDis = Constants.players_per_group - 1
+ else:
+ print("Problem. Check defineEligibleVoters()")
+
+ P1_nGroupAnerkennung = models.IntegerField(initial=0)
+ P1_GroupAcknowledgement = models.IntegerField(initial=0)
+
+ def P1_AckResult(self):
+ self.P1_nGroupAnerkennung = 0
+ for p in self.get_players():
+ if p.P1_AckVote == 1:
+ self.P1_nGroupAnerkennung += 1
+ if self.P1_nGroupAnerkennung == self.P1_NumElegibleToVoteForAck:
+ self.P1_GroupAcknowledgement = 1
+ else:
+ self.P1_GroupAcknowledgement = 0
+
+ #
+ P1_CountGroup = models.IntegerField(
+ initial=0)
+ P1_CountGroup_Corr = models.IntegerField(
+ doc="in zTree: CountGroup2",
+ initial=0)
+ P1_NeueVerteilungErreicht = models.IntegerField(initial=0)
+ P1_NeueVerteilungErreicht_Corr = models.IntegerField(initial=0)
+
+ #
+ P1_TokenAdd_New_1 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_2 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_3 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_4 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_5 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_1 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_2 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_3 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_4 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_5 = models.FloatField(initial=-99)
+
+ #
+
+ def abzahlen(self, Correction):
+ """
+ How many group members entered the same numbers?
+ Old function name in ztree: Countsame.
+ If this function is called after the Correction chat, enter "Corr" when calling the function.
+ """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ for p in self.get_players():
+ setattr(p, "P1_CountSame" + corr, 0)
+ for q in self.get_players():
+ if (vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(1)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(1)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(2)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(2)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(3)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(3)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(4)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(4)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(5)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(5)]): \
+ setattr(p, "P1_CountSame" + corr, getattr(p, "P1_CountSame" + corr) + 1)
+
+ #
+ #
+ def abzahlengruppe(self, Correction):
+ """"Wie viele gleiche Zahleneingaben gibt es höchstens pro Gruppe? """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ setattr(self, "P1_CountGroup" + corr, 0)
+ for p in self.get_players():
+ if (getattr(p, "P1_CountSame" + corr) > (p.group.P1_NumElegibleToVoteNewDis / 2)):
+ setattr(self, "P1_CountGroup" + corr, getattr(self, "P1_CountGroup" + corr) + 1)
+
+ #
+ #
+
+ def NewDisVoteRes(self, Correction):
+ """
+ Prior name: P1_Wahlergebnis1
+ Wird in Pages --> P1_Rej_5_Chat_DistributionProcedure_2WP_After aufgerufen
+ """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ for p in self.get_players():
+ if getattr(p, "P1_CountSame" + corr) > p.group.P1_NumElegibleToVoteNewDis / 2:
+ for i in range(1, 6):
+ setattr(self, "P1_TokenAdd_New" + corr + "_" + str(i),
+ getattr(p, "P1_iTokenAddVoteFor" + corr + "_" + str(i)))
+ break
+
+ if getattr(self, "P1_CountGroup" + corr) > self.P1_NumElegibleToVoteNewDis / 2:
+ setattr(self, "P1_NeueVerteilungErreicht" + corr, 1)
+ # Calculate Token Add
+ for p in self.get_players():
+ for i in range(1, 6):
+ if p.GroupRank == i:
+ p.P1_TokenAdd = getattr(self, "P1_TokenAdd_New" + corr + "_" + str(i))
+
+ # Calculate Roundincome after Tokenadd and Needs-Satisfaction
+ for p in self.get_players():
+ p.P1_SumRoundIncome = p.P1_StartToken + p.P1_TokenAdd
+ if p.P1_SumRoundIncome < Constants.P1_Needs:
+ p.P1_ConsumptionFinal = Constants.P1_Needs
+ p.P1_WealthNewDis_1R = p.P1_SumRoundIncome - Constants.P1_Needs
+ else:
+ p.P1_ConsumptionFinal = p.P1_SumRoundIncome * 0.9
+ p.P1_WealthNewDis_1R = p.P1_SumRoundIncome * 0.1
+ p.P1_WealthNewDis_5R = p.P1_WealthNewDis_1R * 5
+ else:
+ setattr(self, "P1_NeueVerteilungErreicht" + corr, 0)
+
+ #
+ #
+
+ #
+ #
+ #
+
+ P1_BVote_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_BVote_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_BVote_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_Rej_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_Rej_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_Rej_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_AVote_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_AVote_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_AVote_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_Acc_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_Acc_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_Acc_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+ def calcbestarg(self, argpart):
+ # argpart are either BVote,
+
+ #
+ group_acc_base = "P1_" + argpart + "_nArgAkz_"
+ group_accNo_base = "P1_" + argpart + "_nArgAkzNo_"
+ group_best_base = "P1_" + argpart + "_nArgBest_"
+
+ ind_acc_base = "P1_" + argpart + "_ArgAkz_"
+ ind_accNo_base = "P1_" + argpart + "_ArgAkzNo_"
+ ind_best_base = "P1_" + argpart + "_ArgBest_"
+ for i in range(1, 6):
+ group_acc_mod = group_acc_base + str(i)
+ group_accNo_mod = group_accNo_base + str(i)
+ group_best_mod = group_best_base + str(i)
+ ind_acc_mod = ind_acc_base + str(i)
+ ind_accNo_mod = ind_accNo_base + str(i)
+ ind_best_mod = ind_best_base + str(i)
+
+ # Calculations
+ setattr(self, group_acc_mod,
+ sum((vars(p)[ind_acc_mod]) for p in self.get_players() if vars(p)[ind_acc_mod] >= 0))
+ setattr(self, group_accNo_mod, 5 - vars(self)[group_acc_mod])
+ setattr(self, group_best_mod, sum((vars(p)[ind_best_mod]) for p in self.get_players()))
+
+ #
+ #
+ listofbest = [] # Für übersicht
+ for p in self.get_players():
+ setattr(p, "P1_" + argpart + "_nArgBest", vars(self)[group_best_base + str(p.GroupRank)])
+ listofbest.append(vars(p)["P1_" + argpart + "_nArgBest"])
+ # Winners
+ P1_Winners = [i for i, j in enumerate(listofbest) if j == max(listofbest)]
+ #
+ # Falls Gewinner/in
+ for p in self.get_players():
+ if (p.GroupRank - 1) in P1_Winners and len(P1_Winners) <= 2: # There are max 2 winners.
+ setattr(p, "P1_" + argpart + "_ArgBest", 1)
+ setattr(p, "P1_" + argpart + "_ArgToken", Constants.P1_BVote_ArgBestToken)
+ if len(P1_Winners) == 1:
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 1)
+ else:
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 2)
+ # Falls Nicht-Gewinner/in:
+ else:
+ setattr(p, "P1_" + argpart + "_ArgBest", 0)
+ setattr(p, "P1_" + argpart + "_ArgToken", 0)
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 0)
+
+ #
+
+ #
+
+ def P1_ResultsGraph(self):
+ """ Wird in Pages - class P1_Rej_9_Rounds(Page) aufgerufen"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAdd)
+ cumulativedata = [0,
+ p.P1_WealthNewDis_1R * 1,
+ p.P1_WealthNewDis_1R * 2,
+ p.P1_WealthNewDis_1R * 3,
+ p.P1_WealthNewDis_1R * 4,
+ p.P1_WealthNewDis_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthNewDis_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAdd)
+
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def MinMaxGraph(self, list=[]):
+ if min(list) >= 0:
+ minlist = -5
+ maxlist = max(list) + 3
+ else:
+ minlist = min(list) - 5
+ maxlist = max(list) + 3
+ return minlist, maxlist
+
+
+class Player(BasePlayer):
+ Politically_Excluded = models.IntegerField(initial=-99, doc="Excluded from deliberation")
+ Economically_Excluded = models.IntegerField(initial=-99, doc="Excluded from effort tak")
+ GroupRank = models.IntegerField(initial=-99, doc="Rank in group")
+
+ #
+ P1_BVote_nArgBest = models.IntegerField(initial=-99, doc="Number of votes for best vote")
+ P1_BVote_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_BVote_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_BVote_ArgBestSingle = models.IntegerField(initial=-99)
+ #
+
+ Effort_points = models.FloatField(initial=-99)
+ Minus_points = models.FloatField(initial=-99)
+
+ # Start Token
+ P1_StartToken = models.FloatField(initial=-99, doc="StartToken after deduction of Taxes")
+ P1_StartTokenPT = models.FloatField(initial=-99, doc="StartToken pre Taxes; formally coded as StartTokenAlt")
+ P1_Taxes = models.FloatField(initial=-99, doc="Taxes to be deducted from StartTokenPT")
+ P1_ConsumptionFinal = models.FloatField(initial=-99,
+ doc="Final Consumption = with TokenAdd as voted for by group")
+ # Final Payout
+ ProfitEuroUnround = models.FloatField(initial=-99)
+ ProfitEuroRound = models.FloatField(initial=-99)
+ ProfitToken = models.FloatField(initial=-99)
+ P1_FinalWealth_5R = models.FloatField(initial=-99)
+
+ # Suggested Distribution
+ #
+ P1_AckVote = models.IntegerField(
+ choices=[
+ [1, 'Das Verfahren soll anerkannt werden'],
+ [0, 'Das Verfahren soll nicht anerkannt werden'], ],
+ doc="Former variable name: iAnerkennungVerfahren",
+ widget=widgets.RadioSelect,
+ )
+ #
+ #
+
+ P1_TokenAddEqual = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by Experimenter")
+ P1_TokenAddWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by WeakerFirst")
+ P1_TokenAddMixed = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by Mixed")
+ P1_ConsumptionNoDis = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption = no Redistribution")
+ P1_ConsumptionEqual = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption = with TokenAdd as suggested by Experimenter")
+ P1_ConsumptionWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption = with TokenAdd as suggested by Weaker First")
+ P1_ConsumptionMixed = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption = with TokenAdd as suggested by Mixed")
+ P1_SumRoundIncomeEqual = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Experimenter")
+ P1_SumRoundIncomeWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Weaker First")
+ P1_SumRoundIncomeMixed = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Mixed")
+
+ P1_WealthNoDis_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - No Redistribution")
+ P1_WealthNoDis_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - No Redistribution")
+
+ P1_WealthEqual_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthEqual_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthWeakerFirst_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthWeakerFirst_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthMixed_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthMixed_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+ #
+
+ # New Distribution
+ P1_TokenAdd = models.FloatField(initial=-99, doc="Chosen new Distribution - If suggested Distribution was rejected")
+ # Wahl für neue Verteilungen bei Rejection
+ #
+ P1_iTokenAddVoteFor_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_6 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+
+ #
+ #
+ P1_iTokenAddVoteFor_Corr_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ #
+ #
+ P1_CountSame = models.IntegerField(initial=-99)
+ P1_CountSame_Corr = models.IntegerField(
+ doc="CountSame2 in zTree",
+ initial=-99)
+ P1_CountGroup = models.IntegerField(initial=-99)
+
+ #
+ #
+ P1_WealthNewDis_1R = models.FloatField(initial=-99)
+ P1_WealthNewDis_5R = models.FloatField(initial=-99)
+ # 1 R
+ #
+ # Before Voting
+ #
+ P1_BVote_YesNo = models.IntegerField(
+ choices=[
+ [1, 'Ich erkenne das Verteilungsverfahren der zusätzlichen Token an'],
+ [0, 'Ich erkenne das Verteilungsverfahren der zusätzlichen Token nicht an'], ],
+ doc="Former variable name: P1_AnerkennungPrivat",
+ initial=-99,
+ widget=widgets.RadioSelect
+ )
+ P1_BVote_YesNoString = models.TextField()
+
+ P1_YesNoArg_BVote = models.TextField(
+ label="",
+ max_length=250,
+ doc="Argument for Acceptance/Rejection of the suggested distribution. Former variable name: Argument"
+ # blank=True #das wird dann später im javascript aufgehoben
+ )
+ #
+ #
+ P1_BVote_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_BVote_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+
+ # After Voting
+ P1_AVote_AckArg = models.TextField(
+ label="",
+ max_length=250,
+ )
+ #
+ P1_AVote_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_AVote_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_AVote_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_AVote_ArgBest = models.IntegerField(doc="Whether participant is one of the best-vote winners.")
+ P1_AVote_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_AVote_ArgBestSingle = models.IntegerField()
+
+ # #
+
+ # Argumente rejection
+ #
+ P1_iTokenAddSuggestion_1 = models.FloatField(
+ # label="Player 1 (" + str(format(Constants.P1_StartToken_0[1-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_2 = models.FloatField(
+ # label="Player 2 (" + str(format(Constants.P1_StartToken_0[2-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_3 = models.FloatField(
+ # label="Player 3 (" + str(format(Constants.P1_StartToken_0[3-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_4 = models.FloatField(
+ # label="Player 4 (" + str(format(Constants.P1_StartToken_0[4-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_5 = models.FloatField(
+ # label="Player 5 (" + str(format(Constants.P1_StartToken_0[5-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_Rej_Arg = models.TextField(
+ label="",
+ max_length=250,
+ # blank=True #das wird dann später im javascript aufgehoben
+ )
+ #
+ #
+ P1_Rej_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_Rej_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_Rej_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Rej_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Rej_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Rej_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+
+ #
+ # Argumente Acceptance
+ P1_Acc_DistributionChange = models.IntegerField(
+ choices=[
+ [1, 'Ich hätte mich dennoch für Verfahren >Gleichverteilung< entschieden.'],
+ [2, 'Ich hätte mich für das alternative Verfahren >Angleichen von unten< entschieden.'],
+ [3,
+ "Ich hätte mich für das alternative Verfahren >Verteilung gemäß Ausgangseinkommen mit Berücksichtigung des Mindestkonsums< entschieden."]
+ ],
+ doc="Former variable name: P1_AnerkennungPrivat",
+ initial=-99,
+ widget=widgets.RadioSelect)
+ P1_Acc_Arg = models.TextField(
+ label="",
+ max_length=250, )
+ #
+ P1_Acc_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_Acc_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_Acc_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Acc_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Acc_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Acc_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+ #
+ #
+
+ P1_SumRoundIncome = models.FloatField(initial=-99)
+
+ # Hilfsvariablen
+ P1_ChatDisProStart = models.BigIntegerField(initial=-99)
+ P1_ChatDisProStartKorr = models.BigIntegerField(initial=-99)
+ P1_AVote_ChatStart = models.BigIntegerField(initial=-99)
+ P1_AVote_ChatStartKorr = models.BigIntegerField(initial=-99)
+ Nickname = models.TextField(initial=-99)
+
+ #
+
+ #
+
+ def roundupto50(self, number):
+ if math.fmod(number, 0.5) != 0:
+ return number + (0.5 - math.fmod(number, 0.5))
+ else:
+ return number
diff --git a/tests/testthat/testdata/ocode_f2/MIG1/models.py b/tests/testthat/testdata/ocode_f2/MIG1/models.py
new file mode 100644
index 0000000..6d01810
--- /dev/null
+++ b/tests/testthat/testdata/ocode_f2/MIG1/models.py
@@ -0,0 +1,301 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+from scipy.stats import rankdata
+import math
+
+
+author = 'Patricia Zauchner'
+
+doc = """
+Migration Game.
+Run only on Chrome. Never on IE!
+In IE, the dialogue windows won't work.
+"""
+
+class Constants(BaseConstants):
+ name_in_url = 'MIG1'
+ players_per_group = 5
+ num_rounds = 1 # Wie oft das Experiment durchläuft
+ ShowUpFeeEuro = 12
+ ExchangeEuro = 1
+ ExchangeToken = 1
+ ExchangeRate = ExchangeToken / ExchangeEuro
+
+ ShowUpFeeToken = ShowUpFeeEuro * ExchangeRate
+ P1_Needs = 16 # Formerly known as "Bedarf".
+ UsualConsumption = 0.9 # 90% of the income will be consumed
+ Rounds = 5
+ time_for_args = 0.2
+ time_for_argsSek = time_for_args * 60
+ #
+ P1_GesamtZusatzToken = 30
+ P1_TokenAdd_Equal = [30 / 5, 30 / 5, 30 / 5, 30 / 5, 30 / 5] # Zusatztoken bei Gleichverteilung
+ #
+ P1_StartToken_0 = [0, 14, 19, 26, 41] # StartToken --> Netto After Taxes
+ P1_Taxes_0 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_0 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_0.append(P1_StartToken_0[i] + P1_Taxes_0[i])
+ P1_TokenAddWeakerFirst_0 = [21, 7, 2, 0, 0]
+ P1_TokenAddMixed_0 = [16, 2, 3, 4, 5] # so besprochen am 31.3.
+
+ #
+ #
+ P1_StartToken_9 = [9, 14, 19, 26, 41]
+ P1_Taxes_9 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_9 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_9.append(P1_StartToken_9[i] + P1_Taxes_9[i])
+ P1_TokenAddWeakerFirst_9 = [11, 6, 3, 0, 0]
+ P1_TokenAddMixed_9 = [6.5, 1.5, 1, 4, 7]
+
+ #
+ #
+ #
+ ArgCharMax = 250
+ P1_Rej_ArgBestToken = 2
+ P1_BVote_ArgBestToken = 2
+ P1_AVote_ArgBestToken = 2
+ P1_Acc_ArgBestToken = 2
+ #
+ #
+ ChatTime_Ack = 6 # Todo: Check if time is correct. Should be 6 minutes.
+ ChatTime_Ack_Sec = ChatTime_Ack * 60
+ ChatTime_Distribution = 5 # Formerly known as ChatTime_Verteilung #Todo: Check if time is correct. Should be 5 minutes.
+ ChatTime_DistributionCorr = 1 # Formerly known as ChatTime_VerteilungKorr #Todo: Check if time is correct. Should be 1 minute.
+ ChatTime_DistributionCorrSek = ChatTime_DistributionCorr * 60 # Formerly known as ChatTime_VerteilungKorrSek
+ #
+
+ MinArgumentLength = 10
+ MaxArgumentLength = 250
+
+ # Grafiken
+ TickInterval = 5
+ LineWidth = 5
+ ArgumentChatHeight = 600
+
+
+class Session:
+ pass
+
+
+class Subsession(BaseSubsession):
+ def creating_session(self):
+ """"
+ create ID, StartToken, Wealth, and Treatments;
+ """
+ #
+ # Copy the group and player id structure of the first app
+ if "id_matrix" in self.session.vars:
+ self.set_group_matrix(self.session.vars['id_matrix'])
+ else:
+ self.group_randomly()
+ #
+ #
+ # Assign Treatments: Economic participation
+ if "session_treatment_ec" in self.session.config: # if treatment was already assigned in session config
+ for g in self.get_groups():
+ g.treatment_ec = self.session.config['session_treatment_ec']
+ else:
+ for g in self.get_groups():
+ g.treatment_ec = 0 # Todo: Here you can enter the treatment manually.
+ # Assign Treatments: Political participation
+ if "session_treatment_pol" in self.session.config: # if treatment was already assigned in session config
+ for g in self.get_groups():
+ g.treatment_pol = self.session.config['session_treatment_pol']
+ else:
+ for g in self.get_groups():
+ g.treatment_pol = 1 # Todo: Here you can enter the treatment manually.
+ #
+ #
+ for p in self.get_players(): # Exclusion of player 1 in effort task:
+ if "Economically_Excluded" in p.participant.vars:
+ p.Economically_Excluded = p.participant.vars['Economically_Excluded']
+ else:
+ if p.group.treatment_ec == 0 and p.id_in_group == 1:
+ p.participant.vars['Economically_Excluded'] = 1
+ p.Economically_Excluded = 1
+ else:
+ p.participant.vars['Economically_Excluded'] = 0
+ p.Economically_Excluded = 0
+ for p in self.get_players(): # Exclusion of player 1 in deliberation:
+ if "Politically_Excluded" in p.participant.vars:
+ p.Politically_Excluded = p.participant.vars['Politically_Excluded']
+ else:
+ if p.group.treatment_pol == 0 and p.id_in_group == 1:
+ p.participant.vars['Politically_Excluded'] = 1
+ p.Politically_Excluded = 1
+ else:
+ p.participant.vars['Politically_Excluded'] = 0
+ p.Politically_Excluded = 0
+ #
+ # Assign number of eligible voters:
+ for g in self.get_groups():
+ g.defineEligibleVoters()
+
+ #
+ def vars_for_admin_report(self):
+ #Background-Info to Participants
+ list_of_groupmembership = []
+ for p in self.get_players():
+ group = "Group: " + str(p.group.id_in_subsession)
+ name = " - Participant: "+str(p.participant.label)
+ effpoints = " - Effort Points: "+str(p.Effort_points)
+ rank = " - Rank:"+ str(p.GroupRank)
+ list_of_groupmembership.append(group+name+rank+effpoints)
+ list_of_groupmembership = sorted(list_of_groupmembership)
+ #Decisions and Treatments in Game
+ listofgroupack = []
+ polpart_treatmentlist = []
+ ecpart_treatmentlist = []
+ listP1_NeueVerteilungErreicht = []
+ groupnumberlist = []
+ for g in self.get_groups():
+ groupnumberlist.append(g)
+ polpart_treatmentlist.append(g.treatment_pol)
+ ecpart_treatmentlist.append(g.treatment_ec)
+ listofgroupack.append(g.P1_GroupAcknowledgement)
+ listP1_NeueVerteilungErreicht.append(g.P1_NeueVerteilungErreicht)
+ return {
+ "participantsinlist": list_of_groupmembership,
+ "Political_Participation_Treatment": polpart_treatmentlist,
+ "Economic_Participation_Treatment": ecpart_treatmentlist,
+ "groupnumberlist": groupnumberlist,
+ "groupAcknowledgement": listofgroupack,
+ "P1_NeueVerteilungErreicht": listP1_NeueVerteilungErreicht
+ }
+
+ #
+
+
+class Group(BaseGroup):
+ #
+ REDIS = models.IntegerField(initial=1) # 0 = DIS, 1 = REDIS ---> From now on always redis
+ Effort = models.IntegerField(
+ initial=1) # 0 = Lottery, 1 = Effort ---> From now on always effort for core group members
+
+ #
+
+class Player(BasePlayer):
+ P1_ConsumptionFinal = models.FloatField(initial=-99,
+ doc="Final Consumption \= with TokenAdd as voted for by group")
+ # Final Payout
+ ProfitEuroUnround = models.FloatField(initial=-99)
+ # Suggested Distribution
+ #
+ P1_AckVote = models.IntegerField(
+ choices=[
+ [1, 'Das Verfahren soll anerkannt werden'],
+ [0, 'Das Verfahren soll nicht anerkannt werden'], ],
+ doc="Former variable name: iAnerkennungVerfahren",
+ widget=widgets.RadioSelect,
+ )
+ #
+ #
+
+
+ P1_ConsumptionNoDis = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption \= no Redistribution")
+ P1_ConsumptionEqual = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption \= with TokenAdd as suggested by Experimenter")
+ P1_ConsumptionWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption \= with TokenAdd as suggested by Weaker First")
+ P1_ConsumptionMixed = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption \= with TokenAdd as suggested by Mixed")
+ P1_SumRoundIncomeEqual = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Experimenter")
+ P1_SumRoundIncomeWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Weaker First")
+ P1_SumRoundIncomeMixed = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Mixed")
+
+ P1_WealthNoDis_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - No Redistribution")
+ P1_WealthNoDis_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - No Redistribution")
+
+
+ P1_WealthWeakerFirst_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthWeakerFirst_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthMixed_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthMixed_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+ #
+
+ # New Distribution
+ P1_TokenAdd = models.FloatField(initial=-99, doc="Chosen new Distribution - If suggested Distribution was rejected")
+ # Wahl für neue Verteilungen bei Rejection
+ #
+ P1_iTokenAddVoteFor_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_6 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+
+ #
+ #
+ P1_iTokenAddVoteFor_Corr_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ #
+ #
+ P1_CountSame = models.IntegerField(initial=-99)
+ P1_CountSame_Corr = models.IntegerField(
+ doc="CountSame2 in zTree",
+ initial=-99)
+ P1_CountGroup = models.IntegerField(initial=-99)
+
+ #
+ #
+ P1_WealthNewDis_1R = models.FloatField(initial=-99)
+ P1_WealthNewDis_5R = models.FloatField(initial=-99)
+ # 1 R
+ #
+ # Before Voting
diff --git a/tests/testthat/testdata/ocode_f3/MIG1/models.py b/tests/testthat/testdata/ocode_f3/MIG1/models.py
new file mode 100644
index 0000000..bb92fd2
--- /dev/null
+++ b/tests/testthat/testdata/ocode_f3/MIG1/models.py
@@ -0,0 +1,1121 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+from scipy.stats import rankdata
+import math
+
+
+author = 'Patricia Zauchner'
+
+doc = """
+Migration Game.
+Run only on Chrome. Never on IE!
+In IE, the dialogue windows won't work.
+"""
+
+class Constants(BaseConstants):
+ name_in_url = 'MIG1'
+ players_per_group = 5
+ num_rounds = 1 # Wie oft das Experiment durchläuft
+ ShowUpFeeEuro = 12
+ ExchangeEuro = 1
+ ExchangeToken = 1
+ ExchangeRate = ExchangeToken / ExchangeEuro
+
+ ShowUpFeeToken = ShowUpFeeEuro * ExchangeRate
+ P1_Needs = 16 # Formerly known as "Bedarf".
+ UsualConsumption = 0.9 # 90% of the income will be consumed
+ Rounds = 5
+ time_for_args = 0.2
+ time_for_argsSek = time_for_args * 60
+ #
+ P1_GesamtZusatzToken = 30
+ P1_TokenAdd_Equal = [30 / 5, 30 / 5, 30 / 5, 30 / 5, 30 / 5] # Zusatztoken bei Gleichverteilung
+ #
+ P1_StartToken_0 = [0, 14, 19, 26, 41] # StartToken --> Netto After Taxes
+ P1_Taxes_0 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_0 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_0.append(P1_StartToken_0[i] + P1_Taxes_0[i])
+ P1_TokenAddWeakerFirst_0 = [21, 7, 2, 0, 0]
+ P1_TokenAddMixed_0 = [16, 2, 3, 4, 5] # so besprochen am 31.3.
+
+ #
+ #
+ P1_StartToken_9 = [9, 14, 19, 26, 41]
+ P1_Taxes_9 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_9 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_9.append(P1_StartToken_9[i] + P1_Taxes_9[i])
+ P1_TokenAddWeakerFirst_9 = [11, 6, 3, 0, 0]
+ P1_TokenAddMixed_9 = [6.5, 1.5, 1, 4, 7]
+
+ #
+ #
+ #
+ ArgCharMax = 250
+ P1_Rej_ArgBestToken = 2
+ P1_BVote_ArgBestToken = 2
+ P1_AVote_ArgBestToken = 2
+ P1_Acc_ArgBestToken = 2
+ #
+ #
+ ChatTime_Ack = 6 # Todo: Check if time is correct. Should be 6 minutes.
+ ChatTime_Ack_Sec = ChatTime_Ack * 60
+ ChatTime_Distribution = 5 # Formerly known as ChatTime_Verteilung #Todo: Check if time is correct. Should be 5 minutes.
+ ChatTime_DistributionCorr = 1 # Formerly known as ChatTime_VerteilungKorr #Todo: Check if time is correct. Should be 1 minute.
+ ChatTime_DistributionCorrSek = ChatTime_DistributionCorr * 60 # Formerly known as ChatTime_VerteilungKorrSek
+ #
+
+ MinArgumentLength = 10
+ MaxArgumentLength = 250
+
+ # Grafiken
+ TickInterval = 5
+ LineWidth = 5
+ ArgumentChatHeight = 600
+
+
+class Session:
+ pass
+
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ #
+ REDIS = models.IntegerField(initial=1) # 0 = DIS, 1 = REDIS ---> From now on always redis
+ Effort = models.IntegerField(
+ initial=1) # 0 = Lottery, 1 = Effort ---> From now on always effort for core group members
+
+ treatment_ec = models.IntegerField(
+ doc="""Economic Participation Treatment""",
+ choices=[
+ [0, "0 = tolle Anfangssausstattung"], # Person not allowed to participate in effort task
+ [1, "9 Anfangsausstattung"] # Person allowed to participate in effort task
+ ])
+ treatment_pol = models.IntegerField(
+ doc="""Political Participation Treatment""",
+ choices=[
+ [0, "No participation in the decision"],
+ [1, "Participation in the decision"]
+ ])
+
+ #
+ #
+ def randomGroupRank(self):
+ """
+ If Effort = 0, the individuals in the group are assigned random IDs.
+ This method is called by the Intro-WaitPage.
+ I won't need this for the experiment, but it's good for pretesting.
+ """
+ randomnumber = random.sample(list(range(1, 6)), 5)
+ for p in self.get_players():
+ p.GroupRank = randomnumber[p.id_in_group - 1]
+
+ def effortGroupRank(self):
+ """
+ If Effort = 1, the individuals in the group are assigned IDs according to their effort.
+ This method is called by the intro-WaitPage.
+ """
+ if self.treatment_ec == 0:
+ all_group_effort_new = []
+ for p in self.get_players():
+ all_group_effort_new.append(p.Effort_points - (p.Minus_points * 0.0001) - (p.id_in_group * 0.000001))
+ rankgroupeffort = rankdata(all_group_effort_new)
+ else:
+ all_group_effort_new = []
+ for p in self.get_players():
+ if p.id_in_group != 1:
+ all_group_effort_new.append(
+ p.Effort_points - (p.Minus_points * 0.0001) - (p.id_in_group * 0.000001))
+ if p.id_in_group == 1:
+ all_group_effort_new.append(0)
+ rankgroupeffort = rankdata(all_group_effort_new)
+
+ for p in self.get_players():
+ p.GroupRank = int(rankgroupeffort[p.id_in_group - 1])
+
+ def P1_Define_StartToken(self):
+ if self.treatment_ec == 0:
+ for p in self.get_players():
+ # For specific positions
+ p.P1_StartToken = Constants.P1_StartToken_0[p.GroupRank - 1]
+ p.P1_StartTokenPT = Constants.P1_StartTokenPT_0[p.GroupRank - 1]
+ p.P1_Taxes = Constants.P1_Taxes_0[p.GroupRank - 1]
+ p.P1_TokenAddEqual = Constants.P1_TokenAdd_Equal[p.GroupRank - 1]
+ p.P1_TokenAddWeakerFirst = Constants.P1_TokenAddWeakerFirst_0[p.GroupRank - 1]
+ p.P1_TokenAddMixed = Constants.P1_TokenAddMixed_0[p.GroupRank - 1]
+ # For all
+ p.P1_SumRoundIncomeEqual = p.P1_StartToken + p.P1_TokenAddEqual
+ p.P1_SumRoundIncomeWeakerFirst = p.P1_StartToken + p.P1_TokenAddWeakerFirst
+ p.P1_SumRoundIncomeMixed = p.P1_StartToken + p.P1_TokenAddMixed
+ if self.treatment_ec == 1:
+ for p in self.get_players():
+ # For specific positions
+ p.P1_StartToken = Constants.P1_StartToken_9[p.GroupRank - 1]
+ p.P1_StartTokenPT = Constants.P1_StartTokenPT_9[p.GroupRank - 1]
+ p.P1_Taxes = Constants.P1_Taxes_9[p.GroupRank - 1]
+ p.P1_TokenAddEqual = Constants.P1_TokenAdd_Equal[p.GroupRank - 1]
+ p.P1_TokenAddWeakerFirst = Constants.P1_TokenAddWeakerFirst_9[p.GroupRank - 1]
+ p.P1_TokenAddMixed = Constants.P1_TokenAddMixed_9[p.GroupRank - 1]
+ # For all
+ p.P1_SumRoundIncomeEqual = p.P1_StartToken + p.P1_TokenAddEqual
+ p.P1_SumRoundIncomeWeakerFirst = p.P1_StartToken + p.P1_TokenAddWeakerFirst
+ p.P1_SumRoundIncomeMixed = p.P1_StartToken + p.P1_TokenAddMixed
+
+
+
+ def Nickname(self):
+ self.Channel_Ack = str(self.id_in_subsession) + "_Ack"
+ self.Channel_DisProcedure = str(self.id_in_subsession) + "_DisProc"
+ self.Channel_DisProcedureKorr = str(self.id_in_subsession) + "_DisProcKorr"
+ for p in self.get_players():
+ p.Nickname = "Player " + str(p.GroupRank)
+
+ #
+ #
+ def P1_calc_wealthD0(self): # Keine Grafiken, nur Zahlen
+ for p in self.get_players():
+ #
+ if (p.P1_StartTokenPT * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionNoDis = Constants.P1_Needs
+ p.P1_WealthNoDis_1R = p.P1_StartTokenPT - Constants.P1_Needs
+ else:
+ p.P1_ConsumptionNoDis = p.P1_StartTokenPT * 0.9
+ p.P1_WealthNoDis_1R = p.P1_StartTokenPT * 0.1
+ p.P1_WealthNoDis_5R = p.P1_WealthNoDis_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddEqual) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionEqual = Constants.P1_Needs
+ p.P1_WealthEqual_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddEqual
+ else:
+ p.P1_ConsumptionEqual = (p.P1_StartToken + p.P1_TokenAddEqual) * 0.9
+ p.P1_WealthEqual_1R = (p.P1_StartToken + p.P1_TokenAddEqual) * 0.1
+ p.P1_WealthEqual_5R = p.P1_WealthEqual_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionWeakerFirst = Constants.P1_Needs
+ p.P1_WealthWeakerFirst_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddWeakerFirst
+ else:
+ p.P1_ConsumptionWeakerFirst = (p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.9
+ p.P1_WealthWeakerFirst_1R = (p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.1
+ p.P1_WealthWeakerFirst_5R = p.P1_WealthWeakerFirst_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddMixed) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionMixed = Constants.P1_Needs
+ p.P1_WealthMixed_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddMixed
+ else:
+ p.P1_ConsumptionMixed = (p.P1_StartToken + p.P1_TokenAddMixed) * 0.9
+ p.P1_WealthMixed_1R = (p.P1_StartToken + p.P1_TokenAddMixed) * 0.1
+ p.P1_WealthMixed_5R = p.P1_WealthMixed_1R * 5
+ #
+
+
+ def P1_ResultsGraphEqual(self):
+ """ Wird in Pages - class P1_Rej_9_Rounds(Page) aufgerufen"""
+ series_Start_PT = []
+ series_Start = []
+ series_Taxes = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start_PT.append(p.P1_StartTokenPT)
+ series_Start.append(p.P1_StartToken)
+ series_Taxes.append(p.P1_Taxes)
+ series_TokenAdd.append(p.P1_TokenAddEqual)
+ cumulativedata = [0,
+ p.P1_WealthEqual_1R * 1,
+ p.P1_WealthEqual_1R * 2,
+ p.P1_WealthEqual_1R * 3,
+ p.P1_WealthEqual_1R * 4,
+ p.P1_WealthEqual_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthEqual_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddEqual)
+ return {
+ "series_StartToken_PT": series_Start_PT,
+ "StartToken": series_Start,
+ "Taxes": series_Taxes,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def P1_info3graph(self):
+ series = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ playerdata = [0,
+ p.P1_WealthNoDis_1R * 1,
+ p.P1_WealthNoDis_1R * 2,
+ p.P1_WealthNoDis_1R * 3,
+ p.P1_WealthNoDis_1R * 4,
+ p.P1_WealthNoDis_1R * 5]
+ series.append({
+ "name": p.GroupRank,
+ "data": playerdata})
+ series_highest_lowest.append(p.P1_WealthNoDis_5R)
+ return {
+ 'highcharts_series': series,
+ "MinValue": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue": self.MinMaxGraph(series_highest_lowest)[1]
+ }
+
+ def P1_ResultsGraphWeakerFirst(self):
+ """ Wird aufgerufen bei Acceptance - Weaker First"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAddWeakerFirst)
+ cumulativedata = [0,
+ p.P1_WealthWeakerFirst_1R * 1,
+ p.P1_WealthWeakerFirst_1R * 2,
+ p.P1_WealthWeakerFirst_1R * 3,
+ p.P1_WealthWeakerFirst_1R * 4,
+ p.P1_WealthWeakerFirst_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthWeakerFirst_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddWeakerFirst)
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def P1_ResultsGraphMixed(self):
+ """ Wird aufgerufen bei Acceptance - Weaker First"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAddMixed)
+ cumulativedata = [0,
+ p.P1_WealthMixed_1R * 1,
+ p.P1_WealthMixed_1R * 2,
+ p.P1_WealthMixed_1R * 3,
+ p.P1_WealthMixed_1R * 4,
+ p.P1_WealthMixed_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthMixed_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddMixed)
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ #
+
+ # Wahlen
+ P1_NumElegibleToVoteForAck = models.IntegerField(initial=-99)
+ P1_NumElegibleToVoteNewDis = models.IntegerField(initial=-99)
+
+ def defineEligibleVoters(self):
+ if self.treatment_pol == 1:
+ self.P1_NumElegibleToVoteForAck = Constants.players_per_group
+ self.P1_NumElegibleToVoteNewDis = Constants.players_per_group
+ elif self.treatment_pol == 0:
+ self.P1_NumElegibleToVoteForAck = Constants.players_per_group - 1
+ self.P1_NumElegibleToVoteNewDis = Constants.players_per_group - 1
+ else:
+ print("Problem. Check defineEligibleVoters()")
+
+ P1_nGroupAnerkennung = models.IntegerField(initial=0)
+ P1_GroupAcknowledgement = models.IntegerField(initial=0)
+
+ def P1_AckResult(self):
+ self.P1_nGroupAnerkennung = 0
+ for p in self.get_players():
+ if p.P1_AckVote == 1:
+ self.P1_nGroupAnerkennung += 1
+ if self.P1_nGroupAnerkennung == self.P1_NumElegibleToVoteForAck:
+ self.P1_GroupAcknowledgement = 1
+ else:
+ self.P1_GroupAcknowledgement = 0
+
+ #
+ P1_CountGroup = models.IntegerField(
+ initial=0)
+ P1_CountGroup_Corr = models.IntegerField(
+ doc="in zTree: CountGroup2",
+ initial=0)
+ P1_NeueVerteilungErreicht = models.IntegerField(initial=0)
+ P1_NeueVerteilungErreicht_Corr = models.IntegerField(initial=0)
+
+ #
+ P1_TokenAdd_New_1 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_2 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_3 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_4 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_5 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_1 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_2 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_3 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_4 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_5 = models.FloatField(initial=-99)
+
+ #
+
+ def abzahlen(self, Correction):
+ """
+ How many group members entered the same numbers?
+ Old function name in ztree: Countsame.
+ If this function is called after the Correction chat, enter "Corr" when calling the function.
+ """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ for p in self.get_players():
+ setattr(p, "P1_CountSame" + corr, 0)
+ for q in self.get_players():
+ if (vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(1)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(1)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(2)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(2)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(3)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(3)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(4)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(4)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(5)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(5)]): \
+ setattr(p, "P1_CountSame" + corr, getattr(p, "P1_CountSame" + corr) + 1)
+
+ #
+ #
+ def abzahlengruppe(self, Correction):
+ """"Wie viele gleiche Zahleneingaben gibt es höchstens pro Gruppe? """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ setattr(self, "P1_CountGroup" + corr, 0)
+ for p in self.get_players():
+ if (getattr(p, "P1_CountSame" + corr) > (p.group.P1_NumElegibleToVoteNewDis / 2)):
+ setattr(self, "P1_CountGroup" + corr, getattr(self, "P1_CountGroup" + corr) + 1)
+
+ #
+ #
+
+ def NewDisVoteRes(self, Correction):
+ """
+ Prior name: P1_Wahlergebnis1
+ Wird in Pages --> P1_Rej_5_Chat_DistributionProcedure_2WP_After aufgerufen
+ """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ for p in self.get_players():
+ if getattr(p, "P1_CountSame" + corr) > p.group.P1_NumElegibleToVoteNewDis / 2:
+ for i in range(1, 6):
+ setattr(self, "P1_TokenAdd_New" + corr + "_" + str(i),
+ getattr(p, "P1_iTokenAddVoteFor" + corr + "_" + str(i)))
+ break
+
+ if getattr(self, "P1_CountGroup" + corr) > self.P1_NumElegibleToVoteNewDis / 2:
+ setattr(self, "P1_NeueVerteilungErreicht" + corr, 1)
+ # Calculate Token Add
+ for p in self.get_players():
+ for i in range(1, 6):
+ if p.GroupRank == i:
+ p.P1_TokenAdd = getattr(self, "P1_TokenAdd_New" + corr + "_" + str(i))
+
+ # Calculate Roundincome after Tokenadd and Needs-Satisfaction
+ for p in self.get_players():
+ p.P1_SumRoundIncome = p.P1_StartToken + p.P1_TokenAdd
+ if p.P1_SumRoundIncome < Constants.P1_Needs:
+ p.P1_ConsumptionFinal = Constants.P1_Needs
+ p.P1_WealthNewDis_1R = p.P1_SumRoundIncome - Constants.P1_Needs
+ else:
+ p.P1_ConsumptionFinal = p.P1_SumRoundIncome * 0.9
+ p.P1_WealthNewDis_1R = p.P1_SumRoundIncome * 0.1
+ p.P1_WealthNewDis_5R = p.P1_WealthNewDis_1R * 5
+ else:
+ setattr(self, "P1_NeueVerteilungErreicht" + corr, 0)
+
+ #
+ #
+
+ #
+ #
+ #
+
+ P1_BVote_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_BVote_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_BVote_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_Rej_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_Rej_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_Rej_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_AVote_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_AVote_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_AVote_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_Acc_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_Acc_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_Acc_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+ def calcbestarg(self, argpart):
+ # argpart are either BVote,
+
+ #
+ group_acc_base = "P1_" + argpart + "_nArgAkz_"
+ group_accNo_base = "P1_" + argpart + "_nArgAkzNo_"
+ group_best_base = "P1_" + argpart + "_nArgBest_"
+
+ ind_acc_base = "P1_" + argpart + "_ArgAkz_"
+ ind_accNo_base = "P1_" + argpart + "_ArgAkzNo_"
+ ind_best_base = "P1_" + argpart + "_ArgBest_"
+ for i in range(1, 6):
+ group_acc_mod = group_acc_base + str(i)
+ group_accNo_mod = group_accNo_base + str(i)
+ group_best_mod = group_best_base + str(i)
+ ind_acc_mod = ind_acc_base + str(i)
+ ind_accNo_mod = ind_accNo_base + str(i)
+ ind_best_mod = ind_best_base + str(i)
+
+ # Calculations
+ setattr(self, group_acc_mod,
+ sum((vars(p)[ind_acc_mod]) for p in self.get_players() if vars(p)[ind_acc_mod] >= 0))
+ setattr(self, group_accNo_mod, 5 - vars(self)[group_acc_mod])
+ setattr(self, group_best_mod, sum((vars(p)[ind_best_mod]) for p in self.get_players()))
+
+ #
+ #
+ listofbest = [] # Für übersicht
+ for p in self.get_players():
+ setattr(p, "P1_" + argpart + "_nArgBest", vars(self)[group_best_base + str(p.GroupRank)])
+ listofbest.append(vars(p)["P1_" + argpart + "_nArgBest"])
+ # Winners
+ P1_Winners = [i for i, j in enumerate(listofbest) if j == max(listofbest)]
+ #
+ # Falls Gewinner/in
+ for p in self.get_players():
+ if (p.GroupRank - 1) in P1_Winners and len(P1_Winners) <= 2: # There are max 2 winners.
+ setattr(p, "P1_" + argpart + "_ArgBest", 1)
+ setattr(p, "P1_" + argpart + "_ArgToken", Constants.P1_BVote_ArgBestToken)
+ if len(P1_Winners) == 1:
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 1)
+ else:
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 2)
+ # Falls Nicht-Gewinner/in:
+ else:
+ setattr(p, "P1_" + argpart + "_ArgBest", 0)
+ setattr(p, "P1_" + argpart + "_ArgToken", 0)
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 0)
+
+ #
+
+ #
+
+ def P1_ResultsGraph(self):
+ """ Wird in Pages - class P1_Rej_9_Rounds(Page) aufgerufen"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAdd)
+ cumulativedata = [0,
+ p.P1_WealthNewDis_1R * 1,
+ p.P1_WealthNewDis_1R * 2,
+ p.P1_WealthNewDis_1R * 3,
+ p.P1_WealthNewDis_1R * 4,
+ p.P1_WealthNewDis_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthNewDis_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAdd)
+
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def MinMaxGraph(self, list=[]):
+ if min(list) >= 0:
+ minlist = -5
+ maxlist = max(list) + 3
+ else:
+ minlist = min(list) - 5
+ maxlist = max(list) + 3
+ return minlist, maxlist
+
+
+class Player(BasePlayer):
+ Politically_Excluded = models.IntegerField(initial=-99, doc="Excluded from deliberation")
+ Economically_Excluded = models.IntegerField(initial=-99, doc="Excluded from effort tak")
+ GroupRank = models.IntegerField(initial=-99, doc="Rank in group")
+
+ #
+ P1_BVote_nArgBest = models.IntegerField(initial=-99, doc="Number of votes for best vote")
+ P1_BVote_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_BVote_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_BVote_ArgBestSingle = models.IntegerField(initial=-99)
+ #
+
+ Effort_points = models.FloatField(initial=-99)
+ Minus_points = models.FloatField(initial=-99)
+
+ # Start Token
+ P1_StartToken = models.FloatField(initial=-99, doc="StartToken after deduction of Taxes")
+ P1_StartTokenPT = models.FloatField(initial=-99, doc="StartToken pre Taxes; formally coded as StartTokenAlt")
+ P1_Taxes = models.FloatField(initial=-99, doc="Taxes to be deducted from StartTokenPT")
+ P1_ConsumptionFinal = models.FloatField(initial=-99,
+ doc="Final Consumption with TokenAdd as voted for by group")
+ # Final Payout
+ ProfitEuroUnround = models.FloatField(initial=-99)
+ ProfitEuroRound = models.FloatField(initial=-99)
+ ProfitToken = models.FloatField(initial=-99)
+ P1_FinalWealth_5R = models.FloatField(initial=-99)
+
+ # Suggested Distribution
+ #
+ P1_AckVote = models.IntegerField(
+ choices=[
+ [1, 'Das Verfahren x = 1 soll anerkannt werden'],
+ [0, 'Das Verfahren y = 2 soll nicht anerkannt werden'], ],
+ doc="Former variable name: iAnerkennungVerfahren",
+ widget=widgets.RadioSelect,
+ )
+ #
+ #
+
+ P1_TokenAddEqual = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by Experimenter")
+ P1_TokenAddWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by WeakerFirst")
+ P1_TokenAddMixed = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by Mixed")
+ P1_ConsumptionNoDis = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption no Redistribution")
+ P1_ConsumptionEqual = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption with TokenAdd as suggested by Experimenter")
+ P1_ConsumptionWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption with TokenAdd as suggested by Weaker First")
+ P1_ConsumptionMixed = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption with TokenAdd as suggested by Mixed")
+ P1_SumRoundIncomeEqual = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Experimenter")
+ P1_SumRoundIncomeWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Weaker First")
+ P1_SumRoundIncomeMixed = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Mixed")
+
+ P1_WealthNoDis_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - No Redistribution")
+ P1_WealthNoDis_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - No Redistribution")
+
+ P1_WealthEqual_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthEqual_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthWeakerFirst_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthWeakerFirst_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthMixed_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthMixed_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+ #
+
+ # New Distribution
+ P1_TokenAdd = models.FloatField(initial=-99, doc="Chosen new Distribution - If suggested Distribution was rejected")
+ # Wahl für neue Verteilungen bei Rejection
+ #
+ P1_iTokenAddVoteFor_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_6 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+
+ #
+ #
+ P1_iTokenAddVoteFor_Corr_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ #
+ #
+ P1_CountSame = models.IntegerField(initial=-99)
+ P1_CountSame_Corr = models.IntegerField(
+ doc="CountSame2 in zTree",
+ initial=-99)
+ P1_CountGroup = models.IntegerField(initial=-99)
+
+ #
+ #
+ P1_WealthNewDis_1R = models.FloatField(initial=-99)
+ P1_WealthNewDis_5R = models.FloatField(initial=-99)
+ # 1 R
+ #
+ # Before Voting
+ #
+ P1_BVote_YesNo = models.IntegerField(
+ choices=[
+ [1, 'Ich erkenne das Verteilungsverfahren der zusätzlichen Token an'],
+ [0, 'Ich erkenne das Verteilungsverfahren der zusätzlichen Token nicht an'], ],
+ doc="Former variable name: P1_AnerkennungPrivat",
+ initial=-99,
+ widget=widgets.RadioSelect
+ )
+ P1_BVote_YesNoString = models.TextField()
+
+ P1_YesNoArg_BVote = models.TextField(
+ label="",
+ max_length=250,
+ doc="Argument for Acceptance/Rejection of the suggested distribution. Former variable name: Argument"
+ # blank=True #das wird dann später im javascript aufgehoben
+ )
+ #
+ #
+ P1_BVote_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_BVote_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+
+ # After Voting
+ P1_AVote_AckArg = models.TextField(
+ label="",
+ max_length=250,
+ )
+ #
+ P1_AVote_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_AVote_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_AVote_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_AVote_ArgBest = models.IntegerField(doc="Whether participant is one of the best-vote winners.")
+ P1_AVote_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_AVote_ArgBestSingle = models.IntegerField()
+
+ # #
+
+ # Argumente rejection
+ #
+ P1_iTokenAddSuggestion_1 = models.FloatField(
+ # label="Player 1 (" + str(format(Constants.P1_StartToken_0[1-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_2 = models.FloatField(
+ # label="Player 2 (" + str(format(Constants.P1_StartToken_0[2-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_3 = models.FloatField(
+ # label="Player 3 (" + str(format(Constants.P1_StartToken_0[3-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_4 = models.FloatField(
+ # label="Player 4 (" + str(format(Constants.P1_StartToken_0[4-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_5 = models.FloatField(
+ # label="Player 5 (" + str(format(Constants.P1_StartToken_0[5-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_Rej_Arg = models.TextField(
+ label="",
+ max_length=250,
+ # blank=True #das wird dann später im javascript aufgehoben
+ )
+ #
+ #
+ P1_Rej_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_Rej_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_Rej_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Rej_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Rej_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Rej_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+
+ #
+ # Argumente Acceptance
+ P1_Acc_DistributionChange = models.IntegerField(
+ choices=[
+ [1, 'Ich hätte mich dennoch für Verfahren >Gleichverteilung< entschieden.'],
+ [2, 'Ich hätte mich für das alternative Verfahren >Angleichen von unten< entschieden.'],
+ [3,
+ "Ich hätte mich für das alternative Verfahren >Verteilung gemäß Ausgangseinkommen mit Berücksichtigung des Mindestkonsums< entschieden."]
+ ],
+ doc="Former variable name: P1_AnerkennungPrivat",
+ initial=-99,
+ widget=widgets.RadioSelect)
+ P1_Acc_Arg = models.TextField(
+ label="",
+ max_length=250, )
+ #
+ P1_Acc_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_Acc_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_Acc_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Acc_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Acc_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Acc_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+ #
+ #
+
+ P1_SumRoundIncome = models.FloatField(initial=-99)
+
+ # Hilfsvariablen
+ P1_ChatDisProStart = models.BigIntegerField(initial=-99)
+ P1_ChatDisProStartKorr = models.BigIntegerField(initial=-99)
+ P1_AVote_ChatStart = models.BigIntegerField(initial=-99)
+ P1_AVote_ChatStartKorr = models.BigIntegerField(initial=-99)
+ Nickname = models.TextField(initial=-99)
+
+ #
+
+ #
+
+ def roundupto50(self, number):
+ if math.fmod(number, 0.5) != 0:
+ return number + (0.5 - math.fmod(number, 0.5))
+ else:
+ return number
diff --git a/tests/testthat/testdata/ocode_f4/MIG1/models.py b/tests/testthat/testdata/ocode_f4/MIG1/models.py
new file mode 100644
index 0000000..3c03eac
--- /dev/null
+++ b/tests/testthat/testdata/ocode_f4/MIG1/models.py
@@ -0,0 +1,1146 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+from scipy.stats import rankdata
+import math
+
+
+author = 'Patricia Zauchner'
+
+doc = """
+Migration Game.
+Run only on Chrome. Never on IE!
+In IE, the dialogue windows won't work.
+"""
+
+class Constants(BaseConstants):
+ name_in_url = 'MIG1'
+ players_per_group = 5
+ num_rounds = 1 # Wie oft das Experiment durchläuft
+ ShowUpFeeEuro = 12
+ ExchangeEuro = 1
+ ExchangeToken = 1
+ ExchangeRate = ExchangeToken / ExchangeEuro
+
+ ShowUpFeeToken = ShowUpFeeEuro * ExchangeRate
+ P1_Needs = 16 # Formerly known as "Bedarf".
+ UsualConsumption = 0.9 # 90% of the income will be consumed
+ Rounds = 5
+ time_for_args = 0.2
+ time_for_argsSek = time_for_args * 60
+ #
+ P1_GesamtZusatzToken = 30
+ P1_TokenAdd_Equal = [30 / 5, 30 / 5, 30 / 5, 30 / 5, 30 / 5] # Zusatztoken bei Gleichverteilung
+ #
+ P1_StartToken_0 = [0, 14, 19, 26, 41] # StartToken --> Netto After Taxes
+ P1_Taxes_0 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_0 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_0.append(P1_StartToken_0[i] + P1_Taxes_0[i])
+ P1_TokenAddWeakerFirst_0 = [21, 7, 2, 0, 0]
+ P1_TokenAddMixed_0 = [16, 2, 3, 4, 5] # so besprochen am 31.3.
+
+ #
+ #
+ P1_StartToken_9 = [9, 14, 19, 26, 41]
+ P1_Taxes_9 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_9 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_9.append(P1_StartToken_9[i] + P1_Taxes_9[i])
+ P1_TokenAddWeakerFirst_9 = [11, 6, 3, 0, 0]
+ P1_TokenAddMixed_9 = [6.5, 1.5, 1, 4, 7]
+
+ #
+ #
+ #
+ ArgCharMax = 250
+ P1_Rej_ArgBestToken = 2
+ P1_BVote_ArgBestToken = 2
+ P1_AVote_ArgBestToken = 2
+ P1_Acc_ArgBestToken = 2
+ #
+ #
+ ChatTime_Ack = 6 # Todo: Check if time is correct. Should be 6 minutes.
+ ChatTime_Ack_Sec = ChatTime_Ack * 60
+ ChatTime_Distribution = 5 # Formerly known as ChatTime_Verteilung #Todo: Check if time is correct. Should be 5 minutes.
+ ChatTime_DistributionCorr = 1 # Formerly known as ChatTime_VerteilungKorr #Todo: Check if time is correct. Should be 1 minute.
+ ChatTime_DistributionCorrSek = ChatTime_DistributionCorr * 60 # Formerly known as ChatTime_VerteilungKorrSek
+ #
+
+ MinArgumentLength = 10
+ MaxArgumentLength = 250
+
+ # Grafiken
+ TickInterval = 5
+ LineWidth = 5
+ ArgumentChatHeight = 600
+
+
+class Session:
+ pass
+
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ #
+ REDIS = models.IntegerField(initial=1) # 0 = DIS, 1 = REDIS ---> From now on always redis
+ Effort = models.IntegerField(
+ initial=1) # 0 = Lottery, 1 = Effort ---> From now on always effort for core group members
+
+ treatment_ec = models.IntegerField(
+ doc="""Economic Participation Treatment""",
+ choices=[
+ [0, "0 \= tolle Anfangssausstattung"], # Person not allowed to participate in effort task
+ [1, "9 Anfangsausstattung"] # Person allowed to participate in effort task
+ ])
+ treatment_pol = models.IntegerField(
+ doc="""Political Participation Treatment""",
+ choices=[
+ [0, "No participation in the decision"],
+ [1, "Participation in the decision"]
+ ])
+
+ #
+ #
+ def randomGroupRank(self):
+ """
+ If Effort = 0, the individuals in the group are assigned random IDs.
+ This method is called by the Intro-WaitPage.
+ I won't need this for the experiment, but it's good for pretesting.
+ """
+ randomnumber = random.sample(list(range(1, 6)), 5)
+ for p in self.get_players():
+ p.GroupRank = randomnumber[p.id_in_group - 1]
+
+ def effortGroupRank(self):
+ """
+ If Effort = 1, the individuals in the group are assigned IDs according to their effort.
+ This method is called by the intro-WaitPage.
+ """
+ if self.treatment_ec == 0:
+ all_group_effort_new = []
+ for p in self.get_players():
+ all_group_effort_new.append(p.Effort_points - (p.Minus_points * 0.0001) - (p.id_in_group * 0.000001))
+ rankgroupeffort = rankdata(all_group_effort_new)
+ else:
+ all_group_effort_new = []
+ for p in self.get_players():
+ if p.id_in_group != 1:
+ all_group_effort_new.append(
+ p.Effort_points - (p.Minus_points * 0.0001) - (p.id_in_group * 0.000001))
+ if p.id_in_group == 1:
+ all_group_effort_new.append(0)
+ rankgroupeffort = rankdata(all_group_effort_new)
+
+ for p in self.get_players():
+ p.GroupRank = int(rankgroupeffort[p.id_in_group - 1])
+
+ def P1_Define_StartToken(self):
+ if self.treatment_ec == 0:
+ for p in self.get_players():
+ # For specific positions
+ p.P1_StartToken = Constants.P1_StartToken_0[p.GroupRank - 1]
+ p.P1_StartTokenPT = Constants.P1_StartTokenPT_0[p.GroupRank - 1]
+ p.P1_Taxes = Constants.P1_Taxes_0[p.GroupRank - 1]
+ p.P1_TokenAddEqual = Constants.P1_TokenAdd_Equal[p.GroupRank - 1]
+ p.P1_TokenAddWeakerFirst = Constants.P1_TokenAddWeakerFirst_0[p.GroupRank - 1]
+ p.P1_TokenAddMixed = Constants.P1_TokenAddMixed_0[p.GroupRank - 1]
+ # For all
+ p.P1_SumRoundIncomeEqual = p.P1_StartToken + p.P1_TokenAddEqual
+ p.P1_SumRoundIncomeWeakerFirst = p.P1_StartToken + p.P1_TokenAddWeakerFirst
+ p.P1_SumRoundIncomeMixed = p.P1_StartToken + p.P1_TokenAddMixed
+ if self.treatment_ec == 1:
+ for p in self.get_players():
+ # For specific positions
+ p.P1_StartToken = Constants.P1_StartToken_9[p.GroupRank - 1]
+ p.P1_StartTokenPT = Constants.P1_StartTokenPT_9[p.GroupRank - 1]
+ p.P1_Taxes = Constants.P1_Taxes_9[p.GroupRank - 1]
+ p.P1_TokenAddEqual = Constants.P1_TokenAdd_Equal[p.GroupRank - 1]
+ p.P1_TokenAddWeakerFirst = Constants.P1_TokenAddWeakerFirst_9[p.GroupRank - 1]
+ p.P1_TokenAddMixed = Constants.P1_TokenAddMixed_9[p.GroupRank - 1]
+ # For all
+ p.P1_SumRoundIncomeEqual = p.P1_StartToken + p.P1_TokenAddEqual
+ p.P1_SumRoundIncomeWeakerFirst = p.P1_StartToken + p.P1_TokenAddWeakerFirst
+ p.P1_SumRoundIncomeMixed = p.P1_StartToken + p.P1_TokenAddMixed
+
+
+
+ def Nickname(self):
+ self.Channel_Ack = str(self.id_in_subsession) + "_Ack"
+ self.Channel_DisProcedure = str(self.id_in_subsession) + "_DisProc"
+ self.Channel_DisProcedureKorr = str(self.id_in_subsession) + "_DisProcKorr"
+ for p in self.get_players():
+ p.Nickname = "Player " + str(p.GroupRank)
+
+ #
+ #
+ def P1_calc_wealthD0(self): # Keine Grafiken, nur Zahlen
+ for p in self.get_players():
+ #
+ if (p.P1_StartTokenPT * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionNoDis = Constants.P1_Needs
+ p.P1_WealthNoDis_1R = p.P1_StartTokenPT - Constants.P1_Needs
+ else:
+ p.P1_ConsumptionNoDis = p.P1_StartTokenPT * 0.9
+ p.P1_WealthNoDis_1R = p.P1_StartTokenPT * 0.1
+ p.P1_WealthNoDis_5R = p.P1_WealthNoDis_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddEqual) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionEqual = Constants.P1_Needs
+ p.P1_WealthEqual_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddEqual
+ else:
+ p.P1_ConsumptionEqual = (p.P1_StartToken + p.P1_TokenAddEqual) * 0.9
+ p.P1_WealthEqual_1R = (p.P1_StartToken + p.P1_TokenAddEqual) * 0.1
+ p.P1_WealthEqual_5R = p.P1_WealthEqual_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionWeakerFirst = Constants.P1_Needs
+ p.P1_WealthWeakerFirst_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddWeakerFirst
+ else:
+ p.P1_ConsumptionWeakerFirst = (p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.9
+ p.P1_WealthWeakerFirst_1R = (p.P1_StartToken + p.P1_TokenAddWeakerFirst) * 0.1
+ p.P1_WealthWeakerFirst_5R = p.P1_WealthWeakerFirst_1R * 5
+ #
+ #
+ if ((p.P1_StartToken + p.P1_TokenAddMixed) * 0.9) <= Constants.P1_Needs:
+ p.P1_ConsumptionMixed = Constants.P1_Needs
+ p.P1_WealthMixed_1R = p.P1_StartToken - Constants.P1_Needs + p.P1_TokenAddMixed
+ else:
+ p.P1_ConsumptionMixed = (p.P1_StartToken + p.P1_TokenAddMixed) * 0.9
+ p.P1_WealthMixed_1R = (p.P1_StartToken + p.P1_TokenAddMixed) * 0.1
+ p.P1_WealthMixed_5R = p.P1_WealthMixed_1R * 5
+ #
+
+
+ def P1_ResultsGraphEqual(self):
+ """ Wird in Pages - class P1_Rej_9_Rounds(Page) aufgerufen"""
+ series_Start_PT = []
+ series_Start = []
+ series_Taxes = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start_PT.append(p.P1_StartTokenPT)
+ series_Start.append(p.P1_StartToken)
+ series_Taxes.append(p.P1_Taxes)
+ series_TokenAdd.append(p.P1_TokenAddEqual)
+ cumulativedata = [0,
+ p.P1_WealthEqual_1R * 1,
+ p.P1_WealthEqual_1R * 2,
+ p.P1_WealthEqual_1R * 3,
+ p.P1_WealthEqual_1R * 4,
+ p.P1_WealthEqual_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthEqual_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddEqual)
+ return {
+ "series_StartToken_PT": series_Start_PT,
+ "StartToken": series_Start,
+ "Taxes": series_Taxes,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def P1_info3graph(self):
+ series = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ playerdata = [0,
+ p.P1_WealthNoDis_1R * 1,
+ p.P1_WealthNoDis_1R * 2,
+ p.P1_WealthNoDis_1R * 3,
+ p.P1_WealthNoDis_1R * 4,
+ p.P1_WealthNoDis_1R * 5]
+ series.append({
+ "name": p.GroupRank,
+ "data": playerdata})
+ series_highest_lowest.append(p.P1_WealthNoDis_5R)
+ return {
+ 'highcharts_series': series,
+ "MinValue": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue": self.MinMaxGraph(series_highest_lowest)[1]
+ }
+
+ def P1_ResultsGraphWeakerFirst(self):
+ """ Wird aufgerufen bei Acceptance - Weaker First"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAddWeakerFirst)
+ cumulativedata = [0,
+ p.P1_WealthWeakerFirst_1R * 1,
+ p.P1_WealthWeakerFirst_1R * 2,
+ p.P1_WealthWeakerFirst_1R * 3,
+ p.P1_WealthWeakerFirst_1R * 4,
+ p.P1_WealthWeakerFirst_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthWeakerFirst_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddWeakerFirst)
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def P1_ResultsGraphMixed(self):
+ """ Wird aufgerufen bei Acceptance - Weaker First"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAddMixed)
+ cumulativedata = [0,
+ p.P1_WealthMixed_1R * 1,
+ p.P1_WealthMixed_1R * 2,
+ p.P1_WealthMixed_1R * 3,
+ p.P1_WealthMixed_1R * 4,
+ p.P1_WealthMixed_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthMixed_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAddMixed)
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ #
+
+ # Wahlen
+ P1_NumElegibleToVoteForAck = models.IntegerField(initial=-99)
+ P1_NumElegibleToVoteNewDis = models.IntegerField(initial=-99)
+
+ def defineEligibleVoters(self):
+ if self.treatment_pol == 1:
+ self.P1_NumElegibleToVoteForAck = Constants.players_per_group
+ self.P1_NumElegibleToVoteNewDis = Constants.players_per_group
+ elif self.treatment_pol == 0:
+ self.P1_NumElegibleToVoteForAck = Constants.players_per_group - 1
+ self.P1_NumElegibleToVoteNewDis = Constants.players_per_group - 1
+ else:
+ print("Problem. Check defineEligibleVoters()")
+
+ P1_nGroupAnerkennung = models.IntegerField(initial=0)
+ P1_GroupAcknowledgement = models.IntegerField(initial=0)
+
+ def P1_AckResult(self):
+ self.P1_nGroupAnerkennung = 0
+ for p in self.get_players():
+ if p.P1_AckVote == 1:
+ self.P1_nGroupAnerkennung += 1
+ if self.P1_nGroupAnerkennung == self.P1_NumElegibleToVoteForAck:
+ self.P1_GroupAcknowledgement = 1
+ else:
+ self.P1_GroupAcknowledgement = 0
+
+ #
+ P1_CountGroup = models.IntegerField(
+ initial=0)
+ P1_CountGroup_Corr = models.IntegerField(
+ doc="in zTree: CountGroup2",
+ initial=0)
+ P1_NeueVerteilungErreicht = models.IntegerField(initial=0)
+ P1_NeueVerteilungErreicht_Corr = models.IntegerField(initial=0)
+
+ #
+ P1_TokenAdd_New_1 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_2 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_3 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_4 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_5 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_1 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_2 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_3 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_4 = models.FloatField(initial=-99)
+ P1_TokenAdd_New_Corr_5 = models.FloatField(initial=-99)
+
+ #
+
+ def abzahlen(self, Correction):
+ """
+ How many group members entered the same numbers?
+ Old function name in ztree: Countsame.
+ If this function is called after the Correction chat, enter "Corr" when calling the function.
+ """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ for p in self.get_players():
+ setattr(p, "P1_CountSame" + corr, 0)
+ for q in self.get_players():
+ if (vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(1)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(1)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(2)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(2)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(3)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(3)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(4)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(4)] and
+ vars(p)["P1_iTokenAddVoteFor" + corr + "_" + str(5)] == vars(q)[
+ "P1_iTokenAddVoteFor" + corr + "_" + str(5)]): \
+ setattr(p, "P1_CountSame" + corr, getattr(p, "P1_CountSame" + corr) + 1)
+
+ #
+ #
+ def abzahlengruppe(self, Correction):
+ """"Wie viele gleiche Zahleneingaben gibt es höchstens pro Gruppe? """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ setattr(self, "P1_CountGroup" + corr, 0)
+ for p in self.get_players():
+ if (getattr(p, "P1_CountSame" + corr) > (p.group.P1_NumElegibleToVoteNewDis / 2)):
+ setattr(self, "P1_CountGroup" + corr, getattr(self, "P1_CountGroup" + corr) + 1)
+
+ #
+ #
+
+ def NewDisVoteRes(self, Correction):
+ """
+ Prior name: P1_Wahlergebnis1
+ Wird in Pages --> P1_Rej_5_Chat_DistributionProcedure_2WP_After aufgerufen
+ """
+ corr = ""
+ if Correction == "Corr":
+ corr = "_" + "Corr"
+
+ for p in self.get_players():
+ if getattr(p, "P1_CountSame" + corr) > p.group.P1_NumElegibleToVoteNewDis / 2:
+ for i in range(1, 6):
+ setattr(self, "P1_TokenAdd_New" + corr + "_" + str(i),
+ getattr(p, "P1_iTokenAddVoteFor" + corr + "_" + str(i)))
+ break
+
+ if getattr(self, "P1_CountGroup" + corr) > self.P1_NumElegibleToVoteNewDis / 2:
+ setattr(self, "P1_NeueVerteilungErreicht" + corr, 1)
+ # Calculate Token Add
+ for p in self.get_players():
+ for i in range(1, 6):
+ if p.GroupRank == i:
+ p.P1_TokenAdd = getattr(self, "P1_TokenAdd_New" + corr + "_" + str(i))
+
+ # Calculate Roundincome after Tokenadd and Needs-Satisfaction
+ for p in self.get_players():
+ p.P1_SumRoundIncome = p.P1_StartToken + p.P1_TokenAdd
+ if p.P1_SumRoundIncome < Constants.P1_Needs:
+ p.P1_ConsumptionFinal = Constants.P1_Needs
+ p.P1_WealthNewDis_1R = p.P1_SumRoundIncome - Constants.P1_Needs
+ else:
+ p.P1_ConsumptionFinal = p.P1_SumRoundIncome * 0.9
+ p.P1_WealthNewDis_1R = p.P1_SumRoundIncome * 0.1
+ p.P1_WealthNewDis_5R = p.P1_WealthNewDis_1R * 5
+ else:
+ setattr(self, "P1_NeueVerteilungErreicht" + corr, 0)
+
+ #
+ #
+
+ #
+ #
+ #
+
+ P1_BVote_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_BVote_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_BVote_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_BVote_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_Rej_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_Rej_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_Rej_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_Rej_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_AVote_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_AVote_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_AVote_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_AVote_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+
+ P1_Acc_nArgAkz_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkz_5 = models.IntegerField(initial=-99)
+
+ P1_Acc_nArgAkzNo_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgAkzNo_5 = models.IntegerField(initial=-99)
+
+ P1_Acc_nArgBest_1 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_2 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_3 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_4 = models.IntegerField(initial=-99)
+ P1_Acc_nArgBest_5 = models.IntegerField(initial=-99)
+
+ #
+ #
+ def calcbestarg(self, argpart):
+ # argpart are either BVote,
+
+ #
+ group_acc_base = "P1_" + argpart + "_nArgAkz_"
+ group_accNo_base = "P1_" + argpart + "_nArgAkzNo_"
+ group_best_base = "P1_" + argpart + "_nArgBest_"
+
+ ind_acc_base = "P1_" + argpart + "_ArgAkz_"
+ ind_accNo_base = "P1_" + argpart + "_ArgAkzNo_"
+ ind_best_base = "P1_" + argpart + "_ArgBest_"
+ for i in range(1, 6):
+ group_acc_mod = group_acc_base + str(i)
+ group_accNo_mod = group_accNo_base + str(i)
+ group_best_mod = group_best_base + str(i)
+ ind_acc_mod = ind_acc_base + str(i)
+ ind_accNo_mod = ind_accNo_base + str(i)
+ ind_best_mod = ind_best_base + str(i)
+
+ # Calculations
+ setattr(self, group_acc_mod,
+ sum((vars(p)[ind_acc_mod]) for p in self.get_players() if vars(p)[ind_acc_mod] >= 0))
+ setattr(self, group_accNo_mod, 5 - vars(self)[group_acc_mod])
+ setattr(self, group_best_mod, sum((vars(p)[ind_best_mod]) for p in self.get_players()))
+
+ #
+ #
+ listofbest = [] # Für übersicht
+ for p in self.get_players():
+ setattr(p, "P1_" + argpart + "_nArgBest", vars(self)[group_best_base + str(p.GroupRank)])
+ listofbest.append(vars(p)["P1_" + argpart + "_nArgBest"])
+ # Winners
+ P1_Winners = [i for i, j in enumerate(listofbest) if j == max(listofbest)]
+ #
+ # Falls Gewinner/in
+ for p in self.get_players():
+ if (p.GroupRank - 1) in P1_Winners and len(P1_Winners) <= 2: # There are max 2 winners.
+ setattr(p, "P1_" + argpart + "_ArgBest", 1)
+ setattr(p, "P1_" + argpart + "_ArgToken", Constants.P1_BVote_ArgBestToken)
+ if len(P1_Winners) == 1:
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 1)
+ else:
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 2)
+ # Falls Nicht-Gewinner/in:
+ else:
+ setattr(p, "P1_" + argpart + "_ArgBest", 0)
+ setattr(p, "P1_" + argpart + "_ArgToken", 0)
+ setattr(p, "P1_" + argpart + "_ArgBestSingle", 0)
+
+ #
+
+ #
+
+ def P1_ResultsGraph(self):
+ """ Wird in Pages - class P1_Rej_9_Rounds(Page) aufgerufen"""
+ series_Start = []
+ series_TokenAdd = []
+ series_Income = []
+ series_Cumulative = []
+ series_highest_lowest = []
+ for p in self.get_players():
+ series_Start.append(p.P1_StartToken)
+ series_TokenAdd.append(p.P1_TokenAdd)
+ cumulativedata = [0,
+ p.P1_WealthNewDis_1R * 1,
+ p.P1_WealthNewDis_1R * 2,
+ p.P1_WealthNewDis_1R * 3,
+ p.P1_WealthNewDis_1R * 4,
+ p.P1_WealthNewDis_1R * 5
+ ]
+ series_Cumulative.append({
+ "name": p.GroupRank,
+ "data": cumulativedata})
+ series_highest_lowest.append(p.P1_WealthNewDis_1R * 5)
+ series_Income.append(p.P1_StartToken + p.P1_TokenAdd)
+
+ return {
+ "StartToken": series_Start,
+ "TokenAdd": series_TokenAdd,
+ "Cumulative": series_Cumulative,
+ "MinValue_B": self.MinMaxGraph(series_highest_lowest)[0],
+ "MaxValue_B": self.MinMaxGraph(series_highest_lowest)[1],
+ "MinValue_A": 0,
+ "MaxValue_A": self.MinMaxGraph(series_Income)[1],
+ }
+
+ def MinMaxGraph(self, list=[]):
+ if min(list) >= 0:
+ minlist = -5
+ maxlist = max(list) + 3
+ else:
+ minlist = min(list) - 5
+ maxlist = max(list) + 3
+ return minlist, maxlist
+
+
+class Player(BasePlayer):
+ Politically_Excluded = models.IntegerField(initial=-99, doc="Excluded from deliberation")
+ Economically_Excluded = models.IntegerField(initial=-99, doc="Excluded from effort tak")
+ GroupRank = models.IntegerField(initial=-99, doc="Rank in group")
+
+ #
+ P1_BVote_nArgBest = models.IntegerField(initial=-99, doc="Number of votes for best vote")
+ P1_BVote_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_BVote_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_BVote_ArgBestSingle = models.IntegerField(initial=-99)
+ #
+
+ Effort_points = models.FloatField(initial=-99)
+ Minus_points = models.FloatField(initial=-99)
+
+ # Start Token
+ P1_StartToken = models.FloatField(initial=-99, doc="StartToken after deduction of Taxes")
+ P1_StartTokenPT = models.FloatField(initial=-99, doc="StartToken pre Taxes; formally coded as StartTokenAlt")
+ P1_Taxes = models.FloatField(initial=-99, doc="Taxes to be deducted from StartTokenPT")
+ P1_ConsumptionFinal = models.FloatField(initial=-99,
+ doc="Final Consumption \= with TokenAdd as voted for by group")
+ P1_ConsumptionFinal2 = models.FloatField(initial=-99,
+ doc="Final Consumption with TokenAdd as voted for by group")
+ # Final Payout
+ ProfitEuroUnround = models.FloatField(initial=-99)
+ ProfitEuroRound = models.FloatField(initial=-99)
+ ProfitToken = models.FloatField(initial=-99)
+ P1_FinalWealth_5R = models.FloatField(initial=-99)
+
+ # Suggested Distribution
+ #
+ P1_AckVote = models.IntegerField(
+ choices=[
+ [1, 'Das Verfahren x \= 1 soll anerkannt werden'],
+ [0, 'Das Verfahren y \= 2 soll nicht anerkannt werden'], ],
+ doc="Former variable name: iAnerkennungVerfahren",
+ widget=widgets.RadioSelect,
+ )
+ #
+ #
+
+ P1_TokenAddEqual = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by Experimenter")
+ P1_TokenAddWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by WeakerFirst")
+ P1_TokenAddMixed = models.FloatField(
+ initial=-99,
+ doc="TokenAdd as suggested by Mixed")
+ P1_ConsumptionNoDis = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption no Redistribution")
+ P1_ConsumptionEqual = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption with TokenAdd as suggested by Experimenter")
+ P1_ConsumptionWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption with TokenAdd as suggested by Weaker First")
+ P1_ConsumptionMixed = models.FloatField(
+ initial=-99,
+ doc="Initial Consumption with TokenAdd as suggested by Mixed")
+ P1_SumRoundIncomeEqual = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Experimenter")
+ P1_SumRoundIncomeWeakerFirst = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Weaker First")
+ P1_SumRoundIncomeMixed = models.FloatField(
+ initial=-99,
+ doc="Total Income Token minus Taxes but with TokenAdd as suggested by Mixed")
+
+ P1_WealthNoDis_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - No Redistribution")
+ P1_WealthNoDis_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - No Redistribution")
+
+ P1_WealthEqual_1R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthEqual_5R = models.FloatField(
+ initial=-99,
+ doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthWeakerFirst_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthWeakerFirst_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+
+ P1_WealthMixed_1R = models.FloatField(initial=-99, doc="Wealth for 1 Round - Suggested Distribution")
+ P1_WealthMixed_5R = models.FloatField(initial=-99, doc="Wealth for 5 Rounds - Suggested Distribution")
+ #
+
+ # New Distribution
+ P1_TokenAdd = models.FloatField(initial=-99, doc="Chosen new Distribution - If suggested Distribution was rejected")
+ # Wahl für neue Verteilungen bei Rejection
+ #
+ P1_iTokenAddVoteFor_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_6 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+
+ #
+ #
+ P1_iTokenAddVoteFor_Corr_1 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_2 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_3 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_4 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ P1_iTokenAddVoteFor_Corr_5 = models.FloatField(
+ # initial=0,
+ min=0,
+ max=Constants.P1_GesamtZusatzToken)
+ #
+ #
+ P1_CountSame = models.IntegerField(initial=-99)
+ P1_CountSame_Corr = models.IntegerField(
+ doc="CountSame2 in zTree",
+ initial=-99)
+ P1_CountGroup = models.IntegerField(initial=-99)
+
+ #
+ #
+ P1_WealthNewDis_1R = models.FloatField(initial=-99)
+ P1_WealthNewDis_5R = models.FloatField(initial=-99)
+ # 1 R
+ #
+ # Before Voting
+ #
+ P1_BVote_YesNo = models.IntegerField(
+ choices=[
+ [1, 'Ich erkenne das Verteilungsverfahren der zusätzlichen Token an'],
+ [0, 'Ich erkenne das Verteilungsverfahren der zusätzlichen Token nicht an'], ],
+ doc="Former variable name: P1_AnerkennungPrivat",
+ initial=-99,
+ widget=widgets.RadioSelect
+ )
+ P1_BVote_YesNoString = models.TextField()
+
+ P1_YesNoArg_BVote = models.TextField(
+ label="",
+ max_length=250,
+ doc="Argument for Acceptance/Rejection of the suggested distribution. Former variable name: Argument"
+ # blank=True #das wird dann später im javascript aufgehoben
+ )
+ #
+ #
+ P1_BVote_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_BVote_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_BVote_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_BVote_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+
+ # After Voting
+ P1_AVote_AckArg = models.TextField(
+ label="",
+ max_length=250,
+ )
+ #
+ P1_AVote_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_AVote_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_AVote_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_AVote_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_AVote_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_AVote_ArgBest = models.IntegerField(doc="Whether participant is one of the best-vote winners.")
+ P1_AVote_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_AVote_ArgBestSingle = models.IntegerField()
+
+ # #
+
+ # Argumente rejection
+ #
+ P1_iTokenAddSuggestion_1 = models.FloatField(
+ # label="Player 1 (" + str(format(Constants.P1_StartToken_0[1-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_2 = models.FloatField(
+ # label="Player 2 (" + str(format(Constants.P1_StartToken_0[2-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_3 = models.FloatField(
+ # label="Player 3 (" + str(format(Constants.P1_StartToken_0[3-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_4 = models.FloatField(
+ # label="Player 4 (" + str(format(Constants.P1_StartToken_0[4-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_iTokenAddSuggestion_5 = models.FloatField(
+ # label="Player 5 (" + str(format(Constants.P1_StartToken_0[5-1], '.0f')) + "Token)",
+ min=0, max=Constants.P1_GesamtZusatzToken,
+ )
+ P1_Rej_Arg = models.TextField(
+ label="",
+ max_length=250,
+ # blank=True #das wird dann später im javascript aufgehoben
+ )
+ #
+ #
+ P1_Rej_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Rej_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_Rej_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_Rej_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_Rej_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Rej_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Rej_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Rej_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+
+ #
+ # Argumente Acceptance
+ P1_Acc_DistributionChange = models.IntegerField(
+ choices=[
+ [1, 'Ich hätte mich dennoch für Verfahren >Gleichverteilung< entschieden.'],
+ [2, 'Ich hätte mich für das alternative Verfahren >Angleichen von unten< entschieden.'],
+ [3,
+ "Ich hätte mich für das alternative Verfahren >Verteilung gemäß Ausgangseinkommen mit Berücksichtigung des Mindestkonsums< entschieden."]
+ ],
+ doc="Former variable name: P1_AnerkennungPrivat",
+ initial=-99,
+ widget=widgets.RadioSelect)
+ P1_Acc_Arg = models.TextField(
+ label="",
+ max_length=250, )
+ #
+ P1_Acc_ArgAkz_1 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_2 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_3 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ P1_Acc_ArgAkz_5 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+ #
+ #
+ P1_Acc_ArgBest_1 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_2 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_3 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_4 = models.BooleanField(blank=True, initial=False)
+ P1_Acc_ArgBest_5 = models.BooleanField(blank=True, initial=False)
+ #
+ #
+ P1_Acc_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Acc_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Acc_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Acc_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+ #
+ #
+
+ P1_SumRoundIncome = models.FloatField(initial=-99)
+
+ # Hilfsvariablen
+ P1_ChatDisProStart = models.BigIntegerField(initial=-99)
+ P1_ChatDisProStartKorr = models.BigIntegerField(initial=-99)
+ P1_AVote_ChatStart = models.BigIntegerField(initial=-99)
+ P1_AVote_ChatStartKorr = models.BigIntegerField(initial=-99)
+ Nickname = models.TextField(initial=-99)
+
+ #
+
+ #
+
+ def roundupto50(self, number):
+ if math.fmod(number, 0.5) != 0:
+ return number + (0.5 - math.fmod(number, 0.5))
+ else:
+ return number
+
+
+ work_hours = models.IntegerField(
+ label="Wieviele Stunden arbeiten Sie neben des Studiums pro Woche?",
+ choices=[
+ [1, "0 Stunden "],
+ [2, "1-10 Stunden"],
+ [3, "11-20 Stunden"],
+ [4, "21-30 Stunden"],
+ [5, "31 Stunden oder mehr"],
+
+ ]
+ )
+ money_in_month = models.IntegerField(
+ label="Wie viel Geld steht Ihnen im Monat zur Verfügung (in Euro)?",
+ choices=[
+ [1, "0-399"],
+ [2, "400-699"],
+ [3, "700-999"],
+ [4, "1000 oder mehr"],
+
+ ]
+ )
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_f5/MIG1/models.py b/tests/testthat/testdata/ocode_f5/MIG1/models.py
new file mode 100644
index 0000000..aac8c27
--- /dev/null
+++ b/tests/testthat/testdata/ocode_f5/MIG1/models.py
@@ -0,0 +1,107 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+from scipy.stats import rankdata
+import math
+
+
+author = 'Patricia Zauchner'
+
+doc = """
+Migration Game.
+Run only on Chrome. Never on IE!
+In IE, the dialogue windows won't work.
+"""
+
+class Constants(BaseConstants):
+ name_in_url = 'MIG1'
+ players_per_group = 5
+ num_rounds = 1 # Wie oft das Experiment durchläuft
+ ShowUpFeeEuro = 12
+ ExchangeEuro = 1
+ ExchangeToken = 1
+ ExchangeRate = ExchangeToken / ExchangeEuro
+
+ ShowUpFeeToken = ShowUpFeeEuro * ExchangeRate
+ P1_Needs = 16 # Formerly known as "Bedarf".
+ UsualConsumption = 0.9 # 90% of the income will be consumed
+ Rounds = 5
+ time_for_args = 0.2
+ time_for_argsSek = time_for_args * 60
+ #
+ P1_GesamtZusatzToken = 30
+ P1_TokenAdd_Equal = [30 / 5, 30 / 5, 30 / 5, 30 / 5, 30 / 5] # Zusatztoken bei Gleichverteilung
+ #
+ P1_StartToken_0 = [0, 14, 19, 26, 41] # StartToken --> Netto After Taxes
+ P1_Taxes_0 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_0 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_0.append(P1_StartToken_0[i] + P1_Taxes_0[i])
+ P1_TokenAddWeakerFirst_0 = [21, 7, 2, 0, 0]
+ P1_TokenAddMixed_0 = [16, 2, 3, 4, 5] # so besprochen am 31.3.
+
+ #
+ #
+ P1_StartToken_9 = [9, 14, 19, 26, 41]
+ P1_Taxes_9 = [0, 1, 5, 9, 15]
+ P1_StartTokenPT_9 = [] # StartToken --> Brutto Pretaxes
+ for i in range(0, 5):
+ P1_StartTokenPT_9.append(P1_StartToken_9[i] + P1_Taxes_9[i])
+ P1_TokenAddWeakerFirst_9 = [11, 6, 3, 0, 0]
+ P1_TokenAddMixed_9 = [6.5, 1.5, 1, 4, 7]
+
+ #
+ #
+ #
+ ArgCharMax = 250
+ P1_Rej_ArgBestToken = 2
+ P1_BVote_ArgBestToken = 2
+ P1_AVote_ArgBestToken = 2
+ P1_Acc_ArgBestToken = 2
+ #
+ #
+ ChatTime_Ack = 6 # Todo: Check if time is correct. Should be 6 minutes.
+ ChatTime_Ack_Sec = ChatTime_Ack * 60
+ ChatTime_Distribution = 5 # Formerly known as ChatTime_Verteilung #Todo: Check if time is correct. Should be 5 minutes.
+ ChatTime_DistributionCorr = 1 # Formerly known as ChatTime_VerteilungKorr #Todo: Check if time is correct. Should be 1 minute.
+ ChatTime_DistributionCorrSek = ChatTime_DistributionCorr * 60 # Formerly known as ChatTime_VerteilungKorrSek
+ #
+
+ MinArgumentLength = 10
+ MaxArgumentLength = 250
+
+ # Grafiken
+ TickInterval = 5
+ LineWidth = 5
+ ArgumentChatHeight = 600
+
+
+class Session:
+ pass
+
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+class Player(BasePlayer):
+ user_total = models.IntegerField(
+ min = 1,
+ max = 9999,
+ doc="user's summation",
+ widget=widgets.TextInput(attrs='autocomplete':'off'}))
+
+ #
+ P1_Acc_nArgBest = models.IntegerField(doc="Number of votes for best vote")
+ P1_Acc_ArgBest = models.IntegerField(initial=-99, doc="Whether participant is one of the best-vote winners.")
+ P1_Acc_ArgToken = models.IntegerField(initial=0, doc="Token für the argument.")
+ P1_Acc_ArgBestSingle = models.IntegerField(initial=-99)
+
+ # #
+ #
+ #
+
+ P1_SumRoundIncome = models.FloatField(initial=-99)
diff --git a/tests/testthat/testdata/ocode_g/effort_add/Task.html b/tests/testthat/testdata/ocode_g/effort_add/Task.html
index 057d615..bb778d8 100644
--- a/tests/testthat/testdata/ocode_g/effort_add/Task.html
+++ b/tests/testthat/testdata/ocode_g/effort_add/Task.html
@@ -36,7 +36,6 @@
// Correct last answer
let last_answer_correct = {{ player.last_answer_correct|json }};
- // TODO ist ja jetzt nicht mehr null. Deswgen lieber mit index oder rundeninfo arbeiten
if (last_answer_correct !== null) {
showFeedback(last_answer_correct, {{ player.number_of_attempts|json }});
}
diff --git a/tests/testthat/testdata/ocode_g/effort_add/__init__.py b/tests/testthat/testdata/ocode_g/effort_add/__init__.py
index 6232a7a..2fb8cda 100644
--- a/tests/testthat/testdata/ocode_g/effort_add/__init__.py
+++ b/tests/testthat/testdata/ocode_g/effort_add/__init__.py
@@ -113,8 +113,7 @@ class Player(BasePlayer):
last_answer_correct = models.BooleanField(
doc="Did the user answer the last question correctly?",
- initial=False) # TODO: Die Variable scheint in den Daten nicht auf.
-
+ initial=False)
class Answer(ExtraModel):
""" Creates an extra dataframe output. Is called with custom_export """
diff --git a/tests/testthat/testdata/ocode_g/effort_add/tests.py b/tests/testthat/testdata/ocode_g/effort_add/tests.py
index ad4a1fe..3b7536c 100644
--- a/tests/testthat/testdata/ocode_g/effort_add/tests.py
+++ b/tests/testthat/testdata/ocode_g/effort_add/tests.py
@@ -9,9 +9,6 @@ def play_round(self):
# Intro
time.sleep(2) # Sleep for x seconds
yield Intro
-
- # TODO: Find way to properly test live-pages with bots
-
# Task
# while not self.player.final_round:
# if self.round_number == 1:
diff --git a/tests/testthat/testdata/ocode_new/bargaining/__init__.py b/tests/testthat/testdata/ocode_new/bargaining/__init__.py
index a41f451..bc360e9 100644
--- a/tests/testthat/testdata/ocode_new/bargaining/__init__.py
+++ b/tests/testthat/testdata/ocode_new/bargaining/__init__.py
@@ -36,11 +36,12 @@ class Player(BasePlayer):
label="Please enter an amount from 0 to 100",
)
level2 = models.IntegerField(
- choices=["No\, I won't", "yes\, I will", "Maybe I'll do"], # TODO choices were changed to test the code
+ choices=["No\, I won't", "yes\, I will", "Maybe I'll do"],
)
level3 = models.IntegerField(max = 10)
-
+
level = models.IntegerField(
+ doc = "choices with only [1,2,3]",
choices=[1,2,3]
)
diff --git a/tests/testthat/testdata/ocode_new/dictator/__init__.py b/tests/testthat/testdata/ocode_new/dictator/__init__.py
index 5d6274f..77fe9d5 100644
--- a/tests/testthat/testdata/ocode_new/dictator/__init__.py
+++ b/tests/testthat/testdata/ocode_new/dictator/__init__.py
@@ -34,8 +34,12 @@ class Group(BaseGroup):
class Player(BasePlayer):
- pass
-
+ gender = models.IntegerField(doc = "Gender")
+ print("test this")
+
+ chandler = models.IntegerField(doc = "Chandler")
+
+ print("test another thing")
# FUNCTIONS
def set_payoffs(group: Group):
@@ -80,4 +84,4 @@ def vars_for_template(player: Player):
and the assumptions of economics." Journal of business (1986):
S285-S300.
-This code was adjusted to be used by gmotree to make it a bit more messy """
\ No newline at end of file
+This code was adjusted to be used by gmotree to make it a bit more messy """
diff --git a/tests/testthat/testdata/ocode_z/rankaversion/models.py b/tests/testthat/testdata/ocode_z/rankaversion/models.py
index 750faee..dd91199 100644
--- a/tests/testthat/testdata/ocode_z/rankaversion/models.py
+++ b/tests/testthat/testdata/ocode_z/rankaversion/models.py
@@ -164,8 +164,6 @@ def creating_session(self):
random.shuffle(listofpart)
# Select data and set it to a variable
- # TODO: Caution. If there is a warning message "single positional indexer is out-of-bounds",
- # TODO: then the number of participants is higher than the cases in the csv!
for p in self.get_players():
#
diff --git a/tests/testthat/testdata/ocode_z/rankaversion/pages.py b/tests/testthat/testdata/ocode_z/rankaversion/pages.py
index ca2a63f..bd7612d 100644
--- a/tests/testthat/testdata/ocode_z/rankaversion/pages.py
+++ b/tests/testthat/testdata/ocode_z/rankaversion/pages.py
@@ -101,7 +101,6 @@ def before_next_page(self):
#
-# Todo: Delete html and all of it at last
class TaskForPresentationReasons(Page):
# Type 1
diff --git a/tests/testthat/testdata/ocode_z/rankend/pages.py b/tests/testthat/testdata/ocode_z/rankend/pages.py
index a2bea5a..92b5b8c 100644
--- a/tests/testthat/testdata/ocode_z/rankend/pages.py
+++ b/tests/testthat/testdata/ocode_z/rankend/pages.py
@@ -76,9 +76,8 @@ def is_displayed(self):
def vars_for_template(self):
self.player.motivation = "Player is not dictator and must not answer this question."
- # Todo: Change if there is an open question
- # # todo hier weitermachen
+ #
# Pretest
if "assignedRole" not in self.participant.vars: # if not already assigned in the prior app (pretest)
listofpart = [x for x in range(0, self.session.num_participants, 1)]
diff --git a/tests/testthat/testdata/ocode_z/settings.py b/tests/testthat/testdata/ocode_z/settings.py
index 3adaeed..5b53799 100644
--- a/tests/testthat/testdata/ocode_z/settings.py
+++ b/tests/testthat/testdata/ocode_z/settings.py
@@ -29,7 +29,7 @@
ADMIN_USERNAME = 'admin'
# ADMIN_PASSWORD = "admin"
-ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD') # Todo: Change Password
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
SESSION_CONFIG_DEFAULTS = {
@@ -82,4 +82,4 @@
]
POINTS_DECIMAL_PLACES = 2
-REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
\ No newline at end of file
+REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_z10/rankaversion/models.py b/tests/testthat/testdata/ocode_z10/rankaversion/models.py
new file mode 100644
index 0000000..69f844f
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z10/rankaversion/models.py
@@ -0,0 +1,29 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+
+doc = """
+Example code just for testing gmoTree.
+"""
+
+
+class Constants(BaseConstants):
+ Something = [
+ [["List1.1", 1], ["List1.2"]],
+ [["List2.1", 4], ["List2.2"]],
+ ]
+
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+
+class Player(BasePlayer):
+ pass
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z11/rankaversion/models.py b/tests/testthat/testdata/ocode_z11/rankaversion/models.py
new file mode 100644
index 0000000..cdfd97e
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z11/rankaversion/models.py
@@ -0,0 +1,25 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+
+doc = """
+Example code just for testing gmoTree.
+"""
+
+
+class Constants(BaseConstants):
+ Something = settings.Something
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+
+class Player(BasePlayer):
+ pass
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z11/settings.py b/tests/testthat/testdata/ocode_z11/settings.py
new file mode 100644
index 0000000..014bb94
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z11/settings.py
@@ -0,0 +1,41 @@
+from os import environ
+
+# Use Cloudresearch workerId as participant_label:
+EXTENSION_APPS = ["cloudcapturer"] # To redirect cloudresearch WorkerId to participant_label
+
+#
+Something = [
+ [["List1.1", 1], ["List1.2"]],
+ [["List2.1", 4], ["List2.2"]],
+]
+
+#
+
+# LANGUAGE_CODE = 'en' # ISO-639 code # for example: de, fr, ja, ko, zh-hans
+# USE_POINTS = False
+
+# ADMIN_USERNAME = 'admin'
+# ADMIN_PASSWORD = "admin"
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
+
+
+SESSION_CONFIGS = [
+ {
+ "name": "rankendothers",
+ "display_name": "rankend others",
+ "num_demo_participants": 9,
+ 'dictator': 0,
+ "app_sequence": [
+ "rankend",
+ "dismiss"
+ ]
+ }
+ #
+]
+
+# if an app is included in SESSION_CONFIGS, you don't need to list it here
+INSTALLED_APPS = ['otree'
+ ]
+
+# POINTS_DECIMAL_PLACES = 2
+# REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_z13/rankaversion/models.py b/tests/testthat/testdata/ocode_z13/rankaversion/models.py
new file mode 100644
index 0000000..4acb03a
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z13/rankaversion/models.py
@@ -0,0 +1,29 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+
+doc = """
+Example code just for testing gmoTree.
+"""
+
+
+class Constants(BaseConstants):
+ Something = "[[information]"
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+
+class Player(BasePlayer):
+ gender = models.IntegerField(doc = "[[Gender]")
+
+ variable = models.IntegerField(doc = "(A doc in brackets))")
+
+ variable2 = models.IntegerField(doc = "A doc with one closing bracket)")
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z2/rankaversion/models.py b/tests/testthat/testdata/ocode_z2/rankaversion/models.py
index ee83d1e..e684a82 100644
--- a/tests/testthat/testdata/ocode_z2/rankaversion/models.py
+++ b/tests/testthat/testdata/ocode_z2/rankaversion/models.py
@@ -9,16 +9,19 @@
doc = """
Redistribution Game. Third party dictator game varying needs and ranks.
+Major changes to test gmoTree package.
"""
class Constants(BaseConstants):
name_in_url = 'part_1'
errorvariable = settings.error
+ error2 = settings.error2
players_per_group = None
MinutesForSurvey = settings.MinutesForSurvey # Part 2
timer123 = settings.timer123
min_argumentsize = 25
+
max_argumentsize = 300
#
# Payoff Structure
@@ -33,29 +36,43 @@ class Constants(BaseConstants):
maxtrickfalse = 2
#
+ fakevar1 = 1
+ fakevar2 = 1
+ fakevar3 = 1
+ fakevar4 = 1
+ fakevar5 = 1
+ fakevar6 = 1
+ fakevar7 = 1
+ fakevar8 = 1
+ fakevar9 = 1
+ fakevar11 = 1
+ fakevar12 = 1
+ fakevar13 = 1
+ fakevar14 = 1
+
choices = [
# Order: Endowment Richer, Endowment Poorer, Transfer, Threshold,f Type, Result Richer, Result Poorer
# RR = rank reversal, noRR = no rank reversal
- [4, 1, 2, 0.5, "RR_needSat", 2, 3],
- [5, 1, 3, 0.5, "RR_needSat", 2, 4],
- [5, 2, 2, 1.5, "RR_needSat", 3, 4],
- [6, 2, 3, 1.5, "RR_needSat", 3, 5],
- [6, 3, 2, 2.5, "RR_needSat", 4, 5],
- [7, 1, 4, 0.5, "RR_needSat", 3, 5],
- [7, 3, 3, 2.5, "RR_needSat", 4, 6],
- [7, 4, 2, 3.5, "RR_needSat", 5, 6],
- [8, 1, 4, 0.5, "RR_needSat", 4, 5],
- [8, 2, 4, 1.5, "RR_needSat", 4, 6],
- [8, 4, 3, 3.5, "RR_needSat", 5, 7],
- [8, 5, 2, 4.5, "RR_needSat", 6, 7],
- [9, 2, 4, 1.5, "RR_needSat", 5, 6],
- [9, 5, 3, 4.5, "RR_needSat", 6, 8],
- [9, 6, 2, 5.5, "RR_needSat", 7, 8],
- [10, 1, 5, 0.5, "RR_needSat", 5, 6],
- [10, 3, 4, 2.5, "RR_needSat", 6, 7],
- [10, 4, 4, 3.5, "RR_needSat", 6, 8],
- [10, 6, 3, 5.5, "RR_needSat", 7, 9],
- [11, 2, 5, 1.5, "RR_needSat", 6, 7],
+ # [4, 1, 2, 0.5, "RR_needSat", 2, 3],
+ # [5, 1, 3, 0.5, "RR_needSat", 2, 4],
+ # [5, 2, 2, 1.5, "RR_needSat", 3, 4],
+ # [6, 2, 3, 1.5, "RR_needSat", 3, 5],
+ # [6, 3, 2, 2.5, "RR_needSat", 4, 5],
+ # [7, 1, 4, 0.5, "RR_needSat", 3, 5],
+ # [7, 3, 3, 2.5, "RR_needSat", 4, 6],
+ # [7, 4, 2, 3.5, "RR_needSat", 5, 6],
+ # [8, 1, 4, 0.5, "RR_needSat", 4, 5],
+ # [8, 2, 4, 1.5, "RR_needSat", 4, 6],
+ # [8, 4, 3, 3.5, "RR_needSat", 5, 7],
+ # [8, 5, 2, 4.5, "RR_needSat", 6, 7],
+ # [9, 2, 4, 1.5, "RR_needSat", 5, 6],
+ # [9, 5, 3, 4.5, "RR_needSat", 6, 8],
+ # [9, 6, 2, 5.5, "RR_needSat", 7, 8],
+ # [10, 1, 5, 0.5, "RR_needSat", 5, 6],
+ # [10, 3, 4, 2.5, "RR_needSat", 6, 7],
+ # [10, 4, 4, 3.5, "RR_needSat", 6, 8],
+ # [10, 6, 3, 5.5, "RR_needSat", 7, 9],
+ # [11, 2, 5, 1.5, "RR_needSat", 6, 7],
# Type 2 no needs
[4, 1, 1, 0.5, "noRR_needSat", 3, 2],
[5, 1, 1, 0.5, "noRR_needSat", 4, 2],
@@ -123,20 +140,83 @@ class Constants(BaseConstants):
# Order: Endowment Richer, Endowment Poorer, Transfer, Threshold, Type, Result Richer, Result Poorer
[7, 4, 2, 4.5, "Trick1", None, None],
[10, 4, 2, 4.5, "Trick2", None, None],
- [4, 1, 1, 1.5, "Trick1", None, None],
+ [4, 1+10, 1, 1.5, "Trick1", None, None],
[5, 2, 2, 1.5, "Trick2", None, None]
]
num_choices = len(choices) # All possible choices
+ max_choices = max(choices)
+ min_choices = min(choices)
#
# print("choices per type 1: ", num_choicesperrr, " and choices per type 2: ",num_choicespernorr)
num_choicetypes = 4 # Maximum value. Correct value is defined in subsession.
+ P1_iTokenAddVoteFor_6 = 999
+ P1_GesamtZusatzToken = 14
+
num_choicespertype = 20 # Maximum value = 20. Correct value is defined in subsession.
num_trickquestions = 4 # Number of attention checks
num_choicetotal = num_choicetypes * num_choicespertype + num_trickquestions
num_rounds = num_choicetotal # Number of questions. Must be a multiple of 4 + trick questions
assignmentdf = pd.read_csv("rankend/assignment.csv")
+
+ onelevelvectorl = ["a", "b", 3]
+ onelevelvectorl2 = ["a", "b", 3, "asdfadsf", "adsfadsfasdf", "00asasdf", 2342, "wqerwerqewr"]
+ onelevelvectorn = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
+
+ spaceaftercomma = [
+ [2004, 43, 5],
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77]]
+
+
+ commentaftercomma = [
+ [2004, 43, 5], # Comment
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77]]
+
+
+ spacebeforebracket = [
+ [2004, 43, 5],
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77]]
+
+
+ spaceafterbracket = [
+ [69, 43, 5],
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77] ]
+
+ commentafterbracket = [ # Comment
+ [69, 43, 5],
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77]]
+
+ samerowbracke = [
+ [69, 43, 5],
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77]]
+
+ nextrowbracket = [
+ [69, 43, 5],
+ [81, 91, 81],
+ [18, 63, 67],
+ [45, 56, 75],
+ [3, 84, 77]
+ ]
+
class Subsession(BaseSubsession):
@@ -162,8 +242,6 @@ def creating_session(self):
random.shuffle(listofpart)
# Select data and set it to a variable
- # TODO: Caution. If there is a warning message "single positional indexer is out-of-bounds",
- # TODO: then the number of participants is higher than the cases in the csv!
for p in self.get_players():
#
@@ -256,6 +334,19 @@ class Group(BaseGroup):
class Player(BasePlayer):
+ leftright = models.IntegerField(
+ doc= " ",
+ label=" ",
+ choices=[
+ [1, "Left"],
+ [2, ""],
+ [3, ""],
+ [4, ""],
+ [5, "Right"]
+ ],
+ widget=widgets.RadioSelect,
+ )
+
# User-Entries:
acceptance = models.IntegerField(
doc="Did the dictator accept the suggested transfer?",
@@ -278,6 +369,12 @@ class Player(BasePlayer):
[0, "B is the richer person"],
],
)
+
+ testempty = models.IntegerField(
+ doc="""This is an example doc""",
+ )
+
+
is_trick = models.IntegerField(
doc="""Is this question a trick question?""",
@@ -287,6 +384,7 @@ class Player(BasePlayer):
[2, "Answer No trick"]]
)
+
endowmentA = models.FloatField(doc="The initial endowment of Person A")
endowmentB = models.FloatField(doc="The initial endowment of the poorer person")
transfer = models.FloatField(doc="Transfer from richer person to poorer person")
diff --git a/tests/testthat/testdata/ocode_z2/rankaversion/pages.py b/tests/testthat/testdata/ocode_z2/rankaversion/pages.py
index ca2a63f..bd7612d 100644
--- a/tests/testthat/testdata/ocode_z2/rankaversion/pages.py
+++ b/tests/testthat/testdata/ocode_z2/rankaversion/pages.py
@@ -101,7 +101,6 @@ def before_next_page(self):
#
-# Todo: Delete html and all of it at last
class TaskForPresentationReasons(Page):
# Type 1
diff --git a/tests/testthat/testdata/ocode_z2/rankend/models.py b/tests/testthat/testdata/ocode_z2/rankend/models.py
index 7959c41..2d8c2ee 100644
--- a/tests/testthat/testdata/ocode_z2/rankend/models.py
+++ b/tests/testthat/testdata/ocode_z2/rankend/models.py
@@ -22,6 +22,12 @@ class Constants(BaseConstants):
num_rounds = 1
min_argumentsize = 25
max_argumentsize = 300
+ thisisaveryveryveryverylongvariablename = 10
+ firstlastbr = "(firstlastbracketexample)"
+ emptylist = []
+ emptylist2 = [
+
+ ]
# Payoff Structure
payoffPart1_c = settings.payoffPart1_c # Token
@@ -32,6 +38,12 @@ class Constants(BaseConstants):
#
assignmentdf = pd.read_csv("rankend/assignment.csv")
+ Test1 = 1000
+ TestVector = [1,2+8,3,4,5]
+ TestVector2 = settings.TestVector2
+ TestVectorC = ["a", "b", 6]
+ TestVectorC2 = settings.TestVectorC2
+ Test2 = 2000
class Subsession(BaseSubsession):
@@ -71,6 +83,10 @@ class Player(BasePlayer):
doc="Player A and B: Needs threshold",
)
+ thisisaveryveryvery_verylong_variable_name = models.IntegerField(
+ doc = "Testtesttest"
+ )
+
ab_needs_met = models.IntegerField(
doc="Player A and B: Did the person reach the needs threshold?",
choices=[
diff --git a/tests/testthat/testdata/ocode_z2/rankend/pages.py b/tests/testthat/testdata/ocode_z2/rankend/pages.py
index a2bea5a..92b5b8c 100644
--- a/tests/testthat/testdata/ocode_z2/rankend/pages.py
+++ b/tests/testthat/testdata/ocode_z2/rankend/pages.py
@@ -76,9 +76,8 @@ def is_displayed(self):
def vars_for_template(self):
self.player.motivation = "Player is not dictator and must not answer this question."
- # Todo: Change if there is an open question
- # # todo hier weitermachen
+ #
# Pretest
if "assignedRole" not in self.participant.vars: # if not already assigned in the prior app (pretest)
listofpart = [x for x in range(0, self.session.num_participants, 1)]
diff --git a/tests/testthat/testdata/ocode_z2/settings.py b/tests/testthat/testdata/ocode_z2/settings.py
index 3adaeed..30870c2 100644
--- a/tests/testthat/testdata/ocode_z2/settings.py
+++ b/tests/testthat/testdata/ocode_z2/settings.py
@@ -22,6 +22,10 @@
max_payoffPart1_ab = "11.00" # Token
MainCurrencyForSurvey = 3 # Euro or Dollar for participating in the survey
payoff_survey = "{:.2f}".format(MainCurrencyForSurvey*ExchangeToken) # Token
+TestVector2 = [99,66,33]
+TestVectorC2 = ["d", "e", 4]
+error2 = "Error2insettings"
+
#
LANGUAGE_CODE = 'en' # ISO-639 code # for example: de, fr, ja, ko, zh-hans
@@ -29,7 +33,7 @@
ADMIN_USERNAME = 'admin'
# ADMIN_PASSWORD = "admin"
-ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD') # Todo: Change Password
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
SESSION_CONFIG_DEFAULTS = {
@@ -82,4 +86,4 @@
]
POINTS_DECIMAL_PLACES = 2
-REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
\ No newline at end of file
+REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_z3.1/rankaversion/pages.py b/tests/testthat/testdata/ocode_z3.1/rankaversion/pages.py
index ca2a63f..28a1041 100644
--- a/tests/testthat/testdata/ocode_z3.1/rankaversion/pages.py
+++ b/tests/testthat/testdata/ocode_z3.1/rankaversion/pages.py
@@ -100,8 +100,6 @@ def before_next_page(self):
self.participant.vars["needs_threshold_metB"] = 0
#
-
-# Todo: Delete html and all of it at last
class TaskForPresentationReasons(Page):
# Type 1
diff --git a/tests/testthat/testdata/ocode_z3/rankaversion/models.py b/tests/testthat/testdata/ocode_z3/rankaversion/models.py
index 3f5b362..f3b024b 100644
--- a/tests/testthat/testdata/ocode_z3/rankaversion/models.py
+++ b/tests/testthat/testdata/ocode_z3/rankaversion/models.py
@@ -14,6 +14,7 @@
class Constants(BaseConstants):
Testnumber = settings.Testnumber
StartToken = settings.StartToken
+ TestVector = [1,2+8,3,4,5]
StartToken2 = settings.StartToken * 2
StartToken3 = StartToken * 10
Something = settings.Something
@@ -63,4 +64,4 @@ class Player(BasePlayer):
widget=widgets.RadioSelect,
)
- choicenumber = models.IntegerField()
\ No newline at end of file
+ choicenumber = models.IntegerField()
diff --git a/tests/testthat/testdata/ocode_z3/rankaversion/pages.py b/tests/testthat/testdata/ocode_z3/rankaversion/pages.py
index ca2a63f..bd7612d 100644
--- a/tests/testthat/testdata/ocode_z3/rankaversion/pages.py
+++ b/tests/testthat/testdata/ocode_z3/rankaversion/pages.py
@@ -101,7 +101,6 @@ def before_next_page(self):
#
-# Todo: Delete html and all of it at last
class TaskForPresentationReasons(Page):
# Type 1
diff --git a/tests/testthat/testdata/ocode_z3/settings.py b/tests/testthat/testdata/ocode_z3/settings.py
index 472a1ba..0c7169c 100644
--- a/tests/testthat/testdata/ocode_z3/settings.py
+++ b/tests/testthat/testdata/ocode_z3/settings.py
@@ -17,7 +17,7 @@
# ADMIN_USERNAME = 'admin'
# ADMIN_PASSWORD = "admin"
-ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD') # Todo: Change Password
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
SESSION_CONFIGS = [
@@ -39,4 +39,4 @@
]
# POINTS_DECIMAL_PLACES = 2
-# REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
\ No newline at end of file
+# REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_z4/end/__init__.py b/tests/testthat/testdata/ocode_z4/end/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/testthat/testdata/ocode_z4/end/emergency.txt b/tests/testthat/testdata/ocode_z4/end/emergency.txt
new file mode 100644
index 0000000..cc33f0b
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z4/end/emergency.txt
@@ -0,0 +1,59 @@
+
+
+
+class Player(BasePlayer):
+ ConsumptionFinal = models.FloatField(
+ doc="Final consumption \= with TokenAdd as voted for by group as alternative distribution")
+
+ ConsumptionFinal2 = models.FloatField(
+ doc="Final consumption with TokenAdd as voted for by group as alternative distribution")
+
+
+ completionCode = models.StringField(
+ doc="Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are "
+ "legal problems with the participants"
+ )
+
+ # With spaces at end
+ completionCodespaces = models.StringField(
+ doc="Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are "
+ "legal problems with the participants"
+ )
+
+ Acc_DistributionChange = models.IntegerField(
+ choices=[
+ [1, 'Ich hätte mich dennoch für Verfahren >' +
+ C.TOKEN_ADD_1D_NAME + '< entschieden.'],
+ [2, 'Ich hätte mich für das alternative Verfahren >' +
+ C.TOKEN_ADD_2D_NAME + '< entschieden.'],
+ [3, 'Ich hätte mich für das alternative Verfahren >' +
+ C.TOKEN_ADD_2D_NAME + '< entschieden.']
+ ],
+ doc="Former variable name: AnerkennungPrivat",
+
+ widget=widgets.RadioSelect)
+
+ Acc_DistributionChange2 = models.IntegerField(
+ choices=[
+ [1, "Ich hätte mich dennoch für Verfahren >" +
+ C.TOKEN_ADD_1D_NAME + "< entschieden."],
+ [2, "Ich hätte mich für das alternative Verfahren >" +
+ C.TOKEN_ADD_2D_NAME + "< entschieden."],
+ [3, "Ich hätte mich für das alternative Verfahren >" +
+ C.TOKEN_ADD_2D_NAME + "< entschieden."]
+ ],
+ doc='Former variable name: AnerkennungPrivat',
+
+ widget=widgets.RadioSelect)
+
+ hierarchy_of_principlesArg = models.TextField(
+ doc=""" Argument for Rejection """,
+ label="",
+ blank=True
+ )
+
+ hierarchy_of_principlesArg2 = models.TextField(
+ doc=''' Argument for Rejection ''',
+ label="",
+ blank=True
+ )
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z4/end/models.py b/tests/testthat/testdata/ocode_z4/end/models.py
new file mode 100644
index 0000000..dfa82c3
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z4/end/models.py
@@ -0,0 +1,99 @@
+from otree.api import (
+ models,
+ widgets,
+ BaseConstants,
+ BaseSubsession,
+ BaseGroup,
+ BasePlayer,
+)
+import settings
+import string # For completion code
+import random
+
+author = 'Patricia Zauchner'
+
+doc = """
+This is a strongly modified part of the experiment for my dissertation and other experiments
+to test gmoTree on it.
+"""
+
+
+class Constants(BaseConstants):
+ name_in_url = 'end'
+ name_in_url2 = "end"
+ players_per_group = None
+ num_rounds = 1
+ without = "This is a without test"
+ singlequoteinsidedouble = "This is a 'test'"
+ singlequoteinsidedouble2 = "This is a 'test' inside 'another test'"
+ doublequoteinsidesingle = 'This is another "test"'
+ doublequoteinsidesingle2 = 'This is another "test" inside "another test"'
+ escapedsinglequote = 'This ia a \'single quote test\''
+ escapeddoublequote = "This is a \"double quote test\""
+ TOKEN_ADD_1D_NAME = settings.TokenAdd_1dName
+ TOKEN_ADD_2D_NAME = settings.TokenAdd_2dName
+ TOKEN_ADD_3D_NAME = settings.TokenAdd_3dName
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+
+
+class Player(BasePlayer):
+ ConsumptionFinal = models.FloatField(
+ doc="Final consumption \= with TokenAdd as voted for by group as alternative distribution")
+
+ ConsumptionFinal2 = models.FloatField(
+ doc="Final consumption with TokenAdd as voted for by group as alternative distribution")
+
+ completionCode = models.StringField(
+ doc="Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are "
+ "legal problems with the participants"
+ )
+
+ # With spaces at end
+ completionCodespaces = models.StringField(
+ doc="Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are "
+ "legal problems with the participants"
+ )
+
+ Acc_DistributionChange = models.IntegerField(
+ choices=[
+ [1, 'Ich hätte mich dennoch für Verfahren >' +
+ C.TOKEN_ADD_1D_NAME + '< entschieden.'],
+ [2, 'Ich hätte mich für das alternative Verfahren >' +
+ C.TOKEN_ADD_2D_NAME + '< entschieden.'],
+ [3, 'Ich hätte mich für das alternative Verfahren >' +
+ C.TOKEN_ADD_2D_NAME + '< entschieden.']
+ ],
+ doc="Former variable name: AnerkennungPrivat",
+
+ widget=widgets.RadioSelect)
+
+ Acc_DistributionChange2 = models.IntegerField(
+ choices=[
+ [1, "Ich hätte mich dennoch für Verfahren >" +
+ C.TOKEN_ADD_1D_NAME + "< entschieden."],
+ [2, "Ich hätte mich für das alternative Verfahren >" +
+ C.TOKEN_ADD_2D_NAME + "< entschieden."],
+ [3, "Ich hätte mich für das alternative Verfahren >" +
+ C.TOKEN_ADD_2D_NAME + "< entschieden."]
+ ],
+ doc='Former variable name: AnerkennungPrivat',
+
+ widget=widgets.RadioSelect)
+
+ hierarchy_of_principlesArg = models.TextField(
+ doc=""" Argument for Rejection """,
+ label="",
+ blank=True
+ )
+
+ hierarchy_of_principlesArg2 = models.TextField(
+ doc=''' Argument for Rejection ''',
+ label="",
+ blank=True
+ )
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z4/end/pages.py b/tests/testthat/testdata/ocode_z4/end/pages.py
new file mode 100644
index 0000000..3a70c92
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z4/end/pages.py
@@ -0,0 +1,67 @@
+from ._builtin import Page, WaitPage
+from .models import Constants
+import settings
+import random
+from otreeutils.pages import ExtendedPage
+
+
+class Last(Page):
+ def is_displayed(self):
+ #
+ if "kickout" not in self.participant.vars:
+ self.participant.vars["kickout"] = 0
+ print("(Pretest) Kickout not taken from participant vars.")
+ #
+ #
+ if not "NoLevel2" in self.player.participant.vars:
+ self.player.participant.vars["NoLevel2"] = 0
+ #
+ return self.participant.vars["kickout"] != 1 and self.participant.vars["NoLevel2"] == 0
+
+ form_model = "player"
+
+ # Randomize questions
+ def get_form_fields(self):
+ mylist = ["hierNeeds", "hierEquality", "hierRank"]
+ random.shuffle(mylist) # Shuffles original list
+ return ["hierarchy_of_principlesArg"] + mylist
+
+
+class End(Page):
+ """" End page with payoff """
+ def is_displayed(self):
+ return self.participant.vars["kickout"] != 1
+
+ def vars_for_template(self):
+ #
+ if not "NoLevel2" in self.participant.vars:
+ self.player.participant.vars["NoLevel2"] = 0
+ #
+
+
+ #
+ try:
+ self.player.part1Token = self.participant.vars["part1Token"] # Are defined in rankend
+ if self.participant.vars["NoLevel2"] == 0:
+ self.player.part2Token = float(Constants.payoff_survey)
+ elif self.participant.vars["NoLevel2"] == 1:
+ self.player.part2Token = 0
+ else:
+ print("Error in payoff calculation!")
+ self.player.payoffToken = float(Constants.showupToken) + self.player.part1Token + self.player.part2Token
+ self.player.payoff = self.player.payoffToken / settings.ExchangeToken
+ except:
+ print("!!!! Caution: Only pretest values in endpage!!!!")
+ self.player.part1Token = 24
+ self.player.part2Token = 12
+ self.player.payoffToken = float(Constants.showupToken) + self.player.part1Token + self.player.part2Token
+ self.player.payoff = self.player.payoffToken/settings.ExchangeToken
+ #
+
+ return {"Exchange": settings.ExchangeToken,
+ "Showup": Constants.showupToken}
+
+
+page_sequence = [
+ Last,
+ End]
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z4/end/tests.py b/tests/testthat/testdata/ocode_z4/end/tests.py
new file mode 100644
index 0000000..6148a0a
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z4/end/tests.py
@@ -0,0 +1,13 @@
+from . import pages
+from ._builtin import Bot
+
+
+class PlayerBot(Bot):
+ def play_round(self):
+ if self.participant.vars["kickout"] != 1 and self.participant.vars["NoLevel2"] == 0:
+ yield pages.Last, {
+ "hierNeeds": 1,
+ "hierEquality": 2,
+ "hierRank": 3,
+ "hierarchy_of_principlesArg": "no comment!"
+ }
diff --git a/tests/testthat/testdata/ocode_z4/settings.py b/tests/testthat/testdata/ocode_z4/settings.py
new file mode 100644
index 0000000..a22839d
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z4/settings.py
@@ -0,0 +1,80 @@
+from os import environ
+SECRET_KEY = '=3bxca&b&17=bbn4g^ihborndnezuh7d&m&lqn+58zzeg3i05s'
+
+# Use Cloudresearch workerId as participant_label:
+EXTENSION_APPS = ['cloudcapturer'] # To redirect cloudresearch WorkerId to participant_label
+
+# Disable cookies (see app appset)
+MIDDLEWARE = ['appset.middle.DisableCSRFMiddleware']
+
+DEMO_PAGE_INTRO_HTML = """Experiment (30.1.2021)."""
+
+#
+ExchangeToken = 4 # x Token are 1 Dollar
+# Payoff in Token
+showup = "1.40" # In dollar
+showupToken = "{:.2f}".format(float(showup)*ExchangeToken)
+payoffPart1_c = 6*ExchangeToken # Token
+MainCurrencyForSurvey = 3 # Euro or Dollar for participating in the survey
+payoff_survey = "{:.2f}".format(MainCurrencyForSurvey*ExchangeToken) # Token
+#
+
+LANGUAGE_CODE = 'en' # ISO-639 code # for example: de, fr, ja, ko, zh-hans
+USE_POINTS = False
+
+ADMIN_USERNAME = 'admin'
+# ADMIN_PASSWORD = "admin"
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
+
+
+SESSION_CONFIG_DEFAULTS = {
+ 'real_world_currency_per_point': 1.00,
+ 'participation_fee': 0.00,
+ 'doc': "",
+ # if you set a property in SESSION_CONFIG_DEFAULTS, it will be inherited by all configs
+ # in SESSION_CONFIGS, except those that explicitly override it.
+ # the session config can be accessed from methods in your apps as self.session.config,
+ # e.g. self.session.config['participation_fee']
+ "mturk_hit_settings": dict(
+ keywords='bonus, study',
+ title='Title for your experiment',
+ description='Description for your experiment',
+ frame_height=500,
+ template='global/mturk_template.html',
+ minutes_allotted_per_assignment=60,
+ expiration_hours=7 * 24,
+ qualification_requirements=[]
+ # grant_qualification_id='YOUR_QUALIFICATION_ID_HERE', # to prevent retakes
+ )
+}
+ROOMS = [
+ {
+ "name": "room1",
+ "display_name": "room1",
+ },
+ {
+ "name": "room2",
+ "display_name": "room2",
+
+ }
+]
+SESSION_CONFIGS = [
+ {
+ "name": "rankendothers",
+ "display_name": "rankend others",
+ "num_demo_participants": 9,
+ 'dictator': 0,
+ "app_sequence": [
+ "rankend",
+ "dismiss"
+ ]
+ }
+ #
+]
+
+# if an app is included in SESSION_CONFIGS, you don't need to list it here
+INSTALLED_APPS = ['otree'
+ ]
+
+POINTS_DECIMAL_PLACES = 2
+REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_z5/end/models.py b/tests/testthat/testdata/ocode_z5/end/models.py
new file mode 100644
index 0000000..a4ffca6
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z5/end/models.py
@@ -0,0 +1,44 @@
+from otree.api import (
+ models,
+ widgets,
+ BaseConstants,
+ BaseSubsession,
+ BaseGroup,
+ BasePlayer,
+)
+import settings
+import string # For completion code
+import random
+
+class Constants(BaseConstants):
+ pass
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+
+
+class Player(BasePlayer):
+
+ P1_Acc_ArgAkz_4 = models.IntegerField(
+ choices=[
+ [1, "Ich akzeptiere das Argument"],
+ [0, "Ich akzeptiere das Argument nicht"],
+ ],
+ widget=widgets.RadioSelect,
+ initial=-99,
+ )
+
+ money_in_month = models.IntegerField(
+ label="Wie viel Geld steht Ihnen im Monat zur Verfügung (in Euro)?",
+ choices=[
+ [1, "0-399"],
+ [2, "400-699"],
+ [3, "700-999"],
+ [4, "1000 oder mehr"],
+
+ ]
+ )
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z6/rankaversion/models.py b/tests/testthat/testdata/ocode_z6/rankaversion/models.py
new file mode 100644
index 0000000..6a75545
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z6/rankaversion/models.py
@@ -0,0 +1,30 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+author = 'Patricia Zauchner'
+
+doc = """
+Redistribution Game. Third party dictator game varying needs and ranks.
+Major changes to test gmoTree package.
+"""
+
+
+class Constants(BaseConstants):
+ choices = [
+ [8, 2, 2, 2.5, "noRR_needy", settings.v2, 4],
+ [80, 20, 2, 2.5, "noRR_needy", "settings.shouldnotwork", 4],
+ ["8", 2, 2, 2.5, "noRR_needy", settings.v2, 4]
+ ]
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+class Player(BasePlayer):
+ pass
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z6/settings.py b/tests/testthat/testdata/ocode_z6/settings.py
new file mode 100644
index 0000000..366806a
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z6/settings.py
@@ -0,0 +1,55 @@
+from os import environ
+
+v2 = "replacingsettingsworked"
+
+SESSION_CONFIG_DEFAULTS = {
+ 'real_world_currency_per_point': 1.00,
+ 'participation_fee': 0.00,
+ 'doc': "",
+ # if you set a property in SESSION_CONFIG_DEFAULTS, it will be inherited by all configs
+ # in SESSION_CONFIGS, except those that explicitly override it.
+ # the session config can be accessed from methods in your apps as self.session.config,
+ # e.g. self.session.config['participation_fee']
+ "mturk_hit_settings": dict(
+ keywords='bonus, study',
+ title='Title for your experiment',
+ description='Description for your experiment',
+ frame_height=500,
+ template='global/mturk_template.html',
+ minutes_allotted_per_assignment=60,
+ expiration_hours=7 * 24,
+ qualification_requirements=[]
+ # grant_qualification_id='YOUR_QUALIFICATION_ID_HERE', # to prevent retakes
+ )
+}
+ROOMS = [
+ {
+ "name": "room1",
+ "display_name": "room1",
+ },
+ {
+ "name": "room2",
+ "display_name": "room2",
+
+ }
+]
+SESSION_CONFIGS = [
+ {
+ "name": "rankendothers",
+ "display_name": "rankend others",
+ "num_demo_participants": 9,
+ 'dictator': 0,
+ "app_sequence": [
+ "rankend",
+ "dismiss"
+ ]
+ }
+ #
+]
+
+# if an app is included in SESSION_CONFIGS, you don't need to list it here
+INSTALLED_APPS = ['otree'
+ ]
+
+POINTS_DECIMAL_PLACES = 2
+REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_z7/rankaversion/models.py b/tests/testthat/testdata/ocode_z7/rankaversion/models.py
new file mode 100644
index 0000000..1920f2e
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z7/rankaversion/models.py
@@ -0,0 +1,28 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+class Constants(BaseConstants):
+ pass
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+class Player(BasePlayer):
+ gender = models.StringField(
+ choices=[["Male1", "Male"], ["Female", "Femaleval"]],
+ label='What is your gender?',
+ widget=widgets.RadioSelect,
+ )
+
+ gender2 = models.StringField(
+ choices=[['Male', 'Male'], ['Female', 'Femaleval']],
+ label='What is your gender?',
+ widget=widgets.RadioSelect,
+ )
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z8/rankaversion/models.py b/tests/testthat/testdata/ocode_z8/rankaversion/models.py
new file mode 100644
index 0000000..c2383ac
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z8/rankaversion/models.py
@@ -0,0 +1,52 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+class Constants(BaseConstants):
+ pass
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+class Player(BasePlayer):
+ gender = models.IntegerField(
+ doc = "Gender documentation with double quotations",
+ label="What is your gender?",
+ )
+
+ gender2 = models.IntegerField(
+ doc = 'Gender documentation with single quotations',
+ label='What is your gender?',
+ )
+
+ gender3 = models.IntegerField(
+ doc = """Gender documentation with tripple double quotations""",
+ label='What is your gender?',
+ )
+
+ gender4 = models.IntegerField(
+ doc = '''Gender documentation with tripple single quotations''',
+ label='What is your gender?',
+ )
+
+
+ crt_bat = models.IntegerField(
+ label='''
+ A bat and a ball cost 22 dollars in total.
+ The bat costs 20 dollars more than the ball.
+ How many dollars does the ball cost?'''
+ )
+
+ crt_bat2 = models.IntegerField(
+ label="""
+ A bat and a ball cost 22 dollars in total.
+ The bat costs 20 dollars more than the ball.
+ How many dollars does the ball cost?
+ """
+ )
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z9/rankaversion/__init__.py b/tests/testthat/testdata/ocode_z9/rankaversion/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/testthat/testdata/ocode_z9/rankaversion/models.py b/tests/testthat/testdata/ocode_z9/rankaversion/models.py
new file mode 100644
index 0000000..e214740
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z9/rankaversion/models.py
@@ -0,0 +1,26 @@
+from otree.api import (
+ models, widgets, BaseConstants, BaseSubsession, BaseGroup, BasePlayer,
+)
+import random
+import settings
+import pandas as pd # To import csv as dataframe
+
+
+doc = """
+Example code just for testing gmoTree.
+"""
+
+
+class Constants(BaseConstants):
+ Something = settings.Something
+
+
+class Subsession(BaseSubsession):
+ pass
+
+class Group(BaseGroup):
+ pass
+
+
+class Player(BasePlayer):
+ pass
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_z9/rankaversion/pages.py b/tests/testthat/testdata/ocode_z9/rankaversion/pages.py
new file mode 100644
index 0000000..bd7612d
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z9/rankaversion/pages.py
@@ -0,0 +1,167 @@
+from ._builtin import Page, WaitPage
+from .models import Constants
+from otreeutils.pages import ExtendedPage
+import random
+
+
+class YourRole(Page):
+ def is_displayed(self):
+ #
+ if "kickout" not in self.participant.vars:
+ self.participant.vars["kickout"] = 0
+ print("(Pretest) Kickout not taken from participant vars.")
+ #
+ return self.round_number == 1 and self.participant.vars["kickout"] != 1
+
+
+class Task(ExtendedPage):
+ custom_name_in_url = "decision"
+
+ def is_displayed(self):
+ return self.participant.vars["kickout"] != 1 and \
+ self.player.role() == "dictator" and \
+ self.round_number <= self.participant.vars["RRrounds"]
+
+ def vars_for_template(self):
+ if self.player.endowmentA > self.player.endowmentB:
+ a_richer = 1
+ else:
+ a_richer = 0
+ return {
+ "a_richer": a_richer}
+
+ form_model = "player"
+ form_fields = ['acceptance']
+
+ def before_next_page(self):
+ #
+ #
+ if self.player.is_trick == 1:
+ if self.player.acceptance == 0: # If trick question is answered incorrectly
+ self.player.acceptance = -1
+ self.participant.vars["wrong_tricks"] = self.participant.vars["wrong_tricks"] + 1
+ if self.participant.vars["wrong_tricks"] == Constants.maxtrickfalse:
+ self.participant.vars["kickout"] = 1
+ self.participant.vars["kickoutReason"] = "attentionCheck"
+ else:
+ self.player.acceptance = -2 # If trick question is answered correctly
+ #
+ #
+ if self.player.is_trick == 2:
+ if self.player.acceptance == 1: # If trick question is answered incorrectly
+ self.player.acceptance = -1
+ self.participant.vars["wrong_tricks"] = self.participant.vars["wrong_tricks"] + 1
+ if self.participant.vars["wrong_tricks"] == Constants.maxtrickfalse:
+ self.participant.vars["kickout"] = 1
+ self.participant.vars["kickoutReason"] = "attentionCheck"
+ else:
+ self.player.acceptance = -2 # If trick question is answered correctly
+ #
+ #
+
+ #
+ if self.round_number == self.participant.vars["RRrounds"] and self.participant.vars["kickout"] != 1:
+ print("-- Rankaversion -- Save Participant vars.")
+ done_distribution = random.randint(
+ 1, self.participant.vars["RRrounds"] - 4) # 4 trickquestions
+ self.participant.vars["done_distribution"] = done_distribution
+ self.participant.vars["endowmentA_fix"] = self.player.in_round(
+ done_distribution).endowmentA
+ self.participant.vars["endowmentB_fix"] = self.player.in_round(
+ done_distribution).endowmentB
+ self.participant.vars["transfer_fix"] = self.player.in_round(
+ done_distribution).transfer
+ self.participant.vars["needs_threshold_fix"] = self.player.in_round(
+ done_distribution).needs_threshold
+ self.participant.vars["acceptance_fix"] = self.player.in_round(
+ done_distribution).acceptance
+
+ if self.participant.vars["acceptance_fix"] == 1:
+ if self.player.in_round(done_distribution).a_richer == 1:
+ self.participant.vars["finalA"] = self.participant.vars["endowmentA_fix"] - \
+ self.participant.vars["transfer_fix"]
+ self.participant.vars["finalB"] = self.participant.vars["endowmentB_fix"] + \
+ self.participant.vars["transfer_fix"]
+ else:
+ self.participant.vars["finalA"] = self.participant.vars["endowmentA_fix"] + \
+ self.participant.vars["transfer_fix"]
+ self.participant.vars["finalB"] = self.participant.vars["endowmentB_fix"] - \
+ self.participant.vars["transfer_fix"]
+ else:
+ self.participant.vars["finalA"] = self.participant.vars["endowmentA_fix"]
+ self.participant.vars["finalB"] = self.participant.vars["endowmentB_fix"]
+ if self.participant.vars["finalA"] >= self.participant.vars["needs_threshold_fix"]:
+ self.participant.vars["needs_threshold_metA"] = 1
+ else:
+ self.participant.vars["needs_threshold_metA"] = 0
+ if self.participant.vars["finalB"] >= self.participant.vars["needs_threshold_fix"]:
+ self.participant.vars["needs_threshold_metB"] = 1
+ else:
+ self.participant.vars["needs_threshold_metB"] = 0
+ #
+
+
+class TaskForPresentationReasons(Page):
+
+ # Type 1
+ def vars_for_template(self):
+ return {
+ "playerA": 4,
+ "Needs": 1,
+ "playerB": 1,
+ "Transfer": 1,
+ }
+
+ # Type 2
+ def vars_for_template(self):
+ return {
+ "playerA": 4,
+ "Needs": 2,
+ "playerB": 1,
+ "Transfer": 1,
+ }
+
+ # Type 3
+ def vars_for_template(self):
+ return {
+ "playerA": 4,
+ "Needs": 1,
+ "playerB": 1,
+ "Transfer": 2,
+ }
+
+ # Type 4
+ def vars_for_template(self):
+ return {
+ "playerA": 4,
+ "Needs": 2,
+ "playerB": 1,
+ "Transfer": 2,
+ }
+
+
+class TaskWaitPage(ExtendedPage):
+ custom_name_in_url = "nextdecision"
+ """ Waitpage between two tasks.
+ Not really a Waitpage, because the participant doesn't need to wait for the others. """
+
+ def is_displayed(self):
+ return self.participant.vars["kickout"] != 1 and \
+ self.player.role() == "dictator" and \
+ self.round_number < self.participant.vars["RRrounds"]
+
+ def vars_for_template(self):
+ #
+ if self.player.round_number > 1:
+ if self.player.in_round(self.round_number).acceptance == -1:
+ return {"Trickfalse": True} # Answered incorrectly
+ else:
+ return {"Trickfalse": False} # Answered correctly
+ else:
+ return {"Trickfalse": False} # First round
+ #
+
+
+page_sequence = [
+ TaskForPresentationReasons
+]
diff --git a/tests/testthat/testdata/ocode_z9/rankaversion/tests.py b/tests/testthat/testdata/ocode_z9/rankaversion/tests.py
new file mode 100644
index 0000000..8fdc2bf
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z9/rankaversion/tests.py
@@ -0,0 +1,48 @@
+from . import pages
+from ._builtin import Bot
+from .models import Constants
+from otree.api import Submission
+import random
+import time
+
+class PlayerBot(Bot):
+
+ def play_round(self):
+ if self.player.choicetype == "noRR_needSat":
+ prob_acc = 0.75
+ elif self.player.choicetype == "RR_needSat":
+ prob_acc = 0.65
+ elif self.player.choicetype == "noRR_needy":
+ prob_acc = 0.85
+ elif self.player.choicetype == "RR_needy":
+ prob_acc = 0.80
+ else:
+ prob_acc = 0 # Shouldnt happen
+
+ # "YourRole"
+ time.sleep(0)
+ if self.round_number == 1:
+ yield pages.YourRole
+
+ # "Task"
+ time.sleep(0)
+ if self.participant.vars["kickout"] != 1 and \
+ self.player.role() == "dictator" and \
+ self.round_number <= self.participant.vars["RRrounds"]:
+ if self.player.is_trick == 1:
+ yield Submission(pages.Task, {
+ "acceptance": 1})
+ elif self.player.is_trick == 2:
+ yield Submission(pages.Task, {
+ "acceptance": 0})
+ else:
+ yield Submission(pages.Task, {
+ "acceptance": random.choices([0, 1], weights=[1-prob_acc, prob_acc])[0]
+ })
+
+ # "Waitpage" is not a real Waitpage and has to be klicked
+ time.sleep(0)
+ if self.participant.vars["kickout"] != 1 and \
+ self.player.role() == "dictator" and \
+ self.round_number < self.participant.vars["RRrounds"]:
+ yield pages.TaskWaitPage
diff --git a/tests/testthat/testdata/ocode_z9/settings.py b/tests/testthat/testdata/ocode_z9/settings.py
new file mode 100644
index 0000000..0c7169c
--- /dev/null
+++ b/tests/testthat/testdata/ocode_z9/settings.py
@@ -0,0 +1,42 @@
+from os import environ
+
+# Use Cloudresearch workerId as participant_label:
+EXTENSION_APPS = ["cloudcapturer"] # To redirect cloudresearch WorkerId to participant_label
+
+#
+Testnumber = 1
+Testnumber2 = Testnumber
+StartToken = [9, 14, 17, 23, 37 + Testnumber]
+OtherTest1 = StartToken
+OtherTest2 = StartToken * 5
+Something = [1, 3, "test", 3, 1]
+#
+
+# LANGUAGE_CODE = 'en' # ISO-639 code # for example: de, fr, ja, ko, zh-hans
+# USE_POINTS = False
+
+# ADMIN_USERNAME = 'admin'
+# ADMIN_PASSWORD = "admin"
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
+
+
+SESSION_CONFIGS = [
+ {
+ "name": "rankendothers",
+ "display_name": "rankend others",
+ "num_demo_participants": 9,
+ 'dictator': 0,
+ "app_sequence": [
+ "rankend",
+ "dismiss"
+ ]
+ }
+ #
+]
+
+# if an app is included in SESSION_CONFIGS, you don't need to list it here
+INSTALLED_APPS = ['otree'
+ ]
+
+# POINTS_DECIMAL_PLACES = 2
+# REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/testdata/ocode_zch/_static/global/empty.css b/tests/testthat/testdata/ocode_zch/_static/global/empty.css
new file mode 100644
index 0000000..e69de29
diff --git a/tests/testthat/testdata/ocode_zch/end/__init__.py b/tests/testthat/testdata/ocode_zch/end/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/testthat/testdata/ocode_zch/end/models.py b/tests/testthat/testdata/ocode_zch/end/models.py
new file mode 100644
index 0000000..a7f6bef
--- /dev/null
+++ b/tests/testthat/testdata/ocode_zch/end/models.py
@@ -0,0 +1,90 @@
+from otree.api import (
+ models,
+ widgets,
+ BaseConstants,
+ BaseSubsession,
+ BaseGroup,
+ BasePlayer,
+)
+import settings
+import string # For completion code
+import random
+
+author = 'Patricia Zauchner'
+
+doc = """
+This is a strongly modified part of the experiment for my dissertation.
+"""
+
+
+class Constants(BaseConstants):
+ name_in_url = 'end'
+ players_per_group = None
+ num_rounds = 1
+ chinese = 格吕克
+ #
+ showupToken = settings.showupToken
+ showupTokenTest = showupToken
+ # Payoff Part 1
+ payoffPart1_c = settings.payoffPart1_c # Token
+ # Payoff Survey
+ payoff_survey = settings.payoff_survey # Token
+ # Weiters
+ ExchangeMainCurrency = settings.ExchangeMainCurrency # 4 Token = 1 Dollar
+ ExchangeToken = settings.ExchangeToken
+ ExchangeRate = ExchangeToken / ExchangeMainCurrency
+ ExchangeRateTest = settings.ExchangeToken / settings.ExchangeMainCurrency
+ #
+
+
+class Subsession(BaseSubsession):
+ def creating_session(self):
+ # Set language
+ for p in self.get_players():
+ p.participant.vars["planguage"] = "en" # Alternatives: "en" and "de"
+
+ # Create Completion Code
+ for p in self.get_players():
+ p.completionCode = ''.join(random.choices(string.ascii_uppercase + string.digits, k=9))
+
+
+class Group(BaseGroup):
+ pass
+
+
+class Player(BasePlayer):
+ payoffToken = models.FloatField(doc="Token received for the whole experiment")
+ part1Token = models.FloatField(doc="Token received for the redistribution game")
+ part2Token = models.FloatField(doc="Token received for level 2")
+ completionCode = models.StringField(
+ doc="Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are "
+ "legal problems with the participants."
+ )
+
+ hierarchy_of_principlesArg = models.TextField(
+ doc=""" Argument for Rejection """,
+ label="",
+ blank=True
+ )
+
+ hierNeeds = models.IntegerField(
+ doc=""" Rank of Needs """,
+ label="Rank of principle 'needs':",
+ min=1, max=3
+ )
+
+ thisisaveryveryveryverylongvariablename = models.IntegerField(
+ doc = "Testtesttest"
+ )
+
+ hierEquality = models.IntegerField(
+ doc=""" Rank of Equality """,
+ label="Rank of principle 'equality':",
+ min=1, max=3
+ )
+
+ hierRank = models.IntegerField(
+ doc=""" Rank of Ranking """,
+ label="Rank of principle 'stable income rankings':",
+ min=1, max=3
+ )
diff --git a/tests/testthat/testdata/ocode_zch/end/pages.py b/tests/testthat/testdata/ocode_zch/end/pages.py
new file mode 100644
index 0000000..3a70c92
--- /dev/null
+++ b/tests/testthat/testdata/ocode_zch/end/pages.py
@@ -0,0 +1,67 @@
+from ._builtin import Page, WaitPage
+from .models import Constants
+import settings
+import random
+from otreeutils.pages import ExtendedPage
+
+
+class Last(Page):
+ def is_displayed(self):
+ #
+ if "kickout" not in self.participant.vars:
+ self.participant.vars["kickout"] = 0
+ print("(Pretest) Kickout not taken from participant vars.")
+ #
+ #
+ if not "NoLevel2" in self.player.participant.vars:
+ self.player.participant.vars["NoLevel2"] = 0
+ #
+ return self.participant.vars["kickout"] != 1 and self.participant.vars["NoLevel2"] == 0
+
+ form_model = "player"
+
+ # Randomize questions
+ def get_form_fields(self):
+ mylist = ["hierNeeds", "hierEquality", "hierRank"]
+ random.shuffle(mylist) # Shuffles original list
+ return ["hierarchy_of_principlesArg"] + mylist
+
+
+class End(Page):
+ """" End page with payoff """
+ def is_displayed(self):
+ return self.participant.vars["kickout"] != 1
+
+ def vars_for_template(self):
+ #
+ if not "NoLevel2" in self.participant.vars:
+ self.player.participant.vars["NoLevel2"] = 0
+ #
+
+
+ #
+ try:
+ self.player.part1Token = self.participant.vars["part1Token"] # Are defined in rankend
+ if self.participant.vars["NoLevel2"] == 0:
+ self.player.part2Token = float(Constants.payoff_survey)
+ elif self.participant.vars["NoLevel2"] == 1:
+ self.player.part2Token = 0
+ else:
+ print("Error in payoff calculation!")
+ self.player.payoffToken = float(Constants.showupToken) + self.player.part1Token + self.player.part2Token
+ self.player.payoff = self.player.payoffToken / settings.ExchangeToken
+ except:
+ print("!!!! Caution: Only pretest values in endpage!!!!")
+ self.player.part1Token = 24
+ self.player.part2Token = 12
+ self.player.payoffToken = float(Constants.showupToken) + self.player.part1Token + self.player.part2Token
+ self.player.payoff = self.player.payoffToken/settings.ExchangeToken
+ #
+
+ return {"Exchange": settings.ExchangeToken,
+ "Showup": Constants.showupToken}
+
+
+page_sequence = [
+ Last,
+ End]
\ No newline at end of file
diff --git a/tests/testthat/testdata/ocode_zch/end/tests.py b/tests/testthat/testdata/ocode_zch/end/tests.py
new file mode 100644
index 0000000..6148a0a
--- /dev/null
+++ b/tests/testthat/testdata/ocode_zch/end/tests.py
@@ -0,0 +1,13 @@
+from . import pages
+from ._builtin import Bot
+
+
+class PlayerBot(Bot):
+ def play_round(self):
+ if self.participant.vars["kickout"] != 1 and self.participant.vars["NoLevel2"] == 0:
+ yield pages.Last, {
+ "hierNeeds": 1,
+ "hierEquality": 2,
+ "hierRank": 3,
+ "hierarchy_of_principlesArg": "no comment!"
+ }
diff --git a/tests/testthat/testdata/ocode_zch/settings.py b/tests/testthat/testdata/ocode_zch/settings.py
new file mode 100644
index 0000000..35d6ec7
--- /dev/null
+++ b/tests/testthat/testdata/ocode_zch/settings.py
@@ -0,0 +1,88 @@
+from os import environ
+SECRET_KEY = '=3bxca&b&17=bbn4g^ihborndnezuh7d&m&lqn+58zzeg3i05s'
+
+# Use Cloudresearch workerId as participant_label:
+EXTENSION_APPS = ['cloudcapturer'] # To redirect cloudresearch WorkerId to participant_label
+
+# Disable cookies (see app appset)
+MIDDLEWARE = ['appset.middle.DisableCSRFMiddleware']
+
+DEMO_PAGE_INTRO_HTML = """Experiment (30.1.2021)."""
+
+#
+ExchangeToken = 4 # x Token are 1 Dollar
+# Time
+MinutesForSurvey = 18
+timer123 = 500
+# Payoff in Token
+showup = "1.40" # In dollar
+showupToken = "{:.2f}".format(float(showup)*ExchangeToken)
+payoffPart1_c = 6*ExchangeToken # Token
+min_payoffPart1_ab = "1.00" # Token
+max_payoffPart1_ab = "11.00" # Token
+MainCurrencyForSurvey = 3 # Euro or Dollar for participating in the survey
+payoff_survey = "{:.2f}".format(MainCurrencyForSurvey*ExchangeToken) # Token
+TestVector2 = [99,66,33]
+TestVectorC2 = ["d", "e", 4]
+
+#
+
+LANGUAGE_CODE = 'en' # ISO-639 code # for example: de, fr, ja, ko, zh-hans
+USE_POINTS = False
+
+ADMIN_USERNAME = 'admin'
+# ADMIN_PASSWORD = "admin"
+ADMIN_PASSWORD = environ.get('OTREE_ADMIN_PASSWORD')
+
+
+SESSION_CONFIG_DEFAULTS = {
+ 'real_world_currency_per_point': 1.00,
+ 'participation_fee': 0.00,
+ 'doc': "",
+ # if you set a property in SESSION_CONFIG_DEFAULTS, it will be inherited by all configs
+ # in SESSION_CONFIGS, except those that explicitly override it.
+ # the session config can be accessed from methods in your apps as self.session.config,
+ # e.g. self.session.config['participation_fee']
+ "mturk_hit_settings": dict(
+ keywords='bonus, study',
+ title='Title for your experiment',
+ description='Description for your experiment',
+ frame_height=500,
+ template='global/mturk_template.html',
+ minutes_allotted_per_assignment=60,
+ expiration_hours=7 * 24,
+ qualification_requirements=[]
+ # grant_qualification_id='YOUR_QUALIFICATION_ID_HERE', # to prevent retakes
+ )
+}
+ROOMS = [
+ {
+ "name": "room1",
+ "display_name": "room1",
+ },
+ {
+ "name": "room2",
+ "display_name": "room2",
+
+ }
+]
+SESSION_CONFIGS = [
+ {
+ "name": "rankendothers",
+ "display_name": "rankend others",
+ "num_demo_participants": 9,
+ 'dictator': 0,
+ "app_sequence": [
+ "rankend",
+ "dismiss"
+ ]
+ }
+ #
+]
+
+# if an app is included in SESSION_CONFIGS, you don't need to list it here
+INSTALLED_APPS = ['otree'
+ ]
+
+POINTS_DECIMAL_PLACES = 2
+REAL_WORLD_CURRENCY_DECIMAL_PLACES = 2
diff --git a/tests/testthat/tests_codebook.R b/tests/testthat/tests_codebook.R
index fd78474..baa55d1 100644
--- a/tests/testthat/tests_codebook.R
+++ b/tests/testthat/tests_codebook.R
@@ -1,1040 +1,1854 @@
-if (rlang::is_installed(c("withr", "testthat"))) {
+if (rlang::is_installed(c("withr", "testthat"))) {
- print("---- start codebook tests -----")
+ print("---- start codebook tests -----")
+
+ testthat::test_that("Codebook (w) - unmatched square brackets", {
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z13"),
+ fsource = "model",
+ output = "list",
+ doc_info = FALSE),
+ "\\$rankaversion\\$Player\\$gender \\(unmatched square brackets\\).*\\(unmatched brackets\\)")
+
+ # Brackets
+ cbook$rankaversion$Player$variable$doc == "(A doc in brackets))"
+ cbook$rankaversion$Player$variable2$doc == "A doc with one closing bracket"
+
+
+ # No warning when it comes to constants
+ testthat::expect_true(
+ cbook$rankaversion$Constants$Something == "[[information]")
+
+ # Even if there is a warning, it is still shown
+ testthat::expect_true(
+ cbook$rankaversion$Player$gender$doc == "[[Gender]")
+ })
+
+ testthat::test_that("Codebook - quotes", {
+
+ warning <- testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z4"),
+ fsource = "models",
+ output_format = "latex",
+ output_file = "cb_quotestest",
+ output = "list",
+ settings_replace = NULL,
+ doc_info = FALSE)
+ )
+
+ warning <- testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z4"),
+ fsource = "models",
+ output_format = "pdf_simple",
+ output_file = "cb_quotestest_simple",
+ output = "list",
+ settings_replace = NULL,
+ doc_info = FALSE)
+ )
+
+ warning <- testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z4"),
+ fsource = "models",
+ output_format = "pdf",
+ output_file = "cb_quotestest",
+ output = "list",
+ settings_replace = NULL,
+ doc_info = FALSE)
+ )
+
+
+ # Doc with """ in them
+ testthat::expect_true(cbook$end$Player$hierarchy_of_principlesArg$doc ==
+ "Argument for Rejection")
+
+ # Doc with ''' in them
+ testthat::expect_true(cbook$end$Player$hierarchy_of_principlesArg2$doc ==
+ "Argument for Rejection")
+
+ testthat::expect_true(cbook$end$Constants$without == "This is a without test")
+ # Normal string - Single values with single string def
+ testthat::expect_true(cbook$end$Constants$name_in_url == "end")
+ # Normal string - Single values with double string def
+ testthat::expect_true(cbook$end$Constants$name_in_url2 == "end")
+ # Normal string - single quoted strings within double string def
+ testthat::expect_true(cbook$end$Constants$singlequoteinsidedouble ==
+ "This is a 'test'")
+ # Normal string - escaped quoted strings within double string def
+ testthat::expect_true(cbook$end$Constants$doublequoteinsidesingle ==
+ "This is another \"test\"")
+ testthat::expect_true(cbook$end$Constants$doublequoteinsidesingle2 ==
+ "This is another \"test\" inside \"another test\"")
+
+ testthat::expect_true(cbook$end$Constants$escapedsinglequote ==
+ "This ia a 'single quote test'")
+
+ testthat::expect_true(cbook$end$Constants$escapeddoublequote ==
+ "This is a \"double quote test\"")
+
+ # Choices with single quotation marks
+ testthat::expect_true(cbook$end$Player$Acc_DistributionChange$choices$value[1] ==
+ "Ich hätte mich dennoch für Verfahren >settings.TokenAdd_1dName< entschieden.")
+ # Test next argument because they have different quotations:
+
+ testthat::expect_true(cbook$end$Player$Acc_DistributionChange$doc ==
+ "Former variable name: AnerkennungPrivat")
+
+ # Choices with double quotation marks
+
+ testthat::expect_true(
+ cbook$end$Player$Acc_DistributionChange2$choices$value[1] ==
+ "Ich hätte mich dennoch für Verfahren >settings.TokenAdd_1dName< entschieden.")
+ testthat::expect_true(cbook$end$Player$Acc_DistributionChange2$doc ==
+ "Former variable name: AnerkennungPrivat")
+ })
+
+ testthat::test_that("Codebook - print", {
+
+ outputfilewithgetwd <- paste0(getwd(), "codebooktestprint")
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output_dir = "getwd()",
+ output_format = "latex_document",
+ output_file = outputfilewithgetwd,
+ output = "list",
+ app = "dictator",
+ doc_info = FALSE)
+
+ # Check for print removal in Constants
+ testthat::expect_true(cbook$dictator$Constants$NAME_IN_URL == "dictator")
+ testthat::expect_true(cbook$dictator$Constants$PLAYERS_PER_GROUP == 2)
+ testthat::expect_true(cbook$dictator$Constants$NUM_ROUNDS == 1) # Here is print
+ testthat::expect_true(cbook$dictator$Constants$ENDOWMENT == "cu(100)")
+
+ # Check for print removal in Group
+ testthat::expect_true(all(
+ names(cbook$dictator$Group$kept) ==
+ c("noargs", "doc", "min", "max", "label", "field")))
+ testthat::expect_true(cbook$dictator$Group$kept$noargs == FALSE)
+ testthat::expect_true(cbook$dictator$Group$kept$doc ==
+ "Amount dictator decided to keep for himself")
+ testthat::expect_true(cbook$dictator$Group$kept$min == 0)
+ testthat::expect_true(cbook$dictator$Group$kept$label == "I will keep")
+
+ # Check for print removal in Player
+
+ testthat::expect_true(all(
+ names(cbook$dictator$Player) == c("gender", "chandler")))
+
+ testthat::expect_true(cbook$dictator$Player$gender$field == "IntegerField")
+ testthat::expect_true(cbook$dictator$Player$gender$noargs == FALSE)
+ testthat::expect_true(cbook$dictator$Player$gender$doc == "Gender")
+
+ testthat::expect_true(all(
+ names(cbook$dictator$Player$chandler) == c("noargs","doc", "field")))
+ testthat::expect_true(cbook$dictator$Player$chandler$field == "IntegerField")
+ testthat::expect_true(cbook$dictator$Player$chandler$noargs == FALSE)
+ testthat::expect_true(cbook$dictator$Player$chandler$doc == "Chandler")
+
+
+ })
- testthat::test_that("Codebook - double brackets", {
- # Here we see that if a value starts and ends with brackets, it makes no difference
- testthat::expect_warning(
+ testthat::test_that("Codebook - new oTree, app_rm", {
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "list",
+ output_file = "newappapprm",
+ app_rm = "dictator",
+ doc_info = FALSE)
+
+ test1 <- !is.null(cbook$bargaining)
+ test2 <- is.null(cbook$dictator)
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+
+ testthat::expect_true(cbook$bargaining$Player$level$doc ==
+ "choices with only [1,2,3]")
+ })
+
+ testthat::test_that("Codebook - brackets", {
+ # TODO also check in PDF and word
+ testthat::expect_warning(
cbook <- codebook(
path = testthat::test_path("testdata", "ocode_z2"),
+ output = "list",
output_dir = NULL,
+ output_format = "pdf_simple",
+ output_file = "cb_bracket_newline",
fsource = "models",
- output = "list"))
-
- testthat::expect_true(cbook$rankaversion$Player$acceptance$choices$value[1] == "(Yes)")
- })
-
- testthat::test_that("Codebook (e) - wrong output", {
-
- # Wrongt text
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- output_dir = NULL,
- output = "WRONG",
- fsource = "init")}, "Output should be")
-
- # NULL
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- output_dir = NULL,
- output = "NULL",
- fsource = "init")}, "Output should be")
-
-
- # Two inputs
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- output_dir = NULL,
- fsource = "init",
- output = c("file", "list"))},
- "Output should be")
-
- })
-
- testthat::test_that("Codebook (e) - wrong fsource", {
-
- # Wrongt text
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- output_dir = NULL,
- fsource = "none",
- output = "list")}, "fsource must be either")
-
- # NULL
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- output_dir = NULL,
- fsource = NULL,
- output = "list")}, "fsource must be either")
-
- # Wrong length
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- output_dir = NULL,
- fsource = c("init", "model"),
- output = "list")}, "Please enter only one fsource")
-
- })
-
- testthat::test_that("Codebook (w) - user_settings", {
+ splitvarname = TRUE,
+ sep_list = "newline",
+ output_open = FALSE
+ ), "Some variables")
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output = "list",
+ output_dir = NULL,
+ output_format = "latex",
+ output_file = "cb_bracket_newline",
+ fsource = "models",
+ splitvarname = TRUE,
+ sep_list = "newline",
+ output_open = FALSE), "Some variables")
+
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output = "list",
+ output_dir = NULL,
+ output_format = "word",
+ output_file = "bracket_newline_word",
+ fsource = "models",
+ splitvarname = TRUE,
+ sep_list = "newline",
+ output_open = FALSE), "Some variables")
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output = "list",
+ output_dir = NULL,
+ output_file = "bracket_vector",
+ sep_list = "vector",
+ fsource = "models",
+ splitvarname = TRUE), "Some variables")
+
+ # First and last bracket
+ # First and last brackets are not removed for normale variables!
+ testthat::expect_true(
+ cbook$rankend$Constants$firstlastbr == "(firstlastbracketexample)")
+
+ # Empty list
+ testthat::expect_identical(cbook$rankend$Constants$emptylist, list())
+ testthat::expect_identical(cbook$rankend$Constants$emptylist2, list())
+
+ # Vector with numbers and strings
+ testthat::expect_true(is.list(cbook$rankaversion$Constants$onelevelvectorl))
+ testthat::expect_identical(
+ cbook$rankaversion$Constants$onelevelvectorl,
+ list("a", "b", 3))
+
+ testthat::expect_identical(
+ cbook$rankaversion$Constants$onelevelvectorl2,
+ list("a", "b", 3, "asdfadsf", "adsfadsfasdf", "00asasdf", 2342, "wqerwerqewr"))
+ testthat::expect_true(is.list(cbook$rankaversion$Constants$onelevelvectorl2))
+
+ # Original oTree code has brackets: (Yes)
+ testthat::expect_true(cbook$rankaversion$Player$acceptance$choices$value[1] == "(Yes)")
+
+ # Test for numeric vectors in Constants
+ testthat::expect_identical(cbook$rankend$Constants$TestVector,
+ list(1, 10, 3, 4, 5))
+
+ # Test for numeric vectors in Settings
+ testthat::expect_identical(cbook$rankend$Constants$TestVector2,
+ list(99, 66, 33))
+
+
+ # Test for character vectors in Constants
+ testthat::expect_identical(cbook$rankend$Constants$TestVectorC,
+ list("a", "b", 6))
+
+ # Test for character vectors in Settings
+ testthat::expect_identical(cbook$rankend$Constants$TestVectorC2,
+ list("d", "e", 4))
+
+ # Test for two-level lists
+ testthat::expect_true(is.list(cbook$rankaversion$Constants$choices))
+
+ testthat::expect_true(identical(
+ cbook$rankaversion$Constants$choices[[1]],
+ list(4, 1, 1, 0.5, "noRR_needSat", 3, 2)
+ ))
+
+ # If closing bracket is at next row
+ testthat::expect_true(all(cbook$rankaversion$Constants$nextrowbracket[[1]] ==
+ c(69, 43, 5)))
+
+ # If closing bracket is at same row
+ testthat::expect_true(all(cbook$rankaversion$Constants$samerowbracke[[1]] ==
+ c(69, 43, 5)))
+
+
+ # If there is a space before the second opening bracket
+ testthat::expect_true(all(cbook$rankaversion$Constants$spacebeforebracket[[1]] ==
+ c(2004, 43, 5)))
+
+ # If there is a comment before the second opening bracket
+ testthat::expect_true(all(cbook$rankaversion$Constants$commentafterbracket[[1]] ==
+ c(69, 43, 5)))
+
+ # If there is a space before the last closing bracket
+ testthat::expect_true(all(cbook$rankaversion$Constants$spaceafterbracket[[1]] ==
+ c(69, 43, 5)))
+
+
+ # If there is a space after a comma
+ testthat::expect_true(all(cbook$rankaversion$Constants$spaceaftercomma[[1]] ==
+ c(2004, 43, 5)))
+
+ # If there is a comment after a comma
+ testthat::expect_true(all(cbook$rankaversion$Constants$commentaftercomma[[1]] ==
+ c(2004, 43, 5)))
+
+
+ })
- # Try user Var
+ testthat::test_that("Codebook (e) - three level list in constants", {
+
+
+ # In constants
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z10"),
+ output_dir = NULL,
+ output = "list",
+ fsource = "model")
+ }, "This function does not support lists with more.*Constants")
+ })
+
+ testthat::test_that("Codebook - old oTree", {
+
+ testthat::expect_message(
testthat::expect_warning(
cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z2"),
+ path = testthat::test_path("testdata", "ocode_z"),
fsource = "model",
- user_settings = list(error = "Test",
- showupToken = 2,
- max_payoffPart1_ab = 1,
- ExchangeMainCurrency = 1,
- payoff_survey = 1,
- MinutesForSurvey = 20,
- ExchangeToken = 1,
- timer123 = 12,
- payoffPart1_c = 1),
- settings_replace = "user",
- doc_info = FALSE,
- output = "list"), "too complex for this function")
-
- test1 <- cbook$rankaversion$Constants$errorvariable == "Test"
- test2 <- cbook$rankaversion$Constants$MinutesForSurvey == 20
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- })
+ output = "list",
+ doc_info = TRUE),
+ ".*too complex for this function.*rankaversion\\$Constants.*\\$rankend\\$Constants \\(read_csv\\).*\\$settings\\$showupToken \\(float\\).*\\$end\\$Constants\\$showupToken \\(float\\).*\\$end\\$Constants\\$showupTokenTest \\(float\\)"
+ ), "Variables without.*rankaversion\\$Player\\$choicenumber.*rankend\\$Player\\$done_distribution")
+
+ testthat::expect_true(cbook$rankaversion$Constants$randomtest == 35L)
+ test1 <- is.list(cbook)
+
+ # Test settings in settings replacements
+ test2 <- cbook$settings$payoffPart1_c ==
+ 6L * cbook$settings$ExchangeToken
+
+ # Test settings in Constants replacement
+ test3 <- cbook$end$Constants$payoffPart1_c ==
+ cbook$settings$payoffPart1_c
+
+ test4 <- cbook$end$Constants$ExchangeToken ==
+ cbook$settings$ExchangeToken
+
+ test5 <- cbook$end$Constants$ExchangeToken == 4L
+ # Test constants in Constants replacement
+ test6 <- cbook$end$Constants$ExchangeRate ==
+ as.numeric(cbook$end$Constants$ExchangeToken) /
+ as.numeric(cbook$end$Constants$ExchangeMainCurrency)
+
+ test7 <- cbook$end$Constants$showupToken ==
+ cbook$end$Constants$showupTokenTest
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ testthat::expect_true(test7)
+
+ })
+
+ testthat::test_that("Codebook - several lines", {
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_count"),
+ fsource = "init",
+ output_open = FALSE,
+ output = "list",
+ output_file = "cb_severallines",
+ doc_info = TRUE)
+ })
+
+ testthat::test_that("Codebook (w) - vector variable in settings and constants", {
+ # Dissertation code
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z3"),
+ fsource = "models",
+ output = "list",
+ doc_info = FALSE), "too complex for this function")
+
+ # Since R only saves the same type in a vector
+ testthat::expect_identical(
+ cbook$settings$Something,
+ list(1, 3, "test", 3, 1))
+
+ testthat::expect_identical(
+ cbook$rankaversion$Constants$Something,
+ list(1, 3, "test", 3, 1))
+
+ # Otherwise
+ testthat::expect_identical(
+ cbook$settings$StartToken,
+ list(9.0, 14.0, 17.0, 23.0, 38.0))
+
+ test4 <-
+ cbook$rankaversion$Constants$StartToken ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0)
+
+ test5 <- cbook$rankaversion$Constants$StartToken2 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0) * 2.0
+ test6 <- cbook$rankaversion$Constants$StartToken3 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0) * 10.0
+
+ # Calculations
+ test7 <- cbook$settings$Othertest1 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0)
+ test8 <- cbook$settings$Othertest2 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0) * 5L
+
+ test9 <-
+ cbook$rankaversion$Constants$players_per_group == "None"
+
+ test10 <-
+ cbook$rankaversion$Constants$TestToken ==
+ unlist(cbook$settings$StartToken) * 5L
+
+ test11 <- all(
+ cbook$rankaversion$Player$Acc_DistributionChange$value ==
+ c("Ich hätte mich dennoch für Verfahren > xyz < entschieden.",
+ "Ich hätte mich für das alternative Verfahren > aaa < entschieden.",
+ "Ich hätte mich für das alternative Verfahren > bbb < entschieden."))
+
+ test12 <- all(cbook$rankaversion$Player$acceptance$choices$value ==
+ c("xyz", "aaa", "Wrong, trick answer", "Correct trick answer"))
+
+ testthat::expect_true(all(test4))
+ testthat::expect_true(all(test5))
+ testthat::expect_true(all(test6))
+ testthat::expect_true(all(test7))
+ testthat::expect_true(all(test8))
+ testthat::expect_true(all(test9))
+ testthat::expect_true(all(test10))
+ testthat::expect_true(test11)
+ testthat::expect_true(test12)
+
+ })
- testthat::test_that("Codebook (w) - float in variable name", {
+ testthat::test_that("choices ohne key", {
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "list",
+ doc_info = FALSE,
+ app = "bargaining")
+
+ cbook$bargaining$Player$level2$choices[1] == "No, I won't"
+ cbook$bargaining$Player$level2$choices[2] == "yes, I will"
+ cbook$bargaining$Player$level2$choices[3] == "Maybe I'll do"
+
+
+ })
+
+ testthat::test_that("Codebook - documentation of variables", {
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z8"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output = "list")
+
+ testthat::expect_true(cbook$rankaversion$Player$gender$doc == "Gender documentation with double quotations")
+
+ testthat::expect_true(cbook$rankaversion$Player$gender2$doc == "Gender documentation with single quotations")
+
+ testthat::expect_true(
+ cbook$rankaversion$Player$gender3$doc ==
+ "Gender documentation with tripple double quotations")
+
+
+
+ testthat::expect_true(
+ cbook$rankaversion$Player$gender4$doc ==
+ "Gender documentation with tripple single quotations")
+
+
+
+
+
+
+
+
+
+ testthat::expect_true(grepl(
+ cbook$rankaversion$Player$crt_bat$label,
+ pattern = "^A bat and a ball.*cost\\?$"))
+
+
+ testthat::expect_true(grepl(
+ cbook$rankaversion$Player$crt_bat2$label,
+ pattern = "^A bat and a ball.* cost\\?$"))
+
+
+ })
+
+ testthat::test_that("Codebook (w) - constants var not there", {
+
+ # Try user Var
+ testthat::expect_message(
testthat::expect_warning(
- cb <- codebook(
- path = testthat::test_path("testdata", "ocode_y1"),
- fsource = "models",
- output = "list"
- ), paste0(
- "too complex for this function.*",
- "\\$test\\$Constants\\$min_payoffAB.*",
- "\\$test\\$Player\\$min_payoffAB\\$max.*",
- "\\$test\\$Group\\$min_payoffAB\\$max"
- ))
-
- # Info: Correct result but a string instead of a float
- testthat::expect_true(cb$test$Group$variable2$max == "3.3")
-
- test1 <- cb$test$Constants$min_payoffAB ==
- "(float(1.0)) + (float(1.1)) + (float(1.2))"
- test2 <- cb$test$Group$min_payoffAB$max ==
- "(float(1.0)) + (float(1.1)) + (float(1.2))"
- test3 <- cb$test$Player$min_payoffAB$max ==
- "(float(1.0)) + (float(1.1)) + (float(1.2))"
- test4 <- cb$test$Group$variable2$max == 3.3
-
- testthat::expect_true(all(c(test1, test2, test3, test4)))
-
- })
-
- testthat::test_that("Codebook (e) - only list, app and app rm specified", {
-
- testthat::expect_error(
cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
+ path = testthat::test_path("testdata", "ocode_new2"),
fsource = "init",
- output = "list",
- doc_info = FALSE,
- app = "dictator",
- app_rm = "public_goods_simple"),
- "Please specify only \"app\" or \"app_rm")
+ output = "list"), "is not in Constants"),
+ "Variables without documentation.*bargaining\\$Group\\$total_requests")
+
+ test1 <-
+ cbook$bargaining$Player$request$max == "C.AMOUNT_SHARED_false"
+
+ # Check if leading and trailing brackets and comments are removed # TODO compara with prior verison
+ # Original "(Please enter an amount from 0 to 100)"
+ test2 <- cbook$bargaining$Player$request$label ==
+ "(Please enter an amount from 0 to 100)"
- })
+
+ test3 <- cbook$bargaining$Player$request2$label ==
+ "Please enter an amount from 0 to 100"
+ test4 <- cbook$bargaining$Player$request3$label ==
+ "Please enter an amount from 0 to 100"
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ })
+
+ testthat::test_that("Codebook (w) - float in variable name", {
+
+ testthat::expect_warning(
+ cb <- codebook(
+ path = testthat::test_path("testdata", "ocode_y1"),
+ fsource = "models",
+ output = "list"
+ ), paste0(
+ "too complex for this function.*",
+ "\\$test\\$Constants\\$min_payoffAB.*",
+ "\\$test\\$Player\\$min_payoffAB\\$max.*",
+ "\\$test\\$Group\\$min_payoffAB\\$max"
+ ))
+
+ # Info: Correct result but a string instead of a float
+ testthat::expect_true(cb$test$Group$variable2$max == 3.3)
+
+ test1 <- cb$test$Constants$min_payoffAB ==
+ "(float(1.0)) + (float(1.1)) + (float(1.2))"
+ test2 <- cb$test$Group$min_payoffAB$max ==
+ "(float(1.0)) + (float(1.1)) + (float(1.2))"
+ test3 <- cb$test$Player$min_payoffAB$max ==
+ "(float(1.0)) + (float(1.1)) + (float(1.2))"
+
- testthat::test_that("Codebook - only list, new oTree, app_rm", {
+ test4 <- cb$test$Group$variable2$max == 3.3
+ testthat::expect_true(all(c(test1, test2, test3, test4)))
+
+ })
+
+ testthat::test_that("Codebook - new oTree, only one app", {
+
+ testthat::expect_message(
cbook <- codebook(
path = testthat::test_path("testdata", "ocode_new"),
fsource = "init",
output = "list",
- app_rm = "dictator",
- doc_info = FALSE)
-
- test1 <- !is.null(cbook$bargaining)
- test2 <- is.null(cbook$dictator)
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- })
+ doc_info = TRUE,
+ app = "public_goods_simple"),
+ "Variables without documentation, label, or verbose name:"
+ )
- testthat::test_that("Codebook (e) - apps don't exist", {
-
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "init",
- output = "list",
- app = c("dictator", "nonexistingapp"),
- doc_info = FALSE)}, "At least one app")
- })
+ test1 <- is.list(cbook)
+ test2 <- !is.null(cbook$public_goods_simple$Constants)
+ test3 <- !is.null(cbook$public_goods_simple$Group)
+ test4 <- !is.null(cbook$public_goods_simple$Player)
- testthat::test_that("Codebook (e) - wrong format", {
-
- testthat::expect_error({
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "init",
- output = "both",
- output_format = "WrongFormat",
- doc_info = FALSE)}, "Output format should be")
- })
-
- testthat::test_that("Codebook (e) - params", {
- warnings <- testthat::capture_warnings(
- testthat::expect_error(
-
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z2"),
- fsource = "model",
- params = "ab",
- output = "both"),
- "params must be a list"))
+ test5 <-
+ cbook$public_goods_simple$Constants$NAME_IN_URL ==
+ "public_goods_simple"
+ test6 <-
+ cbook$public_goods_simple$Group$total_contribution$noargs ==
+ "TRUE"
+ test7 <-
+ cbook$public_goods_simple$Player$contribution$label ==
+ "How much will you contribute?"
+ test8 <-
+ cbook$public_goods_simple$Player$contribution$noargs ==
+ "FALSE"
+
+ # Remove leading and trailing """ from doc
+ test9 <- cbook$volunteer_dilemma$Player$volunteer$doc ==
+ "Whether player volunteers"
+
+ # Remove leading and trailing ' from label
+ test9 <- cbook$volunteer_dilemma$Player$volunteer$label ==
+ "Do you wish to volunteer?"
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ testthat::expect_true(test7)
+ testthat::expect_true(test8)
+ })
+
+ testthat::test_that("Codebook - key value", {
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z7"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output = "list")
+
+ # Key and value in double quotations
+testthat::expect_true(all(
+ cbook$rankaversion$Player$gender$choices$key == c("Male1", "Female")))
- })
+testthat::expect_true(all(
+ cbook$rankaversion$Player$gender$choices$value == c("Male", "Femaleval")))
- testthat::test_that("Codebook (w) - constants var not there", {
- # Try user Var
- testthat::expect_message(
- testthat::expect_warning(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new2"),
- fsource = "init",
- output = "list"), "is not in Constants"),
- "Variables without documentation.*bargaining\\$Group\\$total_requests")
+# Key and value in single quotations
+testthat::expect_true(all(
+ cbook$rankaversion$Player$gender2$choices$key == c("Male", "Female")))
- test1 <-
- cbook$bargaining$Player$request$max == "C.AMOUNT_SHARED_false"
-
- # Check if leading and trailing brackets and comments are removed
- test2 <- cbook$bargaining$Player$request$label ==
- "Please enter an amount from 0 to 100"
- test3 <- cbook$bargaining$Player$request2$label ==
- "Please enter an amount from 0 to 100"
- test4 <- cbook$bargaining$Player$request3$label ==
- "Please enter an amount from 0 to 100"
+testthat::expect_true(all(
+ cbook$rankaversion$Player$gender2$choices$value == c("Male", "Femaleval")))
+ })
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- })
+ testthat::test_that("Codebook - empty arguments", {
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output = "list"))
- testthat::test_that("Codebook (w) - folder without settings", {
-
- warnings <- testthat::capture_warnings(
- cbook <- codebook(
- fsource = "model",
- path = testthat::test_path("testdata", "ocode_z3.1"),
- output = "list",
- doc_info = FALSE))
-
- test1 <- any(grepl(
- pattern = "There is no settings.* in your path.*Folder .*rankaversion.* reference: .*StartToken",
- x = warnings))
- test2 <- any(grepl(
- pattern = "too complex",
- x = warnings))
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
+
+
+ # Empty argument after choices
+ testthat::expect_true(
+ cbook$rankaversion$Player$a_richer$choices$value[[2]] ==
+ "B is the richer person")
+
+ testthat::expect_true(all(
+ names(cbook$rankaversion$Player$a_richer) == c("noargs", "doc", "choices", "field")))
+
+ testthat::expect_true(all(
+ cbook$rankaversion$Player$a_richer$choices$value ==
+ c("A is the richer person", "B is the richer person")))
+
+ # Empty arguments after doc
+ testthat::expect_true(
+ cbook$rankaversion$Player$testempty$doc == "This is an example doc")
+ testthat::expect_true(all(names(cbook$rankaversion$Player$testempty) ==
+ c("noargs", "doc", "field")))
+
+ # Variable after that
+ testthat::expect_true(exists("is_trick", cbook$rankaversion$Player))
+
+ })
- })
+ testthat::test_that("Codebook - from-to string values", {
- testthat::test_that("Codebook (e) - path", {
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z5"),
+ fsource = "models",
+ output_format = "html",
+ output_file = "fromtovalues",
+ output = "list",
+ settings_replace = NULL,
+ doc_info = FALSE)
+
+
+ cbook$MIG1$Player$money_in_month$choices[1] == "0-399"
+ cbook$MIG1$Player$money_in_month$choices[2] == "400-699"
+
+
+
+ })
+
+ testthat::test_that("Codebook - newlines in doc", {
+
+ warning <- testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z4"),
+ fsource = "models",
+ output = "list",
+ settings_replace = NULL,
+ doc_info = FALSE))
+
+ testthat::expect_true(cbook$end$Player$completionCode$doc ==
+ "Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are legal problems with the participants")
+ testthat::expect_true(cbook$end$Player$completionCodespaces$doc ==
+ "Completion Code for MTurk. Has no role for the experiment and will not be validated unless there are legal problems with the participants")
+
+ })
+
+ testthat::test_that("Codebook (e) - settings var. not there3", {
+
+ # Try user Var but with some missing
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ user_settings = list(error = "Test"),
+ settings_replace = "user",
+ output = "list")
+ , " not in user\\_settings and cannot be replaced.*\\$rankaversion\\$MinutesForSurvey")
+ })
+
+ testthat::test_that("Codebook - pdf brackets", {
+
+ # TODO hier überall checken wie rankaversion$Constants$choices in output angezeigt wird
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output_dir = NULL,
+ fsource = "models",
+ output_file = "newline", # Pretty :)
+ splitvarname = TRUE,
+ doc_info = FALSE,
+ output = "list",
+ sep_list = "newline"), "Some variables")
+
- # Wrong path
- testthat::expect_error(
- cbook <- codebook(
- path = NULL,
- output = "list",
- doc_info = TRUE), "Path must not be NULL")
- })
-
- testthat::test_that("Codebook (e) - relative path", {
-
- # Relative path
- testthat::expect_error(
- cbook <- codebook(
- output_dir = "../",
- output = "list",
- doc_info = TRUE), "Please don't use relative paths in output_dir")
-
- # Relative path
- testthat::expect_error(
- cbook <- codebook(
- output_dir = "..",
- output = "list",
- doc_info = TRUE), "Please don't use relative paths in output_dir")
-
- # Relative path
- testthat::expect_error(
- cbook <- codebook(
- output_dir = ".",
- output = "list",
- doc_info = TRUE), "Please don't use relative paths in output_dir")
-
- # Relative path
- testthat::expect_error(
- cbook <- codebook(
- output_dir = "./",
- output = "list",
- doc_info = TRUE), "Please don't use relative paths in output_dir")
-
- })
-
- testthat::test_that("Codebook (w) - old oTree, only list", {
-
- testthat::expect_message(
- testthat::expect_warning(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z"),
- fsource = "model",
- output = "list",
- doc_info = TRUE),
- ".*too complex for this function.*App rankaversion\\(Constants\\).*App rankend\\(Constants\\) \\(read_csv\\).*\\$settings\\$showupToken \\(float\\).*\\$end\\$Constants\\$showupToken \\(float\\).*\\$end\\$Constants\\$showupTokenTest \\(float\\)"
- ), "Variables without.*rankaversion\\$Player\\$choicenumber.*rankend\\$Player\\$done_distribution")
-
- testthat::expect_true(cbook$rankaversion$Constants$randomtest == 35L)
- test1 <- is.list(cbook)
-
- # Test settings in settings replacements
- test2 <- cbook$settings$payoffPart1_c ==
- 6L * cbook$settings$ExchangeToken
-
- # Test settings in Constants replacement
- test3 <- cbook$end$Constants$payoffPart1_c ==
- cbook$settings$payoffPart1_c
-
- test4 <- cbook$end$Constants$ExchangeToken ==
- cbook$settings$ExchangeToken
-
- test5 <- cbook$end$Constants$ExchangeToken == 4L
- # Test constants in Constants replacement
- test6 <- cbook$end$Constants$ExchangeRate ==
- as.numeric(cbook$end$Constants$ExchangeToken) /
- as.numeric(cbook$end$Constants$ExchangeMainCurrency)
-
- test7 <- cbook$end$Constants$showupToken ==
- cbook$end$Constants$showupTokenTest
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- testthat::expect_true(test7)
-
- })
-
- testthat::test_that("Codebook (w) - i - with example, no settings.py", {
- # Tests code that contains "with" + no settings.py
-
- mywarnings <- testthat::capture_warnings(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_g"),
- fsource = "init", # wrong because old otree
- output = "list",
- doc_info = FALSE)
- )
-
- test1 <- any(grepl(
- pattern = "not in settings and cannot be replaced",
- x = mywarnings))
-
- test2 <- any(grepl(
- pattern = "too complex for this function",
- x = mywarnings))
-
- test3 <- cbook$effort_add$Constants$NUM_ROUNDS == 1L
- test4 <- cbook$effort_add$Constants$NAME_IN_URL == "effort_add"
- test5 <- cbook$effort_add$Constants$NUM_TASKS == "len(INTS)"
- test6 <- cbook$effort_add$Constants$TASK_TIMER == "settings.task_timer"
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- })
-
- testthat::test_that("Codebook (w) - setting var not there 4", {
-
- # Try user Var
- message <- capture_messages(
- testthat::expect_warning(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new3"),
- settings_replace = "global",
- fsource = "init",
- output = "list") , "are not in settings and"))
-
- testthat::expect_true(
- grepl(x = message,
- pattern = "Variables without documentation.*bargaining\\$Group\\$total_requests"))
-
- test1 <-
- cbook$bargaining$Player$request$max == "settings.AMOUNT_SHARED"
-
- testthat::expect_true(test1)
- })
-
- testthat::test_that("Codebook (e) - app not there", {
-
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z"),
- fsource = "init", # wrong because old otree
- output = "list",
- doc_info = TRUE,
- app = "xyp"),
- "not in oTree code"
- )
- })
-
- testthat::test_that("Codebook (e) - settings var. not there3", {
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output_file = "cb_vector_complex", # Not pretty yet
+ doc_info = FALSE,
+ output = "list",
+ sep_list = "vector"), "Some variables") # TODO not working properly because the cell is too large, bzw. kommt da keine warning message
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output_format = "pdf_document_simple", # Not pretty yet
+ output_file = "cb_vector_simple",
+ output = "list",
+ doc_info = FALSE,
+ sep_list = "vector"), "Some variables")
+
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output_format = "word_document", # Word works
+ output_file = "vector_word",
+ output = "list",
+ doc_info = FALSE,
+ sep_list = "vector"), "Some variables")
+ })
- # Try user Var but with some missing
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z2"),
- fsource = "model",
- user_settings = list(error = "Test"),
- settings_replace = "user",
- output = "list"),
- "is not in user_settings")
- })
+ # Equal sign
+ testthat::test_that("Codebook - escaped equal signs in doc values", {
+
+ cbook <- codebook(testthat::test_path("testdata", "ocode_f2"),
+ fsource = "model",
+ app = "MIG1",
+ doc_info = FALSE,
+ output = "list")
+
+ # Vales in oTree code should be written with \=
+ testthat::expect_true(
+ cbook$MIG1$Player$P1_ConsumptionFinal$doc ==
+ "Final Consumption \\= with TokenAdd as voted for by group")
+ testthat::expect_true(
+ cbook$MIG1$Player$P1_ConsumptionNoDis$doc ==
+ "Initial Consumption \\= no Redistribution")
+ testthat::expect_true(
+ cbook$MIG1$Player$P1_ConsumptionEqual$doc ==
+ "Initial Consumption \\= with TokenAdd as suggested by Experimenter")
+ testthat::expect_true(
+ cbook$MIG1$Player$P1_ConsumptionWeakerFirst$doc ==
+ "Initial Consumption \\= with TokenAdd as suggested by Weaker First")
+ testthat::expect_true(
+ cbook$MIG1$Player$P1_ConsumptionMixed$doc ==
+ "Initial Consumption \\= with TokenAdd as suggested by Mixed")
+ })
+
+ testthat::test_that("Codebook (e)- equal signs in doc values", {
+ # If there are unescaped equal signs, errors are thrown
- testthat::test_that("Codebook (e) - wrong settings replace", {
+ testthat::expect_error({
- # Wrong text
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z2"),
- fsource = "model",
- user_settings = list(error = "Test"),
- settings_replace = "wrongString",
- output = "list"),
- "must be either")
- })
-
- testthat::test_that("Codebook (e) - user settings and global_s mismatch", {
-
- # Wrong settings_replace
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z2"),
- fsource = "model",
- user_settings = list(error = "Test",
- showupToken = 2L),
- settings_replace = "global",
- output = "list"),
- "settings_replace must be set to"
- )
+ cbook <- codebook(testthat::test_path("testdata", "ocode_f1"),
+ fsource = "model",
+ doc_info = FALSE,
+ app = "MIG1",
+ output_file = "esindoc",
+ output = "list")
+
+ }, "read properly by gmoTree.*\\$MIG1\\$Player\\$P1_ConsumptionFinal")
+ })
+
+ testthat::test_that("Codebook (e)- equal signs in widgets", {
+ # If there are unescaped equal signs, errors are thrown
+
+ # testthat::expect_error({
+
+ cbook <- codebook(testthat::test_path("testdata", "ocode_f4"),
+ fsource = "model",
+ doc_info = FALSE,
+ app = "MIG1",
+ output_file = "cb_of4", # TODO achtung. hier wird Group blöd angezeigt.
+ output = "list")
+
+ # }, " cannot be read properly by gmoTree.*(MIG1\\$Player\\$user_total") # TODO hier wird kein error gezegit
+ })
+
+ testthat::test_that("Codebook (e)- equal signs in choices values", {
+ # If there are unescaped equal signs, errors are thrown
+
+ testthat::expect_error({
+
+ cbook <- codebook(testthat::test_path("testdata", "ocode_f3"),
+ fsource = "model",
+ doc_info = FALSE,
+ app = "MIG1",
+ output = "list")
+
+ }, "cannot be read properly by gmoTree.*\\$MIG1\\$Group\\$treatment_ec.*\\$MIG1\\$Player\\$P1_AckVote")
+ })
+
+ testthat::test_that("Codebook - escaped equal signs in choices values", {
+ # If there are unescaped equal signs, errors are thrown
+
+ cbook <- codebook(testthat::test_path("testdata", "ocode_f4"),
+ fsource = "model",
+ doc_info = FALSE,
+ app = "MIG1",
+ output = "list")
+
+ # TODO Also check in output file
+ # TODO check auch wie viele antworten
+ testthat::expect_true(length(cbook$MIG1$Group$treatment_ec$choices) == 2)
+ testthat::expect_true(cbook$MIG1$Group$treatment_ec$choices$key[1] == 0)
+ testthat::expect_true(cbook$MIG1$Group$treatment_ec$choices$value[1] ==
+ "0 \\= tolle Anfangssausstattung")
+ testthat::expect_true(length(cbook$MIG1$Player$P1_AckVote$choices) == 2)
+ testthat::expect_true(cbook$MIG1$Player$P1_AckVote$choices$value[1] == "Das Verfahren x \\= 1 soll anerkannt werden")
+
+ # Other tests
+ testthat::expect_true(all(
+ names(cbook$MIG1$Group$P1_Rej_nArgAkzNo_2) == c("noargs", "initial", "field")))
+
+ })
+
+ # Output
+ testthat::test_that("Codebook (e) - wrong output format", {
+
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "both",
+ output_open = TRUE,
+ output_format = "WrongFormat",
+ doc_info = FALSE)}, "Output format should be")
+ })
+
+ testthat::test_that("Codebook (e) - dots in names", {
+
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_file = "coebook.new",
+ output = "both",
+ output_open = TRUE,
+ fsource = "init")
+
+ }, "You are not allowed to use dots in your output_file names")
+
+ })
+
+ testthat::test_that("Codebook (e) - dir not there", {
+
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_file = "codebooknothappening",
+ output_dir = "E:/folder",
+ output = "both",
+ output_open = TRUE,
+ fsource = "init")
+
+ }, "The directory.*does not exist yet.")
+
+ })
+
+ testthat::test_that("Codebook (e) - wrong output", {
+
+ # Wrong text
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = NULL,
+ output = "WRONG",
+ fsource = "init")}, "Output should be")
+
+ # NULL
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = NULL,
+ output = "NULL",
+ fsource = "init")}, "Output should be")
+
+
+ # Two inputs
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = NULL,
+ fsource = "init",
+ output = c("file", "list"))},
+ "Output should be")
+
+ # Output dir and file don't align
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_file = "E:/folder/filename",
+ output_dir = "E:/folder2",
+ output = "both",
+ output_open = TRUE,
+ fsource = "init")}, "When using an absolute path for")
+
+ })
+
+ testthat::test_that("Codebook (e) - output file contains invalid path", {
+
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output_dir = NULL,
+ output_file = "E:/GMO/gmoTree2/codebooktestprint/ocode_newivalpath",
+ output = "both",
+ output_open = TRUE,
+ app = "dictator",
+ doc_info = FALSE), "The directory .* does not exist.")
+ })
+
+ testthat::test_that("Codebook (e) - empty output_file", {
+
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_file = NULL,
+ output = "both",
+ output_open = TRUE,
+ fsource = "init")
- # Wrong variable
+ }, "Please enter a output_file name!")
+
+ })
+
+ testthat::test_that("Codebook (e) - params", {
+ warnings <- testthat::capture_warnings(
testthat::expect_error(
+
cbook <- codebook(
path = testthat::test_path("testdata", "ocode_z2"),
fsource = "model",
- user_settings = list(error = "Test",
- showupToken = 2L),
- settings_replace = "user",
+ params = "ab",
output = "list"),
- "is not in user_settings"
- )
- })
-
- testthat::test_that("Codebook (w) - settings var. not there 1", {
- # Settings not there
-
- warnings <- testthat::capture_warnings(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z2"),
- fsource = "model",
- output = "list",
- doc_info = FALSE)
- )
-
- test1 <- any(grepl(pattern = "not in settings and cannot be replaced",
- x = warnings))
- test2 <- any(grepl(pattern = "too complex for this function",
- x = warnings))
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
-
- })
-
- testthat::test_that("Codebook (e) - wrong source", {
-
- # Wrong source
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "xx",
- output = "list",
- doc_info = TRUE,
- app = "public_goods_simple"),
- "fsource must be either")
-
- # If source is NULL
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = NULL,
- output = "list",
- doc_info = TRUE,
- app = "public_goods_simple"),
- "fsource must be either")
- })
-
- testthat::test_that("Codebook (e) - init instead of models", {
-
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z"),
- fsource = "init", # wrong because old otree
- output = "list",
- doc_info = TRUE),
- "At least one of your init-files is empty"
- )
- })
-
- testthat::test_that("Codebook (e) - models instead of init", {
-
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "model", # wrong because new otree
- output = "list",
- doc_info = TRUE,
- app = "public_goods_simple"), "No files to process"
- )
- })
-
- testthat::test_that("Codebook (e) - path", {
- testthat::expect_error(
- cbook <- codebook(
- path = testthat::test_path("testdata", "nopath"),
- fsource = "init",
- output = "list",
- doc_info = TRUE,
- app = "public_goods_simple"),
- "does not exist")
- })
+ "params must be a list"))
- testthat::test_that("Codebook (w) - vector variable in settings and constants", {
- warning <- testthat::expect_warning(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z3"),
- fsource = "models",
- output = "list",
- output_format = "html_document",
- doc_info = FALSE), "too complex for this function"
- )
-
- # Since R only saves the same type in a vector
- test1 <- cbook$settings$Something == c("1", "3", "test", "3", "1")
-
- test2 <-
- cbook$rankaversion$Constants$Something == c("1", "3", "test", "3", "1")
-
- # Otherwise
- test3 <- cbook$settings$StartToken == c(9.0, 14.0, 17.0, 23.0, 38.0)
-
- test4 <-
- cbook$rankaversion$Constants$StartToken ==
- c(9.0, 14.0, 17.0, 23.0, 38.0)
-
- test5 <- cbook$rankaversion$Constants$StartToken2 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0) * 2.0
- test6 <- cbook$rankaversion$Constants$StartToken3 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0) * 10.0
-
- # Calculations
- test7 <- cbook$settings$Othertest1 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0)
- test8 <- cbook$settings$Othertest2 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0) * 5L
-
- test9 <-
- cbook$rankaversion$Constants$players_per_group == "None"
-
- test10 <-
- cbook$rankaversion$Constants$TestToken ==
- cbook$settings$StartToken * 5.0
-
- test11 <- all(cbook$rankaversion$Player$Acc_DistributionChange$value ==
- c("Ich hätte mich dennoch für Verfahren > xyz < entschieden.",
- "Ich hätte mich für das alternative Verfahren > aaa < entschieden.",
- "Ich hätte mich für das alternative Verfahren > bbb < entschieden."))
-
- test12 <- all(cbook$rankaversion$Player$acceptance$choices$value ==
- c("xyz", "aaa", "Wrong, trick answer", "Correct trick answer"))
-
- testthat::expect_true(all(test1))
- testthat::expect_true(all(test2))
- testthat::expect_true(all(test3))
- testthat::expect_true(all(test4))
- testthat::expect_true(all(test5))
- testthat::expect_true(all(test6))
- testthat::expect_true(all(test7))
- testthat::expect_true(all(test8))
- testthat::expect_true(all(test9))
- testthat::expect_true(all(test10))
- testthat::expect_true(test11)
- testthat::expect_true(test12)
-
- })
-
- testthat::test_that("Codebook (w) - vector variable in settings and constants", {
- # Dissertation code
-
- testthat::expect_warning(
+ })
+
+ # Choosing apps
+ testthat::test_that("Codebook (e) - app and app rm specified", {
+
+ testthat::expect_error(
cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_z3"),
- fsource = "models",
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
output = "list",
- doc_info = FALSE), "too complex for this function")
-
- # Since R only saves the same type in a vector
- test1 <- cbook$settings$Something == c("1", "3", "test", "3", "1")
-
- test2 <-
- cbook$rankaversion$Constants$Something == c("1", "3", "test", "3", "1")
-
- # Otherwise
- test3 <- cbook$settings$StartToken == c(9.0, 14.0, 17.0, 23.0, 38.0)
- test4 <-
- cbook$rankaversion$Constants$StartToken ==
- c(9.0, 14.0, 17.0, 23.0, 38.0)
-
- test5 <- cbook$rankaversion$Constants$StartToken2 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0) * 2.0
- test6 <- cbook$rankaversion$Constants$StartToken3 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0) * 10.0
-
- # Calculations
- test7 <- cbook$settings$Othertest1 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0)
- test8 <- cbook$settings$Othertest2 ==
- c(9.0, 14.0, 17.0, 23.0, 38.0) * 5L
-
- test9 <-
- cbook$rankaversion$Constants$players_per_group == "None"
-
- test10 <-
- cbook$rankaversion$Constants$TestToken ==
- cbook$settings$StartToken * 5L
-
- test11 <- all(
- cbook$rankaversion$Player$Acc_DistributionChange$value ==
- c("Ich hätte mich dennoch für Verfahren > xyz < entschieden.",
- "Ich hätte mich für das alternative Verfahren > aaa < entschieden.",
- "Ich hätte mich für das alternative Verfahren > bbb < entschieden."))
-
- test12 <- all(cbook$rankaversion$Player$acceptance$choices$value ==
- c("xyz", "aaa", "Wrong, trick answer", "Correct trick answer"))
-
- testthat::expect_true(all(test1))
- testthat::expect_true(all(test2))
- testthat::expect_true(all(test3))
- testthat::expect_true(all(test4))
- testthat::expect_true(all(test5))
- testthat::expect_true(all(test6))
- testthat::expect_true(all(test7))
- testthat::expect_true(all(test8))
- testthat::expect_true(all(test9))
- testthat::expect_true(all(test10))
- testthat::expect_true(test11)
- testthat::expect_true(test12)
-
- })
-
- testthat::test_that("Codebook - only list, new oTree, correct sort", {
-
+ doc_info = FALSE,
+ app = "dictator",
+ app_rm = "public_goods_simple"),
+ "Please specify only \"app\" or \"app_rm")
+
+ })
+
+ testthat::test_that("Codebook (e) - apps don't exist", {
+
+ testthat::expect_error({
cbook <- codebook(
path = testthat::test_path("testdata", "ocode_new"),
fsource = "init",
output = "list",
- doc_info = FALSE,
- sort = c("traveler_dilemma", "survey",
- "bargaining", "volunteer_dilemma", "bertrand",
- "common_value_auction", "cournot",
- "dictator", "guess_two_thirds",
- "matching_pennies", "payment_info",
- "prisoner", "public_goods_simple",
- "trust", "trust_simple"))
-
- test1 <- is.list(cbook)
- test2 <- !is.null(cbook$public_goods_simple$Constants)
- test3 <- !is.null(cbook$public_goods_simple$Group)
- test4 <- !is.null(cbook$public_goods_simple$Player)
-
- test5 <-
- cbook$public_goods_simple$Constants$NAME_IN_URL ==
- "public_goods_simple"
- test6 <-
- cbook$public_goods_simple$Group$total_contribution$noargs ==
- "TRUE"
- test7 <-
- cbook$public_goods_simple$Player$contribution$label ==
- "How much will you contribute?"
- test8 <-
- cbook$public_goods_simple$Player$contribution$noargs ==
- "FALSE"
-
- # If there is only one group field without information in it
- test9 <-
- cbook$bertrand$Group$winning_price$field ==
- "CurrencyField"
-
- # If there is one group field that has information in it
- test10 <- cbook$dictator$Group$kept$field ==
- "CurrencyField"
-
- # If there are two group fields with no information in them
- test11 <-
- cbook$public_goods_simple$Group$total_contribution$field ==
- "CurrencyField"
-
- test12 <-
- all(names(cbook) ==
- c("settings", "traveler_dilemma", "survey",
- "bargaining", "volunteer_dilemma", "bertrand",
- "common_value_auction", "cournot",
- "dictator", "guess_two_thirds",
- "matching_pennies", "payment_info",
- "prisoner", "public_goods_simple",
- "trust", "trust_simple"))
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- testthat::expect_true(test7)
- testthat::expect_true(test8)
- testthat::expect_true(test9)
- testthat::expect_true(test10)
- testthat::expect_true(test11)
- testthat::expect_true(test12)
- })
-
- testthat::test_that("Codebook (w) - only list, new oTree, too many sort 2", {
-
- original_sort <-
- c("bargaining", "bertrand", "common_value_auction", "cournot",
- "dictator", "guess_two_thirds", "matching_pennies", "payment_info",
- "prisoner", "public_goods_simple", "survey", "traveler_dilemma",
- "trust", "trust_simple", "volunteer_dilemma")
-
- new_sort <- c("thisisnothere", "payment_info",
- "bargaining", "volunteer_dilemma",
- "bertrand", "common_value_auction",
- "cournot", "dictator",
- "guess_two_thirds", "matching_pennies",
- "prisoner", "public_goods_simple",
- "survey", "traveler_dilemma",
- "trust", "trust_simple")
-
- thiswarning <- capture_warnings(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "init",
- output = "list",
- doc_info = FALSE,
- sort = new_sort)
- )
-
- testthat::expect_true(any(
- grepl(x = thiswarning, pattern = "Sort elements not in apps are")))
-
- testthat::expect_true(
- any(grepl("Sort apps are not equal to all apps", thiswarning)))
-
- testthat::expect_true(any(grepl("Sort elements not in apps are",
- thiswarning)))
-
- test1 <- is.list(cbook)
- test2 <- !is.null(cbook$public_goods_simple$Constants)
- test3 <- !is.null(cbook$public_goods_simple$Group)
- test4 <- !is.null(cbook$public_goods_simple$Player)
-
- test5 <-
- cbook$public_goods_simple$Constants$NAME_IN_URL ==
- "public_goods_simple"
- test6 <-
- cbook$public_goods_simple$Group$total_contribution$noargs ==
- "TRUE"
- test7 <-
- cbook$public_goods_simple$Player$contribution$label ==
- "How much will you contribute?"
- test8 <-
- cbook$public_goods_simple$Player$contribution$noargs ==
- "FALSE"
-
- # If there is only one group field without information in it
- test9 <- cbook$bertrand$Group$winning_price$field == "CurrencyField"
-
- # If there is one group field that has information in it
- test10 <- cbook$dictator$Group$kept$field == "CurrencyField"
-
- # If there are two group fields with no information in them
- test11 <-
- cbook$public_goods_simple$Group$total_contribution$field == "CurrencyField"
-
- test12 <-
- all(names(cbook) == c("settings", original_sort))
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- testthat::expect_true(test7)
- testthat::expect_true(test8)
- testthat::expect_true(test9)
- testthat::expect_true(test10)
- testthat::expect_true(test11)
- testthat::expect_true(test12)
- })
-
- testthat::test_that("Codebook (w) - only list, new oTree, false sort", {
-
- thiswarning <- capture_warnings(
+ app = c("dictator", "nonexistingapp"),
+ doc_info = FALSE)}, "At least one app")
+ })
+
+ testthat::test_that("Codebook (e) - one app not there", {
+
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z"),
+ fsource = "init", # wrong because old otree
+ output = "list",
+ doc_info = TRUE,
+ app = "xyp"),
+ "not in oTree code"
+ )
+ })
+
+ # Settings
+ testthat::test_that("Codebook - three level list in settings work", {
+
+ # If settings_replace is global
+ testthat::expect_error({
+ cbook1 <- codebook(
+ path = testthat::test_path("testdata", "ocode_z11"),
+ output_dir = NULL,
+ output = "list",
+ settings_replace = "global",
+ fsource = "model")
+ }, "not support lists.*settings")
+
+ # If settings_replace is NULL
+ cbook2 <- codebook(
+ path = testthat::test_path("testdata", "ocode_z11"),
+ output_dir = NULL,
+ output = "list",
+ settings_replace = NULL,
+ fsource = "model")
+
+ testthat::expect_null(cbook2$rankaversion$settings)
+ testthat::expect_true(
+ cbook2$rankaversion$Constants$Something == "settings.Something")
+
+ })
+
+ testthat::test_that("Codebook (w) - setting var not there 4", {
+
+ # Try user Var
+ message <- capture_messages(
+ testthat::expect_warning(
cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
+ path = testthat::test_path("testdata", "ocode_new3"),
+ settings_replace = "global",
fsource = "init",
- output = "list",
- doc_info = FALSE,
- sort = c("public_goods_simple", "dictator")
- ))
-
- testthat::expect_true(
- any(grepl("Sort apps are not equal to all apps", thiswarning)))
-
- test1 <- is.list(cbook)
- test2 <- !is.null(cbook$public_goods_simple$Constants)
- test3 <- !is.null(cbook$public_goods_simple$Group)
- test4 <- !is.null(cbook$public_goods_simple$Player)
-
- test5 <-
- cbook$public_goods_simple$Constants$NAME_IN_URL ==
- "public_goods_simple"
- test6 <-
- cbook$public_goods_simple$Group$total_contribution$noargs ==
- "TRUE"
- test7 <-
- cbook$public_goods_simple$Player$contribution$label ==
- "How much will you contribute?"
- test8 <-
- cbook$public_goods_simple$Player$contribution$noargs ==
- "FALSE"
-
- # If there is only one group field without information in it
- test9 <- cbook$bertrand$Group$winning_price$field == "CurrencyField"
+ output = "list")
+ , "are not in settings and"))
+
+ testthat::expect_true(
+ grepl(x = paste(message, collapse = ""),
+ pattern = "Variables without documentation.*bargaining\\$Group\\$total_requests"))
+
+ test1 <-
+ cbook$bargaining$Player$request$max == "settings.AMOUNT_SHARED"
+
+ testthat::expect_true(test1)
+ })
+
+ testthat::test_that("Codebook - setting, constants type", {
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z9"),
+ fsource = "models",
+ output = "list",
+ doc_info = FALSE)
+
+
+ testthat::expect_identical(
+ cbook$settings$Something,
+ list(1, 3, "test", 3, 1))
+
+ testthat::expect_identical(
+ cbook$settings$Something,
+ cbook$rankaversion$Constants$Something)
+
+ })
- # If there is one group field that has information in it
- test10 <- cbook$dictator$Group$kept$field == "CurrencyField"
+ testthat::test_that("Codebook (w) - i - with example, no settings.py", {
+ # Tests code that contains "with" + no settings.py
+
+ mywarnings <- testthat::capture_warnings(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_g"),
+ fsource = "init", # wrong because old otree
+ output = "list",
+ doc_info = FALSE)
+ )
+
+ test1 <- any(grepl(
+ pattern = "not in settings and cannot be replaced",
+ x = mywarnings))
+
+ test2 <- any(grepl(
+ pattern = "too complex for this function",
+ x = mywarnings))
+
+ test3 <- cbook$effort_add$Constants$NUM_ROUNDS == 1L
+ test4 <- cbook$effort_add$Constants$NAME_IN_URL == "effort_add"
+ test5 <- cbook$effort_add$Constants$NUM_TASKS == "len(INTS)"
+ test6 <- cbook$effort_add$Constants$TASK_TIMER == "settings.task_timer"
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ })
+
+ testthat::test_that("Codebook (e) - wrong settings replace", {
+
+ # Wrong text
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ user_settings = list(error = "Test"),
+ settings_replace = "wrongString",
+ output = "list"),
+ "must be either")
+ })
+
+ testthat::test_that("Codebook (e) - user settings and global_s mismatch", {
+
+ # Wrong settings_replace
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ user_settings = list(error = "Test",
+ showupToken = 2L),
+ settings_replace = "global",
+ output = "list")
+ , "settings_replace must be set to"
+ )
+
+ # Wrong variable
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ user_settings = list(error = "Test",
+ showupToken = 2L),
+ settings_replace = "user",
+ output = "list"),
+ "not in user_settings and"
+ )
+ })
+
+ testthat::test_that("Codebook (w) - settings var. not there 1", {
+ # Settings not there
+
+ warnings <- testthat::capture_warnings(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ output = "list",
+ doc_info = FALSE)
+ )
+
+ test1 <- any(grepl(pattern = "not in settings and cannot be replaced",
+ x = warnings))
+ test2 <- any(grepl(pattern = "too complex for this function",
+ x = warnings))
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+
+ })
+
+ testthat::test_that("Codebook (w) - folder without settings", {
+
+ warnings <- testthat::capture_warnings(
+ cbook <- codebook(
+ fsource = "model",
+ path = testthat::test_path("testdata", "ocode_z3.1"),
+ output = "list",
+ doc_info = FALSE))
+
+ test1 <- any(grepl(
+ pattern = "There is no settings.* in your path..*\\$rankaversion\\$Testnumber, reference \"settings.Testnumber",
+ x = warnings))
+
+ test2 <- any(grepl(
+ pattern = "too complex",
+ x = warnings))
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+
+ # Check if variables are there only once
+ testthat::expect_true(
+ stringr::str_count(warnings, "\\$rankaversion\\$Testnumber") == 1)
+ testthat::expect_true(
+ stringr::str_count(warnings, "\\$rankaversion\\$Something") == 1)
+ testthat::expect_true(
+ stringr::str_count(warnings, "\\$rankaversion\\$TestToken") == 1)
+
+ # User settings
+ warnings <- testthat::capture_warnings(
+ cbook <- codebook(
+ fsource = "model",
+ path = testthat::test_path("testdata", "ocode_z3.1"),
+ output = "list",
+ settings_replace = "user",
+ doc_info = FALSE))
+
+ # Check if variables are there only once
+ testthat::expect_true(
+ stringr::str_count(warnings, "\\$rankaversion\\$Testnumber") == 1)
+ testthat::expect_true(
+ stringr::str_count(warnings, "\\$rankaversion\\$Something") == 1)
+ testthat::expect_true(
+ stringr::str_count(warnings, "\\$rankaversion\\$TestToken") == 1)
+
+ })
+
+ testthat::test_that("Codebook - user_settings", {
+
+ # Comparison without settings.py variable
+ testthat::expect_warning(
+ cbook_default <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ settings_replace = "global",
+ doc_info = FALSE,
+ output = "list"))
+
+
+ # Try user Var
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z2"),
+ fsource = "model",
+ user_settings = list(error2 = "Test",
+ showupToken = 2,
+ max_payoffPart1_ab = 1,
+ ExchangeMainCurrency = 1,
+ payoff_survey = 1,
+ MinutesForSurvey = 20,
+ TestVector2 = c(1,2,3),
+ TestVectorC2 = c("a", "b"),
+ ExchangeToken = 1,
+ timer123 = 12,
+ payoffPart1_c = 1),
+ settings_replace = "user",
+ doc_info = FALSE,
+ output = "list"), "too complex for this function")
+
+ cbook$rankend$Constants$settings.TestVector2
+
+ # Models.py: errorvariable <- settings.error
+
+ testthat::expect_true(cbook_default$rankend$Constants$Test1 == 1000)
+ testthat::expect_identical(cbook_default$rankend$Constants$TestVector,
+ list(1,10,3,4,5))
+ testthat::expect_identical(cbook_default$rankend$Constants$TestVectorC,
+ list("a", "b", 6))
+
+ # Variables in settings.py
+ test1 <- cbook_default$rankaversion$Constants$error2 == "Error2insettings"
+ test2 <- cbook_default$rankaversion$Constants$MinutesForSurvey == 18
+ # User setting variables
+ testthat::expect_identical(
+ cbook_default$rankend$Constants$TestVector2,
+ list(99, 66, 33)) # settings.TestVector2
+ testthat::expect_identical(cbook_default$rankend$Constants$TestVectorC2,
+ list("d", "e", 4))
+ test3 <- cbook$rankaversion$Constants$error2 == "Test" # This variable is not in settings.py
+ test4 <- cbook$rankaversion$Constants$MinutesForSurvey == 20
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ })
+
+ # Fsource
+ testthat::test_that("Codebook (e) - fsource not valid", {
+
+ # Wrong source text
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "xx",
+ output = "list",
+ doc_info = TRUE,
+ app = "public_goods_simple"),
+ "fsource must be either")
+
+ # If source is NULL
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = NULL,
+ output = "list",
+ doc_info = TRUE,
+ app = "public_goods_simple"),
+ "fsource must be either")
+
+ # Wrong length
+ testthat::expect_error({
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = NULL,
+ fsource = c("init", "model"),
+ output = "list")}, "Please enter only one fsource")
+
+ })
+
+ testthat::test_that("Codebook (e) - fsource init instead of models", {
+
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z"),
+ fsource = "init", # wrong because old otree
+ output = "list",
+ doc_info = TRUE),
+ "At least one of your init-files is empty"
+ )
+ })
+
+ testthat::test_that("Codebook (e) - fsource models instead of init", {
+
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "model", # wrong because new otree
+ output = "list",
+ doc_info = TRUE,
+ app = "public_goods_simple"), "No files to process"
+ )
+ })
+
+ # List variables
+ testthat::test_that("Codebook - vector variable in settings and constants", {
+ warning <- testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z3"),
+ fsource = "models",
+ output = "list",
+ doc_info = FALSE)
+ , "code that is too complex for this function" # read csv problem
+ )
+
+ # Since R only saves the same type in a vector
+ testthat::expect_identical(cbook$settings$Something,
+ list(1, 3, "test", 3, 1))
+
+ testthat::expect_identical(
+ cbook$rankaversion$Constants$Something,list(1, 3, "test", 3, 1))
+
+ # Otherwise
+ testthat::expect_identical(cbook$settings$StartToken,
+ list(9.0, 14.0, 17.0, 23.0, 38.0))
+
+ test4 <-
+ cbook$rankaversion$Constants$StartToken ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0)
+
+ test5 <- cbook$rankaversion$Constants$StartToken2 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0) * 2.0
+ test6 <- cbook$rankaversion$Constants$StartToken3 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0) * 10.0
+
+ # Calculations
+ test7 <- cbook$settings$Othertest1 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0)
+ test8 <- cbook$settings$Othertest2 ==
+ c(9.0, 14.0, 17.0, 23.0, 38.0) * 5L
+
+ test9 <-
+ cbook$rankaversion$Constants$players_per_group == "None"
+
+ testthat::expect_identical(
+ cbook$rankaversion$Constants$TestToken,
+ unlist(cbook$settings$StartToken) * 5.0
+ )
- # If there are two group fields with no information in them
- test11 <-
- cbook$public_goods_simple$Group$total_contribution$field == "CurrencyField"
+
+ test11 <- all(cbook$rankaversion$Player$Acc_DistributionChange$value ==
+ c("Ich hätte mich dennoch für Verfahren > xyz < entschieden.",
+ "Ich hätte mich für das alternative Verfahren > aaa < entschieden.",
+ "Ich hätte mich für das alternative Verfahren > bbb < entschieden."))
+
+ test12 <- all(cbook$rankaversion$Player$acceptance$choices$value ==
+ c("xyz", "aaa", "Wrong, trick answer", "Correct trick answer"))
+
+ testthat::expect_true(all(test4))
+ testthat::expect_true(all(test5))
+ testthat::expect_true(all(test6))
+ testthat::expect_true(all(test7))
+ testthat::expect_true(all(test8))
+ testthat::expect_true(all(test9))
+ testthat::expect_true(test11)
+ testthat::expect_true(test12)
+
+ })
+
+ testthat::test_that("Codebook - check sublists with different types", {
+ # Other sublist tests are in brackets tests
+
+ testthat::expect_warning(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_z6"),
+ output_dir = NULL,
+ fsource = "models",
+ splitvarname = TRUE,
+ output = "list")
+ )
+
+ # Currently, numbers are still in strings if one of the elements is a string element
+
+ # Check if original numbers are numbers
+ testthat::expect_true(cbook$rankaversion$Constants$choices[[1]][[1]] == 8)
+ testthat::expect_true(cbook$rankaversion$Constants$choices[[2]][[1]] == 80)
+ testthat::expect_true(cbook$rankaversion$Constants$choices[[3]][[1]] == "8")
+ testthat::expect_true(cbook$rankaversion$Constants$choices[[1]][[6]] == "replacingsettingsworked")
+
+ testthat::expect_true(cbook$rankaversion$Constants$choices[[2]][[6]] == "settings.shouldnotwork")
+
+ })
- test12 <-
- all(names(cbook) ==
- c("settings", "bargaining", "bertrand",
+ # Path
+ testthat::test_that("Codebook (e) - path does not exist", {
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "nopath"),
+ fsource = "init",
+ output = "list",
+ doc_info = TRUE,
+ app = "public_goods_simple"),
+ "does not exist")
+ })
+
+ testthat::test_that("Codebook (e) - path is NULL", {
+
+ # Wrong path
+ testthat::expect_error(
+ cbook <- codebook(
+ path = NULL,
+ output = "list",
+ doc_info = TRUE), "Path must not be NULL")
+ })
+
+ testthat::test_that("Codebook (e) - relative path", {
+
+ # Relative path
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output_dir = "../",
+ output = "both",
+ output_open = TRUE,
+ doc_info = TRUE), "Please don't use relative paths in output_dir")
+
+ # Relative path
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = "..",
+ output = "both",
+ output_open = TRUE,
+ doc_info = TRUE), "Please don't use relative paths in output_dir")
+
+ # Relative path
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = ".",
+ output = "both",
+ output_open = TRUE,
+ doc_info = TRUE), "Please don't use relative paths in output_dir")
+
+ # Relative path
+ testthat::expect_error(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ output_dir = "./",
+ output = "both",
+ output_open = TRUE,
+ doc_info = TRUE), "Please don't use relative paths in output_dir")
+
+ })
+
+ # Sort
+ testthat::test_that("Codebook - new oTree, correct sort", {
+
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "list",
+ doc_info = FALSE,
+ sort = c("traveler_dilemma", "survey",
+ "bargaining", "volunteer_dilemma", "bertrand",
"common_value_auction", "cournot",
"dictator", "guess_two_thirds",
"matching_pennies", "payment_info",
"prisoner", "public_goods_simple",
- "survey", "traveler_dilemma",
- "trust", "trust_simple", "volunteer_dilemma"))
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- testthat::expect_true(test7)
- testthat::expect_true(test8)
- testthat::expect_true(test9)
- testthat::expect_true(test10)
- testthat::expect_true(test11)
- testthat::expect_true(test12)
- })
-
- testthat::test_that("Codebook - only list, new oTree, only one app", {
-
- testthat::expect_message(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "init",
- output = "list",
- doc_info = TRUE,
- app = "public_goods_simple"),
- "Variables without documentation, label, or verbose name:"
- )
-
- test1 <- is.list(cbook)
- test2 <- !is.null(cbook$public_goods_simple$Constants)
- test3 <- !is.null(cbook$public_goods_simple$Group)
- test4 <- !is.null(cbook$public_goods_simple$Player)
-
- test5 <-
- cbook$public_goods_simple$Constants$NAME_IN_URL ==
- "public_goods_simple"
- test6 <-
- cbook$public_goods_simple$Group$total_contribution$noargs ==
- "TRUE"
- test7 <-
- cbook$public_goods_simple$Player$contribution$label ==
- "How much will you contribute?"
- test8 <-
- cbook$public_goods_simple$Player$contribution$noargs ==
- "FALSE"
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- testthat::expect_true(test7)
- testthat::expect_true(test8)
- })
-
- testthat::test_that("Codebook (w) - only list, too many sort", {
- # Without trust_simple
-
- original_sort <-
- c("bargaining", "bertrand", "common_value_auction", "cournot",
- "dictator", "guess_two_thirds", "matching_pennies", "payment_info",
- "prisoner", "public_goods_simple", "survey", "traveler_dilemma",
- "trust", "trust_simple", "volunteer_dilemma")
-
- new_sort <- c("thisisnothere", "payment_info",
- "bargaining", "volunteer_dilemma",
- "bertrand", "common_value_auction",
- "cournot", "dictator",
- "guess_two_thirds", "matching_pennies",
- "prisoner", "public_goods_simple",
- "survey", "traveler_dilemma",
- "trust")
-
- thiswarning <- capture_warnings(
- cbook <- codebook(
- path = testthat::test_path("testdata", "ocode_new"),
- fsource = "init",
- output = "list",
- output_format = "html_document",
- doc_info = FALSE,
- sort = new_sort)
- )
-
- testthat::expect_true(any(
- grepl(x = thiswarning, pattern = "Sort elements not in apps are")))
-
- testthat::expect_true(
- any(grepl("Sort apps are not equal to all apps", thiswarning)))
-
- testthat::expect_true(any(grepl("Sort elements not in apps are",
- thiswarning)))
-
- test1 <- is.list(cbook)
- test2 <- !is.null(cbook$public_goods_simple$Constants)
- test3 <- !is.null(cbook$public_goods_simple$Group)
- test4 <- !is.null(cbook$public_goods_simple$Player)
-
- test5 <-
- cbook$public_goods_simple$Constants$NAME_IN_URL ==
- "public_goods_simple"
- test6 <-
- cbook$public_goods_simple$Group$total_contribution$noargs ==
- "TRUE"
- test7 <-
- cbook$public_goods_simple$Player$contribution$label ==
- "How much will you contribute?"
- test8 <-
- cbook$public_goods_simple$Player$contribution$noargs ==
- "FALSE"
-
- # If there is only one group field without information in it
- test9 <- cbook$bertrand$Group$winning_price$field == "CurrencyField"
-
- # If there is one group field that has information in it
- test10 <- cbook$dictator$Group$kept$field == "CurrencyField"
-
- # If there are two group fields with no information in them
- test11 <-
- cbook$public_goods_simple$Group$total_contribution$field == "CurrencyField"
-
- test12 <-
- all(names(cbook) == c("settings", original_sort))
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
- testthat::expect_true(test3)
- testthat::expect_true(test4)
- testthat::expect_true(test5)
- testthat::expect_true(test6)
- testthat::expect_true(test7)
- testthat::expect_true(test8)
- testthat::expect_true(test9)
- testthat::expect_true(test10)
- testthat::expect_true(test11)
- testthat::expect_true(test12)
-
- # Check if "yes, I will" is one element
- testthat::expect_true(
- length(cbook$bargaining$Player$level2$choices) == 3L)
-
- testthat::expect_true(
- cbook$bargaining$Player$level2$choices[1] == "No, I won't")
- testthat::expect_true(
- cbook$bargaining$Player$level2$choices[3] == "Maybe I'll do")
-
- # Test for ''' documentations
- test1 <- grepl(
- pattern = "^A bat and a ball cost 22 dollars in tota.*the ball cost\\?$",
- x = cbook$survey$Player$crt_bat$label)
-
- # Test for """ documentations
- test2 <- grepl(
- pattern = "^If it takes 5 machines 5.*make 100 widgets\\?$",
- x = cbook$survey$Player$crt_widget$label)
-
- testthat::expect_true(test1)
- testthat::expect_true(test2)
-
- # Test for ' choices
- testthat::expect_true(
- cbook$survey$Player$gender$choices$key[1L] == "Male")
- testthat::expect_true(
- cbook$survey$Player$gender$choices$key[2L] == "Female")
- testthat::expect_true(
- cbook$survey$Player$gender$choices$value[1L] == "Male")
- testthat::expect_true(
- cbook$survey$Player$gender$choices$value[2L] == "Female")
-
- # Test for " choices
- testthat::expect_true(
- cbook$survey$Player$gender2$choices$key[1L] == "Male")
- testthat::expect_true(
- cbook$survey$Player$gender2$choices$key[2L] == "Female")
- testthat::expect_true(
- cbook$survey$Player$gender2$choices$value[1L] == "Male")
- testthat::expect_true(
- cbook$survey$Player$gender2$choices$value[2L] == "Female")
-
- # Further
- testthat::expect_equal(length(cbook$prisoner$Player$cooperate$choices), 2L) # True: Cooperate, False Defect
- testthat::expect_true(is.data.frame(cbook$prisoner$Player$cooperate$choices))
- })
+ "trust", "trust_simple"))
+
+ test1 <- is.list(cbook)
+ test2 <- !is.null(cbook$public_goods_simple$Constants)
+ test3 <- !is.null(cbook$public_goods_simple$Group)
+ test4 <- !is.null(cbook$public_goods_simple$Player)
+
+ test5 <-
+ cbook$public_goods_simple$Constants$NAME_IN_URL ==
+ "public_goods_simple"
+ test6 <-
+ cbook$public_goods_simple$Group$total_contribution$noargs ==
+ "TRUE"
+ test7 <-
+ cbook$public_goods_simple$Player$contribution$label ==
+ "How much will you contribute?"
+ test8 <-
+ cbook$public_goods_simple$Player$contribution$noargs ==
+ "FALSE"
+
+ # If there is only one group field without information in it
+ test9 <-
+ cbook$bertrand$Group$winning_price$field ==
+ "CurrencyField"
+
+ # If there is one group field that has information in it
+ test10 <- cbook$dictator$Group$kept$field ==
+ "CurrencyField"
+
+ # If there are two group fields with no information in them
+ test11 <-
+ cbook$public_goods_simple$Group$total_contribution$field ==
+ "CurrencyField"
+
+ test12 <-
+ all(names(cbook) ==
+ c("settings", "traveler_dilemma", "survey",
+ "bargaining", "volunteer_dilemma", "bertrand",
+ "common_value_auction", "cournot",
+ "dictator", "guess_two_thirds",
+ "matching_pennies", "payment_info",
+ "prisoner", "public_goods_simple",
+ "trust", "trust_simple"))
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ testthat::expect_true(test7)
+ testthat::expect_true(test8)
+ testthat::expect_true(test9)
+ testthat::expect_true(test10)
+ testthat::expect_true(test11)
+ testthat::expect_true(test12)
+ })
+
+ testthat::test_that("Codebook (w) - new oTree, too many sort 2", {
+
+ original_sort <-
+ c("bargaining", "bertrand", "common_value_auction", "cournot",
+ "dictator", "guess_two_thirds", "matching_pennies", "payment_info",
+ "prisoner", "public_goods_simple", "survey", "traveler_dilemma",
+ "trust", "trust_simple", "volunteer_dilemma")
+
+ new_sort <- c("thisisnothere", "payment_info",
+ "bargaining", "volunteer_dilemma",
+ "bertrand", "common_value_auction",
+ "cournot", "dictator",
+ "guess_two_thirds", "matching_pennies",
+ "prisoner", "public_goods_simple",
+ "survey", "traveler_dilemma",
+ "trust", "trust_simple")
+
+ thiswarning <- capture_warnings(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "list",
+ doc_info = FALSE,
+ sort = new_sort)
+ )
+
+ testthat::expect_true(any(
+ grepl(x = thiswarning, pattern = "Sort elements not in apps are")))
+
+ testthat::expect_true(
+ any(grepl("Sort apps are not equal to all apps", thiswarning)))
+
+ testthat::expect_true(any(grepl("Sort elements not in apps are",
+ thiswarning)))
+
+ test1 <- is.list(cbook)
+ test2 <- !is.null(cbook$public_goods_simple$Constants)
+ test3 <- !is.null(cbook$public_goods_simple$Group)
+ test4 <- !is.null(cbook$public_goods_simple$Player)
+
+ test5 <-
+ cbook$public_goods_simple$Constants$NAME_IN_URL ==
+ "public_goods_simple"
+ test6 <-
+ cbook$public_goods_simple$Group$total_contribution$noargs ==
+ "TRUE"
+ test7 <-
+ cbook$public_goods_simple$Player$contribution$label ==
+ "How much will you contribute?"
+ test8 <-
+ cbook$public_goods_simple$Player$contribution$noargs ==
+ "FALSE"
+
+ # If there is only one group field without information in it
+ test9 <- cbook$bertrand$Group$winning_price$field == "CurrencyField"
+
+ # If there is one group field that has information in it
+ test10 <- cbook$dictator$Group$kept$field == "CurrencyField"
+
+ # If there are two group fields with no information in them
+ test11 <-
+ cbook$public_goods_simple$Group$total_contribution$field == "CurrencyField"
+
+ test12 <-
+ all(names(cbook) == c("settings", original_sort))
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ testthat::expect_true(test7)
+ testthat::expect_true(test8)
+ testthat::expect_true(test9)
+ testthat::expect_true(test10)
+ testthat::expect_true(test11)
+ testthat::expect_true(test12)
+ })
+
+ testthat::test_that("Codebook (w) - new oTree, false sort", {
+
+ thiswarning <- capture_warnings(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "list",
+ doc_info = FALSE,
+ sort = c("public_goods_simple", "dictator")
+ ))
+
+ testthat::expect_true(
+ any(grepl("Sort apps are not equal to all apps", thiswarning)))
+
+ test1 <- is.list(cbook)
+ test2 <- !is.null(cbook$public_goods_simple$Constants)
+ test3 <- !is.null(cbook$public_goods_simple$Group)
+ test4 <- !is.null(cbook$public_goods_simple$Player)
+
+ test5 <-
+ cbook$public_goods_simple$Constants$NAME_IN_URL ==
+ "public_goods_simple"
+ test6 <-
+ cbook$public_goods_simple$Group$total_contribution$noargs ==
+ "TRUE"
+ test7 <-
+ cbook$public_goods_simple$Player$contribution$label ==
+ "How much will you contribute?"
+ test8 <-
+ cbook$public_goods_simple$Player$contribution$noargs ==
+ "FALSE"
+
+ # If there is only one group field without information in it
+ test9 <- cbook$bertrand$Group$winning_price$field == "CurrencyField"
+
+ # If there is one group field that has information in it
+ test10 <- cbook$dictator$Group$kept$field == "CurrencyField"
+
+ # If there are two group fields with no information in them
+ test11 <-
+ cbook$public_goods_simple$Group$total_contribution$field == "CurrencyField"
+
+ test12 <-
+ all(names(cbook) ==
+ c("settings", "bargaining", "bertrand",
+ "common_value_auction", "cournot",
+ "dictator", "guess_two_thirds",
+ "matching_pennies", "payment_info",
+ "prisoner", "public_goods_simple",
+ "survey", "traveler_dilemma",
+ "trust", "trust_simple", "volunteer_dilemma"))
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ testthat::expect_true(test7)
+ testthat::expect_true(test8)
+ testthat::expect_true(test9)
+ testthat::expect_true(test10)
+ testthat::expect_true(test11)
+ testthat::expect_true(test12)
+ })
+
+ testthat::test_that("Codebook (w) - too many sort", {
+ # Without trust_simple
+
+ original_sort <-
+ c("bargaining", "bertrand", "common_value_auction", "cournot",
+ "dictator", "guess_two_thirds", "matching_pennies", "payment_info",
+ "prisoner", "public_goods_simple", "survey", "traveler_dilemma",
+ "trust", "trust_simple", "volunteer_dilemma")
+
+ new_sort <- c("thisisnothere", "payment_info",
+ "bargaining", "volunteer_dilemma",
+ "bertrand", "common_value_auction",
+ "cournot", "dictator",
+ "guess_two_thirds", "matching_pennies",
+ "prisoner", "public_goods_simple",
+ "survey", "traveler_dilemma",
+ "trust")
+
+ thiswarning <- capture_warnings(
+ cbook <- codebook(
+ path = testthat::test_path("testdata", "ocode_new"),
+ fsource = "init",
+ output = "list",
+ output_format = "word_document",
+ doc_info = FALSE,
+ sort = new_sort)
+ )
+
+ testthat::expect_true(any(
+ grepl(x = thiswarning, pattern = "Sort elements not in apps are")))
+
+ testthat::expect_true(
+ any(grepl("Sort apps are not equal to all apps", thiswarning)))
+
+ testthat::expect_true(any(grepl("Sort elements not in apps are",
+ thiswarning)))
+
+ test1 <- is.list(cbook)
+ test2 <- !is.null(cbook$public_goods_simple$Constants)
+ test3 <- !is.null(cbook$public_goods_simple$Group)
+ test4 <- !is.null(cbook$public_goods_simple$Player)
+
+ test5 <-
+ cbook$public_goods_simple$Constants$NAME_IN_URL ==
+ "public_goods_simple"
+ test6 <-
+ cbook$public_goods_simple$Group$total_contribution$noargs ==
+ "TRUE"
+ test7 <-
+ cbook$public_goods_simple$Player$contribution$label ==
+ "How much will you contribute?"
+ test8 <-
+ cbook$public_goods_simple$Player$contribution$noargs ==
+ "FALSE"
+
+ # If there is only one group field without information in it
+ test9 <- cbook$bertrand$Group$winning_price$field == "CurrencyField"
+
+ # If there is one group field that has information in it
+ test10 <- cbook$dictator$Group$kept$field == "CurrencyField"
+
+ # If there are two group fields with no information in them
+ test11 <-
+ cbook$public_goods_simple$Group$total_contribution$field == "CurrencyField"
+
+ test12 <-
+ all(names(cbook) == c("settings", original_sort))
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+ testthat::expect_true(test3)
+ testthat::expect_true(test4)
+ testthat::expect_true(test5)
+ testthat::expect_true(test6)
+ testthat::expect_true(test7)
+ testthat::expect_true(test8)
+ testthat::expect_true(test9)
+ testthat::expect_true(test10)
+ testthat::expect_true(test11)
+ testthat::expect_true(test12)
+
+ # Check if "yes, I will" is one element
+ testthat::expect_true(
+ length(cbook$bargaining$Player$level2$choices) == 3L) # ACHTUNG. Bei einlistigen Sachen funzt was nicht
+
+
+ testthat::expect_true(
+ cbook$bargaining$Player$level2$choices[1] == "No, I won't")
+ testthat::expect_true(
+ cbook$bargaining$Player$level2$choices[3] == "Maybe I'll do")
+
+ # Test for ''' documentations
+ test1 <- grepl(
+ pattern = "^A bat and a ball cost 22 dollars in tota.*the ball cost\\?$",
+ x = cbook$survey$Player$crt_bat$label)
+
+ # Test for """ documentations
+ test2 <- grepl(
+ pattern = "^If it takes 5 machines 5.*make 100 widgets\\?$",
+ x = cbook$survey$Player$crt_widget$label) # TODO removal of three """
+
+ testthat::expect_true(test1)
+ testthat::expect_true(test2)
+
+ # Test for ' choices
+ testthat::expect_true(
+ cbook$survey$Player$gender$choices$key[1L] == "Male")
+ testthat::expect_true(
+ cbook$survey$Player$gender$choices$key[2L] == "Female")
+ testthat::expect_true(
+ cbook$survey$Player$gender$choices$value[1L] == "Male")
+ testthat::expect_true(
+ cbook$survey$Player$gender$choices$value[2L] == "Female")
+
+ # Test for " choices
+ testthat::expect_true(
+ cbook$survey$Player$gender2$choices$key[1L] == "Male")
+
+ testthat::expect_true(
+ cbook$survey$Player$gender2$choices$key[2L] == "Female")
+ testthat::expect_true(
+ cbook$survey$Player$gender2$choices$value[1L] == "Male")
+ testthat::expect_true(
+ cbook$survey$Player$gender2$choices$value[2L] == "Female")
+
+ # Further
+ testthat::expect_equal(length(cbook$prisoner$Player$cooperate$choices), 2L) # True: Cooperate, False Defect
+ testthat::expect_true(is.data.frame(cbook$prisoner$Player$cooperate$choices))
+ })
}
diff --git a/vignettes/codebook.Rmd b/vignettes/codebook.Rmd
index 2dff96a..9b066a8 100644
--- a/vignettes/codebook.Rmd
+++ b/vignettes/codebook.Rmd
@@ -1,7 +1,7 @@
---
title: "gmoTree Codebooks"
author: "Patricia F. Zauchner"
-date: "2023-09-21 (updated: 2024-09-30)"
+date: "2023-09-21 (updated: 2024-12-06)"
output:
rmarkdown::html_vignette:
toc: yes
@@ -17,20 +17,18 @@ library(gmoTree)
# Overview
-The `gmoTree` package provides tools for generating codebooks based on data from the oTree (Chen et al., 2016) framework with the function `codebook()`. This vignette introduces you to the key features and functionalities, including how to adjust titles, work with oTree data, and customize output formats for your codebooks.
+The `gmoTree` package provides tools for generating codebooks based on data from the oTree (Chen et al., 2016) framework with the function `codebook()`. This vignette introduces its key features and functionalities.
Disclaimer: This code has been tested with both custom implementations and official oTree sample codes.^[The oTree sample codes can be accessed when setting up an oTree project (Chen et al., 2016). All examples presented in this vignette are based on the official oTree sample code, with minor modifications to meet the needs of this package.] However, due to the complexity of oTree setups, it may not address all variations. Please review your output carefully, and feel free to open a GitHub issue if you encounter any problems.
# Running the code
-In its simplest form, the function requires only the path to your oTree code. The code reads the contents of your oTree file, saves a file containing your codebook in your working directory, and returns a list named `cbook`, which contains all the information in a list format.
+In its simplest form, the function requires only the path to your oTree code. The following code reads the contents of your oTree file, saves a file containing your codebook in your working directory, and returns a list named `cbook`, containing the extracted information.
```
-cbook <- codebook(system.file(path = "extdata/ocode_new",
- package = "gmoTree"))
+cbook <- codebook("D:/pathtoyourproject/oTree_codes")
```
-
# Codebook structure and output
The output is structured with clear headings:
@@ -40,26 +38,30 @@ The output is structured with clear headings:
-Below is an example showing the output for the `cournot` app, which includes all `Constants`, `Group`, and `Player` variables. If a class contains no information, the heading will still appear, along with the message "Empty class."
+The example below shows the output for the `cournot` app, which includes all `Constants`, `Group`, and `Player` variables. If a class contains no information, the heading will still appear, along with the message "Empty class."
-If the default codebook design does not meet your requirements, you can either reference the previously created `cbook` list or bypass file creation by setting `output = "list"`. This will return all the information only in list format, which you can then use in `R Markdown` to design your own custom codebook. Below is an example of a section of the list output for the `cournot` app. (The argument `doc_info = FALSE` is used to omit messages about missing variable documentation.)
+Use `output = "list"` to bypass file creation. This option returns all the information in list format, which can then be used in R Markdown to design a custom codebook. Below is an example of how such a list output looks like. (The argument `doc_info = FALSE` suppresses messages about missing variable documentation.)
-```{r}
+```{r cornout codebook}
+# Create the codebook list
cbook <- codebook(path = system.file(path = "extdata/ocode_new",
package = "gmoTree"),
output = "list",
doc_info = FALSE)
-print(cbook$cournot)
+
+
+str(cbook, 1) # Show all apps
+print(cbook$cournot) # Only show cournot app
```
# Choosing what to show
## Apps
-To generate a codebook for only one app, use the `app` argument. For example, to generate a codebook for the `cournot` app:
+Per default, all apps are included in the codebook. To generate a codebook for only one app, use the `app` argument. For example, to generate a codebook for the `cournot` app:
```{r one app}
cbook <- codebook(
@@ -87,7 +89,7 @@ cbook <- codebook(
str(cbook, 1)
```
-You can also choose all but remove one or more apps. Here is an example that removes the app `prisoner`.
+You can also choose all but remove one or more apps. Here is an example that removes the app `prisoner`:
```{r removing apps}
cbook <- codebook(
@@ -104,7 +106,7 @@ str(cbook, 1)
By setting the `preamb = TRUE` parameter, a predefined description of oTree data is inserted at the beginning of the codebook, explaining how experimental data is stored by oTree.
-
+
# Customizing how the codebook is shown
@@ -115,7 +117,7 @@ You can easily modify the titles, subtitles, dates, and author names in your cod
```
codebook(
- path = "YouroTreePath", # Can be either absolute or releative!
+ path = "YouroTreePath", # Can be either absolute or relative!
title = "Codebook",
subtitle = "Example Project",
date = "today",
@@ -123,7 +125,7 @@ codebook(
)
```
-
+
## Sorting the code
@@ -144,7 +146,7 @@ str(cbook, 1)
## Referring to settings
-The `gmoTree` package can automatically replace references to variables in `settings.py` with the values in the `settings.py` file.
+The `gmoTree` package can automatically replace references to variables in `settings.py` with the values in the `settings.py` file. To enable this, set `settings_replace = "global"`.
```{r global settings}
cbook <- codebook(
@@ -157,7 +159,7 @@ cbook <- codebook(
print(cbook$dictator$Constants$Variable)
```
-However, you can also choose to not replace them by using `settings_replace = NULL`:
+You can also choose to not replace the references to settings variables by using `settings_replace = NULL`.
```{r do not replace settings}
cbook <- codebook(
@@ -170,7 +172,7 @@ cbook <- codebook(
print(cbook$dictator$Constants$Variable)
```
-It is also possible to provide a list of variables that should replace the settings variables:
+It is also possible to provide a list of variables to replace the settings variables with the argument `user_settings`. For example:
```{r user settings}
cbook <- codebook(
@@ -188,33 +190,44 @@ print(cbook$dictator$Constants$Variable)
When you choose `output = "file"` or `output = "both"`, your codebook will be saved as a professional document ready for publication or sharing.
-The argument `output_format` allows you to choose the format of the exported codebook file. Available formats are:
+## Output formats
+
+The argument `output_format` allows you to choose the format of the exported codebook file.
+Available formats are:
-* `pdf_document`
* `html_document`
* `word_document`
* `latex_document`
* `odt_document`
* `rtf_document`
* `md_document`
+* `pdf_document`
+* `pdf_document_simple`
+
+You can choose the format that best suits your needs, with all formats except PDF allowing easy post-generation editing.
+
+When knitting to PDF, make sure to have LaTex installed! It is recommended to use `output_format = pdf_document_simple`. However, many non-Latin characters (e.g., Chinese characters) may not work with this format. In such cases, you can choose `output_format = pdf_document`, which is set to use `xelatex`.
+
+Please note that using `xelatex` with gmoTree has some limitations: for example, `gmoTree` currently cannot handle long variable values that result in excessively long table cells. This can cause the PDF to display improperly in certain viewers, such as Nitro. To address this, carefully review your file. If necessary, consider using `output_format = latex_document`. Alternatively, open the file with a PDF viewer that can handle these cases, then save it there to ensure it displays correctly in other PDF viewers.
-You can choose the format that best suits your needs, with all formats except PDF offering easy post-generation editing.
+## Output files
-By default, `gmoTree` codebooks are saved in your working directory with the default file name `codebook`. You can modify this by specifying a custom file name and directory path.
+By default, `gmoTree` codebooks are saved in your working directory with the default file name `codebook`.
+You can modify this by specifying a custom file name and directory path.
For example, to save the codebook with a different name, use the following code:
```
codebook(
- path = "C:/Users/username/Nextcloud/oTree", # Replace!
+ path = "C:/Users/username/folder/oTree", # Replace!
output_file = "gmoTree_codebook")
```
-You can also include the file extension, though it is optional:
+You can also include the file extension, although it is optional:
```
codebook(
- path = "C:/Users/username/Nextcloud/oTree", # Replace!
+ path = "C:/Users/username/folder/oTree", # Replace!
output_file = "gmoTree_codebook.pdf")
```
@@ -222,24 +235,24 @@ You can save the file in a subfolder within the current directory by including t
```
codebook(
- path = "C:/Users/username/Nextcloud/oTree", # Replace!
+ path = "C:/Users/username/folder/oTree", # Replace!
output_file = "codebookfiles/gmoTree_codebook.pdf")
```
-However, you can also specify absolute paths, either in the `output_dir` argument or directly within the file name specified in the `output_file`.
+You can also specify absolute paths, either in the `output_dir` argument or directly within the file name specified in the `output_file`.
For example:
```
codebook(
- path = "C:/Users/username/Nextcloud/oTree", # Replace!
- output_dir = "C:/Users/username/Nextcloud/codebooks",
+ path = "C:/Users/username/folder/oTree", # Replace!
+ output_dir = "C:/Users/username/folder/codebooks",
output_file = "mycodebook")
```
# Summary
-This vignette covers how to customize the codebook generated by the `codebook()` function, including options for selecting content, formatting its presentation, and exporting it in various formats. These tools enable the creation of comprehensive and tailored documentation for your experimental data.
+This vignette documents how to customize the codebook generated by the `codebook()` function, including options for content selection, formatting, and exporting to various formats. These tools enable the creation of comprehensive and tailored documentation for your experimental data.
# References
-Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—An open-source platform for laboratory, online, and field experiments. Journal of Behavioral and Experimental Finance, 9, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001
\ No newline at end of file
+Chen, D. L., Schonger, M., & Wickens, C. (2016). oTree—An open-source platform for laboratory, online, and field experiments. *Journal of Behavioral and Experimental Finance*, *9*, 88–97. https://doi.org/10.1016/j.jbef.2015.12.001
\ No newline at end of file
diff --git a/vignettes/title.PNG b/vignettes/title.PNG
index c931e6f..32027dc 100644
Binary files a/vignettes/title.PNG and b/vignettes/title.PNG differ