library(readr)
library(dplyr)
library(scales)
library(tidyr)
library(ggplot2)
library(cowplot)
library(stringr)
library(forcats)
library(ggallin)
theme_set(theme_bw())
Read in data
alpha_threshold <- qnorm(0.975)
countries <- c("France", "Germany", "Spain", "Italy", "Singapore", "USA" )
countries_code <- c("FR", "DE", "ES", "IT", "SG", "US")
colorBlindGrey6 <- c("#0072B2", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#CC79A7")
races <- c("black", "hispanic_latino", "white", "asian",
"hawaiian_pacific_islander", "american_indian")
Races <- rev(c('White', 'Black', 'Hispanic/Latino', 'Asian',
'American Indian', 'Hawaiian/Pacific Islander', 'Other/Unknown'))
demo_desc <- read_csv('results/demo_prelim.csv') %>%
filter(siteid != 'SITE157', siteid != 'SITE712') %>%
mutate(Country = fct_relevel(Country, countries))
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## .default = col_double(),
## siteid = col_character(),
## Country = col_character()
## )
## ℹ Use `spec()` for the full column specifications.
demo_perc <- demo_desc %>%
mutate_at(vars(- num_patients_all, - siteid, - Country, - median_age),
list(~ . / .data$num_patients_all)) %>%
mutate(Country = as.factor(Country))
demo_perc %>%
rename('perc_patients_ever_severe' = num_patients_ever_severe,
'perc_patients_never_severe' = num_patients_never_severe) %>%
write_csv('results/demographics.csv')
Overall statistics
demo_desc %>%
summarise(across(c(num_patients_all, female, male, unknown_other_sex), sum))
## # A tibble: 1 x 4
## num_patients_all female male unknown_other_sex
## <dbl> <dbl> <dbl> <dbl>
## 1 34647 13546 20814 287
demo_desc %>%
summarise(across(c(num_patients_all, races, unknown_other_race), sum)) %>%
print()
## Note: Using an external vector in selections is ambiguous.
## ℹ Use `all_of(races)` instead of `races` to silence this message.
## ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
## This message is displayed once per session.
## # A tibble: 1 x 8
## num_patients_all black hispanic_latino white asian hawaiian_pacifi…
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 34647 5706 1400 8532 621 9
## # … with 2 more variables: american_indian <dbl>, unknown_other_race <dbl>
unknowns <- demo_perc %>%
select(siteid, Country, contains('unknown')) %>%
pivot_longer(- c(siteid, Country))
unknowns %>% filter(value < 0)
## # A tibble: 6 x 4
## siteid Country name value
## <chr> <fct> <chr> <dbl>
## 1 SITE824 USA unknown_other_sex -0.00293
## 2 SITE864 USA unknown_other_race -0.00443
## 3 SITE295 USA unknown_other_race -0.0822
## 4 SITE200 USA unknown_other_race -0.0145
## 5 SITE775 USA unknown_other_race -0.0769
## 6 SITE923 USA unknown_other_race -0.107
unknowns %>% filter(value < 1, value > 0.1)
## # A tibble: 9 x 4
## siteid Country name value
## <chr> <fct> <chr> <dbl>
## 1 SITE824 USA unknown_other_race 0.152
## 2 SITE599 USA unknown_other_race 0.14
## 3 SITE116 Singapore unknown_other_race 0.378
## 4 SITE798 USA unknown_other_race 0.173
## 5 SITE510 USA unknown_other_race 0.367
## 6 SITE533 USA unknown_other_race 0.148
## 7 SITE432 USA unknown_other_sex 0.107
## 8 SITE432 USA unknown_other_race 0.214
## 9 SITE734 USA unknown_other_race 0.258
# unknowns %>%
# ggplot(aes(y = value, x = name)) +
# ggbeeswarm::geom_beeswarm() +
# facet_wrap(~ name, scales = 'free_x')
Severity vs. gender/age/race?
demo_gender <- demo_perc %>% filter(unknown_other_sex < 1)
lm(num_patients_ever_severe ~ female, demo_gender) %>%
summary()
##
## Call:
## lm(formula = num_patients_ever_severe ~ female, data = demo_gender)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.55272 -0.04966 -0.00420 0.10740 0.42322
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.00420 0.04687 21.43 < 2e-16 ***
## female -1.32622 0.13873 -9.56 9.02e-12 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.1833 on 39 degrees of freedom
## Multiple R-squared: 0.7009, Adjusted R-squared: 0.6932
## F-statistic: 91.38 on 1 and 39 DF, p-value: 9.02e-12
age_perc <- demo_perc %>%
filter(unknown_other_age_group < 1) %>%
select(Country, num_patients_all, num_patients_ever_severe, contains('to'), ends_with('plus'))
lm(num_patients_ever_severe ~ . - Country - num_patients_all, age_perc) %>%
summary()
##
## Call:
## lm(formula = num_patients_ever_severe ~ . - Country - num_patients_all,
## data = age_perc)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.56212 -0.07390 0.03572 0.10181 0.38724
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -3.731 1.712 -2.179 0.03659 *
## `00to02` -4.334 7.509 -0.577 0.56772
## `03to05` 73.690 33.517 2.199 0.03503 *
## `06to11` -18.079 15.938 -1.134 0.26484
## `12to17` 4.277 15.450 0.277 0.78362
## `18to25` 1.723 3.225 0.534 0.59675
## `26to49` 3.803 1.815 2.096 0.04386 *
## `50to69` 4.476 1.902 2.354 0.02470 *
## `70to79` 6.186 1.887 3.278 0.00246 **
## `80plus` 2.964 1.638 1.810 0.07943 .
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.217 on 33 degrees of freedom
## Multiple R-squared: 0.6591, Adjusted R-squared: 0.5661
## F-statistic: 7.089 on 9 and 33 DF, p-value: 1.225e-05
lm(num_patients_ever_severe ~ black + white + asian + hispanic_latino +
american_indian + hawaiian_pacific_islander,
data = filter(demo_perc, unknown_other_race < 1)) %>%
summary()
##
## Call:
## lm(formula = num_patients_ever_severe ~ black + white + asian +
## hispanic_latino + american_indian + hawaiian_pacific_islander,
## data = filter(demo_perc, unknown_other_race < 1))
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.5508 -0.1224 0.1029 0.1451 0.3034
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 0.2270 0.6028 0.377 0.709
## black 0.7031 0.6360 1.105 0.279
## white 0.6638 0.6880 0.965 0.344
## asian -0.4146 1.1398 -0.364 0.719
## hispanic_latino -0.3319 0.6205 -0.535 0.597
## american_indian -31.0987 33.4578 -0.929 0.361
## hawaiian_pacific_islander -60.7964 71.6772 -0.848 0.404
##
## Residual standard error: 0.2678 on 26 degrees of freedom
## Multiple R-squared: 0.3673, Adjusted R-squared: 0.2212
## F-statistic: 2.515 on 6 and 26 DF, p-value: 0.04703
lm(num_patients_ever_severe ~ median_age, demo_perc) %>%
summary()
##
## Call:
## lm(formula = num_patients_ever_severe ~ median_age, data = demo_perc)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.69883 -0.22095 -0.01098 0.26950 0.45614
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -0.417341 0.452308 -0.923 0.3616
## median_age 0.015701 0.006709 2.340 0.0242 *
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.3132 on 41 degrees of freedom
## Multiple R-squared: 0.1178, Adjusted R-squared: 0.09633
## F-statistic: 5.477 on 1 and 41 DF, p-value: 0.02421
Overall plot (A)
gender_count <- demo_desc %>%
# filter(unknown_other_sex/num_patients_all < 1) %>%
# mutate(siteid = as.factor(siteid)) %>%
# mutate(num_patients_all_gender = female + male) %>%
group_by(Country) %>%
summarise(num_patients_country = sum(num_patients_all),
male_count = sum(male),
female_count = sum(female),
.groups = 'drop') %>%
{.}
showtext::showtext_auto()
female <- intToUtf8(9792)
male <- intToUtf8(9794)
overall_plot <- gender_count %>%
mutate(male_count = -male_count) %>%
pivot_longer(- c(Country, num_patients_country)) %>%
ggplot(aes(y = fct_relevel(Country, rev(countries)),
x = value, color = name,
fill = Country)) +
geom_col(position = 'identity') +
scale_color_manual(values = c('white', 'white')) +
scale_x_continuous(breaks = c(-5000, -2000, 0, 2000, 5000),
labels = c(5000, 2000, 0, 2000, 5000),
trans = ssqrt_trans) +
geom_vline(xintercept = 0, color = 'white') +
geom_text(data = . %>% filter(name == 'male_count'),
aes(y = Country, x = value - 22*sqrt(abs(value)),
label = abs(value)), color = 'grey40', size = 3) +
geom_text(data = . %>% filter(name == 'female_count'),
aes(y = Country, x = value + 19*sqrt(abs(value)),
label = abs(value)), color = 'grey40', size = 3) +
geom_text(data = filter(gender_count, Country == 'France'),
aes(y = 6, x = female_count - 600), fontface = 2,
label = female, size = 3, color = 'white') +
geom_text(data = filter(gender_count, Country == 'France'),
aes(y = 6, x = - male_count + 600), fontface = 2,
label = male, size = 3, color = 'white') +
labs(y = NULL,
x = 'Number of male/female patients per country',
fill = NULL) +
scale_fill_manual(values = colorBlindGrey6) +
theme(legend.position = 'None',
plot.margin = margin(15, 5.5, 15.5, 55.5),
axis.ticks.y = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.spacing.y = unit(0, 'pt'),
strip.background = element_blank(),
strip.placement = 'inside',
legend.background = element_blank(),
legend.key.height = unit(1, 'line'),
legend.title = element_text(hjust = 0, size = 9)) +
NULL
Age plot (B)
age_count <- demo_desc %>%
filter(unknown_other_age_group/num_patients_all < 1) %>%
select(Country, num_patients_all, contains('to'), ends_with('plus')) %>%
group_by(Country) %>%
summarise(across(.fns = sum), .groups = 'drop') %>%
mutate_at(vars(- num_patients_all, - Country),
list(~ . / .data$num_patients_all)) %>%
select(-num_patients_all) %>%
pivot_longer(- Country) %>%
mutate(name = case_when(
name == '00to02' ~ '0to2',
name == '03to05' ~ '3to5',
name == '06to11' ~ '6to11',
TRUE ~ name
)) %>%
mutate(name = gsub('to', '–', name) %>% gsub('plus', '+', .))
age_count$name <- factor(age_count$name, levels = unique(age_count$name))
age_plot <- age_count %>%
ggplot(aes(name, value, fill = Country, group = Country)) +
geom_col(position = 'dodge2') +
coord_flip() +
facet_grid(rows = vars(Country)) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1),
breaks = seq(0, 1, 0.2),
expand = expansion(add = c(0,0.02))) +
scale_size_continuous(guide = FALSE) +
labs(x = NULL, y = 'Patients proportion per age group') +
scale_color_manual(values = colorBlindGrey6, drop = FALSE) +
scale_fill_manual(values = colorBlindGrey6, drop = FALSE) +
theme(legend.position = 'None',
axis.text.y = element_text(size = 7),
panel.grid.major.y = element_blank(),
plot.margin = margin(15, 5.5, 5.5, 5.5, 'pt')) +
NULL
Severity vs. age plot (C)
country_codes <- read_csv('https://raw.githubusercontent.com/lukes/ISO-3166-Countries-with-Regional-Codes/master/all/all.csv') %>%
mutate(name = ifelse(name == 'United States of America', 'USA', name)) %>%
filter(name %in% countries) %>%
select(Country = name, coun_code = `alpha-2`) %>%
mutate(coun_code = as.factor(coun_code) %>% fct_relevel(countries_code))
##
## ── Column specification ────────────────────────────────────────────────────────
## cols(
## name = col_character(),
## `alpha-2` = col_character(),
## `alpha-3` = col_character(),
## `country-code` = col_character(),
## `iso_3166-2` = col_character(),
## region = col_character(),
## `sub-region` = col_character(),
## `intermediate-region` = col_character(),
## `region-code` = col_character(),
## `sub-region-code` = col_character(),
## `intermediate-region-code` = col_character()
## )
age_severity <- demo_perc %>%
left_join(country_codes, by = 'Country') %>%
ggplot(aes(median_age, num_patients_ever_severe,
color = coun_code)) +
geom_point(aes(size = num_patients_all), alpha = 0.8) +
scale_y_continuous(labels = scales::percent_format(),
breaks = seq(0, 1, 0.2)) +
labs(x = 'Median age estimate',
y = 'Severe case proportion',
color = NULL) +
scale_size(trans = "log10", guide = FALSE) +
scale_color_manual(values = colorBlindGrey6) +
coord_cartesian(ylim = c(0, 1)) +
theme(
# legend.position = c(0.9, 0.7),
legend.position = 'left',
legend.background = element_blank(),
plot.margin = margin(5.5, 5.5, 10.5, 15.5),
panel.grid.minor = element_blank(),
legend.key.height = unit(0.7, 'line'),
legend.key.width = unit(0.4, 'line'),
legend.title = element_text(hjust = 0, size = 9)) +
NULL
Race plot (D)
race_count <- demo_desc %>%
filter(unknown_other_race/num_patients_all < 1) %>%
select(Country, num_patients_all, all_of(races), unknown_other_race) %>%
group_by(Country) %>%
summarise(across(.fns = sum), .groups = 'drop') %>%
mutate_at(vars(- num_patients_all, - Country),
list(~ . / .data$num_patients_all)) %>%
select(-num_patients_all) %>%
pivot_longer(- Country) %>%
mutate(name = gsub('_', ' ', name) %>%
str_to_title(.) %>%
gsub('Hispanic ', 'Hispanic/', .) %>%
gsub('Hawaiian ', 'Hawaiian/', .) %>%
gsub('Unknown Other Race', 'Other/Unknown',. ),
name = fct_relevel(name, Races))
race_plot <- race_count %>%
# remove one site in Italy that reported all white ethnicity
filter(Country != 'Italy') %>%
ggplot(aes(name, value, fill = Country, group = Country)) +
geom_col(position = 'dodge2') +
coord_flip() +
facet_grid(rows = vars(Country)) +
scale_y_continuous(labels = scales::percent_format(accuracy = 1),
breaks = seq(0, 1, 0.2),
expand = expansion(add = c(0,0.02))) +
scale_size_continuous(guide = FALSE) +
labs(x = NULL, y = 'Patient proportion per race/ethnicity group') +
scale_color_manual(values = colorBlindGrey6, drop = FALSE) +
scale_fill_manual(values = colorBlindGrey6, drop = FALSE) +
theme(legend.position = 'None',
axis.text.y = element_text(size = 8),
panel.grid.major.y = element_blank(),
axis.title.x = element_text(hjust = .8)) +
NULL
Composite plot
gender_race <- plot_grid(overall_plot, age_severity, race_plot, ncol = 1,
rel_heights = c(0.7, 1, 1),
labels = c('A', 'B', 'C'), axis = 'r')
abcd <- plot_grid(gender_race, age_plot, ncol = 2,
rel_widths = c(1.25, 1 ), labels = c('', 'D'),
axis = 'b')
abcd
ggsave('figs/composite_plot.png', abcd, height = 6.5, width = 9)
ggsave('figs/tiffs/fig_2.tiff', abcd, height = 6.5, width = 9, dpi = 300)
LS0tCnRpdGxlOiAiQW5hbHlzaXMgb2YgZGVtb2dyYXBoaWNzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHRoZW1lOiBsdW1lbgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IGZhbHNlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICBoaWdobGlnaHQ6IHRhbmdvCmtuaXQ6IChmdW5jdGlvbihpbnB1dEZpbGUsIGVuY29kaW5nKSB7CiAgcm1hcmtkb3duOjpyZW5kZXIoaW5wdXRGaWxlLCBlbmNvZGluZyA9IGVuY29kaW5nLCBvdXRwdXRfZGlyID0gImRvY3MiKSB9KQotLS0KCmBgYHtyIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkocmVhZHIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoc2NhbGVzKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KGZvcmNhdHMpCmxpYnJhcnkoZ2dhbGxpbikKCnRoZW1lX3NldCh0aGVtZV9idygpKQpgYGAKCiMjIFJlYWQgaW4gZGF0YQpgYGB7cn0KYWxwaGFfdGhyZXNob2xkIDwtIHFub3JtKDAuOTc1KQpjb3VudHJpZXMgPC0gYygiRnJhbmNlIiwgIkdlcm1hbnkiLCAiU3BhaW4iLCAiSXRhbHkiLCAiU2luZ2Fwb3JlIiwgIlVTQSIgKQpjb3VudHJpZXNfY29kZSA8LSBjKCJGUiIsICJERSIsICJFUyIsICJJVCIsICJTRyIsICJVUyIpCmNvbG9yQmxpbmRHcmV5NiA8LSBjKCIjMDA3MkIyIiwgIiNFNjlGMDAiLCAiIzU2QjRFOSIsICIjMDA5RTczIiwgIiNGMEU0NDIiLCAiI0NDNzlBNyIpCnJhY2VzIDwtIGMoImJsYWNrIiwgImhpc3BhbmljX2xhdGlubyIsICJ3aGl0ZSIsICJhc2lhbiIsIAogICAgICAgICAgICJoYXdhaWlhbl9wYWNpZmljX2lzbGFuZGVyIiwgImFtZXJpY2FuX2luZGlhbiIpICAKUmFjZXMgPC0gcmV2KGMoJ1doaXRlJywgJ0JsYWNrJywgJ0hpc3BhbmljL0xhdGlubycsICdBc2lhbicsIAogICAgICAgICAgICAgICAnQW1lcmljYW4gSW5kaWFuJywgJ0hhd2FpaWFuL1BhY2lmaWMgSXNsYW5kZXInLCAnT3RoZXIvVW5rbm93bicpKQoKZGVtb19kZXNjIDwtIHJlYWRfY3N2KCdyZXN1bHRzL2RlbW9fcHJlbGltLmNzdicpICU+JSAKICBmaWx0ZXIoc2l0ZWlkICE9ICdTSVRFMTU3Jywgc2l0ZWlkICE9ICdTSVRFNzEyJykgJT4lIAogIG11dGF0ZShDb3VudHJ5ID0gZmN0X3JlbGV2ZWwoQ291bnRyeSwgY291bnRyaWVzKSkKCmRlbW9fcGVyYyA8LSBkZW1vX2Rlc2MgJT4lIAogIG11dGF0ZV9hdCh2YXJzKC0gbnVtX3BhdGllbnRzX2FsbCwgLSBzaXRlaWQsIC0gQ291bnRyeSwgLSBtZWRpYW5fYWdlKSwKICAgICAgICAgICAgbGlzdCh+IC4gLyAuZGF0YSRudW1fcGF0aWVudHNfYWxsKSkgJT4lIAogIG11dGF0ZShDb3VudHJ5ID0gYXMuZmFjdG9yKENvdW50cnkpKSAKCmRlbW9fcGVyYyAlPiUgCiAgcmVuYW1lKCdwZXJjX3BhdGllbnRzX2V2ZXJfc2V2ZXJlJyA9IG51bV9wYXRpZW50c19ldmVyX3NldmVyZSwKICAgICAgICAgJ3BlcmNfcGF0aWVudHNfbmV2ZXJfc2V2ZXJlJyA9IG51bV9wYXRpZW50c19uZXZlcl9zZXZlcmUpICU+JSAKICB3cml0ZV9jc3YoJ3Jlc3VsdHMvZGVtb2dyYXBoaWNzLmNzdicpCmBgYAoKIyMgT3ZlcmFsbCBzdGF0aXN0aWNzCmBgYHtyfQpkZW1vX2Rlc2MgJT4lIAogIHN1bW1hcmlzZShhY3Jvc3MoYyhudW1fcGF0aWVudHNfYWxsLCBmZW1hbGUsIG1hbGUsIHVua25vd25fb3RoZXJfc2V4KSwgc3VtKSkgCgpkZW1vX2Rlc2MgJT4lIAogIHN1bW1hcmlzZShhY3Jvc3MoYyhudW1fcGF0aWVudHNfYWxsLCByYWNlcywgdW5rbm93bl9vdGhlcl9yYWNlKSwgc3VtKSkgJT4lIAogIHByaW50KCkKCnVua25vd25zIDwtIGRlbW9fcGVyYyAlPiUKICBzZWxlY3Qoc2l0ZWlkLCBDb3VudHJ5LCBjb250YWlucygndW5rbm93bicpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKC0gYyhzaXRlaWQsIENvdW50cnkpKQp1bmtub3ducyAlPiUgZmlsdGVyKHZhbHVlIDwgMCkKdW5rbm93bnMgJT4lIGZpbHRlcih2YWx1ZSA8IDEsIHZhbHVlID4gMC4xKQoKIyB1bmtub3ducyAlPiUgCiMgICBnZ3Bsb3QoYWVzKHkgPSB2YWx1ZSwgeCA9IG5hbWUpKSArCiMgICBnZ2JlZXN3YXJtOjpnZW9tX2JlZXN3YXJtKCkgKwojICAgZmFjZXRfd3JhcCh+IG5hbWUsIHNjYWxlcyA9ICdmcmVlX3gnKQpgYGAKCiMjIFNldmVyaXR5IHZzLiBnZW5kZXIvYWdlL3JhY2U/CmBgYHtyfQpkZW1vX2dlbmRlciA8LSBkZW1vX3BlcmMgJT4lIGZpbHRlcih1bmtub3duX290aGVyX3NleCA8IDEpCmxtKG51bV9wYXRpZW50c19ldmVyX3NldmVyZSB+IGZlbWFsZSwgZGVtb19nZW5kZXIpICU+JSAKICBzdW1tYXJ5KCkKCmFnZV9wZXJjIDwtIGRlbW9fcGVyYyAlPiUgCiAgZmlsdGVyKHVua25vd25fb3RoZXJfYWdlX2dyb3VwIDwgMSkgJT4lIAogIHNlbGVjdChDb3VudHJ5LCBudW1fcGF0aWVudHNfYWxsLCBudW1fcGF0aWVudHNfZXZlcl9zZXZlcmUsIGNvbnRhaW5zKCd0bycpLCBlbmRzX3dpdGgoJ3BsdXMnKSkKCmxtKG51bV9wYXRpZW50c19ldmVyX3NldmVyZSB+IC4gLSBDb3VudHJ5IC0gbnVtX3BhdGllbnRzX2FsbCwgYWdlX3BlcmMpICU+JSAKICBzdW1tYXJ5KCkKCmxtKG51bV9wYXRpZW50c19ldmVyX3NldmVyZSB+IGJsYWNrICsgd2hpdGUgKyBhc2lhbiArIGhpc3BhbmljX2xhdGlubyArIAogICAgIGFtZXJpY2FuX2luZGlhbiArIGhhd2FpaWFuX3BhY2lmaWNfaXNsYW5kZXIsIAogICBkYXRhID0gZmlsdGVyKGRlbW9fcGVyYywgdW5rbm93bl9vdGhlcl9yYWNlIDwgMSkpICU+JSAKICBzdW1tYXJ5KCkKCmxtKG51bV9wYXRpZW50c19ldmVyX3NldmVyZSB+IG1lZGlhbl9hZ2UsIGRlbW9fcGVyYykgJT4lIAogIHN1bW1hcnkoKQpgYGAKCiMjIE92ZXJhbGwgcGxvdCAoQSkKCmBgYHtyfQpnZW5kZXJfY291bnQgPC0gZGVtb19kZXNjICU+JSAKICAjIGZpbHRlcih1bmtub3duX290aGVyX3NleC9udW1fcGF0aWVudHNfYWxsIDwgMSkgJT4lIAogICMgbXV0YXRlKHNpdGVpZCA9IGFzLmZhY3RvcihzaXRlaWQpKSAlPiUgCiAgIyBtdXRhdGUobnVtX3BhdGllbnRzX2FsbF9nZW5kZXIgPSBmZW1hbGUgKyBtYWxlKSAlPiUgCiAgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIAogIHN1bW1hcmlzZShudW1fcGF0aWVudHNfY291bnRyeSA9IHN1bShudW1fcGF0aWVudHNfYWxsKSwKICAgICAgICAgICAgbWFsZV9jb3VudCA9IHN1bShtYWxlKSwKICAgICAgICAgICAgZmVtYWxlX2NvdW50ID0gc3VtKGZlbWFsZSksCiAgICAgICAgICAgIC5ncm91cHMgPSAnZHJvcCcpICU+JSAKICB7Ln0KCnNob3d0ZXh0OjpzaG93dGV4dF9hdXRvKCkKZmVtYWxlIDwtIGludFRvVXRmOCg5NzkyKQptYWxlIDwtIGludFRvVXRmOCg5Nzk0KQoKb3ZlcmFsbF9wbG90IDwtIGdlbmRlcl9jb3VudCAlPiUgCiAgbXV0YXRlKG1hbGVfY291bnQgPSAtbWFsZV9jb3VudCkgJT4lIAogIHBpdm90X2xvbmdlcigtIGMoQ291bnRyeSwgbnVtX3BhdGllbnRzX2NvdW50cnkpKSAlPiUgCiAgZ2dwbG90KGFlcyh5ID0gZmN0X3JlbGV2ZWwoQ291bnRyeSwgcmV2KGNvdW50cmllcykpLCAKICAgICAgICAgICAgIHggPSB2YWx1ZSwgY29sb3IgPSBuYW1lLCAKICAgICAgICAgICAgIGZpbGwgPSBDb3VudHJ5KSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gJ2lkZW50aXR5JykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCd3aGl0ZScsICd3aGl0ZScpKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoLTUwMDAsIC0yMDAwLCAwLCAyMDAwLCA1MDAwKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYyg1MDAwLCAyMDAwLCAwLCAyMDAwLCA1MDAwKSwKICAgICAgICAgICAgICAgICAgICAgdHJhbnMgPSBzc3FydF90cmFucykgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGNvbG9yID0gJ3doaXRlJykgKwogIGdlb21fdGV4dChkYXRhID0gLiAlPiUgZmlsdGVyKG5hbWUgPT0gJ21hbGVfY291bnQnKSwKICAgICAgICAgICAgYWVzKHkgPSBDb3VudHJ5LCB4ID0gdmFsdWUgLSAyMipzcXJ0KGFicyh2YWx1ZSkpLCAKICAgICAgICAgICAgICAgIGxhYmVsID0gYWJzKHZhbHVlKSksIGNvbG9yID0gJ2dyZXk0MCcsIHNpemUgPSAzKSArCiAgICBnZW9tX3RleHQoZGF0YSA9IC4gJT4lIGZpbHRlcihuYW1lID09ICdmZW1hbGVfY291bnQnKSwKICAgICAgICAgICAgYWVzKHkgPSBDb3VudHJ5LCB4ID0gdmFsdWUgKyAxOSpzcXJ0KGFicyh2YWx1ZSkpLCAKICAgICAgICAgICAgICAgIGxhYmVsID0gYWJzKHZhbHVlKSksIGNvbG9yID0gJ2dyZXk0MCcsIHNpemUgPSAzKSArCiAgZ2VvbV90ZXh0KGRhdGEgPSBmaWx0ZXIoZ2VuZGVyX2NvdW50LCBDb3VudHJ5ID09ICdGcmFuY2UnKSwKICAgICAgICAgICAgYWVzKHkgPSA2LCB4ID0gZmVtYWxlX2NvdW50IC0gNjAwKSwgZm9udGZhY2UgPSAyLAogICAgICAgICAgICBsYWJlbCA9IGZlbWFsZSwgc2l6ZSA9IDMsIGNvbG9yID0gJ3doaXRlJykgKwogIGdlb21fdGV4dChkYXRhID0gZmlsdGVyKGdlbmRlcl9jb3VudCwgQ291bnRyeSA9PSAnRnJhbmNlJyksCiAgICAgICAgICAgIGFlcyh5ID0gNiwgeCA9IC0gbWFsZV9jb3VudCArIDYwMCksIGZvbnRmYWNlID0gMiwKICAgICAgICAgICAgbGFiZWwgPSBtYWxlLCBzaXplID0gMywgY29sb3IgPSAnd2hpdGUnKSArCiAgbGFicyh5ID0gTlVMTCwgCiAgICAgICB4ID0gJ051bWJlciBvZiBtYWxlL2ZlbWFsZSBwYXRpZW50cyBwZXIgY291bnRyeScsIAogICAgICAgZmlsbCA9IE5VTEwpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvckJsaW5kR3JleTYpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnTm9uZScsCiAgICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMTUsIDUuNSwgMTUuNSwgNTUuNSksCiAgICAgICAgYXhpcy50aWNrcy55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmJvcmRlciA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwYW5lbC5zcGFjaW5nLnkgPSB1bml0KDAsICdwdCcpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgc3RyaXAucGxhY2VtZW50ID0gJ2luc2lkZScsCiAgICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEsICdsaW5lJyksCiAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDkpKSArCiAgTlVMTApgYGAKCgoKIyMgQWdlIHBsb3QgKEIpCgpgYGB7cn0KYWdlX2NvdW50IDwtIGRlbW9fZGVzYyAlPiUgCiAgZmlsdGVyKHVua25vd25fb3RoZXJfYWdlX2dyb3VwL251bV9wYXRpZW50c19hbGwgPCAxKSAlPiUgCiAgc2VsZWN0KENvdW50cnksIG51bV9wYXRpZW50c19hbGwsIGNvbnRhaW5zKCd0bycpLCBlbmRzX3dpdGgoJ3BsdXMnKSkgJT4lIAogIGdyb3VwX2J5KENvdW50cnkpICU+JSAKICBzdW1tYXJpc2UoYWNyb3NzKC5mbnMgPSBzdW0pLCAuZ3JvdXBzID0gJ2Ryb3AnKSAlPiUgCiAgbXV0YXRlX2F0KHZhcnMoLSBudW1fcGF0aWVudHNfYWxsLCAtIENvdW50cnkpLAogICAgICAgICAgICBsaXN0KH4gLiAvIC5kYXRhJG51bV9wYXRpZW50c19hbGwpKSAlPiUgCiAgc2VsZWN0KC1udW1fcGF0aWVudHNfYWxsKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKC0gQ291bnRyeSkgJT4lIAogIG11dGF0ZShuYW1lID0gY2FzZV93aGVuKAogICAgbmFtZSA9PSAnMDB0bzAyJyB+ICcwdG8yJywKICAgIG5hbWUgPT0gJzAzdG8wNScgfiAnM3RvNScsCiAgICBuYW1lID09ICcwNnRvMTEnIH4gJzZ0bzExJywKICAgIFRSVUUgfiBuYW1lCiAgKSkgJT4lIAogIG11dGF0ZShuYW1lID0gZ3N1YigndG8nLCAn4oCTJywgbmFtZSkgJT4lIGdzdWIoJ3BsdXMnLCAnKycsIC4pKQphZ2VfY291bnQkbmFtZSA8LSBmYWN0b3IoYWdlX2NvdW50JG5hbWUsIGxldmVscyA9IHVuaXF1ZShhZ2VfY291bnQkbmFtZSkpCgphZ2VfcGxvdCA8LSBhZ2VfY291bnQgICU+JSAKICBnZ3Bsb3QoYWVzKG5hbWUsIHZhbHVlLCBmaWxsID0gQ291bnRyeSwgZ3JvdXAgPSBDb3VudHJ5KSkgKwogIGdlb21fY29sKHBvc2l0aW9uID0gJ2RvZGdlMicpICsgCiAgY29vcmRfZmxpcCgpICsKICBmYWNldF9ncmlkKHJvd3MgPSB2YXJzKENvdW50cnkpKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSwKICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDEsIDAuMiksCiAgICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbihhZGQgPSBjKDAsMC4wMikpKSArCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKGd1aWRlID0gRkFMU0UpICsKICBsYWJzKHggPSBOVUxMLCB5ID0gJ1BhdGllbnRzIHByb3BvcnRpb24gcGVyIGFnZSBncm91cCcpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JCbGluZEdyZXk2LCBkcm9wID0gRkFMU0UpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xvckJsaW5kR3JleTYsIGRyb3AgPSBGQUxTRSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdOb25lJywKICAgICAgICBheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDE1LCA1LjUsIDUuNSwgNS41LCAncHQnKSkgKwogIE5VTEwKYGBgCgojIyBTZXZlcml0eSB2cy4gYWdlIHBsb3QgKEMpCgpgYGB7cn0KY291bnRyeV9jb2RlcyA8LSByZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2x1a2VzL0lTTy0zMTY2LUNvdW50cmllcy13aXRoLVJlZ2lvbmFsLUNvZGVzL21hc3Rlci9hbGwvYWxsLmNzdicpICU+JQogIG11dGF0ZShuYW1lID0gaWZlbHNlKG5hbWUgPT0gJ1VuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYScsICdVU0EnLCBuYW1lKSkgJT4lCiAgZmlsdGVyKG5hbWUgJWluJSBjb3VudHJpZXMpICU+JQogIHNlbGVjdChDb3VudHJ5ID0gbmFtZSwgY291bl9jb2RlID0gYGFscGhhLTJgKSAlPiUKICBtdXRhdGUoY291bl9jb2RlID0gYXMuZmFjdG9yKGNvdW5fY29kZSkgJT4lIGZjdF9yZWxldmVsKGNvdW50cmllc19jb2RlKSkKCmFnZV9zZXZlcml0eSA8LSBkZW1vX3BlcmMgJT4lIAogIGxlZnRfam9pbihjb3VudHJ5X2NvZGVzLCBieSA9ICdDb3VudHJ5JykgJT4lCiAgZ2dwbG90KGFlcyhtZWRpYW5fYWdlLCBudW1fcGF0aWVudHNfZXZlcl9zZXZlcmUsIAogICAgICAgICAgICAgY29sb3IgPSBjb3VuX2NvZGUpKSArCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG51bV9wYXRpZW50c19hbGwpLCBhbHBoYSA9IDAuOCkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KCksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxLCAwLjIpKSArCiAgbGFicyh4ID0gJ01lZGlhbiBhZ2UgZXN0aW1hdGUnLCAKICAgICAgIHkgPSAnU2V2ZXJlIGNhc2UgcHJvcG9ydGlvbicsIAogICAgICAgY29sb3IgPSBOVUxMKSArCiAgc2NhbGVfc2l6ZSh0cmFucyA9ICJsb2cxMCIsIGd1aWRlID0gRkFMU0UpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JCbGluZEdyZXk2KSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsIDEpKSArCiAgdGhlbWUoCiAgICAjIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC45LCAwLjcpLAogICAgbGVnZW5kLnBvc2l0aW9uID0gJ2xlZnQnLAogICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbig1LjUsIDUuNSwgMTAuNSwgMTUuNSksCiAgICBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLAogICAgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDAuNywgJ2xpbmUnKSwKICAgIGxlZ2VuZC5rZXkud2lkdGggPSB1bml0KDAuNCwgJ2xpbmUnKSwKICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAsIHNpemUgPSA5KSkgKwogIE5VTEwKYGBgCgojIyBSYWNlIHBsb3QgKEQpCgpgYGB7cn0KcmFjZV9jb3VudCA8LSBkZW1vX2Rlc2MgJT4lIAogIGZpbHRlcih1bmtub3duX290aGVyX3JhY2UvbnVtX3BhdGllbnRzX2FsbCA8IDEpICU+JSAKICBzZWxlY3QoQ291bnRyeSwgbnVtX3BhdGllbnRzX2FsbCwgYWxsX29mKHJhY2VzKSwgdW5rbm93bl9vdGhlcl9yYWNlKSAlPiUgCiAgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIAogIHN1bW1hcmlzZShhY3Jvc3MoLmZucyA9IHN1bSksIC5ncm91cHMgPSAnZHJvcCcpICU+JSAKICBtdXRhdGVfYXQodmFycygtIG51bV9wYXRpZW50c19hbGwsIC0gQ291bnRyeSksCiAgICAgICAgICAgIGxpc3QofiAuIC8gLmRhdGEkbnVtX3BhdGllbnRzX2FsbCkpICU+JSAKICBzZWxlY3QoLW51bV9wYXRpZW50c19hbGwpICU+JSAKICBwaXZvdF9sb25nZXIoLSBDb3VudHJ5KSAlPiUgCiAgbXV0YXRlKG5hbWUgPSBnc3ViKCdfJywgJyAnLCBuYW1lKSAlPiUgCiAgICAgICAgICAgc3RyX3RvX3RpdGxlKC4pICU+JSAKICAgICAgICAgICBnc3ViKCdIaXNwYW5pYyAnLCAnSGlzcGFuaWMvJywgLikgJT4lIAogICAgICAgICAgIGdzdWIoJ0hhd2FpaWFuICcsICdIYXdhaWlhbi8nLCAuKSAlPiUgCiAgICAgICAgICAgZ3N1YignVW5rbm93biBPdGhlciBSYWNlJywgJ090aGVyL1Vua25vd24nLC4gKSwKICAgICAgICAgbmFtZSA9IGZjdF9yZWxldmVsKG5hbWUsIFJhY2VzKSkKCnJhY2VfcGxvdCA8LSByYWNlX2NvdW50ICU+JSAKICAjIHJlbW92ZSBvbmUgc2l0ZSBpbiBJdGFseSB0aGF0IHJlcG9ydGVkIGFsbCB3aGl0ZSBldGhuaWNpdHkKICBmaWx0ZXIoQ291bnRyeSAhPSAnSXRhbHknKSAlPiUgCiAgZ2dwbG90KGFlcyhuYW1lLCB2YWx1ZSwgZmlsbCA9IENvdW50cnksIGdyb3VwID0gQ291bnRyeSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICdkb2RnZTInKSArIAogIGNvb3JkX2ZsaXAoKSArCiAgZmFjZXRfZ3JpZChyb3dzID0gdmFycyhDb3VudHJ5KSkgKwogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSksCiAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAxLCAwLjIpLAogICAgICAgICAgICAgICAgICAgICBleHBhbmQgPSBleHBhbnNpb24oYWRkID0gYygwLDAuMDIpKSkgKwogIHNjYWxlX3NpemVfY29udGludW91cyhndWlkZSA9IEZBTFNFKSArCiAgbGFicyh4ID0gTlVMTCwgeSA9ICdQYXRpZW50IHByb3BvcnRpb24gcGVyIHJhY2UvZXRobmljaXR5IGdyb3VwJykgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvckJsaW5kR3JleTYsIGRyb3AgPSBGQUxTRSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yQmxpbmRHcmV5NiwgZHJvcCA9IEZBTFNFKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gJ05vbmUnLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gLjgpKSArCiAgTlVMTApgYGAKCiMjIENvbXBvc2l0ZSBwbG90CgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9OCwgd2FybmluZz1GQUxTRX0KZ2VuZGVyX3JhY2UgPC0gcGxvdF9ncmlkKG92ZXJhbGxfcGxvdCwgYWdlX3NldmVyaXR5LCByYWNlX3Bsb3QsIG5jb2wgPSAxLAogICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuNywgMSwgMSksIAogICAgICAgICAgbGFiZWxzID0gYygnQScsICdCJywgJ0MnKSwgYXhpcyA9ICdyJykKYWJjZCA8LSBwbG90X2dyaWQoZ2VuZGVyX3JhY2UsIGFnZV9wbG90LCBuY29sID0gMiwKICAgICAgICAgICAgICAgICAgcmVsX3dpZHRocyA9IGMoMS4yNSwgMSApLCBsYWJlbHMgPSBjKCcnLCAnRCcpLAogICAgICAgICAgICAgICAgICBheGlzID0gJ2InKQphYmNkCmdnc2F2ZSgnZmlncy9jb21wb3NpdGVfcGxvdC5wbmcnLCBhYmNkLCBoZWlnaHQgPSA2LjUsIHdpZHRoID0gOSkKZ2dzYXZlKCdmaWdzL3RpZmZzL2ZpZ18yLnRpZmYnLCBhYmNkLCBoZWlnaHQgPSA2LjUsIHdpZHRoID0gOSwgZHBpID0gMzAwKQpgYGAKCgoKCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CiMgZ2VuZGVyX3Bsb3QgPC0gZGVtb19nZW5kZXIgJT4lIAojICAgZ2dwbG90KGFlcyhmZW1hbGUsIG51bV9wYXRpZW50c19ldmVyX3NldmVyZSwgCiMgICAgICAgICAgICAgIGNvbG9yID0gQ291bnRyeSkpICsKIyAgIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAuNSwgbGluZXR5cGUgPSAnZGFzaGVkJykgKwojICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG51bV9wYXRpZW50c19hbGwpLCBhbHBoYSA9IDAuOCkgKwojICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSwKIyAgICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDAsIDAuNjUpLAojICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZCA9IGV4cGFuc2lvbihhZGQgPSBjKDAuMTgsIDApKSkgKwojICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoKSwKIyAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMSwgMC4yKSkgKwojICAgbGFicygKIyAgICAgeCA9ICdQcm9wb3J0aW9uIG9mIGZlbWFsZSBwYXRpZW50cycsIAojICAgICB5ID0gJ1Byb3BvcnRpb24gb2Ygc2V2ZXJlIGNhc2VzJywgCiMgICAgIGNvbG9yID0gTlVMTCwgCiMgICAgIHNpemUgPSAnVG90YWwgbnVtYmVyIG9mIHBhdGllbnRzCiMgYXQgZWFjaCBzaXRlJykgKwojICAgc2NhbGVfc2l6ZSh0cmFucyA9ICJsb2cxMCIsIGd1aWRlID0gRkFMU0UpICsKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvckJsaW5kR3JleTYpICsKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMC4xNSwgMC4yOCksCiMgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigxMC41LCA1LjUsIDUuNSwgNDUuNSwgJ3B0JyksCiMgICAgICAgICBsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKIyAgICAgICAgIGxlZ2VuZC5rZXkuaGVpZ2h0ID0gdW5pdCgxLCAnbGluZScpLAojICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMCwgc2l6ZSA9IDkpKSArCiMgICBOVUxMCgojIGFnZV9yYWRhciA8LSBhZ2VfcGVyYyAlPiUgCiMgICBzZWxlY3QoLWNvbnRhaW5zKCdudW0nKSkgJT4lIAojICAgZ3JvdXBfYnkoQ291bnRyeSkgJT4lIAojICAgc3VtbWFyaXNlKGFjcm9zcyguZm5zID0gbWVhbl9zZSksIC5ncm91cHMgPSAnZHJvcCcpICU+JSAKIyAgIG11dGF0ZShDb3VudHJ5ID0gYXMuY2hhcmFjdGVyKENvdW50cnkpKSAlPiUgCiMgICByZW5hbWUoZ3JvdXAgPSBDb3VudHJ5KQojIAojIG10Y2FycyAlPiUKIyAgICAgIGFkZF9yb3duYW1lcyggdmFyID0gImdyb3VwIiApICU+JQojICAgICAgbXV0YXRlX2VhY2goZnVucyhyZXNjYWxlKSwgLWdyb3VwKSAlPiUKIyAgICAgIHRhaWwoNCkgJT4lIHNlbGVjdCgxOjEwKSAtPiBtdGNhcnNfcmFkYXIKIyAKIyBnZ3JhZGFyKGFnZV9yYWRhciwgCiMgICAgICAgICB2YWx1ZXMucmFkYXIgPSBjKE5BLCBwYXN0ZTAoYygyNSwgNTApLCAnJScpKSwKIyAgICAgICAgIGdyb3VwLmNvbG91cnMgPSBjb2xvckJsaW5kR3JleTZbLTRdLAojICAgICAgICAgZ3JpZC5taWQgPSAwLjI1LAojICAgICAgICAgZ3JpZC5tYXggPSAwLjUsCiMgICAgICAgICBiYXNlLnNpemUgPSAxKQoKIyBhZ2VfcGVyYyAlPiUgCiMgICBwaXZvdF9sb25nZXIoLSBjKENvdW50cnksIG51bV9wYXRpZW50c19hbGwsIG51bV9wYXRpZW50c19ldmVyX3NldmVyZSkpICU+JSAKIyAgIGdncGxvdChhZXModmFsdWUsIG51bV9wYXRpZW50c19ldmVyX3NldmVyZSwgCiMgICAgICAgICAgICAgIGNvbG9yID0gQ291bnRyeSkpICsKIyAgIGZhY2V0X3dyYXAofiBuYW1lKSArCiMgICBnZW9tX3BvaW50KGFlcyhzaXplID0gbG9nMihudW1fcGF0aWVudHNfYWxsKSksIGFscGhhID0gMC44KSArCiMgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDEpKSArCiMgICBzY2FsZV9zaXplX2NvbnRpbnVvdXMoZ3VpZGUgPSBGQUxTRSkgKwojICAgbGFicyh4ID0gJyUgcGF0aWVudHMgaW4gZWFjaCBhZ2UgZ3JvdXAnLCB5ID0gJyUgc2V2ZXJlIGNhc2VzJykgKwojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yQmxpbmRHcmV5NiwgZHJvcCA9IEZBTFNFKSArCiMgICBOVUxMCgojIGFnZV9wZXJjICU+JSAKIyAgIHBpdm90X2xvbmdlcigtIGMoQ291bnRyeSwgbnVtX3BhdGllbnRzX2FsbCwgbnVtX3BhdGllbnRzX2V2ZXJfc2V2ZXJlKSkgJT4lIAojICAgZ2dwbG90KGFlcyhuYW1lLCB2YWx1ZSwgY29sb3IgPSBDb3VudHJ5KSkgKwojICAgIyBmYWNldF9ncmlkKGNvbHMgPSB2YXJzKG5hbWUpLCBzY2FsZXMgPSAnZnJlZV94JykgKwojICAgZ2VvbV9ib3hwbG90KGFscGhhID0gMC44KSArCiMgICAjIGdlb21fdmlvbGluKGFlcyhjb2xvciA9IENvdW50cnkpKSArCiMgICAjIGdlb21faml0dGVyKCkgKwojICAgIyBnZW9tX3BvaW50KGFlcyhzaXplID0gbG9nMihudW1fcGF0aWVudHNfYWxsKSksIGFscGhhID0gMC44KSArCiMgICAjIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMSkpICsKIyAgICMgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAxKSkgKwojICAgc2NhbGVfc2l6ZV9jb250aW51b3VzKGd1aWRlID0gRkFMU0UpICsKIyAgIGxhYnMoeCA9ICclIHBhdGllbnRzIGluIGVhY2ggYWdlIGdyb3VwJywgeSA9ICclIHBhdGllbnQnKSArCiMgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sb3JCbGluZEdyZXk2LCBkcm9wID0gRkFMU0UpICsKIyAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yQmxpbmRHcmV5NiwgZHJvcCA9IEZBTFNFKSArCiMgICBjb29yZF9wb2xhcigpICsKIyAgIE5VTEwKIyAKIyByYWNlX3BlcmMgJT4lIAojICAgcGl2b3RfbG9uZ2VyKC0gYyhDb3VudHJ5LCBudW1fcGF0aWVudHNfYWxsLCBudW1fcGF0aWVudHNfZXZlcl9zZXZlcmUpKSAlPiUgCiMgICBnZ3Bsb3QoYWVzKHZhbHVlLCBudW1fcGF0aWVudHNfZXZlcl9zZXZlcmUsIAojICAgICAgICAgICAgICBjb2xvciA9IENvdW50cnkpKSArCiMgICBmYWNldF93cmFwKH4gbmFtZSkgKwojICAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IGxvZzIobnVtX3BhdGllbnRzX2FsbCkpLCBhbHBoYSA9IDAuOCkgKwojICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoYWNjdXJhY3kgPSAwLjEpKSArCiMgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKIyAgIHNjYWxlX3NpemVfY29udGludW91cyhndWlkZSA9IEZBTFNFKSArCiMgICBsYWJzKHggPSAnJSBwYXRpZW50cyBpbiBlYWNoIHJhY2UvZXRobmljaXR5IGdyb3VwJywgeSA9ICclIHNldmVyZSBjYXNlcycpICsKIyAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjb2xvckJsaW5kR3JleTYsIGRyb3AgPSBGQUxTRSwgZ3VpZGUgPSBGQUxTRSkgKwojICAgTlVMTAojIAojIHJhY2VfcGVyYyAlPiUgCiMgICBwaXZvdF9sb25nZXIoLSBjKENvdW50cnksIG51bV9wYXRpZW50c19hbGwsIG51bV9wYXRpZW50c19ldmVyX3NldmVyZSkpICU+JSAKIyAgIGdncGxvdChhZXMobmFtZSwgdmFsdWUsIGNvbG9yID0gQ291bnRyeSkpICsKIyAgICMgZmFjZXRfd3JhcCh+IG5hbWUpICsKIyAgICMgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IGxvZzIobnVtX3BhdGllbnRzX2FsbCkpLCBhbHBoYSA9IDAuOCkgKwojICAgZ2VvbV9ib3hwbG90KCkgKwojICAgIyBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpwZXJjZW50X2Zvcm1hdChhY2N1cmFjeSA9IDAuMSkpICsKIyAgIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OnBlcmNlbnRfZm9ybWF0KGFjY3VyYWN5ID0gMC4xKSkgKwojICAgc2NhbGVfc2l6ZV9jb250aW51b3VzKGd1aWRlID0gRkFMU0UpICsKIyAgIGxhYnMoeCA9ICclIHBhdGllbnRzIGluIGVhY2ggcmFjZS9ldGhuaWNpdHkgZ3JvdXAnLCB5ID0gJyUgc2V2ZXJlIGNhc2VzJykgKwojICAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbG9yQmxpbmRHcmV5NiwgZHJvcCA9IEZBTFNFLCBndWlkZSA9IEZBTFNFKSArCiMgICBOVUxMCmBgYAo=