Using recurrence networks to summarise time series of MS users in APPS MS

Read in necessary libraries, functions and look up tables

library(igraph)
library(qgraph)
library(casnet)
library(plyr)
library(dplyr)
library(tidyr)
library(caret)
library(psych)
library(lme4)
library(reshape2)
library(lubridate)
library(parallel)
library(wesanderson)
library(stringr)
library(matrixStats)
library(ggthemes)
library(gridExtra)
library(cowplot)
library(DataExplorer)


# save the original plotting space parameters
og_par <- par()
Show the session information
devtools::session_info()
─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 package      * version    date       lib source                               
 abind          1.4-5      2016-07-21 [1] CRAN (R 4.0.2)                       
 assertthat     0.2.1      2019-03-21 [1] CRAN (R 4.0.2)                       
 backports      1.2.0      2020-11-02 [1] CRAN (R 4.0.2)                       
 base64enc      0.1-3      2015-07-28 [1] CRAN (R 4.0.2)                       
 BDgraph        2.63       2020-08-26 [1] CRAN (R 4.0.2)                       
 boot           1.3-25     2020-04-26 [1] CRAN (R 4.0.3)                       
 callr          3.5.1      2020-10-13 [1] CRAN (R 4.0.2)                       
 caret        * 6.0-86     2020-03-20 [1] CRAN (R 4.0.2)                       
 casnet       * 0.1.6      2020-11-14 [1] Github (FredHasselman/casnet@e9e231e)
 checkmate      2.0.0      2020-02-06 [1] CRAN (R 4.0.2)                       
 class          7.3-17     2020-04-26 [1] CRAN (R 4.0.3)                       
 cli            2.1.0      2020-10-12 [1] CRAN (R 4.0.2)                       
 cluster        2.1.0      2019-06-19 [1] CRAN (R 4.0.3)                       
 codetools      0.2-16     2018-12-24 [1] CRAN (R 4.0.3)                       
 colorspace     2.0-0      2020-11-11 [1] CRAN (R 4.0.2)                       
 corpcor        1.6.9      2017-04-01 [1] CRAN (R 4.0.2)                       
 cowplot      * 1.1.0      2020-09-08 [1] CRAN (R 4.0.2)                       
 crayon         1.3.4      2017-09-16 [1] CRAN (R 4.0.2)                       
 d3Network      0.5.2.1    2015-01-31 [1] CRAN (R 4.0.2)                       
 data.table     1.14.0     2021-02-21 [1] CRAN (R 4.0.2)                       
 DataExplorer * 0.8.2      2020-12-15 [1] CRAN (R 4.0.2)                       
 desc           1.2.0      2018-05-01 [1] CRAN (R 4.0.2)                       
 devtools       2.3.2      2020-09-18 [1] CRAN (R 4.0.2)                       
 digest         0.6.27     2020-10-24 [1] CRAN (R 4.0.2)                       
 dplyr        * 1.0.2      2020-08-18 [1] CRAN (R 4.0.2)                       
 ellipsis       0.3.1      2020-05-15 [1] CRAN (R 4.0.2)                       
 evaluate       0.14       2019-05-28 [1] CRAN (R 4.0.1)                       
 fansi          0.4.1      2020-01-08 [1] CRAN (R 4.0.2)                       
 fdrtool        1.2.15     2015-07-08 [1] CRAN (R 4.0.2)                       
 foreach        1.5.1      2020-10-15 [1] CRAN (R 4.0.2)                       
 foreign        0.8-80     2020-05-24 [1] CRAN (R 4.0.3)                       
 Formula        1.2-4      2020-10-16 [1] CRAN (R 4.0.2)                       
 fs             1.5.0      2020-07-31 [1] CRAN (R 4.0.2)                       
 generics       0.1.0      2020-10-31 [1] CRAN (R 4.0.2)                       
 ggplot2      * 3.3.2      2020-06-19 [1] CRAN (R 4.0.2)                       
 ggthemes     * 4.2.0      2019-05-13 [1] CRAN (R 4.0.2)                       
 glasso         1.11       2019-10-01 [1] CRAN (R 4.0.2)                       
 glue           1.4.2      2020-08-27 [1] CRAN (R 4.0.2)                       
 gower          0.2.2      2020-06-23 [1] CRAN (R 4.0.2)                       
 gridExtra    * 2.3        2017-09-09 [1] CRAN (R 4.0.2)                       
 gtable         0.3.0      2019-03-25 [1] CRAN (R 4.0.2)                       
 gtools         3.8.2      2020-03-31 [1] CRAN (R 4.0.2)                       
 Hmisc          4.4-1      2020-08-10 [1] CRAN (R 4.0.2)                       
 htmlTable      2.1.0      2020-09-16 [1] CRAN (R 4.0.2)                       
 htmltools      0.5.0      2020-06-16 [1] CRAN (R 4.0.2)                       
 htmlwidgets    1.5.2      2020-10-03 [1] CRAN (R 4.0.2)                       
 huge           1.3.4.1    2020-04-01 [1] CRAN (R 4.0.2)                       
 igraph       * 1.2.6      2020-10-06 [1] CRAN (R 4.0.2)                       
 invctr         0.1.0      2019-03-07 [1] CRAN (R 4.0.2)                       
 ipred          0.9-9      2019-04-28 [1] CRAN (R 4.0.2)                       
 iterators      1.0.13     2020-10-15 [1] CRAN (R 4.0.2)                       
 jpeg           0.1-8.1    2019-10-24 [1] CRAN (R 4.0.2)                       
 knitr          1.30       2020-09-22 [1] CRAN (R 4.0.2)                       
 lattice      * 0.20-41    2020-04-02 [1] CRAN (R 4.0.3)                       
 latticeExtra   0.6-29     2019-12-19 [1] CRAN (R 4.0.2)                       
 lava           1.6.8.1    2020-11-04 [1] CRAN (R 4.0.2)                       
 lavaan         0.6-7      2020-07-31 [1] CRAN (R 4.0.2)                       
 lifecycle      0.2.0      2020-03-06 [1] CRAN (R 4.0.2)                       
 lme4         * 1.1-25     2020-10-23 [1] CRAN (R 4.0.2)                       
 lubridate    * 1.7.9.2    2020-11-13 [1] CRAN (R 4.0.3)                       
 magrittr       1.5        2014-11-22 [1] CRAN (R 4.0.2)                       
 MASS           7.3-53     2020-09-09 [1] CRAN (R 4.0.3)                       
 Matrix       * 1.2-18     2019-11-27 [1] CRAN (R 4.0.3)                       
 matrixStats  * 0.57.0     2020-09-25 [1] CRAN (R 4.0.2)                       
 memoise        1.1.0      2017-04-21 [1] CRAN (R 4.0.2)                       
 minqa          1.2.4      2014-10-09 [1] CRAN (R 4.0.2)                       
 mnormt         2.0.2      2020-09-01 [1] CRAN (R 4.0.2)                       
 ModelMetrics   1.2.2.2    2020-03-17 [1] CRAN (R 4.0.2)                       
 munsell        0.5.0      2018-06-12 [1] CRAN (R 4.0.2)                       
 networkD3      0.4        2017-03-18 [1] CRAN (R 4.0.2)                       
 nlme           3.1-149    2020-08-23 [1] CRAN (R 4.0.3)                       
 nloptr         1.2.2.2    2020-07-02 [1] CRAN (R 4.0.2)                       
 nnet           7.3-14     2020-04-26 [1] CRAN (R 4.0.3)                       
 pbapply        1.4-3      2020-08-18 [1] CRAN (R 4.0.2)                       
 pbivnorm       0.6.0      2015-01-23 [1] CRAN (R 4.0.2)                       
 pillar         1.4.6      2020-07-10 [1] CRAN (R 4.0.2)                       
 pkgbuild       1.1.0      2020-07-13 [1] CRAN (R 4.0.2)                       
 pkgconfig      2.0.3      2019-09-22 [1] CRAN (R 4.0.2)                       
 pkgload        1.1.0      2020-05-29 [1] CRAN (R 4.0.2)                       
 plyr         * 1.8.6      2020-03-03 [1] CRAN (R 4.0.2)                       
 png            0.1-7      2013-12-03 [1] CRAN (R 4.0.2)                       
 prettyunits    1.1.1      2020-01-24 [1] CRAN (R 4.0.2)                       
 pROC           1.16.2     2020-03-19 [1] CRAN (R 4.0.2)                       
 processx       3.4.4      2020-09-03 [1] CRAN (R 4.0.2)                       
 prodlim        2019.11.13 2019-11-17 [1] CRAN (R 4.0.2)                       
 ps             1.4.0      2020-10-07 [1] CRAN (R 4.0.2)                       
 psych        * 2.0.9      2020-10-05 [1] CRAN (R 4.0.2)                       
 purrr          0.3.4      2020-04-17 [1] CRAN (R 4.0.2)                       
 qgraph       * 1.6.5      2020-02-21 [1] CRAN (R 4.0.2)                       
 R6             2.5.0      2020-10-28 [1] CRAN (R 4.0.2)                       
 RColorBrewer   1.1-2      2014-12-07 [1] CRAN (R 4.0.2)                       
 Rcpp           1.0.5      2020-07-06 [1] CRAN (R 4.0.2)                       
 recipes        0.1.15     2020-11-11 [1] CRAN (R 4.0.2)                       
 remotes        2.4.0      2021-06-02 [1] CRAN (R 4.0.2)                       
 reshape2     * 1.4.4      2020-04-09 [1] CRAN (R 4.0.2)                       
 rjson          0.2.20     2018-06-08 [1] CRAN (R 4.0.2)                       
 rlang          0.4.8      2020-10-08 [1] CRAN (R 4.0.2)                       
 rmarkdown      2.5        2020-10-21 [1] CRAN (R 4.0.3)                       
 rpart          4.1-15     2019-04-12 [1] CRAN (R 4.0.3)                       
 rprojroot      1.3-2      2018-01-03 [1] CRAN (R 4.0.2)                       
 rstudioapi     0.13       2020-11-12 [1] CRAN (R 4.0.3)                       
 scales         1.1.1      2020-05-11 [1] CRAN (R 4.0.2)                       
 sessioninfo    1.1.1      2018-11-05 [1] CRAN (R 4.0.2)                       
 statmod        1.4.35     2020-10-19 [1] CRAN (R 4.0.2)                       
 stringi        1.5.3      2020-09-09 [1] CRAN (R 4.0.2)                       
 stringr      * 1.4.0      2019-02-10 [1] CRAN (R 4.0.2)                       
 survival       3.2-7      2020-09-28 [1] CRAN (R 4.0.3)                       
 testthat       3.0.0      2020-10-31 [1] CRAN (R 4.0.2)                       
 tibble         3.0.4      2020-10-12 [1] CRAN (R 4.0.2)                       
 tidyr        * 1.1.2      2020-08-27 [1] CRAN (R 4.0.2)                       
 tidyselect     1.1.0      2020-05-11 [1] CRAN (R 4.0.2)                       
 timeDate       3043.102   2018-02-21 [1] CRAN (R 4.0.2)                       
 tmvnsim        1.0-2      2016-12-15 [1] CRAN (R 4.0.2)                       
 usethis        1.6.3      2020-09-17 [1] CRAN (R 4.0.2)                       
 vctrs          0.3.4      2020-08-29 [1] CRAN (R 4.0.2)                       
 wesanderson  * 0.3.6      2018-04-20 [1] CRAN (R 4.0.2)                       
 whisker        0.4        2019-08-28 [1] CRAN (R 4.0.2)                       
 withr          2.3.0      2020-09-22 [1] CRAN (R 4.0.2)                       
 xfun           0.19       2020-10-30 [1] CRAN (R 4.0.2)                       

[1] /Library/Frameworks/R.framework/Versions/4.0/Resources/library

Read in data

plot_intro(dai_df)

plot_bar(dai_df)
3 columns ignored with more than 50 categories.
User: 102 categories
date: 125 categories
strategies: 1035 categories

plot_correlation(dai_df)
4 features with more than 20 categories ignored!
User: 102 categories
date: 125 categories
howami_participation_started: 37 categories
strategies: 1035 categories

 [1] "absorption"        "amotivation"       "autonomy"          "competence"        "dedication"        "emotional_drain"   "enjoyment"         "external.pressure"
 [9] "importance"        "interest"          "internal.pressure" "productivity_work" "relatedness"       "satisfaction_work" "time_pressure"     "vigor"            

Split the keystroke df into a list of dfs based on User

# head(dai_df)
# dai_df %>% group_by(User) %>% summarize(count = n())

df_list <- split(dai_df[c("User", vars)], dai_df["User"])

Define the functions which will be applied to each user individually

Select users with long enough time series

user_row_lengths_list <- lapply(df_list, function(x) length(rownames(x)))
user_row_lengths_df <- t(data.frame(user_row_lengths_list))
user_row_lengths_df <- data.frame(cbind(user_row_lengths_df, unique(dai_df$User)))

user_row_lengths_df$X1 <- as.numeric(user_row_lengths_df$X1)

# User_list <- user_row_lengths_df[user_row_lengths_df["X1"] > 30, "X2"]
# User_list <- unique(dai_df$User)
# User_list <- c('Moti148', 'Moti143', 'Moti140', 'Moti156', 'Moti151')
User_list <- c(
  # 'Moti114',
 # 'Moti147',
 'Moti149',
 'Moti164',
 'Moti106',
 'Moti121',
 'Moti137',
 'Moti138',
 'Moti150',
 'Moti157',
 'Moti148',
 'Moti143',
 'Moti140',
 'Moti156',
 'Moti151')

df_list <- df_list[names(df_list) %in% User_list]
# df_list_imp_scal <- df_list_imp_scal[names(df_list_imp_scal) %in% User_list]

Prepare the data (impute and min max scale) and plot an example feature

df_list_imp <- lapply(df_list, apply_imputation, vars)
Number of logged events: 60replacement element 1 has 125 rows to replace 60 rowsNumber of logged events: 35replacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rowsreplacement element 1 has 125 rows to replace 60 rows
df_list_imp_scal <- lapply(df_list_imp, apply_scaling, vars)
df_list_imp[example_user]
$Moti143
df_list_imp_scal[example_user]
$Moti143
NA

Remove users from the imputed and scaled dfs list that had too many missing values

user_drop_list <- c()
for (User in User_list) {
  missing_amount <- sum(sapply(df_list_imp_scal[[as.character(User)]], function(x) sum(is.na(x))))
  # print(User)
  # print(missing_amount)
  if (missing_amount > 0) {
    print(User)
    print(missing_amount)
    user_drop_list <- c(user_drop_list, as.character(User))
  }
}

df_list_imp_scal <- df_list_imp_scal[!names(df_list_imp_scal) %in% user_drop_list]
# for (User in unique(dai_df$User)) {
#   print(User)
#   apply_RP_measures(df_list_imp_scal[as.character(User)], vars, emLag, emDim)
# }

Identify the feature with the most variable Determinism (variance within users) and assign this the feature of interest for the rest of the analysis.

all_RP_measures_df <- reshape::merge_all(RP_measures_list)

rqa_feature <- "ENT_dl" #TT_vl DET

all_RP_measures_df_long <- melt(all_RP_measures_df[, c("feature", rqa_feature)], id.vars = "feature")

g <- ggplot(all_RP_measures_df_long, aes(x=feature, y=value)) +
    geom_boxplot(outlier.colour="#e58038", outlier.shape=8,
                outlier.size=4) +
  theme(axis.text.x = element_text(angle = 90))
print(g)


agg_RP_measures_df <- aggregate(all_RP_measures_df[, c(rqa_feature)], list(all_RP_measures_df$feature), var, na.rm=TRUE)
colnames(agg_RP_measures_df) <- c("feature", rqa_feature)

feature_of_interest <- agg_RP_measures_df[which(agg_RP_measures_df[rqa_feature]==max(agg_RP_measures_df[rqa_feature])), "feature"][1]

print("New feature of interest:")
[1] "New feature of interest:"
feature_of_interest
[1] "satisfaction_work"

Spiral graphs of the feature of interest per user with embedding lag and embedding dimension the same across all users

plot.ts(x=df_list_imp_scal[["Moti156"]]$enjoyment)

plot.ts(x=df_list[["Moti156"]]$enjoyment)

feature_of_interest_RN_measures_df <- reshape::merge_all(RN_measures_list)
# write.csv(feature_of_interest_RN_measures_df, 
#           file=paste("data/", feature_of_interest, "_RN_measures.csv", sep = ""))
LS0tCnRpdGxlOiAiUmVjdXJyZW5jZSBOZXR3b3JrcyBvZiBEYWlseSBxdWVzdGlvbm5haXJlcyBvbiB3b3JrIG1vdGl2YXRpb24iCnN1YnRpdGxlOiAiICIKYXV0aG9yOiAKLSAiSmFtZXMgVHdvc2UiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKIyMgVXNpbmcgcmVjdXJyZW5jZSBuZXR3b3JrcyB0byBzdW1tYXJpc2UgdGltZSBzZXJpZXMgb2YgTVMgdXNlcnMgaW4gQVBQUyBNUwoKIyMjIyBSZWFkIGluIG5lY2Vzc2FyeSBsaWJyYXJpZXMsIGZ1bmN0aW9ucyBhbmQgbG9vayB1cCB0YWJsZXMKCmBgYHtyIGVjaG89VFJVRSwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShpZ3JhcGgpCmxpYnJhcnkocWdyYXBoKQpsaWJyYXJ5KGNhc25ldCkKbGlicmFyeShwbHlyKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGNhcmV0KQpsaWJyYXJ5KHBzeWNoKQpsaWJyYXJ5KGxtZTQpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHBhcmFsbGVsKQpsaWJyYXJ5KHdlc2FuZGVyc29uKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkobWF0cml4U3RhdHMpCmxpYnJhcnkoZ2d0aGVtZXMpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoRGF0YUV4cGxvcmVyKQoKCiMgc2F2ZSB0aGUgb3JpZ2luYWwgcGxvdHRpbmcgc3BhY2UgcGFyYW1ldGVycwpvZ19wYXIgPC0gcGFyKCkKYGBgCgojIyMjIyBTaG93IHRoZSBzZXNzaW9uIGluZm9ybWF0aW9uCmBgYHtyfQpkZXZ0b29sczo6c2Vzc2lvbl9pbmZvKCkKYGBgCgojIyMjIFJlYWQgaW4gZGF0YQoKYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgZGFpX2RmIDwtIHJlYWQuY3N2KCJkYXRhL3JlbGFwc2Vfd19tYXRjaGVkX3VzZXJzX2tleV9jbHVzdGVycy5jc3YiLCByb3cubmFtZXMgPSAiWCIpCmRhaV9kZiA8LSByZWFkLmNzdigiZGF0YS9tb3RpX2ZlYXNpYmlsaXR5X2phbWVzX2RhaWx5X3Bpdm90LmNzdiIsIHJvdy5uYW1lcyA9ICJYIikKZmVhdHVyZV9vZl9pbnRlcmVzdCA8LSAiZGVkaWNhdGlvbiIKYGBgCgpgYGB7cn0KcGxvdF9pbnRybyhkYWlfZGYpCnBsb3RfYmFyKGRhaV9kZikKcGxvdF9jb3JyZWxhdGlvbihkYWlfZGYpCmBgYAoKCmBgYHtyLCBlY2hvPVRydWUsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmV4YW1wbGVfdXNlciA8LSAiTW90aTE0MyIKZGYgPC0gZGFpX2RmW2RhaV9kZlsiVXNlciJdID09IGV4YW1wbGVfdXNlciwgXQojIHZhcnMgPC0gY29sbmFtZXMoZGFpX2RmKVs1OjhdI1szOjYwXQp2YXJzIDwtIGMoImFic29ycHRpb24iLCAiYW1vdGl2YXRpb24iLCAiYXV0b25vbXkiLCAiY29tcGV0ZW5jZSIsICJkZWRpY2F0aW9uIiwgImVtb3Rpb25hbF9kcmFpbiIsICJlbmpveW1lbnQiLCAKICAgICAgICAgICJleHRlcm5hbC5wcmVzc3VyZSIsICJpbXBvcnRhbmNlIiwgImludGVyZXN0IiwgImludGVybmFsLnByZXNzdXJlIiwgInByb2R1Y3Rpdml0eV93b3JrIiwgInJlbGF0ZWRuZXNzIiwgInNhdGlzZmFjdGlvbl93b3JrIiwgInRpbWVfcHJlc3N1cmUiLCAidmlnb3IiKQp2YXJzCmBgYAoKIyMjIFNwbGl0IHRoZSBrZXlzdHJva2UgZGYgaW50byBhIGxpc3Qgb2YgZGZzIGJhc2VkIG9uIFVzZXIKCmBgYHtyfQojIGhlYWQoZGFpX2RmKQojIGRhaV9kZiAlPiUgZ3JvdXBfYnkoVXNlcikgJT4lIHN1bW1hcml6ZShjb3VudCA9IG4oKSkKCmRmX2xpc3QgPC0gc3BsaXQoZGFpX2RmW2MoIlVzZXIiLCB2YXJzKV0sIGRhaV9kZlsiVXNlciJdKQpgYGAKCiMjIyBEZWZpbmUgdGhlIGZ1bmN0aW9ucyB3aGljaCB3aWxsIGJlIGFwcGxpZWQgdG8gZWFjaCB1c2VyIGluZGl2aWR1YWxseQoKYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CiMgSW1wdXRlIG1pc3NpbmcgdmFsdWVzIHdpdGggQ2xhc3NpZmljYXRpb24gQW5kIFJlZ3Jlc3Npb24gVHJlZXMgLyBSYW5kb20gRm9yZXN0cwojIFJGIGFuZCBDQVJUIHJldHVybiAoaWRlbnRpY2FsKSBkaXNjcmV0ZSBudW1iZXJzCiMgaW1wLmNhcnQgIDwtIG1pY2U6Om1pY2UoZGZbdmFyc10sIG1ldGhvZCA9ICdjYXJ0JywgcmVtb3ZlLmNvbnN0YW50ID0gVFJVRSwgcmVtb3ZlLmNvbGxpbmVhciA9IFRSVUUsIHByaW50RmxhZyA9IEZBTFNFKQojIGRmX2ltcCAgPC0gbWljZTo6Y29tcGxldGUoaW1wLmNhcnQpCgpxdWlldCA8LSBmdW5jdGlvbih4KSB7IAogIHNpbmsodGVtcGZpbGUoKSkgCiAgb24uZXhpdChzaW5rKCkpIAogIGludmlzaWJsZShmb3JjZSh4KSkgCn0gCgphcHBseV9pbXB1dGF0aW9uIDwtIGZ1bmN0aW9uKGRmLCB2YXJzKXsKICBpbXAuY2FydCAgPC0gbWljZTo6bWljZShkZlsxOjYwLCB2YXJzXSwgbWV0aG9kID0gJ2NhcnQnLCByZW1vdmUuY29uc3RhbnQgPSBUUlVFLCByZW1vdmUuY29sbGluZWFyID0gVFJVRSwgcHJpbnRGbGFnID0gRkFMU0UpCiAgIyBpbXAuY2FydCAgPC0gbWljZTo6bWljZShkZlt2YXJzXSwgbWV0aG9kID0gJ2NhcnQnLCByZW1vdmUuY29uc3RhbnQgPSBUUlVFLCByZW1vdmUuY29sbGluZWFyID0gVFJVRSwgcHJpbnRGbGFnID0gRkFMU0UpCiAgZGZfaW1wICA8LSBtaWNlOjpjb21wbGV0ZShpbXAuY2FydCkKICBkZl9pbXBbIlVzZXIiXSA8LSBkZlsiVXNlciJdCiAgcmV0dXJuKGRmX2ltcCkKfQoKCmFwcGx5X3NjYWxpbmcgPC0gZnVuY3Rpb24oZGYsIHZhcnMpIHsKICBkZl9zY2FsIDwtIGRhdGEuZnJhbWUoYXBwbHkoZGZbdmFyc10sIDIsIGVsYXNjZXIpKQogIGRmX3NjYWxbIlVzZXIiXSA8LSBkZlsiVXNlciJdCiAgcmV0dXJuKGRmX3NjYWwpCn0KCmFwcGx5X1JQX21lYXN1cmVzIDwtIGZ1bmN0aW9uKGRmLCB2YXJzLCBlbURpbSwgZW1MYWcpIHsKCiAgUlBzIDwtIHBseXI6OmxscGx5KDE6bGVuZ3RoKHZhcnMpLCBmdW5jdGlvbihyKSBycCh5MSA9IGRmWzE6NjAsIHJdLCBlbURpbSA9IGVtRGltLCBlbUxhZyA9IGVtTGFnLCBlbVJhZCA9IE5BLCB0YXJnZXRWYWx1ZSA9IDAuMDUpKQogICMgUlBzIDwtIHBseXI6OmxscGx5KDE6bGVuZ3RoKHZhcnMpLCBmdW5jdGlvbihyKSBycCh5MSA9IGRmWywgcl0sIGVtRGltID0gZW1EaW0sIGVtTGFnID0gZW1MYWcsIGVtUmFkID0gTkEsIHRhcmdldFZhbHVlID0gMC4wNSkpCiAgcHJpbnQoZGZbMSwgIlVzZXIiXSkKICBSUF9tZWFzdXJlc19saXN0IDwtIHBseXI6OmxscGx5KFJQcywgZnVuY3Rpb24ocikgcnBfbWVhc3VyZXMoUk09ciwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVtUmFkID0gMC4wNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERMbWluID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFZMbWluID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEhMbWluID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbGVudCA9IFRSVUUpKQogIAogIHVzZXJfcnBfbWVhc3VyZXNfZGYgPC0gcmVzaGFwZTo6bWVyZ2VfYWxsKFJQX21lYXN1cmVzX2xpc3QpIAogIHVzZXJfcnBfbWVhc3VyZXNfZGYgPC0gdXNlcl9ycF9tZWFzdXJlc19kZltvcmRlcihhcy5udW1lcmljKHJvd25hbWVzKHVzZXJfcnBfbWVhc3VyZXNfZGYpKSksIF0KICB1c2VyX3JwX21lYXN1cmVzX2RmWyJmZWF0dXJlIl0gPC0gdmFycwogIHVzZXJfcnBfbWVhc3VyZXNfZGZbIlVzZXIiXSA8LSBkZlsiVXNlciJdCiAgcmV0dXJuKHVzZXJfcnBfbWVhc3VyZXNfZGYpCn0KCgphcHBseV9STl9wbG90cyA8LSBmdW5jdGlvbihkZiwgZmVhdHVyZV9vZl9pbnRlcmVzdCwgZW1EaW0sIGVtTGFnKSB7CiAgUk4gPC0gcm4oeTEgPSBkZlsxOjYwLCBmZWF0dXJlX29mX2ludGVyZXN0XSwgZW1EaW0gPSBlbURpbSwgZW1MYWcgPSBlbUxhZywgZW1SYWQgPSBOQSwgdGFyZ2V0VmFsdWUgPSAwLjA1KQogICMgUk4gPC0gcm4oeTEgPSBkZlssIGZlYXR1cmVfb2ZfaW50ZXJlc3RdLCBlbURpbSA9IGVtRGltLCBlbUxhZyA9IGVtTGFnLCBlbVJhZCA9IE5BLCB0YXJnZXRWYWx1ZSA9IDAuMDUpCiAgCiAgYXJjcyA8LSA2CiAgVXNlciA8LSBkZlsxLCAiVXNlciJdCgogIGcxIDwtIGlncmFwaDo6Z3JhcGhfZnJvbV9hZGphY2VuY3lfbWF0cml4KFJOLCBtb2RlPSJ1bmRpcmVjdGVkIiwgZGlhZyA9IEZBTFNFKQogIGlncmFwaDo6VihnMSkkc2l6ZSA8LSBpZ3JhcGg6OmRlZ3JlZShnMSkKICBnMXIgPC0gY2FzbmV0OjptYWtlX3NwaXJhbF9ncmFwaChnMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgdHlwZSA9ICJFdWxlciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJjcyA9IGFyY3MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXBvY2hDb2xvdXJzID0gZ2V0Q29sb3VycyhhcmNzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZSA9IHBhc3RlKCJVc2VyID09IiwgVXNlciksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFya1RpbWVCeSA9IFRSVUUpCiAgZ2dzYXZlKHBhc3RlMCgiaW1hZ2VzL3NwaXJhbF9ncmFwaF9zaG9ydCIsIFVzZXIsICIucG5nIikpCiAgcmV0dXJuKGcxcikKfQoKYXBwbHlfUk5fbWVhc3VyZXMgPC0gZnVuY3Rpb24oZGYsIGZlYXR1cmVfb2ZfaW50ZXJlc3QsIGVtRGltLCBlbUxhZykgewogIFJOIDwtIHJuKHkxID0gZGZbMTo2MCwgZmVhdHVyZV9vZl9pbnRlcmVzdF0sIGVtRGltID0gZW1EaW0sIGVtTGFnID0gZW1MYWcsIGVtUmFkID0gTkEsIHRhcmdldFZhbHVlID0gMC4wNSkKICAjIFJOIDwtIHJuKHkxID0gZGZbLCBmZWF0dXJlX29mX2ludGVyZXN0XSwgZW1EaW0gPSBlbURpbSwgZW1MYWcgPSBlbUxhZywgZW1SYWQgPSBOQSwgdGFyZ2V0VmFsdWUgPSAwLjA1KQogIAogIGFyY3MgPC0gNgogIFVzZXIgPC0gZGZbMSwgIlVzZXIiXQoKICBnMSA8LSBpZ3JhcGg6OmdyYXBoX2Zyb21fYWRqYWNlbmN5X21hdHJpeChSTiwgbW9kZT0idW5kaXJlY3RlZCIsIGRpYWcgPSBGQUxTRSkKICBuZXR3b3JrX21lYXN1cmVzIDwtIHJuX21lYXN1cmVzKGcxLCBzaWxlbnQgPSBUUlVFKQogIGdyYXBoX21lYXN1cmVzX2RmIDwtIG5ldHdvcmtfbWVhc3VyZXMkZ3JhcGhfbWVhc3VyZXMKICBncmFwaF9tZWFzdXJlc19kZlsiVXNlciJdIDwtIGRmWyJVc2VyIl0KCiAgcmV0dXJuKGdyYXBoX21lYXN1cmVzX2RmKQp9CgpgYGAKCiMjIyBTZWxlY3QgdXNlcnMgd2l0aCBsb25nIGVub3VnaCB0aW1lIHNlcmllcwpgYGB7cn0KdXNlcl9yb3dfbGVuZ3Roc19saXN0IDwtIGxhcHBseShkZl9saXN0LCBmdW5jdGlvbih4KSBsZW5ndGgocm93bmFtZXMoeCkpKQp1c2VyX3Jvd19sZW5ndGhzX2RmIDwtIHQoZGF0YS5mcmFtZSh1c2VyX3Jvd19sZW5ndGhzX2xpc3QpKQp1c2VyX3Jvd19sZW5ndGhzX2RmIDwtIGRhdGEuZnJhbWUoY2JpbmQodXNlcl9yb3dfbGVuZ3Roc19kZiwgdW5pcXVlKGRhaV9kZiRVc2VyKSkpCgp1c2VyX3Jvd19sZW5ndGhzX2RmJFgxIDwtIGFzLm51bWVyaWModXNlcl9yb3dfbGVuZ3Roc19kZiRYMSkKCiMgVXNlcl9saXN0IDwtIHVzZXJfcm93X2xlbmd0aHNfZGZbdXNlcl9yb3dfbGVuZ3Roc19kZlsiWDEiXSA+IDMwLCAiWDIiXQojIFVzZXJfbGlzdCA8LSB1bmlxdWUoZGFpX2RmJFVzZXIpCiMgVXNlcl9saXN0IDwtIGMoJ01vdGkxNDgnLCAnTW90aTE0MycsICdNb3RpMTQwJywgJ01vdGkxNTYnLCAnTW90aTE1MScpClVzZXJfbGlzdCA8LSBjKAogICMgJ01vdGkxMTQnLAogIyAnTW90aTE0NycsCiAnTW90aTE0OScsCiAnTW90aTE2NCcsCiAnTW90aTEwNicsCiAnTW90aTEyMScsCiAnTW90aTEzNycsCiAnTW90aTEzOCcsCiAnTW90aTE1MCcsCiAnTW90aTE1NycsCiAnTW90aTE0OCcsCiAnTW90aTE0MycsCiAnTW90aTE0MCcsCiAnTW90aTE1NicsCiAnTW90aTE1MScpCgpkZl9saXN0IDwtIGRmX2xpc3RbbmFtZXMoZGZfbGlzdCkgJWluJSBVc2VyX2xpc3RdCiMgZGZfbGlzdF9pbXBfc2NhbCA8LSBkZl9saXN0X2ltcF9zY2FsW25hbWVzKGRmX2xpc3RfaW1wX3NjYWwpICVpbiUgVXNlcl9saXN0XQpgYGAKCiMjIyBQcmVwYXJlIHRoZSBkYXRhIChpbXB1dGUgYW5kIG1pbiBtYXggc2NhbGUpIGFuZCBwbG90IGFuIGV4YW1wbGUgZmVhdHVyZQoKYGBge3J9CmRmX2xpc3RfaW1wIDwtIGxhcHBseShkZl9saXN0LCBhcHBseV9pbXB1dGF0aW9uLCB2YXJzKQpkZl9saXN0X2ltcF9zY2FsIDwtIGxhcHBseShkZl9saXN0X2ltcCwgYXBwbHlfc2NhbGluZywgdmFycykKZGZfbGlzdF9pbXBbZXhhbXBsZV91c2VyXQpkZl9saXN0X2ltcF9zY2FsW2V4YW1wbGVfdXNlcl0KYGBgCgojIyMgUmVtb3ZlIHVzZXJzIGZyb20gdGhlIGltcHV0ZWQgYW5kIHNjYWxlZCBkZnMgbGlzdCB0aGF0IGhhZCB0b28gbWFueSBtaXNzaW5nIHZhbHVlcwoKYGBge3J9CnVzZXJfZHJvcF9saXN0IDwtIGMoKQpmb3IgKFVzZXIgaW4gVXNlcl9saXN0KSB7CiAgbWlzc2luZ19hbW91bnQgPC0gc3VtKHNhcHBseShkZl9saXN0X2ltcF9zY2FsW1thcy5jaGFyYWN0ZXIoVXNlcildXSwgZnVuY3Rpb24oeCkgc3VtKGlzLm5hKHgpKSkpCiAgIyBwcmludChVc2VyKQogICMgcHJpbnQobWlzc2luZ19hbW91bnQpCiAgaWYgKG1pc3NpbmdfYW1vdW50ID4gMCkgewogICAgcHJpbnQoVXNlcikKICAgIHByaW50KG1pc3NpbmdfYW1vdW50KQogICAgdXNlcl9kcm9wX2xpc3QgPC0gYyh1c2VyX2Ryb3BfbGlzdCwgYXMuY2hhcmFjdGVyKFVzZXIpKQogIH0KfQoKZGZfbGlzdF9pbXBfc2NhbCA8LSBkZl9saXN0X2ltcF9zY2FsWyFuYW1lcyhkZl9saXN0X2ltcF9zY2FsKSAlaW4lIHVzZXJfZHJvcF9saXN0XQoKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmVtTGFnIDwtIDIKZW1EaW0gPC0gMgoKUlBfbWVhc3VyZXNfbGlzdCA8LSBxdWlldChsYXBwbHkoZGZfbGlzdF9pbXBfc2NhbCwgYXBwbHlfUlBfbWVhc3VyZXMsIHZhcnMsIGVtTGFnLCBlbURpbSkpCgpgYGAKCmBgYHtyfQojIGZvciAoVXNlciBpbiB1bmlxdWUoZGFpX2RmJFVzZXIpKSB7CiMgICBwcmludChVc2VyKQojICAgYXBwbHlfUlBfbWVhc3VyZXMoZGZfbGlzdF9pbXBfc2NhbFthcy5jaGFyYWN0ZXIoVXNlcildLCB2YXJzLCBlbUxhZywgZW1EaW0pCiMgfQoKYGBgCgoKIyMjIElkZW50aWZ5IHRoZSBmZWF0dXJlIHdpdGggdGhlIG1vc3QgdmFyaWFibGUgRGV0ZXJtaW5pc20gKHZhcmlhbmNlIHdpdGhpbiB1c2VycykgYW5kIGFzc2lnbiB0aGlzIHRoZSBmZWF0dXJlIG9mIGludGVyZXN0IGZvciB0aGUgcmVzdCBvZiB0aGUgYW5hbHlzaXMuCgpgYGB7ciwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTd9CmFsbF9SUF9tZWFzdXJlc19kZiA8LSByZXNoYXBlOjptZXJnZV9hbGwoUlBfbWVhc3VyZXNfbGlzdCkKCnJxYV9mZWF0dXJlIDwtICJFTlRfZGwiICNUVF92bCBERVQKCmFsbF9SUF9tZWFzdXJlc19kZl9sb25nIDwtIG1lbHQoYWxsX1JQX21lYXN1cmVzX2RmWywgYygiZmVhdHVyZSIsIHJxYV9mZWF0dXJlKV0sIGlkLnZhcnMgPSAiZmVhdHVyZSIpCgpnIDwtIGdncGxvdChhbGxfUlBfbWVhc3VyZXNfZGZfbG9uZywgYWVzKHg9ZmVhdHVyZSwgeT12YWx1ZSkpICsKICAgIGdlb21fYm94cGxvdChvdXRsaWVyLmNvbG91cj0iI2U1ODAzOCIsIG91dGxpZXIuc2hhcGU9OCwKICAgICAgICAgICAgICAgIG91dGxpZXIuc2l6ZT00KSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpCnByaW50KGcpCgphZ2dfUlBfbWVhc3VyZXNfZGYgPC0gYWdncmVnYXRlKGFsbF9SUF9tZWFzdXJlc19kZlssIGMocnFhX2ZlYXR1cmUpXSwgbGlzdChhbGxfUlBfbWVhc3VyZXNfZGYkZmVhdHVyZSksIHZhciwgbmEucm09VFJVRSkKY29sbmFtZXMoYWdnX1JQX21lYXN1cmVzX2RmKSA8LSBjKCJmZWF0dXJlIiwgcnFhX2ZlYXR1cmUpCgpmZWF0dXJlX29mX2ludGVyZXN0IDwtIGFnZ19SUF9tZWFzdXJlc19kZlt3aGljaChhZ2dfUlBfbWVhc3VyZXNfZGZbcnFhX2ZlYXR1cmVdPT1tYXgoYWdnX1JQX21lYXN1cmVzX2RmW3JxYV9mZWF0dXJlXSkpLCAiZmVhdHVyZSJdWzFdCgpwcmludCgiTmV3IGZlYXR1cmUgb2YgaW50ZXJlc3Q6IikKZmVhdHVyZV9vZl9pbnRlcmVzdAoKYGBgCgojIyMgU3BpcmFsIGdyYXBocyBvZiB0aGUgZmVhdHVyZSBvZiBpbnRlcmVzdCBwZXIgdXNlciB3aXRoIGVtYmVkZGluZyBsYWcgYW5kIGVtYmVkZGluZyBkaW1lbnNpb24gdGhlIHNhbWUgYWNyb3NzIGFsbCB1c2VycwoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQojIGxhcHBseShYPWRmX2xpc3RfaW1wX3NjYWwsIEZVTj1ucm93KQpmZWF0dXJlX29mX2ludGVyZXN0CiMgUk5zX2xpc3QgPC0gbGFwcGx5KGRmX2xpc3RfaW1wX3NjYWwsIGFwcGx5X1JOcywgZmVhdHVyZV9vZl9pbnRlcmVzdCwgZW1MYWcsIGVtRGltKQpSTl9wbG90c19saXN0IDwtIGxhcHBseShkZl9saXN0X2ltcF9zY2FsLCBhcHBseV9STl9wbG90cywgZmVhdHVyZV9vZl9pbnRlcmVzdCwgZW1MYWcsIGVtRGltKQpSTl9tZWFzdXJlc19saXN0IDwtIGxhcHBseShkZl9saXN0X2ltcF9zY2FsLCBhcHBseV9STl9tZWFzdXJlcywgZmVhdHVyZV9vZl9pbnRlcmVzdCwgZW1MYWcsIGVtRGltKQoKYGBgCmBgYHtyfQpwbG90LnRzKHg9ZGZfbGlzdF9pbXBfc2NhbFtbIk1vdGkxNTYiXV0kZW5qb3ltZW50KQpwbG90LnRzKHg9ZGZfbGlzdFtbIk1vdGkxNTYiXV0kZW5qb3ltZW50KQpgYGAKCgpgYGB7cn0KZmVhdHVyZV9vZl9pbnRlcmVzdF9STl9tZWFzdXJlc19kZiA8LSByZXNoYXBlOjptZXJnZV9hbGwoUk5fbWVhc3VyZXNfbGlzdCkKYGBgCgpgYGB7cn0KIyB3cml0ZS5jc3YoZmVhdHVyZV9vZl9pbnRlcmVzdF9STl9tZWFzdXJlc19kZiwgCiMgICAgICAgICAgIGZpbGU9cGFzdGUoImRhdGEvIiwgZmVhdHVyZV9vZl9pbnRlcmVzdCwgIl9STl9tZWFzdXJlcy5jc3YiLCBzZXAgPSAiIikpCmBgYAo=