From 45f59befdfea023d017552960caf63355af115ba Mon Sep 17 00:00:00 2001 From: Brad Cannell Date: Fri, 21 Feb 2020 20:06:55 -0600 Subject: [PATCH] Changes to data_medstar_epcr_02_variable_management.Rmd - Part of #27 - Replaced spaces with underscores in address street name. - Deleted data_medstar_epcr_02_variable_management.nb.html. It's unnecissary and just takes up extra space. - Saved medstar_epcr_02_variable_management.rds as RDS instead of Feather. It doesn't seem like Feather ever really caught on. --- .gitignore | 2 + ...ta_medstar_epcr_02_variable_management.Rmd | 139 +-- ...edstar_epcr_02_variable_management.nb.html | 873 ------------------ 3 files changed, 31 insertions(+), 983 deletions(-) delete mode 100644 markdown/data_medstar_epcr_02_variable_management.nb.html diff --git a/.gitignore b/.gitignore index 21045d5..57c4cb3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ markdown/pairs_possible_matches.rds markdown/rpairs_epiwt.rds markdown/rpairs_jar.rds + +NOTES.txt diff --git a/markdown/data_medstar_epcr_02_variable_management.Rmd b/markdown/data_medstar_epcr_02_variable_management.Rmd index 97144eb..8837e9c 100644 --- a/markdown/data_medstar_epcr_02_variable_management.Rmd +++ b/markdown/data_medstar_epcr_02_variable_management.Rmd @@ -1,11 +1,6 @@ --- title: "Manage Variables in MedStar EPCR Data" date: "Created: 2018-12-26
Updated: `r Sys.Date()`" -output: - html_notebook: - toc: true - toc_float: true - css: custom-css.css --- # Overview @@ -24,28 +19,21 @@ Sys.setenv(TZ = "US/Central") ```{r message=FALSE} library(tidyverse) -library(bfuncs) ``` medstar_epcr.feather was created in data_medstar_epcr_01_import.Rmd -```{r} -medstar_epcr <- feather::read_feather("/Volumes/sph_research/DETECT/one_year_data/medstar_epcr_01_import.feather") +```{bash} +open 'smb://uctnascifs.uthouston.edu/sph_research/DETECT' ``` ```{r} -about_data(medstar_epcr) # 35,557 observations and 32 variables +medstar_epcr <- feather::read_feather("/Volumes/DETECT/one_year_data/medstar_epcr_01_import.feather") ``` -[top](#top) - - - - - - - - +```{r} +dim(medstar_epcr) # 35,557 32 +``` # Standardize character strings @@ -72,14 +60,6 @@ rm(vars) [top](#top) - - - - - - - - # Remove "city of" from address_city value ```{r} @@ -90,14 +70,6 @@ medstar_epcr <- medstar_epcr %>% [top](#top) - - - - - - - - # Separate names, dob's, and street addresses * Some names have three parts (e.g., Mary Jo Blake). Here, we split up full name into first name and last name. For now, we ignore middle name(s). We may need to change this later. @@ -119,19 +91,18 @@ medstar_epcr <- medstar_epcr %>% ) ``` +Replaces spaces with underscores in address street name. + ```{r} -about_data(medstar_epcr) # 35,557 observations and 39 variables +medstar_epcr <- medstar_epcr %>% + mutate( + address_street_name = stringr::str_replace_all(address_street_name, "\\s", "_") + ) ``` -[top](#top) - - - - - - - - +```{r} +dim(medstar_epcr) # 35,557 39 +``` # Recode categories @@ -158,9 +129,7 @@ medstar_epcr <- medstar_epcr %>% ) %>% mutate_at( vars(starts_with("detect")), - funs( - if_else(. == "N/A", NA_character_, .) - ) + ~ if_else(. == "N/A", NA_character_, .) ) ``` @@ -185,19 +154,9 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 35,557 observations and 40 variables +dim(medstar_epcr) # 35,557 40 ``` -[top](#top) - - - - - - - - - # Create indicator for completed DETECT screening @@ -216,19 +175,9 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 35,557 observations and 56 variables +dim(medstar_epcr) # 35,557 56 ``` -[top](#top) - - - - - - - - - # Process numeric variables @@ -240,19 +189,9 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 35,557 observations and 56 variables +dim(medstar_epcr) # 35,557 56 ``` -[top](#top) - - - - - - - - - # Duplicate (almost) rows @@ -282,7 +221,7 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 35,557 observations and 57 variables +dim(medstar_epcr) # 35,557 57 ``` How many pairs of duplicate pcr numbers are there? @@ -302,14 +241,14 @@ For each of those pcr numbers, if the only thing that differs between the two ro So, for each variable of interest, create a dummy variable that indicates if if values are different within incident pcr number ```{r} -medstar_epcr <- medstar_epcr %>% +medstar_epcr <- medstar_epcr %>% mutate_at( .vars = vars( arrival_time, response_num, incident_pcr, incident_complaint, age, name_full, dob, address_street, address_city, address_state, address_zip, gender, race, symptoms, crew_sig, disposition ), - .funs = funs(diff = as.numeric(length(unique(.)) > 1)) + .funs = list(diff = ~ as.numeric(length(unique(.)) > 1)) ) %>% ungroup() ``` @@ -325,8 +264,8 @@ medstar_epcr <- medstar_epcr %>% ```{r} # Data checking -# medstar_epcr %>% -# filter(pcr_dup) %>% +# medstar_epcr %>% +# filter(pcr_dup) %>% # select(incident_pcr, pcr_dup, ends_with("_diff"), aps_report, answered_count, diff_count) ``` @@ -365,7 +304,7 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 35,556 observations and 58 variables +dim(medstar_epcr) # 35,556 58 ``` @@ -389,7 +328,7 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 35,555 observations and 58 variables +dim(medstar_epcr) # 35,555 58 ``` @@ -449,39 +388,19 @@ medstar_epcr <- medstar_epcr %>% ``` ```{r} -about_data(medstar_epcr) # 28,228 observations and 56 variables +dim(medstar_epcr) # 28,228 56 ``` -[top](#top) - - - - - - - - - # Save data ```{r} -feather::write_feather( +readr::write_rds( medstar_epcr, - "/Volumes/sph_research/Detect/one_year_data/medstar_epcr_02_variable_management.feather" + "/Volumes/DETECT/one_year_data/medstar_epcr_02_variable_management.rds" ) ``` -[top](#top) - - - - - - - - - # Session information diff --git a/markdown/data_medstar_epcr_02_variable_management.nb.html b/markdown/data_medstar_epcr_02_variable_management.nb.html deleted file mode 100644 index b449660..0000000 --- a/markdown/data_medstar_epcr_02_variable_management.nb.html +++ /dev/null @@ -1,873 +0,0 @@ - - - - - - - - - - - - - -Manage Variables in MedStar EPCR Data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - -
-
-
-
-
- -
- - - - - - - - -
-

Overview

-
    -
  • The raw MedStar epcr data was imported in data_medstar_epcr_01_import.Rmd

  • -
  • In this file we prepare the data for analysis

  • -
-
-
-

Load packages and data

- - - - - -
library(tidyverse)
-library(bfuncs)
- - - -

medstar_epcr.feather was created in data_medstar_epcr_01_import.Rmd

- - - -
medstar_epcr <- feather::read_feather("/Volumes/sph_research/DETECT/one_year_data/medstar_epcr_01_import.feather")
- - - - - - -
about_data(medstar_epcr) # 35,557 observations and 32 variables
- - -
[1] "35,557 observations and 32 variables"
- - - -

top

-
-
-

Standardize character strings

-

Because we will merge this data with other data sets in the future based on character strings (e.g., name), we need to go ahead and standardize their formats here. This will prevent mismatches during the merges. Specifically, we:

-
    -
  1. Transform all characters to lower case
    -
  2. -
  3. Remove any special characters (e.g., hyphens, periods)
    -
  4. -
  5. Remove trailing spaces (e.g., “John Smith”)
    -
  6. -
  7. Remove double spaces (e.g., “John Smith”)
  8. -
- - - -
vars <- quos(name_full, address_street, address_city, address_state)
-medstar_epcr <- medstar_epcr %>% 
-  mutate_at(vars(!!! vars), tolower) %>% 
-  mutate_at(vars(!!! vars), stringr::str_replace_all, "[^a-zA-Z\\d\\s]", " ") %>%
-  mutate_at(vars(!!! vars), stringr::str_replace, "[[:blank:]]$", "") %>% 
-  mutate_at(vars(!!! vars), stringr::str_replace_all, "[[:blank:]]{2,}", " ")
-rm(vars)
- - - -

top

-
-
-

Remove “city of” from address_city value

- - - -
medstar_epcr <- medstar_epcr %>% 
-  mutate(address_city = stringr::str_replace(address_city, "city of ", ""))
- - - -

top

-
-
-

Separate names, dob’s, and street addresses

-
    -
  • Some names have three parts (e.g., Mary Jo Blake). Here, we split up full name into first name and last name. For now, we ignore middle name(s). We may need to change this later.

  • -
  • We also separate dob into its component parts: month, day, year.

  • -
  • We also separate the street address into the number part and the street name part

  • -
- - - -
medstar_epcr <- medstar_epcr %>%
-  mutate(
-    name_first          = stringr::str_extract(name_full, "\\w+(?=[[:blank:]])"),
-    name_last           = stringr::str_extract(name_full, "\\S*$"),
-    birth_mnth          = lubridate::month(dob),
-    birth_day           = lubridate::day(dob),
-    birth_year          = lubridate::year(dob),
-    address_num         = stringr::str_extract(address_street, "^\\d{1,5}") %>% as.numeric(),
-    address_street_name = stringr::str_trim(str_replace(address_street, "^\\d{1,5}", ""))
-  )
- - - - - - -
about_data(medstar_epcr) # 35,557 observations and 39 variables
- - -
[1] "35,557 observations and 39 variables"
- - - -

top

-
-
-

Recode categories

-
    -
  • For select variables, recode variants of missing data (e.g. “Unknown”) to NA

  • -
  • For select variables collapse categories

  • -
-
-

Missing

- - - -
medstar_epcr <- medstar_epcr %>%
-  mutate(
-    gender = case_when(
-      gender == "Unknown (Unable to Determine)" ~ NA_character_,
-      gender == "Not Applicable"                ~ NA_character_,
-      TRUE                                      ~ gender
-    ),
-    race = case_when(
-      race == "Not Applicable" ~ NA_character_,
-      race == "Not Recorded"   ~ NA_character_,
-      TRUE                     ~ race
-    )
-  ) %>% 
-  mutate_at(
-    vars(starts_with("detect")),
-    funs(
-      if_else(. == "N/A", NA_character_, .)
-    )
-  )
- - - -
-
-

Collapse categories

- - - -
medstar_epcr <- medstar_epcr %>% 
-  mutate(
-    race_8cat = case_when(
-      race == "American Indian or Alaska Native"          ~ "American Indian or Alaska Native - non-Hispanic",
-      race == "Asian"                                     ~ "Asian - non-Hispanic",
-      race == "Black or African American"                 ~ "Black or African American - non-Hispanic",
-      race == "Hispanic or Latino"                        ~ "Hispanic or Latino, Any Race",
-      race == "Native Hawaiian or Other Pacific Islander" ~ "Native Hawaiian or Other Pacific Islander - non-Hispanic",
-      race == "White"                                     ~ "White - non-Hispanic",
-      stringr::str_detect(race, "Hispanic")               ~ "Hispanic or Latino, Any Race",
-      is.na(race)                                         ~ NA_character_,
-      TRUE                                                ~ "Other Race - non-Hispanic"
-    )
-  )
- - - - - - -
about_data(medstar_epcr) # 35,557 observations and 40 variables
- - -
[1] "35,557 observations and 40 variables"
- - - -

top

-
-
-
-

Create indicator for completed DETECT screening

- - - -
medstar_epcr <- medstar_epcr %>% 
-  mutate_at(
-    .vars = vars(starts_with("detect_")),
-    .funs = funs(answered = !is.na(.))
-  ) %>% 
-  mutate(
-    answered_count = select(., ends_with("answered")) %>% rowSums()
-  ) %>% 
-  mutate(
-    screened = answered_count > 0
-  )
- - - - - - -
about_data(medstar_epcr) # 35,557 observations and 56 variables
- - -
[1] "35,557 observations and 56 variables"
- - - -

top

-
-
-

Process numeric variables

-

All numerical variables must be class numeric – as opposed to integer – to work in fastLink below.

- - - -
medstar_epcr <- medstar_epcr %>% 
-  mutate_if(is.integer, as.numeric)
- - - - - - -
about_data(medstar_epcr) # 35,557 observations and 56 variables
- - -
[1] "35,557 observations and 56 variables"
- - - -

top

-
-
-

Duplicate (almost) rows

-

There were some rows with the same pcr number and only differed by whether or not DETECT screenings were completed.

- - - -
# Data checks
-# Multiple pcr's per response? Yes
-# medstar_epcr %>% 
-#   group_by(response_num) %>% 
-#   summarise(n = length(unique(incident_pcr))) %>% 
-#   filter(n > 1)
-# Multiple responses per pcr? No
-# medstar_epcr %>% 
-#   group_by(incident_pcr) %>% 
-#   summarise(n = length(unique(response_num))) %>% 
-#   filter(n > 1)
- - - -

Add a dummy variable that indicates whether or not the pcr number is duplicated

- - - -
medstar_epcr <- medstar_epcr %>% 
-  group_by(incident_pcr) %>% 
-  mutate(pcr_dup = max(row_number()) > 1)
- - - - - - -
about_data(medstar_epcr) # 35,557 observations and 57 variables
- - -
[1] "35,557 observations and 57 variables"
- - - -

How many pairs of duplicate pcr numbers are there?

- - - -
medstar_epcr %>% 
-  group_by(incident_pcr) %>% 
-  summarise(duplicate_pairs = any(pcr_dup == TRUE)) %>% 
-  pull(duplicate_pairs) %>% 
-  sum() # 7,282
- - -
[1] 7282
- - - -

There are 7,282 incident pcr numbers that are duplicated in the data.

-

For each of those pcr numbers, if the only thing that differs between the two rows is that one has the DETECT tool filled out and the other doesn’t, then we only want to keep the row with the DETECT screening information.

-

So, for each variable of interest, create a dummy variable that indicates if if values are different within incident pcr number

- - - -
medstar_epcr <- medstar_epcr %>% 
-  mutate_at(
-    .vars = vars(
-      arrival_time, response_num, incident_pcr, incident_complaint, age, 
-      name_full, dob, address_street, address_city, address_state,
-      address_zip, gender, race, symptoms, crew_sig, disposition
-    ),
-    .funs = funs(diff = as.numeric(length(unique(.)) > 1))
-  ) %>% 
-  ungroup()
- - - -

Now, count the total number of differences between rows (within incident pcr number) for the variables above

- - - -
medstar_epcr <- medstar_epcr %>% 
-  mutate(
-    diff_count = select(., ends_with("_diff")) %>% rowSums()
-  )
- - - - - - -
# Data checking
-# medstar_epcr %>% 
-#   filter(pcr_dup) %>% 
-#   select(incident_pcr, pcr_dup, ends_with("_diff"), aps_report, answered_count, diff_count)
- - - -
-

Add row numbers

-

Below we will need to drop selected rows from the data. Adding row numbers to the data set here will make it easier to do so without using any potential personal identifiers to filter the data.

- - - -
medstar_epcr <- medstar_epcr %>% mutate(row = row_number()) %>% select(row, everything())
- - - -
-
-

Check: Differences

-

Are there any cases where there is a duplicated incident pcr number and there are differences between the values in the rows other than DETECT screenings? Results are hidden to protect participant privacy.

- - - -
medstar_epcr %>% 
-  filter(pcr_dup & diff_count > 0)
- - - -

Yes. There is one duplicated incident pcr with differing information between rows for race (row 16530 = White, row 16531 = Missing) and disposition (row 16530 = Transported, row 16531 = Canceled False Call). Additionally, row 16530 has a completed DETECT screening. Therefore, we will drop row 16531 and change pcr_dup to FALSE for row 16530.

- - - -
medstar_epcr <- medstar_epcr %>% 
-  filter(row != 16531) %>% 
-  mutate(pcr_dup = if_else(row == 16530, FALSE, pcr_dup))
- - - -

At this point, all remaining duplicate incident pcr numbers have identical values for each of the variables compared above and diff_counts of 0. There is no need to keep those variables in the data.

- - - -
medstar_epcr <- medstar_epcr %>% 
-  select(-ends_with("_diff"), -diff_count)
- - - - - - -
about_data(medstar_epcr) # 35,556 observations and 58 variables
- - -
[1] "35,556 observations and 58 variables"
- - - -
-
-

Check: No DETECT answers

-

Are there any cases where there is a duplicated incident pcr number and answered count is 0 for all rows? Results are hidden to protect participant privacy.

- - - -
medstar_epcr %>%
-  filter(pcr_dup) %>%
-  group_by(incident_pcr) %>%
-  filter(all(answered_count == 0))
- - - -

Yes, there is one such incident pcr number. The only difference between the two rows is that the value for aps_report_num in row 4467 is “homeless” and missing in row 4468. Therefore, we will drop row 4468 and change pcr_dup to FALSE for 4467.

- - - -
medstar_epcr <- medstar_epcr %>% 
-  filter(row != 4468) %>% 
-  mutate(pcr_dup = if_else(row == 4467, FALSE, pcr_dup))
- - - - - - -
about_data(medstar_epcr) # 35,555 observations and 58 variables
- - -
[1] "35,555 observations and 58 variables"
- - - -
-
-

Check: Conflicting DETECT answers

-

Are there any cases where there is a duplicated incident pcr number and answered counts differ, but the answered count is not 0 for any of the rows. In other words, a different number of screening items was answered. Results are hidden to protect participant privacy.

- - - -
medstar_epcr %>% 
-  filter(pcr_dup) %>% 
-  group_by(incident_pcr) %>% 
-  filter(!any(answered_count == 0)) %>% 
-  ungroup() %>% 
-  # I already know there are no differences in name etc. We cleaned that up
-  # above.
-  select(row, name_full, crew_sig, aps_report_num, aps_report, 
-         starts_with("detect_"), answered_count, -ends_with("_answered"))
- - - -

Yes, there are 130 rows (63 unique incident pcr numbers) where more than one row has the DETECT screening filled out.

-

There doesn’t appear to be an systematic differences between the rows. For example, the first row in a pair is always more complete or something like that. Therefore, we’re going to filter in stages in such a way as to maximize information retention.

-
    -
  1. Keep the row with the highest answered count
    -
  2. -
  3. If there is a tie for highest answered count, keep row with aps report number
    -
  4. -
  5. If there is a tie for highest answered count and both rows have an aps report number, then arbitrarily keep the first row.
  6. -
- - - -
medstar_epcr <- medstar_epcr %>%
-  arrange(desc(pcr_dup), incident_pcr, desc(answered_count), aps_report_num) %>% 
-  group_by(incident_pcr) %>% 
-  mutate(
-    group_row = row_number(),
-    keep_row = group_row == 1
-  ) %>% 
-  ungroup() %>% 
-  arrange(row)
- - - -

NOTE: If there is only one row for a given incident pcr number, then it will always have keep_row == 1.

- - - -
# Data checks
-# medstar_epcr %>% 
-#   filter(pcr_dup) %>%
-#   select(row, row, incident_pcr, group_row, keep_row, answered_count, aps_report_num) %>% 
-#   group_by(incident_pcr) %>% 
-#   filter(any(group_row > 2))
- - - -

Drop duplicate rows and unneeded variables

- - - -
medstar_epcr <- medstar_epcr %>% 
-  filter(keep_row) %>% 
-  select(-row, -pcr_dup, -group_row, -keep_row)
- - - - - - -
about_data(medstar_epcr) # 28,228 observations and 56 variables
- - -
[1] "28,228 observations and 56 variables"
- - - -

top

-
-
-
-

Save data

- - - -
feather::write_feather(
-  medstar_epcr, 
-  "/Volumes/sph_research/Detect/one_year_data/medstar_epcr_02_variable_management.feather"
-)
- - - -

top

-
-
-

Session information

- - - -
rm(list = ls())
- - - - - - -
R version 3.5.1 (2018-07-02)
-Platform: x86_64-apple-darwin15.6.0 (64-bit)
-Running under: macOS  10.14.2
-
-Matrix products: default
-BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
-LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRlapack.dylib
-
-locale:
-[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
-
-attached base packages:
-[1] stats     graphics  grDevices utils     datasets  methods   base     
-
-other attached packages:
- [1] bindrcpp_0.2.2  bfuncs_0.2.1    forcats_0.3.0   stringr_1.3.1   dplyr_0.7.8     purrr_0.2.5    
- [7] readr_1.1.1     tidyr_0.8.2     tibble_1.4.2    ggplot2_3.1.0   tidyverse_1.2.1
-
-loaded via a namespace (and not attached):
- [1] Rcpp_1.0.0       cellranger_1.1.0 pillar_1.3.0     compiler_3.5.1   plyr_1.8.4       bindr_0.1.1     
- [7] tools_3.5.1      packrat_0.4.9-3  jsonlite_1.5     lubridate_1.7.4  nlme_3.1-137     gtable_0.2.0    
-[13] lattice_0.20-35  pkgconfig_2.0.2  rlang_0.3.0.1    cli_1.0.1        rstudioapi_0.8   yaml_2.2.0      
-[19] haven_1.1.2      withr_2.1.2      xml2_1.2.0       httr_1.3.1       knitr_1.20       hms_0.4.2       
-[25] grid_3.5.1       tidyselect_0.2.5 glue_1.3.0       R6_2.3.0         readxl_1.1.0     feather_0.3.1   
-[31] modelr_0.1.2     magrittr_1.5     backports_1.1.2  scales_1.0.0     rvest_0.3.2      assertthat_0.2.0
-[37] colorspace_1.3-2 stringi_1.2.4    lazyeval_0.2.1   munsell_0.5.0    broom_0.5.0      crayon_1.3.4    
- - -
- -
LS0tCnRpdGxlOiAiTWFuYWdlIFZhcmlhYmxlcyBpbiBNZWRTdGFyIEVQQ1IgRGF0YSIKZGF0ZTogIkNyZWF0ZWQ6IDIwMTgtMTItMjYgPGJyPiBVcGRhdGVkOiBgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNzczogY3VzdG9tLWNzcy5jc3MKLS0tCgojIE92ZXJ2aWV3CgoqIFRoZSByYXcgTWVkU3RhciBlcGNyIGRhdGEgd2FzIGltcG9ydGVkIGluIGRhdGFfbWVkc3Rhcl9lcGNyXzAxX2ltcG9ydC5SbWQKCiogSW4gdGhpcyBmaWxlIHdlIHByZXBhcmUgdGhlIGRhdGEgZm9yIGFuYWx5c2lzCgoKIyBMb2FkIHBhY2thZ2VzIGFuZCBkYXRhCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGNvbW1lbnQgPSBOQSkKU3lzLnNldGVudihUWiA9ICJVUy9DZW50cmFsIikKYGBgCgpgYGB7ciBtZXNzYWdlPUZBTFNFfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShiZnVuY3MpCmBgYAoKbWVkc3Rhcl9lcGNyLmZlYXRoZXIgd2FzIGNyZWF0ZWQgaW4gZGF0YV9tZWRzdGFyX2VwY3JfMDFfaW1wb3J0LlJtZAoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBmZWF0aGVyOjpyZWFkX2ZlYXRoZXIoIi9Wb2x1bWVzL3NwaF9yZXNlYXJjaC9ERVRFQ1Qvb25lX3llYXJfZGF0YS9tZWRzdGFyX2VwY3JfMDFfaW1wb3J0LmZlYXRoZXIiKQpgYGAKCmBgYHtyfQphYm91dF9kYXRhKG1lZHN0YXJfZXBjcikgIyAzNSw1NTcgb2JzZXJ2YXRpb25zIGFuZCAzMiB2YXJpYWJsZXMKYGBgCgpbdG9wXSgjdG9wKQoKCgoKCgoKCgoKIyBTdGFuZGFyZGl6ZSBjaGFyYWN0ZXIgc3RyaW5ncwoKQmVjYXVzZSB3ZSB3aWxsIG1lcmdlIHRoaXMgZGF0YSB3aXRoIG90aGVyIGRhdGEgc2V0cyBpbiB0aGUgZnV0dXJlIGJhc2VkIG9uIGNoYXJhY3RlciBzdHJpbmdzIChlLmcuLCBuYW1lKSwgd2UgbmVlZCB0byBnbyBhaGVhZCBhbmQgc3RhbmRhcmRpemUgdGhlaXIgZm9ybWF0cyBoZXJlLiBUaGlzIHdpbGwgcHJldmVudCBtaXNtYXRjaGVzIGR1cmluZyB0aGUgbWVyZ2VzLiBTcGVjaWZpY2FsbHksIHdlOgoKMS4gVHJhbnNmb3JtIGFsbCBjaGFyYWN0ZXJzIHRvIGxvd2VyIGNhc2UgICAKMi4gUmVtb3ZlIGFueSBzcGVjaWFsIGNoYXJhY3RlcnMgKGUuZy4sIGh5cGhlbnMsIHBlcmlvZHMpICAgCjMuIFJlbW92ZSB0cmFpbGluZyBzcGFjZXMgKGUuZy4sICJKb2huIFNtaXRoICIpICAgCjQuIFJlbW92ZSBkb3VibGUgc3BhY2VzIChlLmcuLCAiSm9obiAgU21pdGgiKSAgIAoKYGBge3J9CnZhcnMgPC0gcXVvcyhuYW1lX2Z1bGwsIGFkZHJlc3Nfc3RyZWV0LCBhZGRyZXNzX2NpdHksIGFkZHJlc3Nfc3RhdGUpCgptZWRzdGFyX2VwY3IgPC0gbWVkc3Rhcl9lcGNyICU+JSAKICBtdXRhdGVfYXQodmFycyghISEgdmFycyksIHRvbG93ZXIpICU+JSAKICBtdXRhdGVfYXQodmFycyghISEgdmFycyksIHN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbCwgIlteYS16QS1aXFxkXFxzXSIsICIgIikgJT4lCiAgbXV0YXRlX2F0KHZhcnMoISEhIHZhcnMpLCBzdHJpbmdyOjpzdHJfcmVwbGFjZSwgIltbOmJsYW5rOl1dJCIsICIiKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoISEhIHZhcnMpLCBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwsICJbWzpibGFuazpdXXsyLH0iLCAiICIpCgpybSh2YXJzKQpgYGAKClt0b3BdKCN0b3ApCgoKCgoKCgoKCgojIFJlbW92ZSAiY2l0eSBvZiIgZnJvbSBhZGRyZXNzX2NpdHkgdmFsdWUgCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgCiAgbXV0YXRlKGFkZHJlc3NfY2l0eSA9IHN0cmluZ3I6OnN0cl9yZXBsYWNlKGFkZHJlc3NfY2l0eSwgImNpdHkgb2YgIiwgIiIpKQpgYGAKClt0b3BdKCN0b3ApCgoKCgoKCgoKCgojIFNlcGFyYXRlIG5hbWVzLCBkb2IncywgYW5kIHN0cmVldCBhZGRyZXNzZXMKCiogU29tZSBuYW1lcyBoYXZlIHRocmVlIHBhcnRzIChlLmcuLCBNYXJ5IEpvIEJsYWtlKS4gSGVyZSwgd2Ugc3BsaXQgdXAgZnVsbCBuYW1lIGludG8gZmlyc3QgbmFtZSBhbmQgbGFzdCBuYW1lLiBGb3Igbm93LCB3ZSBpZ25vcmUgbWlkZGxlIG5hbWUocykuIFdlIG1heSBuZWVkIHRvIGNoYW5nZSB0aGlzIGxhdGVyLgoKKiBXZSBhbHNvIHNlcGFyYXRlIGRvYiBpbnRvIGl0cyBjb21wb25lbnQgcGFydHM6IG1vbnRoLCBkYXksIHllYXIuCgoqIFdlIGFsc28gc2VwYXJhdGUgdGhlIHN0cmVldCBhZGRyZXNzIGludG8gdGhlIG51bWJlciBwYXJ0IGFuZCB0aGUgc3RyZWV0IG5hbWUgcGFydAoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBtZWRzdGFyX2VwY3IgJT4lCiAgbXV0YXRlKAogICAgbmFtZV9maXJzdCAgICAgICAgICA9IHN0cmluZ3I6OnN0cl9leHRyYWN0KG5hbWVfZnVsbCwgIlxcdysoPz1bWzpibGFuazpdXSkiKSwKICAgIG5hbWVfbGFzdCAgICAgICAgICAgPSBzdHJpbmdyOjpzdHJfZXh0cmFjdChuYW1lX2Z1bGwsICJcXFMqJCIpLAogICAgYmlydGhfbW50aCAgICAgICAgICA9IGx1YnJpZGF0ZTo6bW9udGgoZG9iKSwKICAgIGJpcnRoX2RheSAgICAgICAgICAgPSBsdWJyaWRhdGU6OmRheShkb2IpLAogICAgYmlydGhfeWVhciAgICAgICAgICA9IGx1YnJpZGF0ZTo6eWVhcihkb2IpLAogICAgYWRkcmVzc19udW0gICAgICAgICA9IHN0cmluZ3I6OnN0cl9leHRyYWN0KGFkZHJlc3Nfc3RyZWV0LCAiXlxcZHsxLDV9IikgJT4lIGFzLm51bWVyaWMoKSwKICAgIGFkZHJlc3Nfc3RyZWV0X25hbWUgPSBzdHJpbmdyOjpzdHJfdHJpbShzdHJfcmVwbGFjZShhZGRyZXNzX3N0cmVldCwgIl5cXGR7MSw1fSIsICIiKSkKICApCmBgYAoKYGBge3J9CmFib3V0X2RhdGEobWVkc3Rhcl9lcGNyKSAjIDM1LDU1NyBvYnNlcnZhdGlvbnMgYW5kIDM5IHZhcmlhYmxlcwpgYGAKClt0b3BdKCN0b3ApCgoKCgoKCgoKCgojIFJlY29kZSBjYXRlZ29yaWVzCgoqIEZvciBzZWxlY3QgdmFyaWFibGVzLCByZWNvZGUgdmFyaWFudHMgb2YgbWlzc2luZyBkYXRhIChlLmcuICJVbmtub3duIikgdG8gTkEKCiogRm9yIHNlbGVjdCB2YXJpYWJsZXMgY29sbGFwc2UgY2F0ZWdvcmllcwoKIyMgTWlzc2luZwoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBtZWRzdGFyX2VwY3IgJT4lCiAgbXV0YXRlKAogICAgZ2VuZGVyID0gY2FzZV93aGVuKAogICAgICBnZW5kZXIgPT0gIlVua25vd24gKFVuYWJsZSB0byBEZXRlcm1pbmUpIiB+IE5BX2NoYXJhY3Rlcl8sCiAgICAgIGdlbmRlciA9PSAiTm90IEFwcGxpY2FibGUiICAgICAgICAgICAgICAgIH4gTkFfY2hhcmFjdGVyXywKICAgICAgVFJVRSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfiBnZW5kZXIKICAgICksCiAgICByYWNlID0gY2FzZV93aGVuKAogICAgICByYWNlID09ICJOb3QgQXBwbGljYWJsZSIgfiBOQV9jaGFyYWN0ZXJfLAogICAgICByYWNlID09ICJOb3QgUmVjb3JkZWQiICAgfiBOQV9jaGFyYWN0ZXJfLAogICAgICBUUlVFICAgICAgICAgICAgICAgICAgICAgfiByYWNlCiAgICApCiAgKSAlPiUgCiAgbXV0YXRlX2F0KAogICAgdmFycyhzdGFydHNfd2l0aCgiZGV0ZWN0IikpLAogICAgZnVucygKICAgICAgaWZfZWxzZSguID09ICJOL0EiLCBOQV9jaGFyYWN0ZXJfLCAuKQogICAgKQogICkKYGBgCgoKIyMgQ29sbGFwc2UgY2F0ZWdvcmllcwoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBtZWRzdGFyX2VwY3IgJT4lIAogIG11dGF0ZSgKICAgIHJhY2VfOGNhdCA9IGNhc2Vfd2hlbigKICAgICAgcmFjZSA9PSAiQW1lcmljYW4gSW5kaWFuIG9yIEFsYXNrYSBOYXRpdmUiICAgICAgICAgIH4gIkFtZXJpY2FuIEluZGlhbiBvciBBbGFza2EgTmF0aXZlIC0gbm9uLUhpc3BhbmljIiwKICAgICAgcmFjZSA9PSAiQXNpYW4iICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gIkFzaWFuIC0gbm9uLUhpc3BhbmljIiwKICAgICAgcmFjZSA9PSAiQmxhY2sgb3IgQWZyaWNhbiBBbWVyaWNhbiIgICAgICAgICAgICAgICAgIH4gIkJsYWNrIG9yIEFmcmljYW4gQW1lcmljYW4gLSBub24tSGlzcGFuaWMiLAogICAgICByYWNlID09ICJIaXNwYW5pYyBvciBMYXRpbm8iICAgICAgICAgICAgICAgICAgICAgICAgfiAiSGlzcGFuaWMgb3IgTGF0aW5vLCBBbnkgUmFjZSIsCiAgICAgIHJhY2UgPT0gIk5hdGl2ZSBIYXdhaWlhbiBvciBPdGhlciBQYWNpZmljIElzbGFuZGVyIiB+ICJOYXRpdmUgSGF3YWlpYW4gb3IgT3RoZXIgUGFjaWZpYyBJc2xhbmRlciAtIG5vbi1IaXNwYW5pYyIsCiAgICAgIHJhY2UgPT0gIldoaXRlIiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB+ICJXaGl0ZSAtIG5vbi1IaXNwYW5pYyIsCiAgICAgIHN0cmluZ3I6OnN0cl9kZXRlY3QocmFjZSwgIkhpc3BhbmljIikgICAgICAgICAgICAgICB+ICJIaXNwYW5pYyBvciBMYXRpbm8sIEFueSBSYWNlIiwKICAgICAgaXMubmEocmFjZSkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gTkFfY2hhcmFjdGVyXywKICAgICAgVFJVRSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH4gIk90aGVyIFJhY2UgLSBub24tSGlzcGFuaWMiCiAgICApCiAgKQpgYGAKCmBgYHtyfQphYm91dF9kYXRhKG1lZHN0YXJfZXBjcikgIyAzNSw1NTcgb2JzZXJ2YXRpb25zIGFuZCA0MCB2YXJpYWJsZXMKYGBgCgpbdG9wXSgjdG9wKQoKCgoKCgoKCgoKIyBDcmVhdGUgaW5kaWNhdG9yIGZvciBjb21wbGV0ZWQgREVURUNUIHNjcmVlbmluZwoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBtZWRzdGFyX2VwY3IgJT4lIAogIG11dGF0ZV9hdCgKICAgIC52YXJzID0gdmFycyhzdGFydHNfd2l0aCgiZGV0ZWN0XyIpKSwKICAgIC5mdW5zID0gZnVucyhhbnN3ZXJlZCA9ICFpcy5uYSguKSkKICApICU+JSAKICBtdXRhdGUoCiAgICBhbnN3ZXJlZF9jb3VudCA9IHNlbGVjdCguLCBlbmRzX3dpdGgoImFuc3dlcmVkIikpICU+JSByb3dTdW1zKCkKICApICU+JSAKICBtdXRhdGUoCiAgICBzY3JlZW5lZCA9IGFuc3dlcmVkX2NvdW50ID4gMAogICkKYGBgCgpgYGB7cn0KYWJvdXRfZGF0YShtZWRzdGFyX2VwY3IpICMgMzUsNTU3IG9ic2VydmF0aW9ucyBhbmQgNTYgdmFyaWFibGVzCmBgYAoKW3RvcF0oI3RvcCkKCgoKCgoKCgoKCiMgUHJvY2VzcyBudW1lcmljIHZhcmlhYmxlcwoKQWxsIG51bWVyaWNhbCB2YXJpYWJsZXMgbXVzdCBiZSBjbGFzcyBudW1lcmljIC0tIGFzIG9wcG9zZWQgdG8gaW50ZWdlciAtLSB0byB3b3JrIGluIGZhc3RMaW5rIGJlbG93LgoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBtZWRzdGFyX2VwY3IgJT4lIAogIG11dGF0ZV9pZihpcy5pbnRlZ2VyLCBhcy5udW1lcmljKQpgYGAKCmBgYHtyfQphYm91dF9kYXRhKG1lZHN0YXJfZXBjcikgIyAzNSw1NTcgb2JzZXJ2YXRpb25zIGFuZCA1NiB2YXJpYWJsZXMKYGBgCgpbdG9wXSgjdG9wKQoKCgoKCgoKCgoKIyBEdXBsaWNhdGUgKGFsbW9zdCkgcm93cwoKVGhlcmUgd2VyZSBzb21lIHJvd3Mgd2l0aCB0aGUgc2FtZSBwY3IgbnVtYmVyIGFuZCBvbmx5IGRpZmZlcmVkIGJ5IHdoZXRoZXIgb3Igbm90IERFVEVDVCBzY3JlZW5pbmdzIHdlcmUgY29tcGxldGVkLgoKYGBge3J9CiMgRGF0YSBjaGVja3MKIyBNdWx0aXBsZSBwY3IncyBwZXIgcmVzcG9uc2U/IFllcwojIG1lZHN0YXJfZXBjciAlPiUgCiMgICBncm91cF9ieShyZXNwb25zZV9udW0pICU+JSAKIyAgIHN1bW1hcmlzZShuID0gbGVuZ3RoKHVuaXF1ZShpbmNpZGVudF9wY3IpKSkgJT4lIAojICAgZmlsdGVyKG4gPiAxKQoKIyBNdWx0aXBsZSByZXNwb25zZXMgcGVyIHBjcj8gTm8KIyBtZWRzdGFyX2VwY3IgJT4lIAojICAgZ3JvdXBfYnkoaW5jaWRlbnRfcGNyKSAlPiUgCiMgICBzdW1tYXJpc2UobiA9IGxlbmd0aCh1bmlxdWUocmVzcG9uc2VfbnVtKSkpICU+JSAKIyAgIGZpbHRlcihuID4gMSkKYGBgCgpBZGQgYSBkdW1teSB2YXJpYWJsZSB0aGF0IGluZGljYXRlcyB3aGV0aGVyIG9yIG5vdCB0aGUgcGNyIG51bWJlciBpcyBkdXBsaWNhdGVkCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgCiAgZ3JvdXBfYnkoaW5jaWRlbnRfcGNyKSAlPiUgCiAgbXV0YXRlKHBjcl9kdXAgPSBtYXgocm93X251bWJlcigpKSA+IDEpCmBgYAoKYGBge3J9CmFib3V0X2RhdGEobWVkc3Rhcl9lcGNyKSAjIDM1LDU1NyBvYnNlcnZhdGlvbnMgYW5kIDU3IHZhcmlhYmxlcwpgYGAKCkhvdyBtYW55IHBhaXJzIG9mIGR1cGxpY2F0ZSBwY3IgbnVtYmVycyBhcmUgdGhlcmU/CgpgYGB7cn0KbWVkc3Rhcl9lcGNyICU+JSAKICBncm91cF9ieShpbmNpZGVudF9wY3IpICU+JSAKICBzdW1tYXJpc2UoZHVwbGljYXRlX3BhaXJzID0gYW55KHBjcl9kdXAgPT0gVFJVRSkpICU+JSAKICBwdWxsKGR1cGxpY2F0ZV9wYWlycykgJT4lIAogIHN1bSgpICMgNywyODIKYGBgCgpUaGVyZSBhcmUgNywyODIgaW5jaWRlbnQgcGNyIG51bWJlcnMgdGhhdCBhcmUgZHVwbGljYXRlZCBpbiB0aGUgZGF0YS4KCkZvciBlYWNoIG9mIHRob3NlIHBjciBudW1iZXJzLCBpZiB0aGUgb25seSB0aGluZyB0aGF0IGRpZmZlcnMgYmV0d2VlbiB0aGUgdHdvIHJvd3MgaXMgdGhhdCBvbmUgaGFzIHRoZSBERVRFQ1QgdG9vbCBmaWxsZWQgb3V0IGFuZCB0aGUgb3RoZXIgZG9lc24ndCwgdGhlbiB3ZSBvbmx5IHdhbnQgdG8ga2VlcCB0aGUgcm93IHdpdGggdGhlIERFVEVDVCBzY3JlZW5pbmcgaW5mb3JtYXRpb24uCgpTbywgZm9yIGVhY2ggdmFyaWFibGUgb2YgaW50ZXJlc3QsIGNyZWF0ZSBhIGR1bW15IHZhcmlhYmxlIHRoYXQgaW5kaWNhdGVzIGlmIGlmIHZhbHVlcyBhcmUgZGlmZmVyZW50IHdpdGhpbiBpbmNpZGVudCBwY3IgbnVtYmVyCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgCiAgbXV0YXRlX2F0KAogICAgLnZhcnMgPSB2YXJzKAogICAgICBhcnJpdmFsX3RpbWUsIHJlc3BvbnNlX251bSwgaW5jaWRlbnRfcGNyLCBpbmNpZGVudF9jb21wbGFpbnQsIGFnZSwgCiAgICAgIG5hbWVfZnVsbCwgZG9iLCBhZGRyZXNzX3N0cmVldCwgYWRkcmVzc19jaXR5LCBhZGRyZXNzX3N0YXRlLAogICAgICBhZGRyZXNzX3ppcCwgZ2VuZGVyLCByYWNlLCBzeW1wdG9tcywgY3Jld19zaWcsIGRpc3Bvc2l0aW9uCiAgICApLAogICAgLmZ1bnMgPSBmdW5zKGRpZmYgPSBhcy5udW1lcmljKGxlbmd0aCh1bmlxdWUoLikpID4gMSkpCiAgKSAlPiUgCiAgdW5ncm91cCgpCmBgYAoKTm93LCBjb3VudCB0aGUgdG90YWwgbnVtYmVyIG9mIGRpZmZlcmVuY2VzIGJldHdlZW4gcm93cyAod2l0aGluIGluY2lkZW50IHBjciBudW1iZXIpIGZvciB0aGUgdmFyaWFibGVzIGFib3ZlCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgCiAgbXV0YXRlKAogICAgZGlmZl9jb3VudCA9IHNlbGVjdCguLCBlbmRzX3dpdGgoIl9kaWZmIikpICU+JSByb3dTdW1zKCkKICApCmBgYAoKYGBge3J9CiMgRGF0YSBjaGVja2luZwojIG1lZHN0YXJfZXBjciAlPiUgCiMgICBmaWx0ZXIocGNyX2R1cCkgJT4lIAojICAgc2VsZWN0KGluY2lkZW50X3BjciwgcGNyX2R1cCwgZW5kc193aXRoKCJfZGlmZiIpLCBhcHNfcmVwb3J0LCBhbnN3ZXJlZF9jb3VudCwgZGlmZl9jb3VudCkKYGBgCgoKIyMgQWRkIHJvdyBudW1iZXJzCgpCZWxvdyB3ZSB3aWxsIG5lZWQgdG8gZHJvcCBzZWxlY3RlZCByb3dzIGZyb20gdGhlIGRhdGEuIEFkZGluZyByb3cgbnVtYmVycyB0byB0aGUgZGF0YSBzZXQgaGVyZSB3aWxsIG1ha2UgaXQgZWFzaWVyIHRvIGRvIHNvIHdpdGhvdXQgdXNpbmcgYW55IHBvdGVudGlhbCBwZXJzb25hbCBpZGVudGlmaWVycyB0byBmaWx0ZXIgdGhlIGRhdGEuCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgbXV0YXRlKHJvdyA9IHJvd19udW1iZXIoKSkgJT4lIHNlbGVjdChyb3csIGV2ZXJ5dGhpbmcoKSkKYGBgCgoKIyMgQ2hlY2s6IERpZmZlcmVuY2VzCgpBcmUgdGhlcmUgYW55IGNhc2VzIHdoZXJlIHRoZXJlIGlzIGEgZHVwbGljYXRlZCBpbmNpZGVudCBwY3IgbnVtYmVyIGFuZCB0aGVyZSBhcmUgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgdmFsdWVzIGluIHRoZSByb3dzIG90aGVyIHRoYW4gREVURUNUIHNjcmVlbmluZ3M/IFJlc3VsdHMgYXJlIGhpZGRlbiB0byBwcm90ZWN0IHBhcnRpY2lwYW50IHByaXZhY3kuCgpgYGB7ciBldmFsPUZBTFNFfQptZWRzdGFyX2VwY3IgJT4lIAogIGZpbHRlcihwY3JfZHVwICYgZGlmZl9jb3VudCA+IDApCmBgYAoKWWVzLiBUaGVyZSBpcyBvbmUgZHVwbGljYXRlZCBpbmNpZGVudCBwY3Igd2l0aCBkaWZmZXJpbmcgaW5mb3JtYXRpb24gYmV0d2VlbiByb3dzIGZvciByYWNlIChyb3cgMTY1MzAgPSBXaGl0ZSwgcm93IDE2NTMxID0gTWlzc2luZykgYW5kIGRpc3Bvc2l0aW9uIChyb3cgMTY1MzAgPSBUcmFuc3BvcnRlZCwgcm93IDE2NTMxID0gQ2FuY2VsZWQgRmFsc2UgQ2FsbCkuIEFkZGl0aW9uYWxseSwgcm93IDE2NTMwIGhhcyBhIGNvbXBsZXRlZCBERVRFQ1Qgc2NyZWVuaW5nLiBUaGVyZWZvcmUsIHdlIHdpbGwgZHJvcCByb3cgMTY1MzEgYW5kIGNoYW5nZSBwY3JfZHVwIHRvIEZBTFNFIGZvciByb3cgMTY1MzAuCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgCiAgZmlsdGVyKHJvdyAhPSAxNjUzMSkgJT4lIAogIG11dGF0ZShwY3JfZHVwID0gaWZfZWxzZShyb3cgPT0gMTY1MzAsIEZBTFNFLCBwY3JfZHVwKSkKYGBgCgpBdCB0aGlzIHBvaW50LCBhbGwgcmVtYWluaW5nIGR1cGxpY2F0ZSBpbmNpZGVudCBwY3IgbnVtYmVycyBoYXZlIGlkZW50aWNhbCB2YWx1ZXMgZm9yIGVhY2ggb2YgdGhlIHZhcmlhYmxlcyBjb21wYXJlZCBhYm92ZSBhbmQgZGlmZl9jb3VudHMgb2YgMC4gVGhlcmUgaXMgbm8gbmVlZCB0byBrZWVwIHRob3NlIHZhcmlhYmxlcyBpbiB0aGUgZGF0YS4KCmBgYHtyfQptZWRzdGFyX2VwY3IgPC0gbWVkc3Rhcl9lcGNyICU+JSAKICBzZWxlY3QoLWVuZHNfd2l0aCgiX2RpZmYiKSwgLWRpZmZfY291bnQpCmBgYAoKYGBge3J9CmFib3V0X2RhdGEobWVkc3Rhcl9lcGNyKSAjIDM1LDU1NiBvYnNlcnZhdGlvbnMgYW5kIDU4IHZhcmlhYmxlcwpgYGAKCgojIyBDaGVjazogTm8gREVURUNUIGFuc3dlcnMKCkFyZSB0aGVyZSBhbnkgY2FzZXMgd2hlcmUgdGhlcmUgaXMgYSBkdXBsaWNhdGVkIGluY2lkZW50IHBjciBudW1iZXIgYW5kIGFuc3dlcmVkIGNvdW50IGlzIDAgZm9yIGFsbCByb3dzPyBSZXN1bHRzIGFyZSBoaWRkZW4gdG8gcHJvdGVjdCBwYXJ0aWNpcGFudCBwcml2YWN5LgoKYGBge3IgZXZhbD1GQUxTRX0KbWVkc3Rhcl9lcGNyICU+JQogIGZpbHRlcihwY3JfZHVwKSAlPiUKICBncm91cF9ieShpbmNpZGVudF9wY3IpICU+JQogIGZpbHRlcihhbGwoYW5zd2VyZWRfY291bnQgPT0gMCkpCmBgYAoKWWVzLCB0aGVyZSBpcyBvbmUgc3VjaCBpbmNpZGVudCBwY3IgbnVtYmVyLiBUaGUgb25seSBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHR3byByb3dzIGlzIHRoYXQgdGhlIHZhbHVlIGZvciBhcHNfcmVwb3J0X251bSBpbiByb3cgNDQ2NyBpcyAiaG9tZWxlc3MiIGFuZCBtaXNzaW5nIGluIHJvdyA0NDY4LiBUaGVyZWZvcmUsIHdlIHdpbGwgZHJvcCByb3cgNDQ2OCBhbmQgY2hhbmdlIHBjcl9kdXAgdG8gRkFMU0UgZm9yIDQ0NjcuCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUgCiAgZmlsdGVyKHJvdyAhPSA0NDY4KSAlPiUgCiAgbXV0YXRlKHBjcl9kdXAgPSBpZl9lbHNlKHJvdyA9PSA0NDY3LCBGQUxTRSwgcGNyX2R1cCkpCmBgYAoKYGBge3J9CmFib3V0X2RhdGEobWVkc3Rhcl9lcGNyKSAjIDM1LDU1NSBvYnNlcnZhdGlvbnMgYW5kIDU4IHZhcmlhYmxlcwpgYGAKCgojIyBDaGVjazogQ29uZmxpY3RpbmcgREVURUNUIGFuc3dlcnMKCkFyZSB0aGVyZSBhbnkgY2FzZXMgd2hlcmUgdGhlcmUgaXMgYSBkdXBsaWNhdGVkIGluY2lkZW50IHBjciBudW1iZXIgYW5kIGFuc3dlcmVkIGNvdW50cyBkaWZmZXIsIGJ1dCB0aGUgYW5zd2VyZWQgY291bnQgaXMgbm90IDAgZm9yIGFueSBvZiB0aGUgcm93cy4gSW4gb3RoZXIgd29yZHMsIGEgZGlmZmVyZW50IG51bWJlciBvZiBzY3JlZW5pbmcgaXRlbXMgd2FzIGFuc3dlcmVkLiBSZXN1bHRzIGFyZSBoaWRkZW4gdG8gcHJvdGVjdCBwYXJ0aWNpcGFudCBwcml2YWN5LgoKYGBge3IgZXZhbD1GQUxTRX0KbWVkc3Rhcl9lcGNyICU+JSAKICBmaWx0ZXIocGNyX2R1cCkgJT4lIAogIGdyb3VwX2J5KGluY2lkZW50X3BjcikgJT4lIAogIGZpbHRlcighYW55KGFuc3dlcmVkX2NvdW50ID09IDApKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICAjIEkgYWxyZWFkeSBrbm93IHRoZXJlIGFyZSBubyBkaWZmZXJlbmNlcyBpbiBuYW1lIGV0Yy4gV2UgY2xlYW5lZCB0aGF0IHVwCiAgIyBhYm92ZS4KICBzZWxlY3Qocm93LCBuYW1lX2Z1bGwsIGNyZXdfc2lnLCBhcHNfcmVwb3J0X251bSwgYXBzX3JlcG9ydCwgCiAgICAgICAgIHN0YXJ0c193aXRoKCJkZXRlY3RfIiksIGFuc3dlcmVkX2NvdW50LCAtZW5kc193aXRoKCJfYW5zd2VyZWQiKSkKYGBgCgpZZXMsIHRoZXJlIGFyZSAxMzAgcm93cyAoNjMgdW5pcXVlIGluY2lkZW50IHBjciBudW1iZXJzKSB3aGVyZSBtb3JlIHRoYW4gb25lIHJvdyBoYXMgdGhlIERFVEVDVCBzY3JlZW5pbmcgZmlsbGVkIG91dC4KClRoZXJlIGRvZXNuJ3QgYXBwZWFyIHRvIGJlIGFuIHN5c3RlbWF0aWMgZGlmZmVyZW5jZXMgYmV0d2VlbiB0aGUgcm93cy4gRm9yIGV4YW1wbGUsIHRoZSBmaXJzdCByb3cgaW4gYSBwYWlyIGlzIGFsd2F5cyBtb3JlIGNvbXBsZXRlIG9yIHNvbWV0aGluZyBsaWtlIHRoYXQuIFRoZXJlZm9yZSwgd2UncmUgZ29pbmcgdG8gZmlsdGVyIGluIHN0YWdlcyBpbiBzdWNoIGEgd2F5IGFzIHRvIG1heGltaXplIGluZm9ybWF0aW9uIHJldGVudGlvbi4gICAKCjEuIEtlZXAgdGhlIHJvdyB3aXRoIHRoZSBoaWdoZXN0IGFuc3dlcmVkIGNvdW50ICAgCjIuIElmIHRoZXJlIGlzIGEgdGllIGZvciBoaWdoZXN0IGFuc3dlcmVkIGNvdW50LCBrZWVwIHJvdyB3aXRoIGFwcyByZXBvcnQgbnVtYmVyICAgCjMuIElmIHRoZXJlIGlzIGEgdGllIGZvciBoaWdoZXN0IGFuc3dlcmVkIGNvdW50IGFuZCBib3RoIHJvd3MgaGF2ZSBhbiBhcHMgcmVwb3J0IG51bWJlciwgdGhlbiBhcmJpdHJhcmlseSBrZWVwIHRoZSBmaXJzdCByb3cuICAgCgpgYGB7cn0KbWVkc3Rhcl9lcGNyIDwtIG1lZHN0YXJfZXBjciAlPiUKICBhcnJhbmdlKGRlc2MocGNyX2R1cCksIGluY2lkZW50X3BjciwgZGVzYyhhbnN3ZXJlZF9jb3VudCksIGFwc19yZXBvcnRfbnVtKSAlPiUgCiAgZ3JvdXBfYnkoaW5jaWRlbnRfcGNyKSAlPiUgCiAgbXV0YXRlKAogICAgZ3JvdXBfcm93ID0gcm93X251bWJlcigpLAogICAga2VlcF9yb3cgPSBncm91cF9yb3cgPT0gMQogICkgJT4lIAogIHVuZ3JvdXAoKSAlPiUgCiAgYXJyYW5nZShyb3cpCmBgYAoKTk9URTogSWYgdGhlcmUgaXMgb25seSBvbmUgcm93IGZvciBhIGdpdmVuIGluY2lkZW50IHBjciBudW1iZXIsIHRoZW4gaXQgd2lsbCBhbHdheXMgaGF2ZSBrZWVwX3JvdyA9PSAxLgoKYGBge3J9CiMgRGF0YSBjaGVja3MKIyBtZWRzdGFyX2VwY3IgJT4lIAojICAgZmlsdGVyKHBjcl9kdXApICU+JQojICAgc2VsZWN0KHJvdywgcm93LCBpbmNpZGVudF9wY3IsIGdyb3VwX3Jvdywga2VlcF9yb3csIGFuc3dlcmVkX2NvdW50LCBhcHNfcmVwb3J0X251bSkgJT4lIAojICAgZ3JvdXBfYnkoaW5jaWRlbnRfcGNyKSAlPiUgCiMgICBmaWx0ZXIoYW55KGdyb3VwX3JvdyA+IDIpKQpgYGAKCkRyb3AgZHVwbGljYXRlIHJvd3MgYW5kIHVubmVlZGVkIHZhcmlhYmxlcwoKYGBge3J9Cm1lZHN0YXJfZXBjciA8LSBtZWRzdGFyX2VwY3IgJT4lIAogIGZpbHRlcihrZWVwX3JvdykgJT4lIAogIHNlbGVjdCgtcm93LCAtcGNyX2R1cCwgLWdyb3VwX3JvdywgLWtlZXBfcm93KQpgYGAKCmBgYHtyfQphYm91dF9kYXRhKG1lZHN0YXJfZXBjcikgIyAyOCwyMjggb2JzZXJ2YXRpb25zIGFuZCA1NiB2YXJpYWJsZXMKYGBgCgpbdG9wXSgjdG9wKQoKCgoKCgoKCgoKIyBTYXZlIGRhdGEKCmBgYHtyfQpmZWF0aGVyOjp3cml0ZV9mZWF0aGVyKAogIG1lZHN0YXJfZXBjciwgCiAgIi9Wb2x1bWVzL3NwaF9yZXNlYXJjaC9EZXRlY3Qvb25lX3llYXJfZGF0YS9tZWRzdGFyX2VwY3JfMDJfdmFyaWFibGVfbWFuYWdlbWVudC5mZWF0aGVyIgopCmBgYAoKW3RvcF0oI3RvcCkKCgoKCgoKCgoKCiMgU2Vzc2lvbiBpbmZvcm1hdGlvbgoKYGBge3J9CnJtKGxpc3QgPSBscygpKQpgYGAKCmBgYHtyIGVjaG89RkFMU0V9CnNlc3Npb25JbmZvKCkKYGBgCg==
- - -
-
- -
- - - - - - - -