Reasons for Exclusion

source("0_helpers.R")
library(tidylog)
load("data/cleaned.rdata")

library(knitr)
opts_chunk$set(fig.width = 9, fig.height = 7, cache = T, warning = T, message = T, cache = F, error = FALSE)

comma_separated_to_columns <- function(df, col) {
  colname <- deparse(substitute(col))
  df$splitcol <- df %>% pull(colname)
  separate_rows(df, splitcol, convert = TRUE, sep = ", ") %>% 
    mutate(splitcol = if_else(is.na(splitcol), "no", 
                        if_else(splitcol == "" | 
                                  splitcol %in% c(), "included", as.character(splitcol)))) %>% 
    mutate(#splitcol = stringr::str_c(colname, "_", splitcol), 
           value = 1) %>% 
    spread(splitcol, value, fill = 0) %>% 
    select(-colname)
}

all_survey_length <- nrow(all_surveys)
diary_length <- nrow(diary)
diary_social_length <- nrow(diary_social)
diary$reasons_for_exclusion_diary <- ""

Lab participants that did not do the online diary (not merged)

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(is.na(session), "lab_only, ", "", "")
                                       )
  )
## mutate: no changes

Disclosed that they responded dishonestly on that day.

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(dishonest_discard == 1, "dishonest_answer, ", "", "")
                                       )
  )
## mutate: changed 150 values (<1%) of 'reasons_for_exclusion_diary' (0 new NA)

Did not finish diary entry.

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(is.na(ended_diary) & !is.na(modified_diary), "did_not_finish_entry, ", "", "")
                                       )
  )
## mutate: changed 856 values (1%) of 'reasons_for_exclusion_diary' (0 new NA)

Cycle shorter than 20 days.

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(coalesce(minimum_cycle_length_diary, as.numeric(menstruation_length)) < 20, "cycle_shorter_than_20, ", "", "")
                                       )
  )
## mutate: changed 4,736 values (6%) of 'reasons_for_exclusion_diary' (0 new NA)

Cycle longer than 40 days.

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(coalesce(minimum_cycle_length_diary, as.numeric(menstruation_length)) > 40, "cycle_longer_than_40, ", "", "")
                                       )
  )
## mutate: changed 7,461 values (10%) of 'reasons_for_exclusion_diary' (0 new NA)

Next menstrual onset not observed

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(
                                              menstruation_regular == 1 &
                                              coalesce(minimum_cycle_length_diary, as.numeric(menstruation_length)) <= 40 &
                                              coalesce(minimum_cycle_length_diary, as.numeric(menstruation_length)) >= 20 &
                                              is.na(fertile_fab), "next_menstrual_onset_unobserved, ", "", "")
                                       )
  )
## mutate: changed 4,100 values (5%) of 'reasons_for_exclusion_diary' (0 new NA)

Skipped this diary day (days after dropping out not included)

diary <- diary %>% 
  mutate(reasons_for_exclusion_diary = str_c(reasons_for_exclusion_diary,
                                            if_else(is.na(ended_diary) & is.na(modified_diary), "skipped_diary_entry, ", "")
                                       )
  )
## mutate: changed 15,321 values (20%) of 'reasons_for_exclusion_diary' (0 new NA)
usable_diary_days <- diary %>% group_by(session) %>% 
  summarise(usable_diary_days = any(reasons_for_exclusion_diary == ""))
## group_by: one grouping variable (session)
## summarise: now 1,373 rows and 2 columns, ungrouped

Who completed what?

We create a character variable reasons_for_exclusion. We will concatenate (abbreviated) reasons for exclusion in this variable.

all_surveys$reasons_for_exclusion <- ""

Did not finish demographics survey

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(is.na(ended_demo), "didnt_finish_demographics, ", "")
                                       )
  )
## mutate: changed 53 values (3%) of 'reasons_for_exclusion' (0 new NA)

Reported no regular menstruation

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(menstruation_regular == 0, "no_regular_menstruation, ", "", "")
                                       )
  )
## mutate: changed 302 values (18%) of 'reasons_for_exclusion' (0 new NA)

Menopausal or in climacteric period

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(menopause_yes == 1 | menopause_yes == 2, "menopausal, ", "", "")
                                       )
  )
## mutate: changed 41 values (2%) of 'reasons_for_exclusion' (0 new NA)

Older than 50

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(age >= 50, "older_than_50, ", "", "")
                                       )
  )
## mutate: changed 35 values (2%) of 'reasons_for_exclusion' (0 new NA)

Pregnant

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(pregnant == 1, "pregnant, ", "", "")
                                       )
  )
## mutate: changed 23 values (1%) of 'reasons_for_exclusion' (0 new NA)

Breast-feeding

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(breast_feeding == 1, "breast_feeding, ", "", "")
                                       )
  )
## mutate: changed 28 values (2%) of 'reasons_for_exclusion' (0 new NA)

Not primarily heterosexual. This excludes women who reported being equally interested in men and women, women who reported being asexual or aromantic, and participants who did not identify as female gender.

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(sex_orientation >= 4 | gender != 1, "not_heterosexual_female, ", "", "")
                                       )
  )
## mutate: changed 26 values (2%) of 'reasons_for_exclusion' (0 new NA)

Did not finish personality survey

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(!is.na(ended_demo) & is.na(ended_initial), "didnt_finish_personality, ", "")
                                       )
  )
## mutate: changed 196 values (12%) of 'reasons_for_exclusion' (0 new NA)

Changed contraception

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(change_to_nonhormonal != 0 | change_to_hormonal_contraception != 0, "switched_contraception, ", "", "")
                                       )
  )
## mutate: changed 18 values (1%) of 'reasons_for_exclusion' (0 new NA)

Taking sex hormones (other than the pill)

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(medication_name %contains% "Cycloprognova" |
                                                      medication_name %contains% "Cyproderm" |
                                                       medication_name %contains% "DHEA" |
                                                       medication_name %contains% "Hormone" |
                                                       medication_name %contains% "Cyclo-Progynova" |
                                                       medication_name %contains% "Femoston" |
                                                       medication_name %contains% "Gynokadin", "sex_hormones, ", "", "")
                                       )
  )
## mutate: changed 7 values (<1%) of 'reasons_for_exclusion' (0 new NA)

No diary days

all_surveys <- all_surveys %>% 
  left_join(diary %>% group_by(session) %>% summarise(diary_days = n_nonmissing(ended_diary)), by = 'session') %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(!is.na(ended_initial) & diary_days == 0, "didnt_do_diary, ", "", "didnt_do_diary, ")
                                       )
  )
## group_by: one grouping variable (session)
## summarise: now 1,373 rows and 2 columns, ungrouped
## left_join: added one column (diary_days)
##            > rows only in x     287
##            > rows only in y  (    0)
##            > matched rows     1,373
##            >                 =======
##            > rows total       1,660
## mutate: changed 66 values (4%) of 'reasons_for_exclusion' (0 new NA)

Fertility never estimable

all_surveys <- all_surveys %>% 
  left_join(diary %>% group_by(session) %>% summarise(fertility_days = n_nonmissing(fertile_fab)), by = 'session') %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(menstruation_regular != 0  & diary_days > 0 & fertility_days == 0, 
                                                    "fertility_never_estimable, ", "", "")
                                       )
  )
## group_by: one grouping variable (session)
## summarise: now 1,373 rows and 2 columns, ungrouped
## left_join: added one column (fertility_days)
##            > rows only in x     287
##            > rows only in y  (    0)
##            > matched rows     1,373
##            >                 =======
##            > rows total       1,660
## mutate: changed 143 values (9%) of 'reasons_for_exclusion' (0 new NA)
all_surveys <- all_surveys %>% left_join(usable_diary_days, by = "session") %>% 
    mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
            if_else(menstruation_regular != 0  & diary_days > 0 & fertility_days > 0 & !usable_diary_days, "diary_days_not_usable, ", "", "")
                                       )
  )
## left_join: added one column (usable_diary_days)
##            > rows only in x     287
##            > rows only in y  (    0)
##            > matched rows     1,373
##            >                 =======
##            > rows total       1,660
## mutate: changed 45 values (3%) of 'reasons_for_exclusion' (0 new NA)

Women who are in monogamous heterosexual relationships

all_surveys <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(hetero_relationship == 0 & relationship_status != 1, "non_heterosexual_relationship, ", "", "")
                                       )
  )
## mutate: changed 9 values (1%) of 'reasons_for_exclusion' (0 new NA)
testthat::expect_equal(all_surveys %>% group_by(session) %>% filter(n() > 1) %>% nrow(),
                       0)
## group_by: one grouping variable (session)
## filter (grouped): removed all rows (100%)
table(all_surveys$reasons_for_exclusion == "", exclude = NULL)
## 
## FALSE  TRUE 
##   788   872
diary <- diary %>% left_join(all_surveys %>% select(session, reasons_for_exclusion), by = 'session') %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion, reasons_for_exclusion_diary))
## select: dropped 368 variables (created_demo, modified_demo, ended_demo, expired_demo, info_study, …)
## left_join: added one column (reasons_for_exclusion)
##            > rows only in x        0
##            > rows only in y  (   287)
##            > matched rows     77,364
##            >                 ========
##            > rows total       77,364
## mutate: changed 27,531 values (36%) of 'reasons_for_exclusion' (0 new NA)
library(UpSetR)
exclusion_reasons <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_sub(reasons_for_exclusion, 1, -3)) %>% 
  select(session, reasons_for_exclusion) %>% 
  comma_separated_to_columns(reasons_for_exclusion) %>% 
  select(-session)
## mutate: changed 788 values (47%) of 'reasons_for_exclusion' (0 new NA)
## select: dropped 368 variables (created_demo, modified_demo, ended_demo, expired_demo, info_study, …)
## mutate: changed 872 values (47%) of 'splitcol' (0 new NA)
## mutate: new variable 'value' with one unique value and 0% NA
## spread: reorganized (splitcol, value) into (breast_feeding, diary_days_not_usable, didnt_do_diary, didnt_finish_demographics, didnt_finish_personality, …) [was 1864x4, now 1660x17]
## select: dropped one variable (reasons_for_exclusion)
## select: dropped one variable (session)
exclusion_reasons_table <- exclusion_reasons %>% 
  summarise_all(sum) %>% sort() %>% 
  gather(reason, n) %>% 
  left_join(all_surveys %>% mutate(reason = str_sub(reasons_for_exclusion, 1, -3)) %>% group_by(reason) %>% summarise(unique = n())) %>% 
  mutate(unique = if_else(is.na(unique), 0L, unique))
## summarise_all: now one row and 15 columns, ungrouped
## gather: reorganized (sex_hormones, non_heterosexual_relationship, switched_contraception, pregnant, not_heterosexual_female, …) into (reason, n) [was 1x15, now 15x2]
## mutate: new variable 'reason' with 57 unique values and 0% NA
## group_by: one grouping variable (reason)
## summarise: now 57 rows and 2 columns, ungrouped
## Joining, by = "reason"
## left_join: added one column (unique)
##            > rows only in x    3
##            > rows only in y  (45)
##            > matched rows     12
##            >                 ====
##            > rows total       15
## mutate: changed 3 values (20%) of 'unique' (3 fewer NA)
exclusion_reasons_hc <- all_surveys %>% 
  mutate(reasons_for_exclusion = str_sub(reasons_for_exclusion, 1, -3)) %>% 
  select(session, hormonal_contraception, reasons_for_exclusion) %>% 
  mutate(hormonal_contraception = if_else(hormonal_contraception, 1, 0)) %>% 
  comma_separated_to_columns(reasons_for_exclusion) %>% 
  # filter(included == 0) %>%
  select(-session)
## mutate: changed 788 values (47%) of 'reasons_for_exclusion' (0 new NA)
## select: dropped 367 variables (created_demo, modified_demo, ended_demo, expired_demo, info_study, …)
## mutate: converted 'hormonal_contraception' from logical to double (0 new NA)
## mutate: changed 872 values (47%) of 'splitcol' (0 new NA)
## mutate: new variable 'value' with one unique value and 0% NA
## spread: reorganized (splitcol, value) into (breast_feeding, diary_days_not_usable, didnt_do_diary, didnt_finish_demographics, didnt_finish_personality, …) [was 1864x5, now 1660x18]
## select: dropped one variable (reasons_for_exclusion)
## select: dropped one variable (session)
exclusion_reasons_hc_table <- exclusion_reasons_hc %>% group_by(hormonal_contraception) %>% 
  summarise_all(sum) %>% gather(reason, n, -hormonal_contraception) %>% 
  spread(hormonal_contraception, n) %>% 
  arrange(`0`)
## group_by: one grouping variable (hormonal_contraception)
## summarise_all: now 2 rows and 16 columns, ungrouped
## gather: reorganized (breast_feeding, diary_days_not_usable, didnt_do_diary, didnt_finish_demographics, didnt_finish_personality, …) into (reason, n) [was 2x16, now 30x3]
## spread: reorganized (hormonal_contraception, n) into (0, 1) [was 30x3, now 15x3]
exclusion_reasons_diary <- diary %>% 
  mutate(reasons_for_exclusion = str_sub(reasons_for_exclusion, 1, -3)) %>% 
  select(session, created_date, reasons_for_exclusion) %>% 
  drop_na(session, created_date) %>% 
  comma_separated_to_columns(reasons_for_exclusion) %>% 
  select( -created_date)
## mutate: changed 39,110 values (51%) of 'reasons_for_exclusion' (0 new NA)
## select: dropped 788 variables (person, short, created_diary, modified_diary, ended_diary, …)
## drop_na: no rows removed
## mutate: changed 38,254 values (39%) of 'splitcol' (0 new NA)
## mutate: new variable 'value' with one unique value and 0% NA
## spread: reorganized (splitcol, value) into (breast_feeding, cycle_longer_than_40, cycle_shorter_than_20, diary_days_not_usable, did_not_finish_entry, …) [was 97954x5, now 77364x22]
## select: dropped one variable (reasons_for_exclusion)
## select: dropped one variable (created_date)
exclusion_reasons_diary_table <- exclusion_reasons_diary %>% 
  select(-session) %>% 
  summarise_all(sum) %>% 
  sort() %>% 
  gather(reason, n) %>% 
  left_join(diary %>% mutate(reason = str_sub(reasons_for_exclusion, 1, -3)) %>% group_by(reason) %>% summarise(unique = n())) %>% 
  mutate(unique = if_else(is.na(unique), 0L, unique)) %>% 
  left_join(exclusion_reasons_diary %>% 
  gather(reason, n, -session) %>% 
  filter(n > 0) %>% 
  distinct(session, reason, n) %>% 
  group_by(reason) %>%
  summarise(n_women = sum(n)))
## select: dropped one variable (session)
## summarise_all: now one row and 19 columns, ungrouped
## gather: reorganized (dishonest_answer, didnt_do_diary, non_heterosexual_relationship, sex_hormones, did_not_finish_entry, …) into (reason, n) [was 1x19, now 19x2]
## mutate: new variable 'reason' with 181 unique values and 0% NA
## group_by: one grouping variable (reason)
## summarise: now 181 rows and 2 columns, ungrouped
## Joining, by = "reason"
## left_join: added one column (unique)
##            > rows only in x     6
##            > rows only in y  (168)
##            > matched rows      13
##            >                 =====
##            > rows total        19
## mutate: changed 6 values (32%) of 'unique' (6 fewer NA)
## gather: reorganized (breast_feeding, cycle_longer_than_40, cycle_shorter_than_20, diary_days_not_usable, did_not_finish_entry, …) into (reason, n) [was 77364x20, now 1469916x3]
## filter: removed 1,371,962 rows (93%), 97,954 rows remaining
## distinct: removed 93,686 rows (96%), 4,268 rows remaining
## group_by: one grouping variable (reason)
## summarise: now 19 rows and 2 columns, ungrouped
## Joining, by = "reason"
## left_join: added one column (n_women)
##            > rows only in x    0
##            > rows only in y  ( 0)
##            > matched rows     19
##            >                 ====
##            > rows total       19

Reasons for exclusion

exclusion_reasons %>% 
  filter(included == 0) %>% 
  select(-included) %>% 
  as.data.frame() %>% 
  {
  upset(., ncol(.), 20, show.numbers = TRUE, order.by = "freq",
      main.bar.color = "#6E8691",
      matrix.color = "#6E8691",
      sets.bar.color = "#53AC9B")
  }
## filter: removed 872 rows (53%), 788 rows remaining
## select: dropped one variable (included)
How to read this plot: The horizontal green bars show for how many women this reason for exclusion applies. The blue bars show how many women are excluded for multiple reasons (e.g., they're menopausal _and_ not heterosexual). If reasons for exclusion necessarily depend on another (i.e. participants had to finish the first survey to get to the second), we counted only those who had not yet been excluded earlier. If reasons for exclusion depended on each other only stochastically (e.g., age and menopause), we did not do this.

How to read this plot: The horizontal green bars show for how many women this reason for exclusion applies. The blue bars show how many women are excluded for multiple reasons (e.g., they’re menopausal and not heterosexual). If reasons for exclusion necessarily depend on another (i.e. participants had to finish the first survey to get to the second), we counted only those who had not yet been excluded earlier. If reasons for exclusion depended on each other only stochastically (e.g., age and menopause), we did not do this.

exclusion_reasons_table %>% 
  knitr::kable(caption = "Reasons for exclusion. _n_ shows the number of affected women, _unique_ those who for whom this was the only reason to be excluded.")
Reasons for exclusion. n shows the number of affected women, unique those who for whom this was the only reason to be excluded.
reason n unique
sex_hormones 7 4
non_heterosexual_relationship 9 4
switched_contraception 18 15
pregnant 23 2
not_heterosexual_female 26 10
breast_feeding 28 6
older_than_50 35 0
menopausal 41 0
diary_days_not_usable 45 43
didnt_finish_demographics 53 45
didnt_do_diary 66 51
fertility_never_estimable 143 134
didnt_finish_personality 196 141
no_regular_menstruation 302 178
included 872 0

By contraception

exclusion_reasons_hc %>% 
  as.data.frame() %>% 
  {
  upset(., ncol(.), 20, show.numbers = TRUE, order.by = "freq",
      main.bar.color = "#6E8691",
      matrix.color = "#6E8691",
      sets.bar.color = "#53AC9B")
  }

exclusion_reasons_hc_table %>% 
  knitr::kable(caption = "Reasons for exclusion. _n_ shows the number of affected women, _unique_ those who for whom this was the only reason to be excluded.")
Reasons for exclusion. n shows the number of affected women, unique those who for whom this was the only reason to be excluded.
reason 0 1
non_heterosexual_relationship 5 4
sex_hormones 6 1
switched_contraception 8 10
not_heterosexual_female 19 7
diary_days_not_usable 20 25
pregnant 23 0
breast_feeding 27 1
older_than_50 34 1
didnt_do_diary 38 28
menopausal 40 1
didnt_finish_demographics 47 6
didnt_finish_personality 66 130
fertility_never_estimable 67 76
no_regular_menstruation 162 140
included 580 292

In the diary

exclusion_reasons_diary %>% 
  filter(included == 0) %>%
  select(-session, -included, -didnt_do_diary) %>% 
  as.data.frame() %>% 
  {
  upset(., ncol(.), 20, show.numbers = TRUE, order.by = "freq",
      main.bar.color = "#6E8691",
      matrix.color = "#6E8691",
      sets.bar.color = "#53AC9B")
  }
## filter: removed 38,254 rows (49%), 39,110 rows remaining
## select: dropped 3 variables (session, didnt_do_diary, included)

exclusion_reasons_diary_table %>% 
  knitr::kable(caption = "Reasons for exclusion. _n_ shows the number of affected women, _unique_ those who for whom this was the only reason to be excluded.")
Reasons for exclusion. n shows the number of affected women, unique those who for whom this was the only reason to be excluded.
reason n unique n_women
dishonest_answer 150 120 86
didnt_do_diary 187 0 28
non_heterosexual_relationship 338 135 8
sex_hormones 442 181 7
did_not_finish_entry 856 392 542
not_heterosexual_female 896 362 16
pregnant 1047 89 19
breast_feeding 1137 267 22
switched_contraception 1178 540 18
older_than_50 1560 0 28
menopausal 2166 0 39
diary_days_not_usable 2361 0 45
fertility_never_estimable 2527 0 143
next_menstrual_onset_unobserved 4100 2065 207
cycle_shorter_than_20 4736 3162 476
cycle_longer_than_40 7461 2704 222
no_regular_menstruation 13237 6893 245
skipped_diary_entry 15321 6823 1245
included 38254 0 872
included <- diary %>% filter(reasons_for_exclusion == "") %>% distinct(session)
## filter: removed 39,110 rows (51%), 38,254 rows remaining
## distinct: removed 37,382 rows (98%), 872 rows remaining
testthat::expect_equal(
  all_surveys %>% filter(reasons_for_exclusion == "") %>% nrow(), 
  nrow(included)
)
## filter: removed 788 rows (47%), 872 rows remaining

Sanity Checks

library(testthat)
expect_equal(nrow(diary), diary_length)
expect_equal(nrow(all_surveys), all_survey_length)
expect_equal(nrow(diary_social), diary_social_length)
expect_false(any(names(diary) %contains% ".x"))
expect_false(any(names(diary) %contains% ".y"))
expect_false(any(names(all_surveys) %contains% ".y"))
expect_equal(groups(s3_daily), list())
expect_equal(groups(diary), list())
expect_equal(groups(all_surveys), list())
expect_equal(sum(duplicated(all_surveys$session)), 0)
expect_equal(sum(duplicated(s1_demo$session)), 0)
expect_equal(diary %>% drop_na(session, day_number) %>% 
               group_by(short, day_number) %>% filter(n() > 1) %>% nrow(), 0)
## drop_na: no rows removed
## group_by: 2 grouping variables (short, day_number)
## filter (grouped): removed all rows (100%)
expect_equal(diary %>% drop_na(session, created_diary) %>%  
            group_by(session, created_diary) %>% filter(n()>1) %>% nrow(), 0)
## drop_na: removed 14,698 rows (19%), 62,666 rows remaining
## group_by: 2 grouping variables (session, created_diary)
## filter (grouped): removed all rows (100%)
expect_equal(s3_daily %>% drop_na(session, created_date) %>%  
            group_by(session, created_date) %>% filter(n()>1) %>% nrow(), 0)
## drop_na: no rows removed
## group_by: 2 grouping variables (session, created_date)
## filter (grouped): removed all rows (100%)
expect_equal(diary %>% drop_na(session, created_date) %>%  
            group_by(session, created_date) %>% filter(n()>1) %>% nrow(), 0)
## drop_na: no rows removed
## group_by: 2 grouping variables (session, created_date)
## filter (grouped): removed all rows (100%)
expect_equal(diary_social %>% drop_na(session, created_diary, person) %>%  
            group_by(session, created_diary, person) %>% filter(n() > 1) %>% nrow(), 0)
## drop_na: removed 47,466 rows (48%), 50,666 rows remaining
## group_by: 3 grouping variables (session, created_diary, person)
## filter (grouped): removed all rows (100%)
expect_equal(network %>% drop_na(session, person) %>%  
            group_by(session, person) %>% filter(n()>1) %>% nrow(), 0)
## drop_na: no rows removed
## group_by: 2 grouping variables (session, person)
## filter (grouped): removed all rows (100%)

Save

save(diary_social, diary, sex_long, network_nominations, network, s1_demo, s1_filter, s2_initial, s3_daily, s4_followup, s4_timespent, withfollowup, all_surveys, file = "data/cleaned_selected.rdata")
IyBSZWFzb25zIGZvciBFeGNsdXNpb24gCgpgYGB7cn0Kc291cmNlKCIwX2hlbHBlcnMuUiIpCmxpYnJhcnkodGlkeWxvZykKbG9hZCgiZGF0YS9jbGVhbmVkLnJkYXRhIikKCmxpYnJhcnkoa25pdHIpCm9wdHNfY2h1bmskc2V0KGZpZy53aWR0aCA9IDksIGZpZy5oZWlnaHQgPSA3LCBjYWNoZSA9IFQsIHdhcm5pbmcgPSBULCBtZXNzYWdlID0gVCwgY2FjaGUgPSBGLCBlcnJvciA9IEZBTFNFKQoKY29tbWFfc2VwYXJhdGVkX3RvX2NvbHVtbnMgPC0gZnVuY3Rpb24oZGYsIGNvbCkgewogIGNvbG5hbWUgPC0gZGVwYXJzZShzdWJzdGl0dXRlKGNvbCkpCiAgZGYkc3BsaXRjb2wgPC0gZGYgJT4lIHB1bGwoY29sbmFtZSkKICBzZXBhcmF0ZV9yb3dzKGRmLCBzcGxpdGNvbCwgY29udmVydCA9IFRSVUUsIHNlcCA9ICIsICIpICU+JSAKICAgIG11dGF0ZShzcGxpdGNvbCA9IGlmX2Vsc2UoaXMubmEoc3BsaXRjb2wpLCAibm8iLCAKICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShzcGxpdGNvbCA9PSAiIiB8IAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BsaXRjb2wgJWluJSBjKCksICJpbmNsdWRlZCIsIGFzLmNoYXJhY3RlcihzcGxpdGNvbCkpKSkgJT4lIAogICAgbXV0YXRlKCNzcGxpdGNvbCA9IHN0cmluZ3I6OnN0cl9jKGNvbG5hbWUsICJfIiwgc3BsaXRjb2wpLCAKICAgICAgICAgICB2YWx1ZSA9IDEpICU+JSAKICAgIHNwcmVhZChzcGxpdGNvbCwgdmFsdWUsIGZpbGwgPSAwKSAlPiUgCiAgICBzZWxlY3QoLWNvbG5hbWUpCn0KCmFsbF9zdXJ2ZXlfbGVuZ3RoIDwtIG5yb3coYWxsX3N1cnZleXMpCmRpYXJ5X2xlbmd0aCA8LSBucm93KGRpYXJ5KQpkaWFyeV9zb2NpYWxfbGVuZ3RoIDwtIG5yb3coZGlhcnlfc29jaWFsKQpgYGAKCmBgYHtyfQpkaWFyeSRyZWFzb25zX2Zvcl9leGNsdXNpb25fZGlhcnkgPC0gIiIKYGBgCgoKTGFiIHBhcnRpY2lwYW50cyB0aGF0IGRpZCBub3QgZG8gdGhlIG9ubGluZSBkaWFyeSAobm90IG1lcmdlZCkKCmBgYHtyfQpkaWFyeSA8LSBkaWFyeSAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGlzLm5hKHNlc3Npb24pLCAibGFiX29ubHksICIsICIiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgpEaXNjbG9zZWQgdGhhdCB0aGV5IHJlc3BvbmRlZCBkaXNob25lc3RseSBvbiB0aGF0IGRheS4KCmBgYHtyfQpkaWFyeSA8LSBkaWFyeSAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGRpc2hvbmVzdF9kaXNjYXJkID09IDEsICJkaXNob25lc3RfYW5zd2VyLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKRGlkIG5vdCBmaW5pc2ggZGlhcnkgZW50cnkuCgpgYGB7cn0KZGlhcnkgPC0gZGlhcnkgJT4lIAogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb25fZGlhcnkgPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb25fZGlhcnksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShpcy5uYShlbmRlZF9kaWFyeSkgJiAhaXMubmEobW9kaWZpZWRfZGlhcnkpLCAiZGlkX25vdF9maW5pc2hfZW50cnksICIsICIiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgoKQ3ljbGUgc2hvcnRlciB0aGFuIDIwIGRheXMuCmBgYHtyfQpkaWFyeSA8LSBkaWFyeSAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGNvYWxlc2NlKG1pbmltdW1fY3ljbGVfbGVuZ3RoX2RpYXJ5LCBhcy5udW1lcmljKG1lbnN0cnVhdGlvbl9sZW5ndGgpKSA8IDIwLCAiY3ljbGVfc2hvcnRlcl90aGFuXzIwLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKQ3ljbGUgbG9uZ2VyIHRoYW4gNDAgZGF5cy4KYGBge3J9CmRpYXJ5IDwtIGRpYXJ5ICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uX2RpYXJ5ID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uX2RpYXJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoY29hbGVzY2UobWluaW11bV9jeWNsZV9sZW5ndGhfZGlhcnksIGFzLm51bWVyaWMobWVuc3RydWF0aW9uX2xlbmd0aCkpID4gNDAsICJjeWNsZV9sb25nZXJfdGhhbl80MCwgIiwgIiIsICIiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgKQpgYGAKCk5leHQgbWVuc3RydWFsIG9uc2V0IG5vdCBvYnNlcnZlZAoKYGBge3J9CmRpYXJ5IDwtIGRpYXJ5ICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uX2RpYXJ5ID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uX2RpYXJ5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZW5zdHJ1YXRpb25fcmVndWxhciA9PSAxICYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvYWxlc2NlKG1pbmltdW1fY3ljbGVfbGVuZ3RoX2RpYXJ5LCBhcy5udW1lcmljKG1lbnN0cnVhdGlvbl9sZW5ndGgpKSA8PSA0MCAmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2FsZXNjZShtaW5pbXVtX2N5Y2xlX2xlbmd0aF9kaWFyeSwgYXMubnVtZXJpYyhtZW5zdHJ1YXRpb25fbGVuZ3RoKSkgPj0gMjAgJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoZmVydGlsZV9mYWIpLCAibmV4dF9tZW5zdHJ1YWxfb25zZXRfdW5vYnNlcnZlZCwgIiwgIiIsICIiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgKQpgYGAKCgpTa2lwcGVkIHRoaXMgZGlhcnkgZGF5IChkYXlzIGFmdGVyIGRyb3BwaW5nIG91dCBub3QgaW5jbHVkZWQpCmBgYHtyfQpkaWFyeSA8LSBkaWFyeSAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9kaWFyeSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGlzLm5hKGVuZGVkX2RpYXJ5KSAmIGlzLm5hKG1vZGlmaWVkX2RpYXJ5KSwgInNraXBwZWRfZGlhcnlfZW50cnksICIsICIiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgKQpgYGAKCmBgYHtyfQp1c2FibGVfZGlhcnlfZGF5cyA8LSBkaWFyeSAlPiUgZ3JvdXBfYnkoc2Vzc2lvbikgJT4lIAogIHN1bW1hcmlzZSh1c2FibGVfZGlhcnlfZGF5cyA9IGFueShyZWFzb25zX2Zvcl9leGNsdXNpb25fZGlhcnkgPT0gIiIpKQpgYGAKCgoKIyMgV2hvIGNvbXBsZXRlZCB3aGF0PwoKV2UgY3JlYXRlIGEgY2hhcmFjdGVyIHZhcmlhYmxlIGByZWFzb25zX2Zvcl9leGNsdXNpb25gLiBXZSB3aWxsIGNvbmNhdGVuYXRlIChhYmJyZXZpYXRlZCkKcmVhc29ucyBmb3IgZXhjbHVzaW9uIGluIHRoaXMgdmFyaWFibGUuCgpgYGB7cn0KYWxsX3N1cnZleXMkcmVhc29uc19mb3JfZXhjbHVzaW9uIDwtICIiCmBgYAoKCkRpZCBub3QgZmluaXNoIGRlbW9ncmFwaGljcyBzdXJ2ZXkKYGBge3J9CmFsbF9zdXJ2ZXlzIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoaXMubmEoZW5kZWRfZGVtbyksICJkaWRudF9maW5pc2hfZGVtb2dyYXBoaWNzLCAiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgoKUmVwb3J0ZWQgbm8gcmVndWxhciBtZW5zdHJ1YXRpb24KYGBge3J9CmFsbF9zdXJ2ZXlzIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UobWVuc3RydWF0aW9uX3JlZ3VsYXIgPT0gMCwgIm5vX3JlZ3VsYXJfbWVuc3RydWF0aW9uLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKCk1lbm9wYXVzYWwgb3IgaW4gY2xpbWFjdGVyaWMgcGVyaW9kCmBgYHtyfQphbGxfc3VydmV5cyA8LSBhbGxfc3VydmV5cyAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKG1lbm9wYXVzZV95ZXMgPT0gMSB8IG1lbm9wYXVzZV95ZXMgPT0gMiwgIm1lbm9wYXVzYWwsICIsICIiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgpPbGRlciB0aGFuIDUwCmBgYHtyfQphbGxfc3VydmV5cyA8LSBhbGxfc3VydmV5cyAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGFnZSA+PSA1MCwgIm9sZGVyX3RoYW5fNTAsICIsICIiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgpQcmVnbmFudApgYGB7cn0KYWxsX3N1cnZleXMgPC0gYWxsX3N1cnZleXMgJT4lIAogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShwcmVnbmFudCA9PSAxLCAicHJlZ25hbnQsICIsICIiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgpCcmVhc3QtZmVlZGluZwpgYGB7cn0KYWxsX3N1cnZleXMgPC0gYWxsX3N1cnZleXMgJT4lIAogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShicmVhc3RfZmVlZGluZyA9PSAxLCAiYnJlYXN0X2ZlZWRpbmcsICIsICIiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgoKTm90IHByaW1hcmlseSBoZXRlcm9zZXh1YWwuIFRoaXMgZXhjbHVkZXMgd29tZW4gd2hvIHJlcG9ydGVkIGJlaW5nIGVxdWFsbHkgaW50ZXJlc3RlZCBpbiBtZW4gYW5kIHdvbWVuLCB3b21lbiB3aG8gcmVwb3J0ZWQgYmVpbmcgYXNleHVhbCBvciBhcm9tYW50aWMsIGFuZCBwYXJ0aWNpcGFudHMgd2hvIGRpZCBub3QgaWRlbnRpZnkgYXMgZmVtYWxlIGdlbmRlci4KYGBge3J9CmFsbF9zdXJ2ZXlzIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2Uoc2V4X29yaWVudGF0aW9uID49IDQgfCBnZW5kZXIgIT0gMSwgIm5vdF9oZXRlcm9zZXh1YWxfZmVtYWxlLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKRGlkIG5vdCBmaW5pc2ggcGVyc29uYWxpdHkgc3VydmV5CmBgYHtyfQphbGxfc3VydmV5cyA8LSBhbGxfc3VydmV5cyAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKCFpcy5uYShlbmRlZF9kZW1vKSAmIGlzLm5hKGVuZGVkX2luaXRpYWwpLCAiZGlkbnRfZmluaXNoX3BlcnNvbmFsaXR5LCAiLCAiIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgpDaGFuZ2VkIGNvbnRyYWNlcHRpb24KYGBge3J9CmFsbF9zdXJ2ZXlzIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoY2hhbmdlX3RvX25vbmhvcm1vbmFsICE9IDAgfCBjaGFuZ2VfdG9faG9ybW9uYWxfY29udHJhY2VwdGlvbiAhPSAwLCAic3dpdGNoZWRfY29udHJhY2VwdGlvbiwgIiwgIiIsICIiKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCiAgKQoKYGBgCgoKVGFraW5nIHNleCBob3Jtb25lcyAob3RoZXIgdGhhbiB0aGUgcGlsbCkKYGBge3J9CmFsbF9zdXJ2ZXlzIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UobWVkaWNhdGlvbl9uYW1lICVjb250YWlucyUgIkN5Y2xvcHJvZ25vdmEiIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWNhdGlvbl9uYW1lICVjb250YWlucyUgIkN5cHJvZGVybSIgfAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWNhdGlvbl9uYW1lICVjb250YWlucyUgIkRIRUEiIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGljYXRpb25fbmFtZSAlY29udGFpbnMlICJIb3Jtb25lIiB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpY2F0aW9uX25hbWUgJWNvbnRhaW5zJSAiQ3ljbG8tUHJvZ3lub3ZhIiB8CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpY2F0aW9uX25hbWUgJWNvbnRhaW5zJSAiRmVtb3N0b24iIHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGljYXRpb25fbmFtZSAlY29udGFpbnMlICJHeW5va2FkaW4iLCAic2V4X2hvcm1vbmVzLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCgpgYGAKCk5vIGRpYXJ5IGRheXMKYGBge3J9CmFsbF9zdXJ2ZXlzIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBsZWZ0X2pvaW4oZGlhcnkgJT4lIGdyb3VwX2J5KHNlc3Npb24pICU+JSBzdW1tYXJpc2UoZGlhcnlfZGF5cyA9IG5fbm9ubWlzc2luZyhlbmRlZF9kaWFyeSkpLCBieSA9ICdzZXNzaW9uJykgJT4lIAogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZSghaXMubmEoZW5kZWRfaW5pdGlhbCkgJiBkaWFyeV9kYXlzID09IDAsICJkaWRudF9kb19kaWFyeSwgIiwgIiIsICJkaWRudF9kb19kaWFyeSwgIikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQogICkKYGBgCgpGZXJ0aWxpdHkgbmV2ZXIgZXN0aW1hYmxlCmBgYHtyfQphbGxfc3VydmV5cyA8LSBhbGxfc3VydmV5cyAlPiUgCiAgbGVmdF9qb2luKGRpYXJ5ICU+JSBncm91cF9ieShzZXNzaW9uKSAlPiUgc3VtbWFyaXNlKGZlcnRpbGl0eV9kYXlzID0gbl9ub25taXNzaW5nKGZlcnRpbGVfZmFiKSksIGJ5ID0gJ3Nlc3Npb24nKSAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKG1lbnN0cnVhdGlvbl9yZWd1bGFyICE9IDAgICYgZGlhcnlfZGF5cyA+IDAgJiBmZXJ0aWxpdHlfZGF5cyA9PSAwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJmZXJ0aWxpdHlfbmV2ZXJfZXN0aW1hYmxlLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKCmBgYHtyfQphbGxfc3VydmV5cyA8LSBhbGxfc3VydmV5cyAlPiUgbGVmdF9qb2luKHVzYWJsZV9kaWFyeV9kYXlzLCBieSA9ICJzZXNzaW9uIikgJT4lIAogICAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwKICAgICAgICAgICAgaWZfZWxzZShtZW5zdHJ1YXRpb25fcmVndWxhciAhPSAwICAmIGRpYXJ5X2RheXMgPiAwICYgZmVydGlsaXR5X2RheXMgPiAwICYgIXVzYWJsZV9kaWFyeV9kYXlzLCAiZGlhcnlfZGF5c19ub3RfdXNhYmxlLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKV29tZW4gd2hvIGFyZSBpbiBtb25vZ2Ftb3VzIGhldGVyb3NleHVhbCByZWxhdGlvbnNoaXBzCmBgYHtyfQphbGxfc3VydmV5cyA8LSBhbGxfc3VydmV5cyAlPiUgCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGhldGVyb19yZWxhdGlvbnNoaXAgPT0gMCAmIHJlbGF0aW9uc2hpcF9zdGF0dXMgIT0gMSwgIm5vbl9oZXRlcm9zZXh1YWxfcmVsYXRpb25zaGlwLCAiLCAiIiwgIiIpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkKICApCmBgYAoKYGBge3J9CnRlc3R0aGF0OjpleHBlY3RfZXF1YWwoYWxsX3N1cnZleXMgJT4lIGdyb3VwX2J5KHNlc3Npb24pICU+JSBmaWx0ZXIobigpID4gMSkgJT4lIG5yb3coKSwKICAgICAgICAgICAgICAgICAgICAgICAwKQp0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gPT0gIiIsIGV4Y2x1ZGUgPSBOVUxMKQpkaWFyeSA8LSBkaWFyeSAlPiUgbGVmdF9qb2luKGFsbF9zdXJ2ZXlzICU+JSBzZWxlY3Qoc2Vzc2lvbiwgcmVhc29uc19mb3JfZXhjbHVzaW9uKSwgYnkgPSAnc2Vzc2lvbicpICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLCByZWFzb25zX2Zvcl9leGNsdXNpb25fZGlhcnkpKQoKbGlicmFyeShVcFNldFIpCmV4Y2x1c2lvbl9yZWFzb25zIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX3N1YihyZWFzb25zX2Zvcl9leGNsdXNpb24sIDEsIC0zKSkgJT4lIAogIHNlbGVjdChzZXNzaW9uLCByZWFzb25zX2Zvcl9leGNsdXNpb24pICU+JSAKICBjb21tYV9zZXBhcmF0ZWRfdG9fY29sdW1ucyhyZWFzb25zX2Zvcl9leGNsdXNpb24pICU+JSAKICBzZWxlY3QoLXNlc3Npb24pCgpleGNsdXNpb25fcmVhc29uc190YWJsZSA8LSBleGNsdXNpb25fcmVhc29ucyAlPiUgCiAgc3VtbWFyaXNlX2FsbChzdW0pICU+JSBzb3J0KCkgJT4lIAogIGdhdGhlcihyZWFzb24sIG4pICU+JSAKICBsZWZ0X2pvaW4oYWxsX3N1cnZleXMgJT4lIG11dGF0ZShyZWFzb24gPSBzdHJfc3ViKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwgMSwgLTMpKSAlPiUgZ3JvdXBfYnkocmVhc29uKSAlPiUgc3VtbWFyaXNlKHVuaXF1ZSA9IG4oKSkpICU+JSAKICBtdXRhdGUodW5pcXVlID0gaWZfZWxzZShpcy5uYSh1bmlxdWUpLCAwTCwgdW5pcXVlKSkKCmV4Y2x1c2lvbl9yZWFzb25zX2hjIDwtIGFsbF9zdXJ2ZXlzICU+JSAKICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX3N1YihyZWFzb25zX2Zvcl9leGNsdXNpb24sIDEsIC0zKSkgJT4lIAogIHNlbGVjdChzZXNzaW9uLCBob3Jtb25hbF9jb250cmFjZXB0aW9uLCByZWFzb25zX2Zvcl9leGNsdXNpb24pICU+JSAKICBtdXRhdGUoaG9ybW9uYWxfY29udHJhY2VwdGlvbiA9IGlmX2Vsc2UoaG9ybW9uYWxfY29udHJhY2VwdGlvbiwgMSwgMCkpICU+JSAKICBjb21tYV9zZXBhcmF0ZWRfdG9fY29sdW1ucyhyZWFzb25zX2Zvcl9leGNsdXNpb24pICU+JSAKICAjIGZpbHRlcihpbmNsdWRlZCA9PSAwKSAlPiUKICBzZWxlY3QoLXNlc3Npb24pCgpleGNsdXNpb25fcmVhc29uc19oY190YWJsZSA8LSBleGNsdXNpb25fcmVhc29uc19oYyAlPiUgZ3JvdXBfYnkoaG9ybW9uYWxfY29udHJhY2VwdGlvbikgJT4lIAogIHN1bW1hcmlzZV9hbGwoc3VtKSAlPiUgZ2F0aGVyKHJlYXNvbiwgbiwgLWhvcm1vbmFsX2NvbnRyYWNlcHRpb24pICU+JSAKICBzcHJlYWQoaG9ybW9uYWxfY29udHJhY2VwdGlvbiwgbikgJT4lIAogIGFycmFuZ2UoYDBgKQoKZXhjbHVzaW9uX3JlYXNvbnNfZGlhcnkgPC0gZGlhcnkgJT4lIAogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfc3ViKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwgMSwgLTMpKSAlPiUgCiAgc2VsZWN0KHNlc3Npb24sIGNyZWF0ZWRfZGF0ZSwgcmVhc29uc19mb3JfZXhjbHVzaW9uKSAlPiUgCiAgZHJvcF9uYShzZXNzaW9uLCBjcmVhdGVkX2RhdGUpICU+JSAKICBjb21tYV9zZXBhcmF0ZWRfdG9fY29sdW1ucyhyZWFzb25zX2Zvcl9leGNsdXNpb24pICU+JSAKICBzZWxlY3QoIC1jcmVhdGVkX2RhdGUpCgpleGNsdXNpb25fcmVhc29uc19kaWFyeV90YWJsZSA8LSBleGNsdXNpb25fcmVhc29uc19kaWFyeSAlPiUgCiAgc2VsZWN0KC1zZXNzaW9uKSAlPiUgCiAgc3VtbWFyaXNlX2FsbChzdW0pICU+JSAKICBzb3J0KCkgJT4lIAogIGdhdGhlcihyZWFzb24sIG4pICU+JSAKICBsZWZ0X2pvaW4oZGlhcnkgJT4lIG11dGF0ZShyZWFzb24gPSBzdHJfc3ViKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwgMSwgLTMpKSAlPiUgZ3JvdXBfYnkocmVhc29uKSAlPiUgc3VtbWFyaXNlKHVuaXF1ZSA9IG4oKSkpICU+JSAKICBtdXRhdGUodW5pcXVlID0gaWZfZWxzZShpcy5uYSh1bmlxdWUpLCAwTCwgdW5pcXVlKSkgJT4lIAogIGxlZnRfam9pbihleGNsdXNpb25fcmVhc29uc19kaWFyeSAlPiUgCiAgZ2F0aGVyKHJlYXNvbiwgbiwgLXNlc3Npb24pICU+JSAKICBmaWx0ZXIobiA+IDApICU+JSAKICBkaXN0aW5jdChzZXNzaW9uLCByZWFzb24sIG4pICU+JSAKICBncm91cF9ieShyZWFzb24pICU+JQogIHN1bW1hcmlzZShuX3dvbWVuID0gc3VtKG4pKSkKYGBgCgojIyBSZWFzb25zIGZvciBleGNsdXNpb24KYGBge3IgZmlnLmNhcD0iSG93IHRvIHJlYWQgdGhpcyBwbG90OiBUaGUgaG9yaXpvbnRhbCBncmVlbiBiYXJzIHNob3cgZm9yIGhvdyBtYW55IHdvbWVuIHRoaXMgcmVhc29uIGZvciBleGNsdXNpb24gYXBwbGllcy4gVGhlIGJsdWUgYmFycyBzaG93IGhvdyBtYW55IHdvbWVuIGFyZSBleGNsdWRlZCBmb3IgbXVsdGlwbGUgcmVhc29ucyAoZS5nLiwgdGhleSdyZSBtZW5vcGF1c2FsIF9hbmRfIG5vdCBoZXRlcm9zZXh1YWwpLiBJZiByZWFzb25zIGZvciBleGNsdXNpb24gbmVjZXNzYXJpbHkgZGVwZW5kIG9uIGFub3RoZXIgKGkuZS4gcGFydGljaXBhbnRzIGhhZCB0byBmaW5pc2ggdGhlIGZpcnN0IHN1cnZleSB0byBnZXQgdG8gdGhlIHNlY29uZCksIHdlIGNvdW50ZWQgb25seSB0aG9zZSB3aG8gaGFkIG5vdCB5ZXQgYmVlbiBleGNsdWRlZCBlYXJsaWVyLiBJZiByZWFzb25zIGZvciBleGNsdXNpb24gZGVwZW5kZWQgb24gZWFjaCBvdGhlciBvbmx5IHN0b2NoYXN0aWNhbGx5IChlLmcuLCBhZ2UgYW5kIG1lbm9wYXVzZSksIHdlIGRpZCBub3QgZG8gdGhpcy4ifQpleGNsdXNpb25fcmVhc29ucyAlPiUgCiAgZmlsdGVyKGluY2x1ZGVkID09IDApICU+JSAKICBzZWxlY3QoLWluY2x1ZGVkKSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICB7CiAgdXBzZXQoLiwgbmNvbCguKSwgMjAsIHNob3cubnVtYmVycyA9IFRSVUUsIG9yZGVyLmJ5ID0gImZyZXEiLAogICAgICBtYWluLmJhci5jb2xvciA9ICIjNkU4NjkxIiwKICAgICAgbWF0cml4LmNvbG9yID0gIiM2RTg2OTEiLAogICAgICBzZXRzLmJhci5jb2xvciA9ICIjNTNBQzlCIikKICB9CmBgYAoKYGBge3J9CmV4Y2x1c2lvbl9yZWFzb25zX3RhYmxlICU+JSAKICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJSZWFzb25zIGZvciBleGNsdXNpb24uIF9uXyBzaG93cyB0aGUgbnVtYmVyIG9mIGFmZmVjdGVkIHdvbWVuLCBfdW5pcXVlXyB0aG9zZSB3aG8gZm9yIHdob20gdGhpcyB3YXMgdGhlIG9ubHkgcmVhc29uIHRvIGJlIGV4Y2x1ZGVkLiIpCmBgYAoKCiMjIyBCeSBjb250cmFjZXB0aW9uCmBgYHtyfQpleGNsdXNpb25fcmVhc29uc19oYyAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICB7CiAgdXBzZXQoLiwgbmNvbCguKSwgMjAsIHNob3cubnVtYmVycyA9IFRSVUUsIG9yZGVyLmJ5ID0gImZyZXEiLAogICAgICBtYWluLmJhci5jb2xvciA9ICIjNkU4NjkxIiwKICAgICAgbWF0cml4LmNvbG9yID0gIiM2RTg2OTEiLAogICAgICBzZXRzLmJhci5jb2xvciA9ICIjNTNBQzlCIikKICB9CmBgYAoKYGBge3J9CmV4Y2x1c2lvbl9yZWFzb25zX2hjX3RhYmxlICU+JSAKICBrbml0cjo6a2FibGUoY2FwdGlvbiA9ICJSZWFzb25zIGZvciBleGNsdXNpb24uIF9uXyBzaG93cyB0aGUgbnVtYmVyIG9mIGFmZmVjdGVkIHdvbWVuLCBfdW5pcXVlXyB0aG9zZSB3aG8gZm9yIHdob20gdGhpcyB3YXMgdGhlIG9ubHkgcmVhc29uIHRvIGJlIGV4Y2x1ZGVkLiIpCmBgYAoKCiMjIEluIHRoZSBkaWFyeQpgYGB7cn0KZXhjbHVzaW9uX3JlYXNvbnNfZGlhcnkgJT4lIAogIGZpbHRlcihpbmNsdWRlZCA9PSAwKSAlPiUKICBzZWxlY3QoLXNlc3Npb24sIC1pbmNsdWRlZCwgLWRpZG50X2RvX2RpYXJ5KSAlPiUgCiAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICB7CiAgdXBzZXQoLiwgbmNvbCguKSwgMjAsIHNob3cubnVtYmVycyA9IFRSVUUsIG9yZGVyLmJ5ID0gImZyZXEiLAogICAgICBtYWluLmJhci5jb2xvciA9ICIjNkU4NjkxIiwKICAgICAgbWF0cml4LmNvbG9yID0gIiM2RTg2OTEiLAogICAgICBzZXRzLmJhci5jb2xvciA9ICIjNTNBQzlCIikKICB9CgpgYGAKCmBgYHtyfQpleGNsdXNpb25fcmVhc29uc19kaWFyeV90YWJsZSAlPiUgCiAga25pdHI6OmthYmxlKGNhcHRpb24gPSAiUmVhc29ucyBmb3IgZXhjbHVzaW9uLiBfbl8gc2hvd3MgdGhlIG51bWJlciBvZiBhZmZlY3RlZCB3b21lbiwgX3VuaXF1ZV8gdGhvc2Ugd2hvIGZvciB3aG9tIHRoaXMgd2FzIHRoZSBvbmx5IHJlYXNvbiB0byBiZSBleGNsdWRlZC4iKQpgYGAKCmBgYHtyfQppbmNsdWRlZCA8LSBkaWFyeSAlPiUgZmlsdGVyKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9PSAiIikgJT4lIGRpc3RpbmN0KHNlc3Npb24pCgp0ZXN0dGhhdDo6ZXhwZWN0X2VxdWFsKAogIGFsbF9zdXJ2ZXlzICU+JSBmaWx0ZXIocmVhc29uc19mb3JfZXhjbHVzaW9uID09ICIiKSAlPiUgbnJvdygpLCAKICBucm93KGluY2x1ZGVkKQopCmBgYAoKCiMgU2FuaXR5IENoZWNrcwpgYGB7cn0KbGlicmFyeSh0ZXN0dGhhdCkKZXhwZWN0X2VxdWFsKG5yb3coZGlhcnkpLCBkaWFyeV9sZW5ndGgpCmV4cGVjdF9lcXVhbChucm93KGFsbF9zdXJ2ZXlzKSwgYWxsX3N1cnZleV9sZW5ndGgpCmV4cGVjdF9lcXVhbChucm93KGRpYXJ5X3NvY2lhbCksIGRpYXJ5X3NvY2lhbF9sZW5ndGgpCmV4cGVjdF9mYWxzZShhbnkobmFtZXMoZGlhcnkpICVjb250YWlucyUgIi54IikpCmV4cGVjdF9mYWxzZShhbnkobmFtZXMoZGlhcnkpICVjb250YWlucyUgIi55IikpCmV4cGVjdF9mYWxzZShhbnkobmFtZXMoYWxsX3N1cnZleXMpICVjb250YWlucyUgIi55IikpCmV4cGVjdF9lcXVhbChncm91cHMoczNfZGFpbHkpLCBsaXN0KCkpCmV4cGVjdF9lcXVhbChncm91cHMoZGlhcnkpLCBsaXN0KCkpCmV4cGVjdF9lcXVhbChncm91cHMoYWxsX3N1cnZleXMpLCBsaXN0KCkpCmV4cGVjdF9lcXVhbChzdW0oZHVwbGljYXRlZChhbGxfc3VydmV5cyRzZXNzaW9uKSksIDApCmV4cGVjdF9lcXVhbChzdW0oZHVwbGljYXRlZChzMV9kZW1vJHNlc3Npb24pKSwgMCkKZXhwZWN0X2VxdWFsKGRpYXJ5ICU+JSBkcm9wX25hKHNlc3Npb24sIGRheV9udW1iZXIpICU+JSAKICAgICAgICAgICAgICAgZ3JvdXBfYnkoc2hvcnQsIGRheV9udW1iZXIpICU+JSBmaWx0ZXIobigpID4gMSkgJT4lIG5yb3coKSwgMCkKZXhwZWN0X2VxdWFsKGRpYXJ5ICU+JSBkcm9wX25hKHNlc3Npb24sIGNyZWF0ZWRfZGlhcnkpICU+JSAgCiAgICAgICAgICAgIGdyb3VwX2J5KHNlc3Npb24sIGNyZWF0ZWRfZGlhcnkpICU+JSBmaWx0ZXIobigpPjEpICU+JSBucm93KCksIDApCmV4cGVjdF9lcXVhbChzM19kYWlseSAlPiUgZHJvcF9uYShzZXNzaW9uLCBjcmVhdGVkX2RhdGUpICU+JSAgCiAgICAgICAgICAgIGdyb3VwX2J5KHNlc3Npb24sIGNyZWF0ZWRfZGF0ZSkgJT4lIGZpbHRlcihuKCk+MSkgJT4lIG5yb3coKSwgMCkKZXhwZWN0X2VxdWFsKGRpYXJ5ICU+JSBkcm9wX25hKHNlc3Npb24sIGNyZWF0ZWRfZGF0ZSkgJT4lICAKICAgICAgICAgICAgZ3JvdXBfYnkoc2Vzc2lvbiwgY3JlYXRlZF9kYXRlKSAlPiUgZmlsdGVyKG4oKT4xKSAlPiUgbnJvdygpLCAwKQpleHBlY3RfZXF1YWwoZGlhcnlfc29jaWFsICU+JSBkcm9wX25hKHNlc3Npb24sIGNyZWF0ZWRfZGlhcnksIHBlcnNvbikgJT4lICAKICAgICAgICAgICAgZ3JvdXBfYnkoc2Vzc2lvbiwgY3JlYXRlZF9kaWFyeSwgcGVyc29uKSAlPiUgZmlsdGVyKG4oKSA+IDEpICU+JSBucm93KCksIDApCmV4cGVjdF9lcXVhbChuZXR3b3JrICU+JSBkcm9wX25hKHNlc3Npb24sIHBlcnNvbikgJT4lICAKICAgICAgICAgICAgZ3JvdXBfYnkoc2Vzc2lvbiwgcGVyc29uKSAlPiUgZmlsdGVyKG4oKT4xKSAlPiUgbnJvdygpLCAwKQpgYGAgCgoKIyBTYXZlCmBgYHtyfQpzYXZlKGRpYXJ5X3NvY2lhbCwgZGlhcnksIHNleF9sb25nLCBuZXR3b3JrX25vbWluYXRpb25zLCBuZXR3b3JrLCBzMV9kZW1vLCBzMV9maWx0ZXIsIHMyX2luaXRpYWwsIHMzX2RhaWx5LCBzNF9mb2xsb3d1cCwgczRfdGltZXNwZW50LCB3aXRoZm9sbG93dXAsIGFsbF9zdXJ2ZXlzLCBmaWxlID0gImRhdGEvY2xlYW5lZF9zZWxlY3RlZC5yZGF0YSIpCmBgYCAKCgo=