Reasons for Exclusion

The following reasons for exclusion apply:

  • missing data (not finishing the initial survey)
  • not female
  • homosexuality
  • currently in a homosexual relationship
  • older than 50
  • menopausal
  • pregnant
  • breastfeeding
  • participants, who do not want to avoid pregnancy
  • participants, who ‘took a chance’ on getting pregnant
  • participants, who used no contraception for ‘other reasons’
  • use of one of the following contraceptive methods: morning-after pill, breastfeeding, I am infertile, my partner is infertile, I am sterilized, my partner is sterilized, other
  • incongruent information about current contraceptive method and method used in the last three months
  • use of medication including sex hormones in the last three months.

Data and Functions

source("0_helpers.R")
load("data/cleaned.rdata")
# opts_chunk$set(warning = F, message = F, error = T)

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

# function to seperate the reasons for exclusion variable for upsetr
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)

Exclusion Steps

all_surveys$reasons_for_exclusion = "" #insert new variable reasons_for_exclusion to list all exclusion criteria
all_surveys$reasons_for_exclusion_contraception = "" #insert new variable reasons_for_exclusion_contraception to list different contraceptions that lead to exclusion

Missing data (not finishing the initial survey)

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(is.na(ended_initial), "didnt_finish_initial, ", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "didnt_finish_initial"))
Var1 Freq
FALSE 1411
TRUE 249

Not female

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(gender != 1 & !is.na(gender), "not_female, ", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "not_female"))
Var1 Freq
FALSE 1657
TRUE 3

Homosexuality

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, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "not_heterosexual_female"))
Var1 Freq
FALSE 1634
TRUE 26

Currently in a non-heterosexual relationship

all_surveys = all_surveys %>%
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(partner_gender == 1,
                                               "non_heterosexual_relationship, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "non_heterosexual_relationship"))
Var1 Freq
FALSE 1651
TRUE 9

Older than 50

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(age >= 50, "older_than_50, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "older_than_50"))
Var1 Freq
FALSE 1625
TRUE 35

Menopausal

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(menopause_yes == 1 | menopause_yes == 2,
                                               "menopausal, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "menopausal"))
Var1 Freq
FALSE 1619
TRUE 41

Pregnant

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(pregnant == 1, "pregnant, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "pregnant"))
Var1 Freq
FALSE 1637
TRUE 23

Breastfeeding

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(breast_feeding == 1, "breast_feeding, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "breast_feeding"))
Var1 Freq
FALSE 1632
TRUE 28

Participants, who do not want to avoid pregnancy

all_surveys = all_surveys %>%
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(pregnant_trying >= 4,
                                               "pregnant_trying, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "pregnant_trying"))
Var1 Freq
FALSE 1599
TRUE 61

Participants, who ‘took a chance’ on getting pregnant

all_surveys = all_surveys %>%
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(contraception_at_all == 4,
                                               "pregnant_chance, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "pregnant_chance"))
Var1 Freq
FALSE 1619
TRUE 41

Participants, who used no contraception for ‘other reasons’

all_surveys = all_surveys %>%
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(contraception_at_all == 6,
                                               "no_contraception, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "no_contraception"))
Var1 Freq
FALSE 1605
TRUE 55

Conraceptive Method

Use of one of the following contraceptive methods

Morning-after pill

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "hormonal_morning_after_pill",
            "contraception_hormonal_morning_after_pill, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_hormonal_morning_after_pill"))
Var1 Freq
FALSE 1648
TRUE 12

Breastfeeding

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "breast_feeding",
            "contraception_breast_feeding, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_breast_feeding"))
Var1 Freq
FALSE 1659
TRUE 1

I am infertile

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "infertile" &
              !(contraception_method %contains% "partner_infertile"),
            "contraception_infertile, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_infertile"))
Var1 Freq
FALSE 1658
TRUE 2

My partner is infertile

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "partner_infertile",
            "contraception_partner_infertile, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_partner_infertile"))
Var1 Freq
FALSE 1658
TRUE 2

I am sterilized

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "sterilised" &
              !(contraception_method %contains% "partner_sterilised"),
            "contraception_sterilised, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_sterilised"))
Var1 Freq
FALSE 1658
TRUE 2

My partner is sterilized

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "partner_sterilised",
            "contraception_partner_sterilised, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_partner_sterilised"))
Var1 Freq
FALSE 1653
TRUE 7

Other

all_surveys = all_surveys %>% 
  mutate(reasons_for_exclusion_contraception = str_c(
    reasons_for_exclusion_contraception,
    if_else(contraception_method %contains% "not_listed",
            "contraception_not_listed, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion_contraception %contains% "contraception_not_listed"))
Var1 Freq
FALSE 1651
TRUE 9

Summary

All participants that will be excluded based on their choice of contraception

all_surveys = all_surveys %>%
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(reasons_for_exclusion_contraception != "",
                                       "contraceptive_method, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "contraceptive_method"))
Var1 Freq
FALSE 1626
TRUE 34

Incongruent information about current contraceptive method and method used in the last three months

all_surveys = all_surveys %>%
  mutate(incongruent_information_about_hormonal_contraception =
           ifelse((hormonal_contraception_last3m == 0 & hormonal_contraception == T), 1, 0),
         reasons_for_exclusion = str_c(reasons_for_exclusion,
                                       if_else(incongruent_information_about_hormonal_contraception == 1,
                                               "incongruent_information_about_hormonal_contraception, ",
                                               "", "")))


kable(table(all_surveys$reasons_for_exclusion %contains% "incongruent_information_about_hormonal_contraception"))
Var1 Freq
FALSE 1621
TRUE 39

Use of medication including sex hormones in the last three months.

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, ", "", "")))

kable(table(all_surveys$reasons_for_exclusion %contains% "sex_hormones"))
Var1 Freq
FALSE 1653
TRUE 7

Total number of excluded participants

kable(table(all_surveys$reasons_for_exclusion == ""))
Var1 Freq
FALSE 481
TRUE 1179

In total 481 participants were excluded, leaving 1179 subjects which were included in the analysis.

Reasons for exclusion

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).

Table

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) 

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)) %>% 
  knitr::kable()
reason n unique
not_female 3 0
sex_hormones 7 5
non_heterosexual_relationship 9 6
pregnant 23 13
not_heterosexual_female 26 14
breast_feeding 28 13
contraceptive_method 34 21
older_than_50 35 1
incongruent_information_about_hormonal_contraception 39 22
menopausal 41 5
pregnant_chance 41 13
no_contraception 55 15
pregnant_trying 61 17
didnt_finish_initial 249 205
included 1179 0

Figure 3: Exclusion criteria and most common combinations of exclusion criteria.

The horizontal green bars show for how many women this exclusion criteria applies. The blue bars show how many women are excluded for multiple reasons (e.g., not finishing the initial survey and being pregnant). Only the 20 most common overlaps are displayed. See Figure S1 in the supplementary materials for all combinations.

upset1 = exclusion_reasons %>% 
  rename(`Breastfeeding` = breast_feeding, 
         `Choice of Contraceptive Methode` = contraceptive_method,
         `Missing Data` = didnt_finish_initial,
         `Incongruent Information about Contraceptive Method` =
           incongruent_information_about_hormonal_contraception,
         `(Post-)Menopausal` = menopausal,
         `Using no Contraceptive Methods for Other Reasons` = no_contraception,
         `Not Female` = not_female,
         `Not Predominantly Heterosexual` = not_heterosexual_female,
         `Older than 50` = older_than_50,
         `Pregnant` = pregnant,
         `“Taking a Chance” of Becoming Pregnant` = pregnant_chance,
         `Trying to Become Pregnant` = pregnant_trying,
         `Medication Including Sex Hormones` = sex_hormones,
         `Currently in a Homosexual Relationship` = non_heterosexual_relationship) %>%
  filter(included == 0) %>% 
  select(-included) %>% 
  as.data.frame() %>%
  {
  upset(., ncol(.),
        20,
        order.by = "freq",
      main.bar.color = "#6E8691",
      matrix.color = "#6E8691",
      sets.bar.color = "#53AC9B",
      text.scale = 1.2)
  }
upset1

jpeg('Exclusion criteria and most common combinations of exclusion criteria.jpg', 
     width = 900, height = 470, quality = 1000)
upset1
dev.off()
## png 
##   2

Figure S1: Exclusion criteria and all combinations of exclusion criteria.

The horizontal green bars show for how many women this exclusion criteria applies. The blue bars show how many women are excluded for multiple reasons (e.g., not finishing the initial survey and being pregnant). All 52 combinations of exclusion criteria are displayed.

upset2 = exclusion_reasons %>% 
  rename(`Breastfeeding` = breast_feeding, 
         `Choice of Contraceptive Methode` = contraceptive_method,
         `Missing Data` = didnt_finish_initial,
         `Incongruent Information about Contraceptive Method` =
           incongruent_information_about_hormonal_contraception,
         `(Post-)Menopausal` = menopausal,
         `Using no Contraceptive Methods for Other Reasons` = no_contraception,
         `Not Female` = not_female,
         `Not Predominantly Heterosexual` = not_heterosexual_female,
         `Older than 50` = older_than_50,
         `Pregnant` = pregnant,
         `“Taking a Chance” of Becoming Pregnant` = pregnant_chance,
         `Trying to Become Pregnant` = pregnant_trying,
         `Medication Including Sex Hormones` = sex_hormones,
         `Currently in a Homosexual Relationship` = non_heterosexual_relationship) %>%
  filter(included == 0) %>% 
  select(-included) %>% 
  as.data.frame() %>% 
  {
  upset(., ncol(.), 80, order.by = "freq",
      main.bar.color = "#6E8691",
      matrix.color = "#6E8691",
      sets.bar.color = "#53AC9B",
      text.scale = 1.2)
  }
upset2

jpeg('Exclusion criteria and all combinations of exclusion criteria.jpg', 
     width = 900, height = 500, quality = 1000)
upset2
dev.off()
## png 
##   2

Exlusion Steps Diary

To calculate Libido and Sexual Frequency we need Information from the diary. Therefore, two additional exlusion reasons for the diary apply:

  • Skipping a diary day
  • Dishonest answers on that day
diary = diary %>% left_join(all_surveys %>% select(session, reasons_for_exclusion), by = 'session')

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

diary = diary %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(is.na(ended_diary) & is.na(modified_diary),
                                                    "skipped_diary_entry, ", "")))

table(diary$reasons_for_exclusion %contains% "skipped_diary_entry")
## 
## FALSE  TRUE 
## 62043  1103

Disclosed that they responded dishonestly on that day.

diary = diary %>% 
  mutate(reasons_for_exclusion = str_c(reasons_for_exclusion,
                                            if_else(dishonest_discard == 1,
                                                    "dishonest_answer, ", "", "")))

table(diary$reasons_for_exclusion %contains% "dishonest_answer")
## 
## FALSE  TRUE 
## 62996   150

Create included variable

all_surveys = all_surveys %>%
  mutate(included = if_else(reasons_for_exclusion == "", TRUE, FALSE))

diary = diary %>%
  mutate(included = if_else(reasons_for_exclusion == "", TRUE, FALSE))

Save

library(testthat)
expect_equal(nrow(diary), diary_length)
expect_equal(nrow(all_surveys), all_survey_length)

save(diary, all_surveys, file = "data/cleaned_selected.rdata")
LS0tDQp0aXRsZTogIkV4Y2x1c2lvbiINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6ICdzaG93Jw0KICAgIHNlbGZfY29udGFpbmVkOiBmYWxzZQ0KLS0tDQoNCiMgUmVhc29ucyBmb3IgRXhjbHVzaW9uIHsudGFic2V0fQ0KDQoNClRoZSBmb2xsb3dpbmcgcmVhc29ucyBmb3IgZXhjbHVzaW9uIGFwcGx5Og0KDQoqIG1pc3NpbmcgZGF0YSAobm90IGZpbmlzaGluZyB0aGUgaW5pdGlhbCBzdXJ2ZXkpDQoqIG5vdCBmZW1hbGUNCiogaG9tb3NleHVhbGl0eQ0KKiBjdXJyZW50bHkgaW4gYSBob21vc2V4dWFsIHJlbGF0aW9uc2hpcA0KKiBvbGRlciB0aGFuIDUwDQoqIG1lbm9wYXVzYWwNCiogcHJlZ25hbnQNCiogYnJlYXN0ZmVlZGluZw0KKiBwYXJ0aWNpcGFudHMsIHdobyBkbyBub3Qgd2FudCB0byBhdm9pZCBwcmVnbmFuY3kNCiogcGFydGljaXBhbnRzLCB3aG8g4oCYdG9vayBhIGNoYW5jZeKAmSBvbiBnZXR0aW5nIHByZWduYW50DQoqIHBhcnRpY2lwYW50cywgd2hvIHVzZWQgbm8gY29udHJhY2VwdGlvbiBmb3Ig4oCYb3RoZXIgcmVhc29uc+KAmQ0KKiB1c2Ugb2Ygb25lIG9mIHRoZSBmb2xsb3dpbmcgY29udHJhY2VwdGl2ZSBtZXRob2RzOiBtb3JuaW5nLWFmdGVyIHBpbGwsIGJyZWFzdGZlZWRpbmcsIEkgYW0gaW5mZXJ0aWxlLCBteSBwYXJ0bmVyIGlzIGluZmVydGlsZSwgSSBhbSBzdGVyaWxpemVkLCBteSBwYXJ0bmVyIGlzIHN0ZXJpbGl6ZWQsIG90aGVyDQoqIGluY29uZ3J1ZW50IGluZm9ybWF0aW9uIGFib3V0IGN1cnJlbnQgY29udHJhY2VwdGl2ZSBtZXRob2QgYW5kIG1ldGhvZCB1c2VkIGluIHRoZSBsYXN0IHRocmVlIG1vbnRocw0KKiB1c2Ugb2YgbWVkaWNhdGlvbiBpbmNsdWRpbmcgc2V4IGhvcm1vbmVzIGluIHRoZSBsYXN0IHRocmVlIG1vbnRocy4NCg0KIyMgRGF0YSBhbmQgRnVuY3Rpb25zDQpgYGB7ciBkYXRhIGFuZCBmdW5jdGlvbnN9DQpzb3VyY2UoIjBfaGVscGVycy5SIikNCmxvYWQoImRhdGEvY2xlYW5lZC5yZGF0YSIpDQojIG9wdHNfY2h1bmskc2V0KHdhcm5pbmcgPSBGLCBtZXNzYWdlID0gRiwgZXJyb3IgPSBUKQ0KDQpsaWJyYXJ5KGtuaXRyKQ0Kb3B0c19jaHVuayRzZXQoZmlnLndpZHRoID0gOSwgZmlnLmhlaWdodCA9IDcsIGNhY2hlID0gVCwgd2FybmluZyA9IEYsIG1lc3NhZ2UgPSBGLCBjYWNoZSA9IEYsIGVycm9yID0gVCkNCg0KIyBmdW5jdGlvbiB0byBzZXBlcmF0ZSB0aGUgcmVhc29ucyBmb3IgZXhjbHVzaW9uIHZhcmlhYmxlIGZvciB1cHNldHINCmNvbW1hX3NlcGFyYXRlZF90b19jb2x1bW5zID0gZnVuY3Rpb24oZGYsIGNvbCkgew0KICBjb2xuYW1lID0gZGVwYXJzZShzdWJzdGl0dXRlKGNvbCkpDQogIGRmJHNwbGl0Y29sID0gZGYgJT4lIHB1bGwoY29sbmFtZSkNCiAgc2VwYXJhdGVfcm93cyhkZiwgc3BsaXRjb2wsIGNvbnZlcnQgPSBUUlVFLCBzZXAgPSAiLCAiKSAlPiUgDQogICAgbXV0YXRlKHNwbGl0Y29sID0gaWZfZWxzZShpcy5uYShzcGxpdGNvbCksICJubyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShzcGxpdGNvbCA9PSAiIiB8IA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwbGl0Y29sICVpbiUgYygpLCAiaW5jbHVkZWQiLCBhcy5jaGFyYWN0ZXIoc3BsaXRjb2wpKSkpICU+JSANCiAgICBtdXRhdGUoI3NwbGl0Y29sID0gc3RyaW5ncjo6c3RyX2MoY29sbmFtZSwgIl8iLCBzcGxpdGNvbCksIA0KICAgICAgICAgICB2YWx1ZSA9IDEpICU+JSANCiAgICBzcHJlYWQoc3BsaXRjb2wsIHZhbHVlLCBmaWxsID0gMCkgJT4lIA0KICAgIHNlbGVjdCgtY29sbmFtZSkNCn0NCg0KYWxsX3N1cnZleV9sZW5ndGggPSBucm93KGFsbF9zdXJ2ZXlzKQ0KZGlhcnlfbGVuZ3RoID0gbnJvdyhkaWFyeSkNCmRpYXJ5X3NvY2lhbF9sZW5ndGggPSBucm93KGRpYXJ5X3NvY2lhbCkNCmBgYA0KDQojIyBFeGNsdXNpb24gU3RlcHMgey50YWJzZXR9DQpgYGB7ciByZWFzb25zX2Zvcl9leGNsdXNpb259DQphbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gPSAiIiAjaW5zZXJ0IG5ldyB2YXJpYWJsZSByZWFzb25zX2Zvcl9leGNsdXNpb24gdG8gbGlzdCBhbGwgZXhjbHVzaW9uIGNyaXRlcmlhDQphbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiA9ICIiICNpbnNlcnQgbmV3IHZhcmlhYmxlIHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uIHRvIGxpc3QgZGlmZmVyZW50IGNvbnRyYWNlcHRpb25zIHRoYXQgbGVhZCB0byBleGNsdXNpb24NCmBgYA0KDQojIyMgTWlzc2luZyBkYXRhIChub3QgZmluaXNoaW5nIHRoZSBpbml0aWFsIHN1cnZleSkNCmBgYHtyIGRpZG50X2ZpbmlzaF9pbml0aWFsfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUgDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGlzLm5hKGVuZGVkX2luaXRpYWwpLCAiZGlkbnRfZmluaXNoX2luaXRpYWwsICIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiAlY29udGFpbnMlICJkaWRudF9maW5pc2hfaW5pdGlhbCIpKQ0KYGBgDQoNCiMjIyBOb3QgZmVtYWxlDQpgYGB7ciBub3RfZmVtYWxlfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUgDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGdlbmRlciAhPSAxICYgIWlzLm5hKGdlbmRlciksICJub3RfZmVtYWxlLCAiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gJWNvbnRhaW5zJSAibm90X2ZlbWFsZSIpKQ0KYGBgDQoNCiMjIyBIb21vc2V4dWFsaXR5DQpOb3QgcHJpbWFyaWx5IGhldGVyb3NleHVhbC4gVGhpcyBleGNsdWRlcyB3b21lbiB3aG8gcmVwb3J0ZWQgYmVpbmcgZXF1YWxseSBpbnRlcmVzdGVkIGluIG1lbiBhbmQgd29tZW4sIHdvbWVuIHdobyByZXBvcnRlZCBiZWluZyBhc2V4dWFsIG9yIGFyb21hbnRpYywgYW5kIHBhcnRpY2lwYW50cyB3aG8gZGlkIG5vdCBpZGVudGlmeSBhcyBmZW1hbGUgZ2VuZGVyLg0KYGBge3Igbm90X2hldGVyb3NleHVhbF9mZW1hbGV9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JQ0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShzZXhfb3JpZW50YXRpb24gPj0gNCB8IGdlbmRlciAhPSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm90X2hldGVyb3NleHVhbF9mZW1hbGUsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gJWNvbnRhaW5zJSAibm90X2hldGVyb3NleHVhbF9mZW1hbGUiKSkNCmBgYA0KDQojIyMgQ3VycmVudGx5IGluIGEgbm9uLWhldGVyb3NleHVhbCByZWxhdGlvbnNoaXANCmBgYHtyfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUNCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UocGFydG5lcl9nZW5kZXIgPT0gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIm5vbl9oZXRlcm9zZXh1YWxfcmVsYXRpb25zaGlwLCAiLCAiIiwgIiIpKSkNCg0Ka2FibGUodGFibGUoYWxsX3N1cnZleXMkcmVhc29uc19mb3JfZXhjbHVzaW9uICVjb250YWlucyUgIm5vbl9oZXRlcm9zZXh1YWxfcmVsYXRpb25zaGlwIikpDQpgYGANCg0KIyMjIE9sZGVyIHRoYW4gNTANCmBgYHtyIG9sZGVyX3RoYW5fNTB9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JSANCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShhZ2UgPj0gNTAsICJvbGRlcl90aGFuXzUwLCAiLCAiIiwgIiIpKSkNCg0Ka2FibGUodGFibGUoYWxsX3N1cnZleXMkcmVhc29uc19mb3JfZXhjbHVzaW9uICVjb250YWlucyUgIm9sZGVyX3RoYW5fNTAiKSkNCmBgYA0KDQojIyMgTWVub3BhdXNhbA0KYGBge3IgbWVub3BhdXNhbH0NCmFsbF9zdXJ2ZXlzID0gYWxsX3N1cnZleXMgJT4lIA0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShtZW5vcGF1c2VfeWVzID09IDEgfCBtZW5vcGF1c2VfeWVzID09IDIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtZW5vcGF1c2FsLCAiLCAiIiwgIiIpKSkNCg0Ka2FibGUodGFibGUoYWxsX3N1cnZleXMkcmVhc29uc19mb3JfZXhjbHVzaW9uICVjb250YWlucyUgIm1lbm9wYXVzYWwiKSkNCmBgYA0KDQojIyMgUHJlZ25hbnQNCmBgYHtyIHByZWduYW50fQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUgDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKHByZWduYW50ID09IDEsICJwcmVnbmFudCwgIiwgIiIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiAlY29udGFpbnMlICJwcmVnbmFudCIpKQ0KYGBgDQoNCg0KIyMjIEJyZWFzdGZlZWRpbmcNCmBgYHtyIGJyZWFzdGZlZWRpbmd9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JSANCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShicmVhc3RfZmVlZGluZyA9PSAxLCAiYnJlYXN0X2ZlZWRpbmcsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gJWNvbnRhaW5zJSAiYnJlYXN0X2ZlZWRpbmciKSkNCmBgYA0KDQojIyMgUGFydGljaXBhbnRzLCB3aG8gZG8gbm90IHdhbnQgdG8gYXZvaWQgcHJlZ25hbmN5DQpgYGB7ciBwcmVnbmFudF90cnlpbmd9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JQ0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShwcmVnbmFudF90cnlpbmcgPj0gNCwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInByZWduYW50X3RyeWluZywgIiwgIiIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiAlY29udGFpbnMlICJwcmVnbmFudF90cnlpbmciKSkNCmBgYA0KDQojIyMgUGFydGljaXBhbnRzLCB3aG8g4oCYdG9vayBhIGNoYW5jZeKAmSBvbiBnZXR0aW5nIHByZWduYW50DQpgYGB7cn0NCmFsbF9zdXJ2ZXlzID0gYWxsX3N1cnZleXMgJT4lDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGNvbnRyYWNlcHRpb25fYXRfYWxsID09IDQsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwcmVnbmFudF9jaGFuY2UsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gJWNvbnRhaW5zJSAicHJlZ25hbnRfY2hhbmNlIikpDQpgYGANCg0KIyMjIFBhcnRpY2lwYW50cywgd2hvIHVzZWQgbm8gY29udHJhY2VwdGlvbiBmb3Ig4oCYb3RoZXIgcmVhc29uc+KAmQ0KYGBge3J9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JQ0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShjb250cmFjZXB0aW9uX2F0X2FsbCA9PSA2LA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibm9fY29udHJhY2VwdGlvbiwgIiwgIiIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiAlY29udGFpbnMlICJub19jb250cmFjZXB0aW9uIikpDQpgYGANCg0KIyMjIENvbnJhY2VwdGl2ZSBNZXRob2Qgey50YWJzZXR9DQpVc2Ugb2Ygb25lIG9mIHRoZSBmb2xsb3dpbmcgY29udHJhY2VwdGl2ZSBtZXRob2RzDQoNCg0KIyMjIyBNb3JuaW5nLWFmdGVyIHBpbGwNCmBgYHtyIGNvbnRyYWNlcHRpb25faG9ybW9uYWxfbW9ybmluZ19hZnRlcl9waWxsfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUgDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiA9IHN0cl9jKA0KICAgIHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uLA0KICAgIGlmX2Vsc2UoY29udHJhY2VwdGlvbl9tZXRob2QgJWNvbnRhaW5zJSAiaG9ybW9uYWxfbW9ybmluZ19hZnRlcl9waWxsIiwNCiAgICAgICAgICAgICJjb250cmFjZXB0aW9uX2hvcm1vbmFsX21vcm5pbmdfYWZ0ZXJfcGlsbCwgIiwgIiIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uICVjb250YWlucyUgImNvbnRyYWNlcHRpb25faG9ybW9uYWxfbW9ybmluZ19hZnRlcl9waWxsIikpDQpgYGANCg0KIyMjIyBCcmVhc3RmZWVkaW5nDQpgYGB7ciBjb250cmFjZXB0aW9uX2JyZWFzdF9mZWVkaW5nfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUgDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiA9IHN0cl9jKA0KICAgIHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uLA0KICAgIGlmX2Vsc2UoY29udHJhY2VwdGlvbl9tZXRob2QgJWNvbnRhaW5zJSAiYnJlYXN0X2ZlZWRpbmciLA0KICAgICAgICAgICAgImNvbnRyYWNlcHRpb25fYnJlYXN0X2ZlZWRpbmcsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiAlY29udGFpbnMlICJjb250cmFjZXB0aW9uX2JyZWFzdF9mZWVkaW5nIikpDQpgYGANCg0KIyMjIyBJIGFtIGluZmVydGlsZQ0KYGBge3IgY29udHJhY2VwdGlvbl9pbmZlcnRpbGV9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JSANCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uID0gc3RyX2MoDQogICAgcmVhc29uc19mb3JfZXhjbHVzaW9uX2NvbnRyYWNlcHRpb24sDQogICAgaWZfZWxzZShjb250cmFjZXB0aW9uX21ldGhvZCAlY29udGFpbnMlICJpbmZlcnRpbGUiICYNCiAgICAgICAgICAgICAgIShjb250cmFjZXB0aW9uX21ldGhvZCAlY29udGFpbnMlICJwYXJ0bmVyX2luZmVydGlsZSIpLA0KICAgICAgICAgICAgImNvbnRyYWNlcHRpb25faW5mZXJ0aWxlLCAiLCAiIiwgIiIpKSkNCg0Ka2FibGUodGFibGUoYWxsX3N1cnZleXMkcmVhc29uc19mb3JfZXhjbHVzaW9uX2NvbnRyYWNlcHRpb24gJWNvbnRhaW5zJSAiY29udHJhY2VwdGlvbl9pbmZlcnRpbGUiKSkNCmBgYA0KDQojIyMjIE15IHBhcnRuZXIgaXMgaW5mZXJ0aWxlDQpgYGB7ciBjb250cmFjZXB0aW9uX3BhcnRuZXJfaW5mZXJ0aWxlfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUgDQogIG11dGF0ZShyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiA9IHN0cl9jKA0KICAgIHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uLA0KICAgIGlmX2Vsc2UoY29udHJhY2VwdGlvbl9tZXRob2QgJWNvbnRhaW5zJSAicGFydG5lcl9pbmZlcnRpbGUiLA0KICAgICAgICAgICAgImNvbnRyYWNlcHRpb25fcGFydG5lcl9pbmZlcnRpbGUsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiAlY29udGFpbnMlICJjb250cmFjZXB0aW9uX3BhcnRuZXJfaW5mZXJ0aWxlIikpDQpgYGANCg0KIyMjIyBJIGFtIHN0ZXJpbGl6ZWQNCmBgYHtyIGNvbnRyYWNlcHRpb25fc3RlcmlsaXNlZH0NCmFsbF9zdXJ2ZXlzID0gYWxsX3N1cnZleXMgJT4lIA0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uX2NvbnRyYWNlcHRpb24gPSBzdHJfYygNCiAgICByZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiwNCiAgICBpZl9lbHNlKGNvbnRyYWNlcHRpb25fbWV0aG9kICVjb250YWlucyUgInN0ZXJpbGlzZWQiICYNCiAgICAgICAgICAgICAgIShjb250cmFjZXB0aW9uX21ldGhvZCAlY29udGFpbnMlICJwYXJ0bmVyX3N0ZXJpbGlzZWQiKSwNCiAgICAgICAgICAgICJjb250cmFjZXB0aW9uX3N0ZXJpbGlzZWQsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiAlY29udGFpbnMlICJjb250cmFjZXB0aW9uX3N0ZXJpbGlzZWQiKSkNCmBgYA0KDQoNCiMjIyMgTXkgcGFydG5lciBpcyBzdGVyaWxpemVkDQpgYGB7ciBjb250cmFjZXB0aW9uX3BhcnRuZXJfc3RlcmlsaXNlZH0NCmFsbF9zdXJ2ZXlzID0gYWxsX3N1cnZleXMgJT4lIA0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uX2NvbnRyYWNlcHRpb24gPSBzdHJfYygNCiAgICByZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiwNCiAgICBpZl9lbHNlKGNvbnRyYWNlcHRpb25fbWV0aG9kICVjb250YWlucyUgInBhcnRuZXJfc3RlcmlsaXNlZCIsDQogICAgICAgICAgICAiY29udHJhY2VwdGlvbl9wYXJ0bmVyX3N0ZXJpbGlzZWQsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiAlY29udGFpbnMlICJjb250cmFjZXB0aW9uX3BhcnRuZXJfc3RlcmlsaXNlZCIpKQ0KYGBgDQoNCiMjIyMgT3RoZXINCmBgYHtyIGNvbnRyYWNlcHRpb25fbm90X2xpc3RlZH0NCmFsbF9zdXJ2ZXlzID0gYWxsX3N1cnZleXMgJT4lIA0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uX2NvbnRyYWNlcHRpb24gPSBzdHJfYygNCiAgICByZWFzb25zX2Zvcl9leGNsdXNpb25fY29udHJhY2VwdGlvbiwNCiAgICBpZl9lbHNlKGNvbnRyYWNlcHRpb25fbWV0aG9kICVjb250YWlucyUgIm5vdF9saXN0ZWQiLA0KICAgICAgICAgICAgImNvbnRyYWNlcHRpb25fbm90X2xpc3RlZCwgIiwgIiIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbl9jb250cmFjZXB0aW9uICVjb250YWlucyUgImNvbnRyYWNlcHRpb25fbm90X2xpc3RlZCIpKQ0KYGBgDQoNCiMjIyMgU3VtbWFyeQ0KQWxsIHBhcnRpY2lwYW50cyB0aGF0IHdpbGwgYmUgZXhjbHVkZWQgYmFzZWQgb24gdGhlaXIgY2hvaWNlIG9mIGNvbnRyYWNlcHRpb24NCmBgYHtyfQ0KYWxsX3N1cnZleXMgPSBhbGxfc3VydmV5cyAlPiUNCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UocmVhc29uc19mb3JfZXhjbHVzaW9uX2NvbnRyYWNlcHRpb24gIT0gIiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY29udHJhY2VwdGl2ZV9tZXRob2QsICIsICIiLCAiIikpKQ0KDQprYWJsZSh0YWJsZShhbGxfc3VydmV5cyRyZWFzb25zX2Zvcl9leGNsdXNpb24gJWNvbnRhaW5zJSAiY29udHJhY2VwdGl2ZV9tZXRob2QiKSkNCmBgYA0KDQoNCg0KIyMjIEluY29uZ3J1ZW50IGluZm9ybWF0aW9uIGFib3V0IGN1cnJlbnQgY29udHJhY2VwdGl2ZSBtZXRob2QgYW5kIG1ldGhvZCB1c2VkIGluIHRoZSBsYXN0IHRocmVlIG1vbnRocw0KYGBge3IgaW5jb25ncnVlbnRfaW5mb3JtYXRpb25fYWJvdXRfaG9ybW9uYWxfY29udHJhY2VwdGlvbn0NCmFsbF9zdXJ2ZXlzID0gYWxsX3N1cnZleXMgJT4lDQogIG11dGF0ZShpbmNvbmdydWVudF9pbmZvcm1hdGlvbl9hYm91dF9ob3Jtb25hbF9jb250cmFjZXB0aW9uID0NCiAgICAgICAgICAgaWZlbHNlKChob3Jtb25hbF9jb250cmFjZXB0aW9uX2xhc3QzbSA9PSAwICYgaG9ybW9uYWxfY29udHJhY2VwdGlvbiA9PSBUKSwgMSwgMCksDQogICAgICAgICByZWFzb25zX2Zvcl9leGNsdXNpb24gPSBzdHJfYyhyZWFzb25zX2Zvcl9leGNsdXNpb24sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGluY29uZ3J1ZW50X2luZm9ybWF0aW9uX2Fib3V0X2hvcm1vbmFsX2NvbnRyYWNlcHRpb24gPT0gMSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImluY29uZ3J1ZW50X2luZm9ybWF0aW9uX2Fib3V0X2hvcm1vbmFsX2NvbnRyYWNlcHRpb24sICIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiLCAiIikpKQ0KDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiAlY29udGFpbnMlICJpbmNvbmdydWVudF9pbmZvcm1hdGlvbl9hYm91dF9ob3Jtb25hbF9jb250cmFjZXB0aW9uIikpDQpgYGANCg0KDQojIyMgVXNlIG9mIG1lZGljYXRpb24gaW5jbHVkaW5nIHNleCBob3Jtb25lcyBpbiB0aGUgbGFzdCB0aHJlZSBtb250aHMuDQpUYWtpbmcgc2V4IGhvcm1vbmVzIChvdGhlciB0aGFuIHRoZSBwaWxsKQ0KYGBge3J9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JSANCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UobWVkaWNhdGlvbl9uYW1lICVjb250YWlucyUgIkN5Y2xvcHJvZ25vdmEiIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpY2F0aW9uX25hbWUgJWNvbnRhaW5zJSAiQ3lwcm9kZXJtIiB8DQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVkaWNhdGlvbl9uYW1lICVjb250YWlucyUgIkRIRUEiIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpY2F0aW9uX25hbWUgJWNvbnRhaW5zJSAiSG9ybW9uZSIgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lZGljYXRpb25fbmFtZSAlY29udGFpbnMlICJDeWNsby1Qcm9neW5vdmEiIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpY2F0aW9uX25hbWUgJWNvbnRhaW5zJSAiRmVtb3N0b24iIHwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZWRpY2F0aW9uX25hbWUgJWNvbnRhaW5zJSAiR3lub2thZGluIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInNleF9ob3Jtb25lcywgIiwgIiIsICIiKSkpDQoNCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiAlY29udGFpbnMlICJzZXhfaG9ybW9uZXMiKSkNCmBgYA0KDQojIyBUb3RhbCBudW1iZXIgb2YgZXhjbHVkZWQgcGFydGljaXBhbnRzDQpgYGB7cn0NCmthYmxlKHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9PSAiIikpDQpgYGANCkluIHRvdGFsIGByIHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9PSAiIilbIkZBTFNFIl1gIHBhcnRpY2lwYW50cyB3ZXJlIGV4Y2x1ZGVkLCBsZWF2aW5nIGByIHRhYmxlKGFsbF9zdXJ2ZXlzJHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9PSAiIilbIlRSVUUiXWAgc3ViamVjdHMgd2hpY2ggd2VyZSBpbmNsdWRlZCBpbiB0aGUgYW5hbHlzaXMuDQoNCg0KIyMgUmVhc29ucyBmb3IgZXhjbHVzaW9uIHsudGFic2V0fQ0KSG93IHRvIHJlYWQgdGhpcyBwbG90OiBUaGUgaG9yaXpvbnRhbCBncmVlbiBiYXJzIHNob3cgZm9yIGhvdyBtYW55IHdvbWVuIHRoaXMgcmVhc29uIGZvcg0KZXhjbHVzaW9uIGFwcGxpZXMuIFRoZSBibHVlIGJhcnMgc2hvdyBob3cgbWFueSB3b21lbiBhcmUgZXhjbHVkZWQgZm9yIG11bHRpcGxlIHJlYXNvbnMgKGUuZy4sDQp0aGV5J3JlIG1lbm9wYXVzYWwgX2FuZF8gbm90IGhldGVyb3NleHVhbCkuDQoNCiMjIyBUYWJsZQ0KYGBge3J9DQpleGNsdXNpb25fcmVhc29ucyA9IGFsbF9zdXJ2ZXlzICU+JSANCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9zdWIocmVhc29uc19mb3JfZXhjbHVzaW9uLCAxLCAtMykpICU+JSANCiAgc2VsZWN0KHNlc3Npb24sIHJlYXNvbnNfZm9yX2V4Y2x1c2lvbikgJT4lIA0KICBjb21tYV9zZXBhcmF0ZWRfdG9fY29sdW1ucyhyZWFzb25zX2Zvcl9leGNsdXNpb24pICU+JSANCiAgc2VsZWN0KC1zZXNzaW9uKSANCg0KZXhjbHVzaW9uX3JlYXNvbnMgJT4lIA0KICBzdW1tYXJpc2VfYWxsKHN1bSkgJT4lDQogIHNvcnQoKSAlPiUgDQogIGdhdGhlcihyZWFzb24sIG4pICU+JSANCiAgbGVmdF9qb2luKGFsbF9zdXJ2ZXlzICU+JSBtdXRhdGUocmVhc29uID0gc3RyX3N1YihyZWFzb25zX2Zvcl9leGNsdXNpb24sIDEsIC0zKSkgJT4lDQogICAgICAgICAgICAgIGdyb3VwX2J5KHJlYXNvbikgJT4lDQogICAgICAgICAgICAgIHN1bW1hcmlzZSh1bmlxdWUgPSBuKCkpKSAlPiUgDQogIG11dGF0ZSh1bmlxdWUgPSBpZl9lbHNlKGlzLm5hKHVuaXF1ZSksIDBMLCB1bmlxdWUpKSAlPiUgDQogIGtuaXRyOjprYWJsZSgpDQpgYGANCg0KIyMjIEZpZ3VyZSAzOiBFeGNsdXNpb24gY3JpdGVyaWEgYW5kIG1vc3QgY29tbW9uIGNvbWJpbmF0aW9ucyBvZiBleGNsdXNpb24gY3JpdGVyaWEuIHsuYWN0aXZlfQ0KVGhlIGhvcml6b250YWwgZ3JlZW4gYmFycyBzaG93IGZvciBob3cgbWFueSB3b21lbiB0aGlzIGV4Y2x1c2lvbiBjcml0ZXJpYSBhcHBsaWVzLiBUaGUgYmx1ZSBiYXJzIHNob3cgaG93IG1hbnkgd29tZW4gYXJlIGV4Y2x1ZGVkIGZvciBtdWx0aXBsZSByZWFzb25zIChlLmcuLCBub3QgZmluaXNoaW5nIHRoZSBpbml0aWFsIHN1cnZleSBhbmQgYmVpbmcgcHJlZ25hbnQpLiBPbmx5IHRoZSAyMCBtb3N0IGNvbW1vbiBvdmVybGFwcyBhcmUgZGlzcGxheWVkLiBTZWUgRmlndXJlIFMxIGluIHRoZSBzdXBwbGVtZW50YXJ5IG1hdGVyaWFscyBmb3IgYWxsIGNvbWJpbmF0aW9ucy4NCg0KYGBge3J9DQp1cHNldDEgPSBleGNsdXNpb25fcmVhc29ucyAlPiUgDQogIHJlbmFtZShgQnJlYXN0ZmVlZGluZ2AgPSBicmVhc3RfZmVlZGluZywgDQogICAgICAgICBgQ2hvaWNlIG9mIENvbnRyYWNlcHRpdmUgTWV0aG9kZWAgPSBjb250cmFjZXB0aXZlX21ldGhvZCwNCiAgICAgICAgIGBNaXNzaW5nIERhdGFgID0gZGlkbnRfZmluaXNoX2luaXRpYWwsDQogICAgICAgICBgSW5jb25ncnVlbnQgSW5mb3JtYXRpb24gYWJvdXQgQ29udHJhY2VwdGl2ZSBNZXRob2RgID0NCiAgICAgICAgICAgaW5jb25ncnVlbnRfaW5mb3JtYXRpb25fYWJvdXRfaG9ybW9uYWxfY29udHJhY2VwdGlvbiwNCiAgICAgICAgIGAoUG9zdC0pTWVub3BhdXNhbGAgPSBtZW5vcGF1c2FsLA0KICAgICAgICAgYFVzaW5nIG5vIENvbnRyYWNlcHRpdmUgTWV0aG9kcyBmb3IgT3RoZXIgUmVhc29uc2AgPSBub19jb250cmFjZXB0aW9uLA0KICAgICAgICAgYE5vdCBGZW1hbGVgID0gbm90X2ZlbWFsZSwNCiAgICAgICAgIGBOb3QgUHJlZG9taW5hbnRseSBIZXRlcm9zZXh1YWxgID0gbm90X2hldGVyb3NleHVhbF9mZW1hbGUsDQogICAgICAgICBgT2xkZXIgdGhhbiA1MGAgPSBvbGRlcl90aGFuXzUwLA0KICAgICAgICAgYFByZWduYW50YCA9IHByZWduYW50LA0KICAgICAgICAgYOKAnFRha2luZyBhIENoYW5jZeKAnSBvZiBCZWNvbWluZyBQcmVnbmFudGAgPSBwcmVnbmFudF9jaGFuY2UsDQogICAgICAgICBgVHJ5aW5nIHRvIEJlY29tZSBQcmVnbmFudGAgPSBwcmVnbmFudF90cnlpbmcsDQogICAgICAgICBgTWVkaWNhdGlvbiBJbmNsdWRpbmcgU2V4IEhvcm1vbmVzYCA9IHNleF9ob3Jtb25lcywNCiAgICAgICAgIGBDdXJyZW50bHkgaW4gYSBIb21vc2V4dWFsIFJlbGF0aW9uc2hpcGAgPSBub25faGV0ZXJvc2V4dWFsX3JlbGF0aW9uc2hpcCkgJT4lDQogIGZpbHRlcihpbmNsdWRlZCA9PSAwKSAlPiUgDQogIHNlbGVjdCgtaW5jbHVkZWQpICU+JSANCiAgYXMuZGF0YS5mcmFtZSgpICU+JQ0KICB7DQogIHVwc2V0KC4sIG5jb2woLiksDQogICAgICAgIDIwLA0KICAgICAgICBvcmRlci5ieSA9ICJmcmVxIiwNCiAgICAgIG1haW4uYmFyLmNvbG9yID0gIiM2RTg2OTEiLA0KICAgICAgbWF0cml4LmNvbG9yID0gIiM2RTg2OTEiLA0KICAgICAgc2V0cy5iYXIuY29sb3IgPSAiIzUzQUM5QiIsDQogICAgICB0ZXh0LnNjYWxlID0gMS4yKQ0KICB9DQp1cHNldDENCg0KanBlZygnRXhjbHVzaW9uIGNyaXRlcmlhIGFuZCBtb3N0IGNvbW1vbiBjb21iaW5hdGlvbnMgb2YgZXhjbHVzaW9uIGNyaXRlcmlhLmpwZycsIA0KICAgICB3aWR0aCA9IDkwMCwgaGVpZ2h0ID0gNDcwLCBxdWFsaXR5ID0gMTAwMCkNCnVwc2V0MQ0KZGV2Lm9mZigpDQpgYGANCg0KIyMjIEZpZ3VyZSBTMTogRXhjbHVzaW9uIGNyaXRlcmlhIGFuZCBhbGwgY29tYmluYXRpb25zIG9mIGV4Y2x1c2lvbiBjcml0ZXJpYS4gDQpUaGUgaG9yaXpvbnRhbCBncmVlbiBiYXJzIHNob3cgZm9yIGhvdyBtYW55IHdvbWVuIHRoaXMgZXhjbHVzaW9uIGNyaXRlcmlhIGFwcGxpZXMuIFRoZSBibHVlIGJhcnMgc2hvdyBob3cgbWFueSB3b21lbiBhcmUgZXhjbHVkZWQgZm9yIG11bHRpcGxlIHJlYXNvbnMgKGUuZy4sIG5vdCBmaW5pc2hpbmcgdGhlIGluaXRpYWwgc3VydmV5IGFuZCBiZWluZyBwcmVnbmFudCkuIEFsbCA1MiBjb21iaW5hdGlvbnMgb2YgZXhjbHVzaW9uIGNyaXRlcmlhIGFyZSBkaXNwbGF5ZWQuIA0KDQpgYGB7cn0NCnVwc2V0MiA9IGV4Y2x1c2lvbl9yZWFzb25zICU+JSANCiAgcmVuYW1lKGBCcmVhc3RmZWVkaW5nYCA9IGJyZWFzdF9mZWVkaW5nLCANCiAgICAgICAgIGBDaG9pY2Ugb2YgQ29udHJhY2VwdGl2ZSBNZXRob2RlYCA9IGNvbnRyYWNlcHRpdmVfbWV0aG9kLA0KICAgICAgICAgYE1pc3NpbmcgRGF0YWAgPSBkaWRudF9maW5pc2hfaW5pdGlhbCwNCiAgICAgICAgIGBJbmNvbmdydWVudCBJbmZvcm1hdGlvbiBhYm91dCBDb250cmFjZXB0aXZlIE1ldGhvZGAgPQ0KICAgICAgICAgICBpbmNvbmdydWVudF9pbmZvcm1hdGlvbl9hYm91dF9ob3Jtb25hbF9jb250cmFjZXB0aW9uLA0KICAgICAgICAgYChQb3N0LSlNZW5vcGF1c2FsYCA9IG1lbm9wYXVzYWwsDQogICAgICAgICBgVXNpbmcgbm8gQ29udHJhY2VwdGl2ZSBNZXRob2RzIGZvciBPdGhlciBSZWFzb25zYCA9IG5vX2NvbnRyYWNlcHRpb24sDQogICAgICAgICBgTm90IEZlbWFsZWAgPSBub3RfZmVtYWxlLA0KICAgICAgICAgYE5vdCBQcmVkb21pbmFudGx5IEhldGVyb3NleHVhbGAgPSBub3RfaGV0ZXJvc2V4dWFsX2ZlbWFsZSwNCiAgICAgICAgIGBPbGRlciB0aGFuIDUwYCA9IG9sZGVyX3RoYW5fNTAsDQogICAgICAgICBgUHJlZ25hbnRgID0gcHJlZ25hbnQsDQogICAgICAgICBg4oCcVGFraW5nIGEgQ2hhbmNl4oCdIG9mIEJlY29taW5nIFByZWduYW50YCA9IHByZWduYW50X2NoYW5jZSwNCiAgICAgICAgIGBUcnlpbmcgdG8gQmVjb21lIFByZWduYW50YCA9IHByZWduYW50X3RyeWluZywNCiAgICAgICAgIGBNZWRpY2F0aW9uIEluY2x1ZGluZyBTZXggSG9ybW9uZXNgID0gc2V4X2hvcm1vbmVzLA0KICAgICAgICAgYEN1cnJlbnRseSBpbiBhIEhvbW9zZXh1YWwgUmVsYXRpb25zaGlwYCA9IG5vbl9oZXRlcm9zZXh1YWxfcmVsYXRpb25zaGlwKSAlPiUNCiAgZmlsdGVyKGluY2x1ZGVkID09IDApICU+JSANCiAgc2VsZWN0KC1pbmNsdWRlZCkgJT4lIA0KICBhcy5kYXRhLmZyYW1lKCkgJT4lIA0KICB7DQogIHVwc2V0KC4sIG5jb2woLiksIDgwLCBvcmRlci5ieSA9ICJmcmVxIiwNCiAgICAgIG1haW4uYmFyLmNvbG9yID0gIiM2RTg2OTEiLA0KICAgICAgbWF0cml4LmNvbG9yID0gIiM2RTg2OTEiLA0KICAgICAgc2V0cy5iYXIuY29sb3IgPSAiIzUzQUM5QiIsDQogICAgICB0ZXh0LnNjYWxlID0gMS4yKQ0KICB9DQp1cHNldDINCg0KanBlZygnRXhjbHVzaW9uIGNyaXRlcmlhIGFuZCBhbGwgY29tYmluYXRpb25zIG9mIGV4Y2x1c2lvbiBjcml0ZXJpYS5qcGcnLCANCiAgICAgd2lkdGggPSA5MDAsIGhlaWdodCA9IDUwMCwgcXVhbGl0eSA9IDEwMDApDQp1cHNldDINCmRldi5vZmYoKQ0KYGBgDQoNCg0KDQojIyBFeGx1c2lvbiBTdGVwcyBEaWFyeSB7LnRhYnNldH0NClRvIGNhbGN1bGF0ZSBMaWJpZG8gYW5kIFNleHVhbCBGcmVxdWVuY3kgd2UgbmVlZCBJbmZvcm1hdGlvbiBmcm9tIHRoZSBkaWFyeS4gVGhlcmVmb3JlLCB0d28gYWRkaXRpb25hbCBleGx1c2lvbiByZWFzb25zIGZvciB0aGUgZGlhcnkgYXBwbHk6DQoNCiogU2tpcHBpbmcgYSBkaWFyeSBkYXkNCiogRGlzaG9uZXN0IGFuc3dlcnMgb24gdGhhdCBkYXkNCg0KYGBge3J9DQpkaWFyeSA9IGRpYXJ5ICU+JSBsZWZ0X2pvaW4oYWxsX3N1cnZleXMgJT4lIHNlbGVjdChzZXNzaW9uLCByZWFzb25zX2Zvcl9leGNsdXNpb24pLCBieSA9ICdzZXNzaW9uJykNCmBgYA0KDQoNCiMjIyBTa2lwcGVkIHRoaXMgZGlhcnkgZGF5IChkYXlzIGFmdGVyIGRyb3BwaW5nIG91dCBub3QgaW5jbHVkZWQpDQpgYGB7cn0NCmRpYXJ5ID0gZGlhcnkgJT4lIA0KICBtdXRhdGUocmVhc29uc19mb3JfZXhjbHVzaW9uID0gc3RyX2MocmVhc29uc19mb3JfZXhjbHVzaW9uLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZl9lbHNlKGlzLm5hKGVuZGVkX2RpYXJ5KSAmIGlzLm5hKG1vZGlmaWVkX2RpYXJ5KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2tpcHBlZF9kaWFyeV9lbnRyeSwgIiwgIiIpKSkNCg0KdGFibGUoZGlhcnkkcmVhc29uc19mb3JfZXhjbHVzaW9uICVjb250YWlucyUgInNraXBwZWRfZGlhcnlfZW50cnkiKQ0KYGBgDQoNCg0KIyMjIERpc2Nsb3NlZCB0aGF0IHRoZXkgcmVzcG9uZGVkIGRpc2hvbmVzdGx5IG9uIHRoYXQgZGF5Lg0KYGBge3J9DQpkaWFyeSA9IGRpYXJ5ICU+JSANCiAgbXV0YXRlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9IHN0cl9jKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZfZWxzZShkaXNob25lc3RfZGlzY2FyZCA9PSAxLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJkaXNob25lc3RfYW5zd2VyLCAiLCAiIiwgIiIpKSkNCg0KdGFibGUoZGlhcnkkcmVhc29uc19mb3JfZXhjbHVzaW9uICVjb250YWlucyUgImRpc2hvbmVzdF9hbnN3ZXIiKQ0KYGBgDQoNCiMjIENyZWF0ZSBpbmNsdWRlZCB2YXJpYWJsZQ0KYGBge3J9DQphbGxfc3VydmV5cyA9IGFsbF9zdXJ2ZXlzICU+JQ0KICBtdXRhdGUoaW5jbHVkZWQgPSBpZl9lbHNlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9PSAiIiwgVFJVRSwgRkFMU0UpKQ0KDQpkaWFyeSA9IGRpYXJ5ICU+JQ0KICBtdXRhdGUoaW5jbHVkZWQgPSBpZl9lbHNlKHJlYXNvbnNfZm9yX2V4Y2x1c2lvbiA9PSAiIiwgVFJVRSwgRkFMU0UpKQ0KYGBgDQoNCg0KIyMgU2F2ZQ0KYGBge3J9DQpsaWJyYXJ5KHRlc3R0aGF0KQ0KZXhwZWN0X2VxdWFsKG5yb3coZGlhcnkpLCBkaWFyeV9sZW5ndGgpDQpleHBlY3RfZXF1YWwobnJvdyhhbGxfc3VydmV5cyksIGFsbF9zdXJ2ZXlfbGVuZ3RoKQ0KDQpzYXZlKGRpYXJ5LCBhbGxfc3VydmV5cywgZmlsZSA9ICJkYXRhL2NsZWFuZWRfc2VsZWN0ZWQucmRhdGEiKQ0KYGBgIA0K