1 Read, Clean, Recode, Merge

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Read, Clean, Recode, Unite
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

## Read files
folder <- "C:/Users/Mihai/Desktop/R Notebooks/notebooks/A.1.3. Drama Exercises Kids"
file <- "A13 Tabel date copii.xlsx"

setwd(folder)
Data <- rio::import(file.path(folder, file),
                           skip = 1)


## Tidy up data
# Function coalesce rows: colapse when NA, unite with "_" when not NA
coalesce2 <- function(...) {
  Reduce(function(x, y) {
    i <- which(is.na(x))
    j <- which(!is.na(x) & !is.na(y))
    x[i] <- y[i]
    x[j] <- paste(x[j], y[j], sep = "_")
    x},
    list(...))
}

colnames(Data) <- coalesce2(Data[2,], Data[3,])
Data <- Data[-c(1:3),]



## Solve duplicate names due to excel double header
# Function to paste a string before column name if it doesnt already start with that string
paste_tocolnames <- function(vec_colnames, string_paste){
  ind <- grep(pattern = string_paste, vec_colnames)                   # ignore column that already has string patterm
  vec_colnames[-ind] <- paste0(string_paste, vec_colnames[-ind])      # paste pattern to the rest of them
  return(vec_colnames)
}

# PANAS pre 7:26, post 37:56
colnames(Data)[7:26] <- paste_tocolnames(colnames(Data)[7:26], "PANAS pre_")
colnames(Data)[37:56] <- paste_tocolnames(colnames(Data)[37:56], "PANAS post_")

colnames(Data) <- enc2native(colnames(Data))      # fix encoding


## Recode known missing values
# str(Data_psiho, list.len = ncol(Data_psiho))
# str(Data_psiho, list.len = ncol(Data_psiho))
Data <-
  Data %>%
  replace(. == "/", NA) %>%                                     # missing values are coded "/"
  replace(. == "-", NA) %>%                                     # missing values are coded "-"
  replace(. == "NA", NA)                                        # missing values are coded "NA"


# Exclude some extra rows and columns & some IDs
Data <- Data[, -c(57:86)]
rownames(Data) <- seq(length=nrow(Data))  # 83 trebuie sa fie
Data <- 
  Data %>%
  mutate (`Nr crt` = as.numeric(.$`Nr crt`)) %>%
  filter(!`Nr crt` %in% c(36, 38:39, 41:43, 50:51, 53:55, 75, 84:97)) %>%
  filter(`Nr crt` < 84)

## Check for non-numeric elements in data sets
check_numeric1 <- as.data.frame(sapply(Data, varhandle::check.numeric)) 
# sapply(check_numeric1, function(x) length(which(!x)))     # look at columns with non-numeric and count of non-numeric values

nonnumeric1 <- sapply(check_numeric1, function(x) which(!x, arr.ind = TRUE))    # find row numbers for non-numeric values
nonnumeric1[lapply(nonnumeric1, length) > 0]                                   # return only columns and rown numbers were non-numeric
## Recode to numeric
Data[, 7:56] <- sapply(Data[, 7:56], as.numeric)     # mutate_at fails due to encoding

## Rename columns
Data <- 
  Data %>% 
 dplyr::rename(ID = `Indica tiv subiect`) %>% 
 dplyr::rename(Zi = `(Etapa III), zi`)
names(Data) <- gsub(" ", "_", names(Data))


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Scoring Questionnaire and Unite
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Define function that calculates RowSums but only for rows with less than 10% NAs; and return NA if all row values are NA 
SpecialRowSums <- function(df, napercent = .1) {
  ifelse(rowSums(is.na(df)) > ncol(df) * napercent,
         NA,
         rowSums(df, na.rm = TRUE) * NA ^ (rowSums(!is.na(df)) == 0)
  )
}

## PANAS: Positive Affect Score = sum items 1, 3, 5, 9, 10, 12, 14, 16, 17, 19. Negative Affect Score = sum items 2, 4, 6, 7, 8, 11, 13, 15, 18, 20.
Data$PA_pre_Total <- SpecialRowSums(Data[ ,6 + c(1,3,5,9,10,12,14,16,17,19)], napercent = .11) # not more than 1 NAs for 10 items
Data$NA_pre_Total <- SpecialRowSums(Data[ ,6 + c(2,4,6,7,8,11,13,15,18,20)], napercent = .11)


Data$PA_post_Total <- SpecialRowSums(Data[ ,36 + c(1,3,5,9,10,12,14,16,17,19)], napercent = .11) 
Data$NA_post_Total <- SpecialRowSums(Data[ ,36 + c(2,4,6,7,8,11,13,15,18,20)], napercent = .11)

2 Sample descriptives

## Number of subjects

3 Define Function

4 PANAS

4.0.1 Positeive - Zi 1

4.0.1.1 PA_pre_Total PA_post_Total

4.0.2 Positeive - Zi 2

4.0.2.1 PA_pre_Total PA_post_Total

4.0.3 Negative - Zi 1

4.0.3.1 NA_pre_Total NA_post_Total

4.0.4 Negative - Zi 2

4.0.4.1 NA_pre_Total NA_post_Total

5 VAS

5.0.1 Stress - Zi 1

5.0.1.1 VAS_stres_pre VAS_stres_post_ex1

5.0.2 Stress - Zi 2

5.0.2.1 VAS_stres_pre VAS_stres_post_ex1

5.0.3 Well being - Zi 1

5.0.3.1 VAS_stare_de_bine_pre VAS_stare_de_bine_post_ex1

5.0.4 Well being - Zi 2

5.0.4.1 VAS_stare_de_bine_pre VAS_stare_de_bine_post_ex1

6 IOS

6.0.1 IOS - Zi 1

6.0.1.1 IOS_pre IOS_post

6.0.2 IOS - Zi 2

6.0.2.1 IOS_pre IOS_post


7 Session Info

R version 3.6.1 (2019-07-05)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 8.1 x64 (build 9600)

Matrix products: default

locale:
[1] LC_COLLATE=Romanian_Romania.1250  LC_CTYPE=Romanian_Romania.1250    LC_MONETARY=Romanian_Romania.1250 LC_NUMERIC=C                     
[5] LC_TIME=Romanian_Romania.1250    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] rio_0.5.16                 scales_1.0.0               ggpubr_0.2                 magrittr_1.5               tadaatoolbox_0.16.1       
 [6] summarytools_0.8.8         rstatix_0.2.0              broom_0.5.2                PerformanceAnalytics_1.5.2 xts_0.11-2                
[11] zoo_1.8-4                  psych_1.8.12               plyr_1.8.4                 forcats_0.4.0              stringr_1.4.0             
[16] dplyr_0.8.3                purrr_0.3.2                readr_1.3.1                tidyr_1.0.0                tibble_2.1.3              
[21] ggplot2_3.2.1              tidyverse_1.2.1            papaja_0.1.0.9842          pacman_0.5.1              

loaded via a namespace (and not attached):
 [1] nlme_3.1-140       bitops_1.0-6       matrixStats_0.54.0 lubridate_1.7.4    httr_1.4.0         tools_3.6.1        backports_1.1.4   
 [8] R6_2.4.0           nortest_1.0-4      lazyeval_0.2.2     colorspace_1.4-1   withr_2.1.2        tidyselect_0.2.5   gridExtra_2.3     
[15] mnormt_1.5-5       pixiedust_0.8.6    curl_3.2           compiler_3.6.1     cli_1.1.0          rvest_0.3.2        expm_0.999-3      
[22] xml2_1.2.0         labeling_0.3       mvtnorm_1.0-11     quadprog_1.5-5     digest_0.6.21      foreign_0.8-71     pkgconfig_2.0.3   
[29] htmltools_0.3.6    pwr_1.2-2          rlang_0.4.0        readxl_1.1.0       rstudioapi_0.8     pryr_0.1.4         generics_0.0.2    
[36] jsonlite_1.6       zip_1.0.0          car_3.0-2          RCurl_1.95-4.11    rapportools_1.0    Matrix_1.2-17      Rcpp_1.0.2        
[43] DescTools_0.99.29  munsell_0.5.0      abind_1.4-5        viridis_0.5.1      lifecycle_0.1.0    stringi_1.4.3      carData_3.0-2     
[50] MASS_7.3-51.4      grid_3.6.1         parallel_3.6.1     crayon_1.3.4       lattice_0.20-38    haven_2.1.1        pander_0.6.3      
[57] hms_0.5.1          zeallot_0.1.0      knitr_1.25         pillar_1.4.2       varhandle_2.0.4    boot_1.3-22        ggsignif_0.4.0    
[64] codetools_0.2-16   glue_1.3.1         data.table_1.11.8  modelr_0.1.5       vctrs_0.2.0        cellranger_1.1.0   gtable_0.3.0      
[71] assertthat_0.2.1   xfun_0.9           openxlsx_4.1.0     viridisLite_0.3.0  ellipsis_0.3.0    
 

A work by Claudiu Papasteri

 

LS0tDQp0aXRsZTogIjxicj4gRHJhbWEgRXhlcmNpc2VzIEtpZHMiIA0Kc3VidGl0bGU6ICJSZXBvcnQgZm9yIENoaWxkcmVuIGFuZCBBZG9sZXNjZW50cyINCmF1dGhvcjogIjxicj4gQ2xhdWRpdSBQYXBhc3RlcmkiDQpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlbSAlWScpYCINCm91dHB1dDogDQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgICAgICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgICAgICAgICAgdG9jOiB0cnVlDQogICAgICAgICAgICB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgIG51bWJlcl9zZWN0aW9uczogdHJ1ZQ0KICAgICAgICAgICAgdGhlbWU6IHNwYWNlbGFiDQogICAgICAgICAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgICAgICAgICBmb250LWZhbWlseTogQXJpYWwNCiAgICAgICAgICAgIGZpZ193aWR0aDogMTANCiAgICAgICAgICAgIGZpZ19oZWlnaHQ6IDkNCiAgICAjIHBkZl9kb2N1bWVudDogDQogICAgICAgICAgICAjIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgIyAgdG9jX2RlcHRoOiAyDQogICAgICAgICAgICAjICBudW1iZXJfc2VjdGlvbnM6IHRydWUNCiAgICAgICAgICAgICMgZm9udHNpemU6IDExcHQNCiAgICAgICAgICAgICMgZ2VvbWV0cnk6IG1hcmdpbj0xaW4NCiAgICAgICAgICAgICMgZmlnX3dpZHRoOiA3DQogICAgICAgICAgICAjIGZpZ19oZWlnaHQ6IDYNCiAgICAgICAgICAgICMgZmlnX2NhcHRpb246IHRydWUNCiAgICAjIGdpdGh1Yl9kb2N1bWVudDogDQogICAgICAgICAgICAjIHRvYzogdHJ1ZQ0KICAgICAgICAgICAgIyB0b2NfZGVwdGg6IDINCiAgICAgICAgICAgICMgaHRtbF9wcmV2aWV3OiBmYWxzZQ0KICAgICAgICAgICAgIyBmaWdfd2lkdGg6IDUNCiAgICAgICAgICAgICMgZmlnX2hlaWdodDogNQ0KICAgICAgICAgICAgIyBkZXY6IGpwZWcNCi0tLQ0KDQoNCjwhLS0gU2V0dXAgLS0+DQoNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQojIGtpbnRyIG9wdGlvbnMNCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCiAgY29tbWVudCA9ICIjIiwNCiAgY29sbGFwc2UgPSBUUlVFLA0KICBlY2hvID0gVFJVRSwgd2FybmluZyA9IEZBTFNFLCBtZXNzYWdlID0gVFJVRSwgY2FjaGUgPSBUUlVFICAgICAgICMgZWNobyA9IEZhbHNlIGZvciBnaXRodWJfZG9jdW1lbnQsIGJ1dCB3aWxsIGJlIGZvbGRlZCBpbiBodG1sX25vdGVib29rDQopDQoNCiMgR2VuZXJhbCBSIG9wdGlvbnMgYW5kIGluZm8NCnNldC5zZWVkKDExMSkgICAgICAgICAgICAgICAjIGluIGNhc2Ugd2UgdXNlIHJhbmRvbWl6ZWQgcHJvY2VkdXJlcyAgICAgICANCm9wdGlvbnMoc2NpcGVuID0gOTk5KSAgICAgICAjIHBvc2l0aXZlIHZhbHVlcyBiaWFzIHRvd2FyZHMgZml4ZWQgYW5kIG5lZ2F0aXZlIHRvd2FyZHMgc2NpZW50aWZpYyBub3RhdGlvbg0KDQojIExvYWQgcGFja2FnZXMNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNrYWdlcyA8LSBjKA0KICAicGFwYWphIiwNCiAgInRpZHl2ZXJzZSIsICJwbHlyIiwgICAgICANCiAgInBzeWNoIiwgIlBlcmZvcm1hbmNlQW5hbHl0aWNzIiwgICAgICAgICAgDQogICJicm9vbSIsICJyc3RhdGl4IiwNCiAgInN1bW1hcnl0b29scyIsICJ0YWRhYXRvb2xib3giLCAgICAgICAgICAgDQogICJnZ3Bsb3QyIiwgImdncHViciIsICJzY2FsZXMiLCAgICAgICAgDQogICJyaW8iDQogICMgLCAuLi4NCikNCmlmICghcmVxdWlyZSgicGFjbWFuIikpIGluc3RhbGwucGFja2FnZXMoInBhY21hbiIpDQpwYWNtYW46OnBfbG9hZChjaGFyID0gcGFja2FnZXMpDQoNCiMgVGhlbWVzIGZvciBnZ3Bsb3QyIHBsb3RpbmcgKGhlcmUgdXNlZCBBUEEgc3R5bGUpDQp0aGVtZV9zZXQodGhlbWVfYXBhKCkpDQpgYGANCg0KDQoNCg0KDQo8IS0tIFJlcG9ydCAtLT4NCg0KDQojIFJlYWQsIENsZWFuLCBSZWNvZGUsIE1lcmdlDQoNCmBgYHtyIHJlZF9jbGVhbl9yZWNvZGVfbWVyZ2UsIHJlc3VsdHM9J2hpZGUnfQ0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgUmVhZCwgQ2xlYW4sIFJlY29kZSwgVW5pdGUNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQoNCiMjIFJlYWQgZmlsZXMNCmZvbGRlciA8LSAiQzovVXNlcnMvTWloYWkvRGVza3RvcC9SIE5vdGVib29rcy9ub3RlYm9va3MvQS4xLjMuIERyYW1hIEV4ZXJjaXNlcyBLaWRzIg0KZmlsZSA8LSAiQTEzIFRhYmVsIGRhdGUgY29waWkueGxzeCINCg0Kc2V0d2QoZm9sZGVyKQ0KRGF0YSA8LSByaW86OmltcG9ydChmaWxlLnBhdGgoZm9sZGVyLCBmaWxlKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHNraXAgPSAxKQ0KDQoNCiMjIFRpZHkgdXAgZGF0YQ0KIyBGdW5jdGlvbiBjb2FsZXNjZSByb3dzOiBjb2xhcHNlIHdoZW4gTkEsIHVuaXRlIHdpdGggIl8iIHdoZW4gbm90IE5BDQpjb2FsZXNjZTIgPC0gZnVuY3Rpb24oLi4uKSB7DQogIFJlZHVjZShmdW5jdGlvbih4LCB5KSB7DQogICAgaSA8LSB3aGljaChpcy5uYSh4KSkNCiAgICBqIDwtIHdoaWNoKCFpcy5uYSh4KSAmICFpcy5uYSh5KSkNCiAgICB4W2ldIDwtIHlbaV0NCiAgICB4W2pdIDwtIHBhc3RlKHhbal0sIHlbal0sIHNlcCA9ICJfIikNCiAgICB4fSwNCiAgICBsaXN0KC4uLikpDQp9DQoNCmNvbG5hbWVzKERhdGEpIDwtIGNvYWxlc2NlMihEYXRhWzIsXSwgRGF0YVszLF0pDQpEYXRhIDwtIERhdGFbLWMoMTozKSxdDQoNCg0KDQojIyBTb2x2ZSBkdXBsaWNhdGUgbmFtZXMgZHVlIHRvIGV4Y2VsIGRvdWJsZSBoZWFkZXINCiMgRnVuY3Rpb24gdG8gcGFzdGUgYSBzdHJpbmcgYmVmb3JlIGNvbHVtbiBuYW1lIGlmIGl0IGRvZXNudCBhbHJlYWR5IHN0YXJ0IHdpdGggdGhhdCBzdHJpbmcNCnBhc3RlX3RvY29sbmFtZXMgPC0gZnVuY3Rpb24odmVjX2NvbG5hbWVzLCBzdHJpbmdfcGFzdGUpew0KICBpbmQgPC0gZ3JlcChwYXR0ZXJuID0gc3RyaW5nX3Bhc3RlLCB2ZWNfY29sbmFtZXMpICAgICAgICAgICAgICAgICAgICMgaWdub3JlIGNvbHVtbiB0aGF0IGFscmVhZHkgaGFzIHN0cmluZyBwYXR0ZXJtDQogIHZlY19jb2xuYW1lc1staW5kXSA8LSBwYXN0ZTAoc3RyaW5nX3Bhc3RlLCB2ZWNfY29sbmFtZXNbLWluZF0pICAgICAgIyBwYXN0ZSBwYXR0ZXJuIHRvIHRoZSByZXN0IG9mIHRoZW0NCiAgcmV0dXJuKHZlY19jb2xuYW1lcykNCn0NCg0KIyBQQU5BUyBwcmUgNzoyNiwgcG9zdCAzNzo1Ng0KY29sbmFtZXMoRGF0YSlbNzoyNl0gPC0gcGFzdGVfdG9jb2xuYW1lcyhjb2xuYW1lcyhEYXRhKVs3OjI2XSwgIlBBTkFTIHByZV8iKQ0KY29sbmFtZXMoRGF0YSlbMzc6NTZdIDwtIHBhc3RlX3RvY29sbmFtZXMoY29sbmFtZXMoRGF0YSlbMzc6NTZdLCAiUEFOQVMgcG9zdF8iKQ0KDQpjb2xuYW1lcyhEYXRhKSA8LSBlbmMybmF0aXZlKGNvbG5hbWVzKERhdGEpKSAgICAgICMgZml4IGVuY29kaW5nDQoNCg0KIyMgUmVjb2RlIGtub3duIG1pc3NpbmcgdmFsdWVzDQojIHN0cihEYXRhX3BzaWhvLCBsaXN0LmxlbiA9IG5jb2woRGF0YV9wc2lobykpDQojIHN0cihEYXRhX3BzaWhvLCBsaXN0LmxlbiA9IG5jb2woRGF0YV9wc2lobykpDQpEYXRhIDwtDQogIERhdGEgJT4lDQogIHJlcGxhY2UoLiA9PSAiLyIsIE5BKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtaXNzaW5nIHZhbHVlcyBhcmUgY29kZWQgIi8iDQogIHJlcGxhY2UoLiA9PSAiLSIsIE5BKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtaXNzaW5nIHZhbHVlcyBhcmUgY29kZWQgIi0iDQogIHJlcGxhY2UoLiA9PSAiTkEiLCBOQSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBtaXNzaW5nIHZhbHVlcyBhcmUgY29kZWQgIk5BIg0KDQoNCiMgRXhjbHVkZSBzb21lIGV4dHJhIHJvd3MgYW5kIGNvbHVtbnMgJiBzb21lIElEcw0KRGF0YSA8LSBEYXRhWywgLWMoNTc6ODYpXQ0Kcm93bmFtZXMoRGF0YSkgPC0gc2VxKGxlbmd0aD1ucm93KERhdGEpKSAgIyA4MyB0cmVidWllIHNhIGZpZQ0KRGF0YSA8LSANCiAgRGF0YSAlPiUNCiAgbXV0YXRlIChgTnIgY3J0YCA9IGFzLm51bWVyaWMoLiRgTnIgY3J0YCkpICU+JQ0KICBmaWx0ZXIoIWBOciBjcnRgICVpbiUgYygzNiwgMzg6MzksIDQxOjQzLCA1MDo1MSwgNTM6NTUsIDc1LCA4NDo5NykpICU+JQ0KICBmaWx0ZXIoYE5yIGNydGAgPCA4NCkNCg0KIyMgQ2hlY2sgZm9yIG5vbi1udW1lcmljIGVsZW1lbnRzIGluIGRhdGEgc2V0cw0KY2hlY2tfbnVtZXJpYzEgPC0gYXMuZGF0YS5mcmFtZShzYXBwbHkoRGF0YSwgdmFyaGFuZGxlOjpjaGVjay5udW1lcmljKSkgDQojIHNhcHBseShjaGVja19udW1lcmljMSwgZnVuY3Rpb24oeCkgbGVuZ3RoKHdoaWNoKCF4KSkpICAgICAjIGxvb2sgYXQgY29sdW1ucyB3aXRoIG5vbi1udW1lcmljIGFuZCBjb3VudCBvZiBub24tbnVtZXJpYyB2YWx1ZXMNCg0Kbm9ubnVtZXJpYzEgPC0gc2FwcGx5KGNoZWNrX251bWVyaWMxLCBmdW5jdGlvbih4KSB3aGljaCgheCwgYXJyLmluZCA9IFRSVUUpKSAgICAjIGZpbmQgcm93IG51bWJlcnMgZm9yIG5vbi1udW1lcmljIHZhbHVlcw0Kbm9ubnVtZXJpYzFbbGFwcGx5KG5vbm51bWVyaWMxLCBsZW5ndGgpID4gMF0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgcmV0dXJuIG9ubHkgY29sdW1ucyBhbmQgcm93biBudW1iZXJzIHdlcmUgbm9uLW51bWVyaWMNCg0KIyMgUmVjb2RlIHRvIG51bWVyaWMNCkRhdGFbLCA3OjU2XSA8LSBzYXBwbHkoRGF0YVssIDc6NTZdLCBhcy5udW1lcmljKSAgICAgIyBtdXRhdGVfYXQgZmFpbHMgZHVlIHRvIGVuY29kaW5nDQoNCiMjIFJlbmFtZSBjb2x1bW5zDQpEYXRhIDwtIA0KICBEYXRhICU+JSANCiBkcGx5cjo6cmVuYW1lKElEID0gYEluZGljYSB0aXYgc3ViaWVjdGApICU+JSANCiBkcGx5cjo6cmVuYW1lKFppID0gYChFdGFwYSBJSUkpLCB6aWApDQpuYW1lcyhEYXRhKSA8LSBnc3ViKCIgIiwgIl8iLCBuYW1lcyhEYXRhKSkNCg0KDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyBTY29yaW5nIFF1ZXN0aW9ubmFpcmUgYW5kIFVuaXRlDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyMgRGVmaW5lIGZ1bmN0aW9uIHRoYXQgY2FsY3VsYXRlcyBSb3dTdW1zIGJ1dCBvbmx5IGZvciByb3dzIHdpdGggbGVzcyB0aGFuIDEwJSBOQXM7IGFuZCByZXR1cm4gTkEgaWYgYWxsIHJvdyB2YWx1ZXMgYXJlIE5BIA0KU3BlY2lhbFJvd1N1bXMgPC0gZnVuY3Rpb24oZGYsIG5hcGVyY2VudCA9IC4xKSB7DQogIGlmZWxzZShyb3dTdW1zKGlzLm5hKGRmKSkgPiBuY29sKGRmKSAqIG5hcGVyY2VudCwNCiAgICAgICAgIE5BLA0KICAgICAgICAgcm93U3VtcyhkZiwgbmEucm0gPSBUUlVFKSAqIE5BIF4gKHJvd1N1bXMoIWlzLm5hKGRmKSkgPT0gMCkNCiAgKQ0KfQ0KDQojIyBQQU5BUzogUG9zaXRpdmUgQWZmZWN0IFNjb3JlID0gc3VtIGl0ZW1zIDEsIDMsIDUsIDksIDEwLCAxMiwgMTQsIDE2LCAxNywgMTkuIE5lZ2F0aXZlIEFmZmVjdCBTY29yZSA9IHN1bSBpdGVtcyAyLCA0LCA2LCA3LCA4LCAxMSwgMTMsIDE1LCAxOCwgMjAuDQpEYXRhJFBBX3ByZV9Ub3RhbCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWyAsNiArIGMoMSwzLDUsOSwxMCwxMiwxNCwxNiwxNywxOSldLCBuYXBlcmNlbnQgPSAuMTEpICMgbm90IG1vcmUgdGhhbiAxIE5BcyBmb3IgMTAgaXRlbXMNCkRhdGEkTkFfcHJlX1RvdGFsIDwtIFNwZWNpYWxSb3dTdW1zKERhdGFbICw2ICsgYygyLDQsNiw3LDgsMTEsMTMsMTUsMTgsMjApXSwgbmFwZXJjZW50ID0gLjExKQ0KDQoNCkRhdGEkUEFfcG9zdF9Ub3RhbCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWyAsMzYgKyBjKDEsMyw1LDksMTAsMTIsMTQsMTYsMTcsMTkpXSwgbmFwZXJjZW50ID0gLjExKSANCkRhdGEkTkFfcG9zdF9Ub3RhbCA8LSBTcGVjaWFsUm93U3VtcyhEYXRhWyAsMzYgKyBjKDIsNCw2LDcsOCwxMSwxMywxNSwxOCwyMCldLCBuYXBlcmNlbnQgPSAuMTEpDQpgYGANCg0KDQojIFNhbXBsZSBkZXNjcmlwdGl2ZXMNCg0KYGBge3Igc2FtcGxlX2Rlc2N9DQpjYXQoIiMjIE51bWJlciBvZiBzdWJqZWN0cyIpDQpEYXRhICU+JSANCiBkcGx5cjo6c3VtbWFyaXNlKGNvdW50ID0gZHBseXI6Om5fZGlzdGluY3QoSUQpKQ0KYGBgDQoNCg0KIyBEZWZpbmUgRnVuY3Rpb24NCg0KYGBge3IgZGVmX2Z1bmMsIGhpZGU9VFJVRX0NCiMjIEZ1bmMgdCB0ZXN0IHNpIGJveHBsb3Qgc2ltcGx1DQpmdW5jX3RfYm94IDwtIGZ1bmN0aW9uKGRmLCBpbmQsIHByZV92YXIsIHBvc3RfdmFyKXsNCiAgZGZfbW9kaWYgPC0NCiAgICBkZiAlPiUNCiAgICBzZWxlY3QoaW5kLCBwcmVfdmFyLCBwb3N0X3ZhcikgJT4lIA0KICAgIHRpZHlyOjpkcm9wX25hKCkgJT4lDQogICAgZ2F0aGVyKHByZV92YXIsIHBvc3RfdmFyLCBrZXkgPSAiQ29uZCIsIHZhbHVlID0gInZhbHVlIikgJT4lIA0KICAgIG11dGF0ZV9hdCh2YXJzKGMoMSwgMikpLCBmdW5zKGFzLmZhY3RvcikpICU+JSANCiAgICBtdXRhdGUoQ29uZCA9IGZhY3RvcihDb25kLCBsZXZlbHMgPSBjKHByZV92YXIsIHBvc3RfdmFyKSkpIA0KICANCiAgc3RhdF9jb21wIDwtIGdncHVicjo6Y29tcGFyZV9tZWFucyh2YWx1ZSB+IENvbmQsIGRhdGEgPSBkZl9tb2RpZiwgbWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUpDQogIA0KICBzdGF0X2NvbXAyIDwtDQogICAgZGZfbW9kaWYgJT4lIA0KICAgIGRvKHRpZHkodC50ZXN0KC4kdmFsdWUgfiAuJENvbmQsDQogICAgICAgICAgICAgICAgICAgcGFpcmVkID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICBkYXRhPS4pKSkNCiAgDQogIHBsb3QgPC0gDQogICAgZ2dwdWJyOjpnZ3BhaXJlZChkZl9tb2RpZiwgeCA9ICJDb25kIiwgeSA9ICJ2YWx1ZSIsIGlkID0gaW5kLCANCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIkNvbmQiLCBsaW5lLmNvbG9yID0gImdyYXkiLCBsaW5lLnNpemUgPSAwLjQsDQogICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gYygiIzAwQUZCQiIsICIjRkM0RTA3IiksIGxlZ2VuZCA9ICJub25lIikgKw0KICAgICAgc3RhdF9zdW1tYXJ5KGZ1bi5kYXRhID0gbWVhbl9zZSwgIGNvbG91ciA9ICJkYXJrcmVkIikgKw0KICAgICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsLnggPSBhcy5udW1lcmljKGRmX21vZGlmJENvbmQpLTAuNCwgbGFiZWwueSA9IG1heChkZl9tb2RpZiR2YWx1ZSkrMC41KSArIA0KICAgICAgZ2dwdWJyOjpzdGF0X2NvbXBhcmVfbWVhbnMobWV0aG9kID0gInQudGVzdCIsIHBhaXJlZCA9IFRSVUUsIGxhYmVsID0gInAuc2lnbmlmIiwgY29tcGFyaXNvbnMgPSBsaXN0KGMocHJlX3ZhciwgcG9zdF92YXIpKSkNCiAgDQogIGNhdChwYXN0ZTAoIiMjIyMgIiwgcHJlX3ZhciwgIiAiLCBwb3N0X3ZhciwgIlxuIiwgIlxuIikpDQogIHByaW50KHN0YXRfY29tcCkNCiAgcHJpbnQoc3RhdF9jb21wMikNCiAgcHJpbnQocGxvdCkNCn0NCmBgYA0KDQoNCg0KIyBQQU5BUyANCg0KYGBge3IgdF90ZXN0X3BhbmFzLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD03LCByZXN1bHRzPSdhc2lzJ30NCmNhdCgiIyMjIFBvc2l0ZWl2ZSAtIFppIDEiKQ0KRGF0YSAlPiUNCiAgZmlsdGVyKFppID09IDEpICU+JQ0KICBmdW5jX3RfYm94KCJJRCIsICJQQV9wcmVfVG90YWwiLCAiUEFfcG9zdF9Ub3RhbCIpDQoNCmNhdCgiIyMjIFBvc2l0ZWl2ZSAtICBaaSAyIikNCkRhdGEgJT4lDQogIGZpbHRlcihaaSA9PSAyKSAlPiUNCiAgZnVuY190X2JveCgiSUQiLCAiUEFfcHJlX1RvdGFsIiwgIlBBX3Bvc3RfVG90YWwiKQ0KDQoNCmNhdCgiIyMjIE5lZ2F0aXZlIC0gWmkgMSIpDQpEYXRhICU+JQ0KICBmaWx0ZXIoWmkgPT0gMSkgJT4lDQogIGZ1bmNfdF9ib3goIklEIiwgIk5BX3ByZV9Ub3RhbCIsICJOQV9wb3N0X1RvdGFsIikNCg0KY2F0KCIjIyMgTmVnYXRpdmUgLSAgWmkgMiIpDQpEYXRhICU+JQ0KICBmaWx0ZXIoWmkgPT0gMikgJT4lDQogIGZ1bmNfdF9ib3goIklEIiwgIk5BX3ByZV9Ub3RhbCIsICJOQV9wb3N0X1RvdGFsIikNCmBgYA0KDQoNCiMgVkFTIA0KDQpgYGB7ciB0X3Rlc3RfdmFzLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD03LCByZXN1bHRzPSdhc2lzJ30NCmNhdCgiIyMjIFN0cmVzcyAtIFppIDEiKQ0KRGF0YSAlPiUNCiAgZmlsdGVyKFppID09IDEpICU+JQ0KICBmdW5jX3RfYm94KCJJRCIsICJWQVNfc3RyZXNfcHJlIiwgIlZBU19zdHJlc19wb3N0X2V4MSIpDQoNCmNhdCgiIyMjIFN0cmVzcyAtICBaaSAyIikNCkRhdGEgJT4lDQogIGZpbHRlcihaaSA9PSAyKSAlPiUNCiAgZnVuY190X2JveCgiSUQiLCAiVkFTX3N0cmVzX3ByZSIsICJWQVNfc3RyZXNfcG9zdF9leDEiKQ0KDQoNCmNhdCgiIyMjIFdlbGwgYmVpbmcgLSBaaSAxIikNCkRhdGEgJT4lDQogIGZpbHRlcihaaSA9PSAxKSAlPiUNCiAgZnVuY190X2JveCgiSUQiLCAiVkFTX3N0YXJlX2RlX2JpbmVfcHJlIiwgIlZBU19zdGFyZV9kZV9iaW5lX3Bvc3RfZXgxIikNCg0KY2F0KCIjIyMgV2VsbCBiZWluZyAtICBaaSAyIikNCkRhdGEgJT4lDQogIGZpbHRlcihaaSA9PSAyKSAlPiUNCiAgZnVuY190X2JveCgiSUQiLCAiVkFTX3N0YXJlX2RlX2JpbmVfcHJlIiwgIlZBU19zdGFyZV9kZV9iaW5lX3Bvc3RfZXgxIikNCmBgYA0KDQoNCiMgSU9TDQoNCmBgYHtyIHRfdGVzdF9pb3MsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTcsIHJlc3VsdHM9J2FzaXMnfQ0KY2F0KCIjIyMgSU9TIC0gWmkgMSIpDQpEYXRhICU+JQ0KICBmaWx0ZXIoWmkgPT0gMSkgJT4lDQogIGZ1bmNfdF9ib3goIklEIiwgIklPU19wcmUiLCAiSU9TX3Bvc3QiKQ0KDQpjYXQoIiMjIyBJT1MgLSAgWmkgMiIpDQpEYXRhICU+JQ0KICBmaWx0ZXIoWmkgPT0gMikgJT4lDQogIGZ1bmNfdF9ib3goIklEIiwgIklPU19wcmUiLCAiSU9TX3Bvc3QiKQ0KYGBgDQoNCg0KDQoNCjwhLS0gU2Vzc2lvbiBJbmZvIGFuZCBMaWNlbnNlIC0tPg0KDQo8YnI+DQoNCiMgU2Vzc2lvbiBJbmZvDQpgYGB7ciBzZXNzaW9uX2luZm8sIGVjaG8gPSBGQUxTRSwgcmVzdWx0cyA9ICdtYXJrdXAnfQ0Kc2Vzc2lvbkluZm8oKSAgICANCmBgYA0KDQo8IS0tIEZvb3RlciAtLT4NCiZuYnNwOw0KPGhyIC8+DQo8cCBzdHlsZT0idGV4dC1hbGlnbjogY2VudGVyOyI+QSB3b3JrIGJ5IDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9DbGF1ZGl1UGFwYXN0ZXJpLyI+Q2xhdWRpdSBQYXBhc3Rlcmk8L2E+PC9wPg0KPHAgc3R5bGU9InRleHQtYWxpZ246IGNlbnRlcjsiPjxzcGFuIHN0eWxlPSJjb2xvcjogIzgwODA4MDsiPjxlbT5jbGF1ZGl1LnBhcGFzdGVyaUBnbWFpbC5jb208L2VtPjwvc3Bhbj48L3A+DQombmJzcDsNCg==