Debois Project
A Lot of this is an absolute mess. Not many Comments. Just figured I should post it anyways.
1 Database load and setup
Used a local postgressql database to fit full data in memory. This code is mostly just importing it into the database, loading it, etc.
# Load Database
conn <-
dbConnect(
drv = Postgres(),
user = 'lizsql',
password = 'lizsql',
host = "localhost",
port = "5432",
dbname = "postgres"
)debois_1900 <- tbl(conn, in_schema('public', 'debois_1900'))
acs_2019_5yr <- tbl(conn, in_schema('public', 'acs_2019_5yr_v2'))# Reads into Postgres. Replace variable and table names for each dataset.
# Had to use postgres as full 1900 census would not fit in memory.
cps_ddi_file <- "usa_00009.xml"
cps_data_file <- "usa_00009.dat"
# Add data to tables in chunks
ddi <- read_ipums_ddi(cps_ddi_file)
read_ipums_micro_chunked(
ddi,
data_file = cps_data_file,
readr::SideEffectChunkCallback$new(function(x, pos) {
if (pos == 1) {
dbWriteTable(conn, "acs_2019_5yr_v2", x)
} else {
dbWriteTable(conn, "acs_2019_5yr_v2", x, row.names = FALSE, append = TRUE)
}
}),
chunk_size = 30000,
verbose = FALSE
)
sf <- debois_1900 |>
filter(STATEFIP == 13, RACE == 2) |>
count(BPL) |>
ipums_collect(ddi)
f2 <- debois_1900 |>
filter(BPL == 13, RACE == 2) |>
count(STATEFIP) |>
ipums_collect(ddi)2 Migration Chart
This is very messy. But basically involved filtering out various parts of the dataset and then creating the different figures.
migration_to_georgia <- f |> mutate(region = labelled::to_factor(BPL), FIPS = labelled::remove_labels(BPL)) |> select(region, FIPS, n)
saveRDS(migration_to_georgia, file = "migration_to_georgia")
migration_from_georgia <- f2 |> mutate(region = labelled::to_factor(STATEFIP), FIPS = labelled::remove_labels(STATEFIP)) |>
select(region, FIPS, n)
#saveRDS(migration_from_georgia, file = 'migration_from_georgia')fixed_numbers <-
migration_from_georgia %>% filter(FIPS < 60) %>% mutate(region = tolower(region)) %>% filter(region != 'district of columbia', FIPS != 13) %>% mutate(n = as.numeric(n)) %>% select(region, n)
states_map <- map_data('state')
total_map <- left_join(states_map, fixed_numbers, by = 'region')
state_name <-
data.frame(
abb = state.abb,
region = tolower(state.name),
x = state.center$x,
y = state.center$y
) |> filter(abb != 'HI', abb != 'AK') |>
left_join(fixed_numbers) #,
# TRUE ~ n))
from_ga <- ggplot(total_map, aes(long, lat, group = group)) +
# annotation_map_tile("stamenwatercolor") +
geom_polygon(aes(fill = n), color = "white") +
scale_fill_viridis_c(option = "C",
trans = 'log',
direction = -1) + geom_shadowtext(data = state_name,
aes(
x = x,
y = y,
label = ifelse(abb == 'GA', "GA\n ", paste0(abb,'\n', ifelse(is.na(n), 0, n))),
group = 1
),
size = 2) +
# annotation_scale() +
# theme_void() +
theme(axis.line=element_blank(),axis.text.x=element_blank(),
axis.text.y=element_blank(),axis.ticks=element_blank(),
axis.title.x=element_blank(), legend.position = 'none',
axis.title.y=element_blank(),
panel.background=element_blank(),panel.border=element_blank(),panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),plot.background=element_blank()) +
labs(
color = 'Population',
title = 'Populated Migrated from Georgia',
subtitle = 'Population born in Georgia by current state of residence (if living outside Georgia)'
)
# theme(plot.title = element_text(hjust = 0.5))
#theme(legend.position="none")
from_ga
ggsave(
'from_ga.png',
from_ga,
width = 2560,
height = 1440,
units = c('px')
)
fixed_numbers <-
migration_to_georgia %>% filter(FIPS < 60) %>% mutate(region = tolower(region)) %>% filter(region != 'district of columbia', FIPS != 13) %>% mutate(n = as.numeric(n)) %>% select(region, n)
states_map <- map_data('state')
total_map <- left_join(states_map, fixed_numbers, by = 'region')
state_name <-
data.frame(
abb = state.abb,
region = tolower(state.name),
x = state.center$x,
y = state.center$y
) |> filter(abb != 'HI', abb != 'AK') |>
left_join(fixed_numbers)# %>% mutate(n = case_when(abb == 'GA' ~ 958984,
# TRUE ~ n))
to_ga <- ggplot(total_map, aes(long, lat, group = group)) +
# annotation_map_tile("stamenwatercolor") +
geom_polygon(aes(fill = n), color = "white") +
scale_fill_viridis_c(option = "C",
trans = 'log',
direction = -1) + geom_shadowtext(data = state_name,
aes(
x = x,
y = y,
label = ifelse(abb == 'GA', "GA\n ", paste0(abb,'\n', ifelse(is.na(n), 0, n))),
group = 1
),
size = 2) +
# annotation_scale() +
# theme_void() +
#theme(plot.title = element_text(hjust = 0.5)) +
labs(
color = 'Population',
title = 'Population Migrated to Georgia',
subtitle = 'Number of current Georgia residents by place of birth (if born outside georgia)'
) +
theme(axis.line=element_blank(),axis.text.x=element_blank(),
axis.text.y=element_blank(),axis.ticks=element_blank(),
axis.title.x=element_blank(),
axis.title.y=element_blank(), legend.position = 'none',
panel.background=element_blank(),panel.border=element_blank(),panel.grid.major=element_blank(),
panel.grid.minor=element_blank(),plot.background=element_blank())
# plot.margin = margin())
#theme(legend.position="none")
to_ga
ggsave(
'to_ga.png',
to_ga,
width = 2560,
height = 1440,
units = c('px')
)
patchwork = to_ga / from_ga
patchwork <- patchwork +
plot_annotation(
theme = theme(legend.position = 'none',
plot.title = element_text(size = 20),
plot.margin = margin(t = 25, b = 25, l = 25, r = 25)),
title = 'Migration of African Americans to and from Georgia, 1900',
subtitle = 'Residents of Georgia born in another state, and residents of other states born in Georgia\n ',
caption = 'Created by Elizabeth Goodwin using the full 1900 Census, IPUMS USA'
# subtitle = 'These 3 plots will reveal yet-untold secrets about our beloved data-set',
# caption = 'Disclaimer: None of these plots are insightful',
# tag_levels = c('A', '1'),
# tag_prefix = 'Fig. ',
# tag_sep = '.',
# tag_suffix = ':'
)
patchwork
filename = 'lot-11931-no-08-GOODWIN.pdf'
filenamepng = 'lot-11931-no-08-GOODWIN.png'
ggsave(filename,
plot = patchwork,
dpi = 300,
height = 11,
width = 8.5
)3 Marital Status Figure
density <- acs_2019_5yr |>
filter(RACE == 1) |>
mutate(
age_bucket = case_when(
AGE < 16 ~ "0-15",
AGE < 21 ~ "15-20",
AGE < 26 ~ "20-25",
AGE < 31 ~ "25-30",
AGE < 36 ~ "30-35",
AGE < 46 ~ "35-45",
AGE < 56 ~ "45-55",
AGE < 66 ~ "55-65",
AGE < 76 ~ "65-75",
AGE < 89 ~ "Over 75",
TRUE ~ 'other'
),
Marital_Status = case_when(
MARST < 3 ~ 'Married',
MARST < 5 ~ 'Separated/\nDivorced',
MARST == 5 ~ "Widowed",
MARST == 6 ~ "Single"
)
) |>
count(SEX, age_bucket, Marital_Status) |>
ipums_collect(ddi) |>
filter(age_bucket != 'other') |>
add_count(SEX, age_bucket, wt = n, name = 'total') |>
mutate(pct = 100*n / total) |>
mutate(SEX = case_when(SEX == 1 ~ 'Male', TRUE ~ "Female")) |>
mutate(Marital_Status = factor(Marital_Status, levels = rev(c('Single', 'Married', "Separated/\nDivorced", 'Widowed'))))to_swap = rev(c("#9A8A76", "#db735c", "#EFA86E","#555555" ))
male <-
ggplot((density |> filter(SEX == 'Male')),
aes(x = age_bucket, y = as.numeric(pct), fill = Marital_Status)) +
geom_bar(stat = "identity", width = 1, color = 'black', size = .3) +
coord_flip() +
labs(subtitle = 'Male',
y = element_blank(),
fill = "Status",
x = "Age (Years)") +
# hrbrthemes::theme_ipsum_ps() +
theme(legend.position = 'bottom'
# plot.subtitle = element_text(hjust = 0.5)
) +
geom_shadowtext(aes(label = ifelse(round(pct) > 3, paste0(round(pct), "%"), "")), size = 2.8,position = position_stack(vjust = .5)) +
scale_y_reverse(limits=c(101,0), labels = scales::percent_format(scale = 1), expand = expansion(mult = c(.05,.025))) +
scale_fill_manual(values = to_swap)
female <-
ggplot((density |> filter(SEX == 'Female')),
aes(
x = age_bucket,
y = as.numeric(pct),
fill = Marital_Status
)) +
geom_bar(stat = "identity", width = 1, color = 'black', size = .3) +
coord_flip() +
labs(subtitle = 'Female',
fill = "Status",
y = element_blank()
) +
# hrbrthemes::theme_ipsum_ps() +
geom_shadowtext(aes(label = ifelse(round(pct) > 3, paste0(round(pct), "%"), "")), size = 2.8,position = position_stack(vjust = .5)) +
scale_y_continuous(labels = scales::percent_format(scale = 1), expand = expansion(mult = c(.025,0.05))) +
coord_flip() + #+ coord_flip() + scale_y_reverse(limits=c(100,-100))+
theme(
legend.position = 'none',
axis.title.y = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.line.y = element_blank(),
# plot.subtitle = element_text(hjust = 0.5),
plot.margin = margin(l = 0)
) + scale_fill_manual(values = to_swap)
combined <- male + female & theme(legend.position = "right", legend.text=element_text(size=8))
combined <- combined + plot_layout(guides = "collect") + plot_annotation(
title = 'Marital Status of African Americans',
subtitle = 'By Age and Sex, 2015-2019',
caption = element_text('Made by Elizabeth Goodwin\n Source: 2015-2019 ACS, IPUMS USA', size = 8)) +
plot_annotation(theme = theme(plot.margin = margin(r = 15, l = 15, t = 20, b = 20, unit = 'pt')))
combined
ggsave('lot-11931-no-53-GOODWIN.pdf',combined, dpi = 400, height = 5.83, width = 9)
#ggsave('lot-11931-no-53-GOODWIN.png',combined, dpi = 400, height = 5.83, width = 9)4 Employment Figure
acs_occ_pct <- acs_2019_5yr %>% count(OCC2010, RACE, wt = PERWT) |> add_count(OCC2010, wt = n, name = 'total') |> mutate(pct = 100*n/total) |> ipums_collect(ddi)acs_occ <- acs_occ_pct |>
mutate(OCC2010 = as.numeric(OCC2010),
occ = case_when(
((OCC2010 >= 10) & (OCC2010 <= 430)) ~ 'Management, Business, Science, and Arts',
((OCC2010 >= 500 ) & (OCC2010 <= 730)) ~ 'Business Operations Specialists',
((OCC2010 >= 800) & (OCC2010 <= 950)) ~ 'Financial Specialists',
((OCC2010 >= 1000) & (OCC2010 <= 1240)) ~ 'Computer and Mathematical',
((OCC2010 >= 1300) & (OCC2010 <= 1540)) ~ 'Architecture and Engineering',
((OCC2010 >= 1550) & (OCC2010 <= 1560)) ~ 'Technicians',
((OCC2010 >= 1600) & (OCC2010 <= 1980)) ~ 'Life, Physical, and Social Science',
((OCC2010 >= 2000) & (OCC2010 <= 2060)) ~ 'Community and Social Services',
((OCC2010 >= 2100) & (OCC2010 <= 2150)) ~ 'Legal',
((OCC2010 >= 2200) & (OCC2010 <= 2550)) ~ 'Education, Training, and Library',
((OCC2010 >= 2600) & (OCC2010 <= 2920)) ~ 'Arts, Design, Entertainment, Sports, and Media',
((OCC2010 >= 3000) & (OCC2010 <= 3540)) ~ 'Healthcare Practitioners and Technicians',
((OCC2010 >= 3600) & (OCC2010 <= 3650)) ~ 'Healthcare Support',
((OCC2010 >= 3700) & (OCC2010 <= 3950)) ~ 'Protective Service',
((OCC2010 >= 4000) & (OCC2010 <= 4150)) ~ 'Food Preparation and Serving',
((OCC2010 >= 4200) & (OCC2010 <= 4250)) ~ 'Building and Grounds Cleaning and Maintenance',
((OCC2010 >= 4300) & (OCC2010 <= 4650)) ~ 'Personal Care and Service',
((OCC2010 >= 4700) & (OCC2010 <= 4965)) ~ 'Sales and Related',
((OCC2010 >= 5000) & (OCC2010 <= 5940)) ~ 'Office and Administrative Support',
((OCC2010 >= 6005) & (OCC2010 <= 6130)) ~ 'Farming, Fishing, and Forestry',
((OCC2010 >= 6200) & (OCC2010 <= 6765)) ~ 'Construction',
((OCC2010 >= 6800) & (OCC2010 <= 6940)) ~ 'Extraction',
((OCC2010 >= 7000) & (OCC2010 <= 7630)) ~ 'Installation, Maintenance, and Repair',
((OCC2010 >= 7700) & (OCC2010 <= 8965)) ~ 'Production',
((OCC2010 >= 9000) & (OCC2010 <= 9750)) ~ 'Transportation and Material Moving',
((OCC2010 >= 9800) & (OCC2010 <= 9830)) ~ 'Military Specific',
((OCC2010 >= 9920) & (OCC2010 <= 9920)) ~ 'Unemployed for 5+ years or Never Worked',
TRUE ~ 'Other'),
race = case_when(RACE == 1 ~ 'White', RACE == 2 ~ 'Black', TRUE ~ 'Other')
) |>
ungroup() |>
select(occ, race, n, total, pct) |>
count(occ, race, wt = n) |>
add_count(occ, wt = n, name = 'total') |>
mutate(pct = 100*n/total) |>
filter(race != 'Other') |>
select(occ, race, pct, n) |>
pivot_wider(names_from = race, values_from = c(pct,n)) |>
mutate(avg_pct_black = weighted.mean(pct_Black, n_Black),
diff_from_mean = pct_Black - avg_pct_black,
occ = fct_reorder(occ, diff_from_mean),
tot = sum(n_Black, n_White),
ci = 196 * sqrt(((n_Black / tot) * (1 - (n_Black / tot))) / tot))acs_occ_fig <- acs_occ %>%
ggplot(aes(x = pct_Black, y = occ, color = diff_from_mean)) +
geom_point(size = 3) +
geom_vline(aes(xintercept = avg_pct_black), linetype = 2) +
scale_color_viridis() +
theme(legend.position = 'none',
plot.title.position = "plot",
plot.caption.position = "plot",
plot.margin = margin(r=25, l=25, t=25, b=10)
) +
labs(
title = 'Percent African American by Employment Sector',
subtitle = 'Grouped by overall Employment Category. Dotted line is overall percent of population',
x = "Percent African American",
y = "Employment Sector",
color = 'Difference from overall percent'
)
acs_occ_figacs_occ_2 <- acs_occ_pct |>
mutate(occ = labelled::to_character(OCC2010),
#race = labelled::to_factor(RACE)
race = case_when(RACE == 1 ~ 'White', RACE == 2 ~ 'Black', TRUE ~ 'Other')
) |>
ungroup() |>
mutate(
occ = case_when(occ == 'Postal Service Mail Sorters, Processors, and Processing Machine Operators' ~ "Postal Service Mail Sorters and Processors",
occ == "Farmers, Ranchers, and Other Agricultural Managers" ~ "Farmers and Ranchers",
occ == "Security Guards and Gaming Surveillance Officers" ~ "Security Guards",
TRUE ~ occ)) |>
select(occ, race, n, total, pct) |>
count(occ, race, wt = n) |>
add_count(occ, wt = n, name = 'total') |>
mutate(pct = 100*n/total) |>
filter(race != 'Other') |>
#add_count(race, wt = n, name = 'test') |>
# filter(race < 3) |>
# mutate(race = case_when(RACE == 1 ~ 'White', TRUE ~ 'Black'))|>
select(occ, race, pct, n) |>
pivot_wider(names_from = race, values_from = c(pct,n)) |>
mutate(avg_pct_black = weighted.mean(pct_Black, n_Black),
diff_from_mean = pct_Black - avg_pct_black,
occ = fct_reorder(occ, diff_from_mean),
tot = sum(n_Black, n_White),
ci = 196 * sqrt(((n_Black / tot) * (1 - (n_Black / tot))) / tot)) %>% mutate(type = case_when(diff_from_mean < 0 ~ 'Low', TRUE ~ 'High')) |> group_by(type) %>%
slice_min(desc(abs(diff_from_mean)), n= 8) %>%
ungroup()
acs_occ_fig_2 <- acs_occ_2 %>%
ggplot(aes(x = pct_Black, y = occ, color = diff_from_mean)) +
geom_point(size = 3) +
geom_vline(aes(xintercept = avg_pct_black), linetype = 2) +
scale_color_viridis() +
theme(legend.position = 'none',
plot.title.position = "plot", # NEW parameter. Apply for subtitle too.
plot.caption.position = "plot",
plot.margin = margin(r=25, l=25, t=25, b=25)
) +
labs(
title = 'Top 8 Highest and Lowest Jobs by African American representation',
subtitle = 'Grouped by specific employment classification, not overall sector',
x = "Percent African American",
y = "Employment Role",
color = 'Difference from overall percent'
) + facet_free(type ~ .)
acs_occ_fig_2#+ coord_flip()combined_occ <- acs_occ_fig / acs_occ_fig_2 + plot_layout(heights = c(1.5,1)) + plot_annotation(theme = theme(legend.position = 'none', plot.margin = margin(b = 10)), caption = 'Made by Elizabeth Goodwin | 2010 OCCSCORE, 2015-2019 ACS, IPUMS USA')
ggsave('original-GOODWIN.pdf', plot = combined_occ, dpi = 400, height = 10, width = 8)
#ggsave('original-GOODWIN.png', plot = combined_occ, dpi = 400, height = 10, width = 8)LS0tCnRpdGxlOiAnRGVib2lzIFByb2plY3QnCmF1dGhvcnNzOiBFbGl6YWJldGggR29vZHdpbgpkYXRlOiAyMDIyLTA5LTIzCm91dHB1dDoKICBybWRmb3JtYXRzOjpyb2JvYm9vazoKICMgICBmaWdfY2FwdGlvbjogdHJ1ZQojICAgIGxpZ2h0Ym94OiB0cnVlCiAjICAgZ2FsbGVyeTogdHJ1ZQogICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAjICBkZl9wcmludDogcGFnZWQKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIG51bWJlcl9zZWN0aW9uczogVFJVRQogICAgdG9jX2RlcHRoOiA1CiAgIyAgY29kZV9mb2xkaW5nOiBoaWRlIAogICAgdXNlX2Jvb2tkb3duOiB0cnVlCiAgICAjICAgI3BkZi1lbmdpbmU6CiAgICAgICAjICAgICBwZGZsYXRleAogICMgcm1kZm9ybWF0czo6cm9ib2Jvb2s6CiAgIyAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgIyAgIGxpZ2h0Ym94OiB0cnVlCiAgIyAgIGdhbGxlcnk6IHRydWUKICAjICAgc2VsZl9jb250YWluZWQ6IHRydWUKICAjICAgZGZfcHJpbnQ6IHBhZ2VkCiAgIyAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAjICAgbnVtYmVyX3NlY3Rpb25zOiBUUlVFCiAgIyAgIHRvY19kZXB0aDogNQogICMgICBjb2RlX2ZvbGRpbmc6IGhpZGUgCiAgIyAgIHVzZV9ib29rZG93bjogdHJ1ZQojZW1iZWQtcmVzb3VyY2VzOiB0cnVlCgpmb250c2l6ZTogMTJwdAplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGNvbnNvbGUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KHRhYi50b3BjYXB0aW9uID0gVCwgZnRfZG9fYXV0b2ZpdCA9IFQsIGZ0LmFsaWduID0gImxlZnQiLCBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDEyLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkKCiNzZXR3ZCgiL1VzZXJzL2xpei9Eb2N1bWVudHMvUHJvamVjdHMvIikKCiMgTW9zdCBvZiB0aGVzZSBwYWNrYWdlcyBhcmUgbm90IG5lZWRlZCBhdCBhbGwsIEkganVzdCBrZWVwIGEgYmlnIGltcG9ydCBsaXN0IHNvIEkgaGF2ZSBldmVyeXRoaW5nIEkgd291bGQgZXZlciBuZWVkCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KG1hZ3JpdHRyKQpsaWJyYXJ5KGhhdmVuKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dmb3J0aWZ5KQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHNqbGFiZWxsZWQpCmxpYnJhcnkoZ2dyZXBlbCkKbGlicmFyeShzY2FsZXMpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkoaHRtbHRvb2xzKQpsaWJyYXJ5KEhtaXNjKQpsaWJyYXJ5KHNoYWRvd3RleHQpCmxpYnJhcnkoaHJicnRoZW1lcykKbGlicmFyeShSUG9zdGdyZXMpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3NwYXRpYWwpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KHNjaWNvKQpsaWJyYXJ5KHVzbWFwKQpsaWJyYXJ5KGRicGx5cikKbGlicmFyeShEQkkpCmxpYnJhcnkoZ2d0aGVtcikKbGlicmFyeShmb3JtYXRSKQpsaWJyYXJ5KGlwdW1zcikKZ2d0aGVtcihwYWxldHRlID0gJ2R1c3QnLCB0eXBlID0gJ291dGVyJykKYGBgCkEgTG90IG9mIHRoaXMgaXMgYW4gYWJzb2x1dGUgbWVzcy4gTm90IG1hbnkgQ29tbWVudHMuIEp1c3QgZmlndXJlZCBJIHNob3VsZCBwb3N0IGl0IGFueXdheXMuIAoKIyBEYXRhYmFzZSBsb2FkIGFuZCBzZXR1cCAKClVzZWQgYSBsb2NhbCBwb3N0Z3Jlc3NxbCBkYXRhYmFzZSB0byBmaXQgZnVsbCBkYXRhIGluIG1lbW9yeS4gVGhpcyBjb2RlIGlzIG1vc3RseSBqdXN0IGltcG9ydGluZyBpdCBpbnRvIHRoZSBkYXRhYmFzZSwgbG9hZGluZyBpdCwgZXRjLiAKCmBgYHtyIGV2YWwgPSBGfQojIExvYWQgRGF0YWJhc2UKY29ubiA8LSAKICAgIGRiQ29ubmVjdCgKICAgICAgICBkcnYgPSBQb3N0Z3JlcygpLAogICAgICAgIHVzZXIgPSAnbGl6c3FsJywgCiAgICAgICAgcGFzc3dvcmQgPSAnbGl6c3FsJywgCiAgICAgICAgaG9zdCA9ICJsb2NhbGhvc3QiLAogICAgICAgIHBvcnQgPSAiNTQzMiIsCiAgICAgICAgZGJuYW1lID0gInBvc3RncmVzIgogICAgKQpgYGAKCmBgYHtyIGV2YWwgPSBGfQpkZWJvaXNfMTkwMCA8LSB0YmwoY29ubiwgaW5fc2NoZW1hKCdwdWJsaWMnLCAnZGVib2lzXzE5MDAnKSkKYWNzXzIwMTlfNXlyIDwtIHRibChjb25uLCBpbl9zY2hlbWEoJ3B1YmxpYycsICdhY3NfMjAxOV81eXJfdjInKSkKYGBgCmBgYHtyIGV2YWwgPSBGfQojIFJlYWRzIGludG8gUG9zdGdyZXMuIFJlcGxhY2UgdmFyaWFibGUgYW5kIHRhYmxlIG5hbWVzIGZvciBlYWNoIGRhdGFzZXQuIAojIEhhZCB0byB1c2UgcG9zdGdyZXMgYXMgZnVsbCAxOTAwIGNlbnN1cyB3b3VsZCBub3QgZml0IGluIG1lbW9yeS4gCmNwc19kZGlfZmlsZSA8LSAidXNhXzAwMDA5LnhtbCIKY3BzX2RhdGFfZmlsZSA8LSAidXNhXzAwMDA5LmRhdCIKIyBBZGQgZGF0YSB0byB0YWJsZXMgaW4gY2h1bmtzCmRkaSA8LSByZWFkX2lwdW1zX2RkaShjcHNfZGRpX2ZpbGUpCnJlYWRfaXB1bXNfbWljcm9fY2h1bmtlZCgKICBkZGksCiAgZGF0YV9maWxlID0gY3BzX2RhdGFfZmlsZSwKICByZWFkcjo6U2lkZUVmZmVjdENodW5rQ2FsbGJhY2skbmV3KGZ1bmN0aW9uKHgsIHBvcykgewogICAgaWYgKHBvcyA9PSAxKSB7CiAgICAgIGRiV3JpdGVUYWJsZShjb25uLCAiYWNzXzIwMTlfNXlyX3YyIiwgeCkKICAgIH0gZWxzZSB7CiAgICAgIGRiV3JpdGVUYWJsZShjb25uLCAiYWNzXzIwMTlfNXlyX3YyIiwgeCwgcm93Lm5hbWVzID0gRkFMU0UsIGFwcGVuZCA9IFRSVUUpCiAgICB9CiAgfSksCiAgY2h1bmtfc2l6ZSA9IDMwMDAwLAogIHZlcmJvc2UgPSBGQUxTRQopCnMKYGBgCgpgYGB7ciBldmFsID0gRn0KZiA8LSBkZWJvaXNfMTkwMCB8PiAKICAgIGZpbHRlcihTVEFURUZJUCA9PSAxMywgUkFDRSA9PSAyKSB8PiAKICAgIGNvdW50KEJQTCkgfD4gCiAgICBpcHVtc19jb2xsZWN0KGRkaSkKCmYyIDwtIGRlYm9pc18xOTAwIHw+IAogICAgZmlsdGVyKEJQTCA9PSAxMywgUkFDRSA9PSAyKSB8PiAKICAgIGNvdW50KFNUQVRFRklQKSB8PiAKICAgIGlwdW1zX2NvbGxlY3QoZGRpKQpgYGAKCiMgTWlncmF0aW9uIENoYXJ0ClRoaXMgaXMgdmVyeSBtZXNzeS4gQnV0IGJhc2ljYWxseSBpbnZvbHZlZCBmaWx0ZXJpbmcgb3V0IHZhcmlvdXMgcGFydHMgb2YgdGhlIGRhdGFzZXQgYW5kIHRoZW4gY3JlYXRpbmcgdGhlIGRpZmZlcmVudCBmaWd1cmVzLiAKCmBgYHtyIGV2YWwgPSBGfQptaWdyYXRpb25fdG9fZ2VvcmdpYSA8LSBmIHw+IG11dGF0ZShyZWdpb24gPSBsYWJlbGxlZDo6dG9fZmFjdG9yKEJQTCksIEZJUFMgPSBsYWJlbGxlZDo6cmVtb3ZlX2xhYmVscyhCUEwpKSB8PiBzZWxlY3QocmVnaW9uLCBGSVBTLCBuKQpzYXZlUkRTKG1pZ3JhdGlvbl90b19nZW9yZ2lhLCBmaWxlID0gIm1pZ3JhdGlvbl90b19nZW9yZ2lhIikKbWlncmF0aW9uX2Zyb21fZ2VvcmdpYSA8LSBmMiB8PiBtdXRhdGUocmVnaW9uID0gbGFiZWxsZWQ6OnRvX2ZhY3RvcihTVEFURUZJUCksIEZJUFMgPSBsYWJlbGxlZDo6cmVtb3ZlX2xhYmVscyhTVEFURUZJUCkpIHw+IAogICAgc2VsZWN0KHJlZ2lvbiwgRklQUywgbikKI3NhdmVSRFMobWlncmF0aW9uX2Zyb21fZ2VvcmdpYSwgZmlsZSA9ICdtaWdyYXRpb25fZnJvbV9nZW9yZ2lhJykKYGBgCgpgYGB7ciBldmFsID0gRn0KZml4ZWRfbnVtYmVycyA8LQogICAgbWlncmF0aW9uX2Zyb21fZ2VvcmdpYSAlPiUgZmlsdGVyKEZJUFMgPCA2MCkgJT4lIG11dGF0ZShyZWdpb24gPSB0b2xvd2VyKHJlZ2lvbikpICU+JSBmaWx0ZXIocmVnaW9uICE9ICdkaXN0cmljdCBvZiBjb2x1bWJpYScsIEZJUFMgIT0gMTMpICU+JSBtdXRhdGUobiA9IGFzLm51bWVyaWMobikpICU+JSBzZWxlY3QocmVnaW9uLCBuKQpzdGF0ZXNfbWFwIDwtIG1hcF9kYXRhKCdzdGF0ZScpCnRvdGFsX21hcCA8LSBsZWZ0X2pvaW4oc3RhdGVzX21hcCwgZml4ZWRfbnVtYmVycywgYnkgPSAncmVnaW9uJykKc3RhdGVfbmFtZSA8LQogICAgZGF0YS5mcmFtZSgKICAgICAgICBhYmIgPSBzdGF0ZS5hYmIsCiAgICAgICAgcmVnaW9uID0gdG9sb3dlcihzdGF0ZS5uYW1lKSwKICAgICAgICB4ID0gc3RhdGUuY2VudGVyJHgsCiAgICAgICAgeSA9IHN0YXRlLmNlbnRlciR5CiAgICApIHw+IGZpbHRlcihhYmIgIT0gJ0hJJywgYWJiICE9ICdBSycpIHw+CiAgICBsZWZ0X2pvaW4oZml4ZWRfbnVtYmVycykgIywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgICAgICAgICAgIFRSVUUgfiBuKSkgCmZyb21fZ2EgPC0gZ2dwbG90KHRvdGFsX21hcCwgYWVzKGxvbmcsIGxhdCwgZ3JvdXAgPSBncm91cCkpICsKICAgICMgICAgYW5ub3RhdGlvbl9tYXBfdGlsZSgic3RhbWVud2F0ZXJjb2xvciIpICsKICAgIGdlb21fcG9seWdvbihhZXMoZmlsbCA9IG4pLCBjb2xvciA9ICJ3aGl0ZSIpICsKICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG9wdGlvbiA9ICJDIiwKICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zID0gJ2xvZycsCiAgICAgICAgICAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSAtMSkgKyBnZW9tX3NoYWRvd3RleHQoZGF0YSA9IHN0YXRlX25hbWUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4ID0geCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeSA9IHksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsID0gaWZlbHNlKGFiYiA9PSAnR0EnLCAiR0FcbiAiLCBwYXN0ZTAoYWJiLCdcbicsIGlmZWxzZShpcy5uYShuKSwgMCwgbikpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAgPSAxCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplID0gMikgKwogICAgIyAgYW5ub3RhdGlvbl9zY2FsZSgpICsKICMgICB0aGVtZV92b2lkKCkgKwogICAgdGhlbWUoYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAnbm9uZScsCiAgICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkscGFuZWwuYm9yZGVyPWVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWlub3I9ZWxlbWVudF9ibGFuaygpLHBsb3QuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkpICsKICAgICBsYWJzKAogICAgICAgIGNvbG9yID0gJ1BvcHVsYXRpb24nLAogICAgICAgIHRpdGxlID0gJ1BvcHVsYXRlZCBNaWdyYXRlZCBmcm9tIEdlb3JnaWEnLAogICAgICAgIHN1YnRpdGxlID0gJ1BvcHVsYXRpb24gYm9ybiBpbiBHZW9yZ2lhIGJ5IGN1cnJlbnQgc3RhdGUgb2YgcmVzaWRlbmNlIChpZiBsaXZpbmcgb3V0c2lkZSBHZW9yZ2lhKScKICAgICkgCiAgICMgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCiN0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpmcm9tX2dhCmdnc2F2ZSgKICAgICdmcm9tX2dhLnBuZycsCiAgICBmcm9tX2dhLAogICAgd2lkdGggPSAyNTYwLAogICAgaGVpZ2h0ID0gMTQ0MCwKICAgIHVuaXRzID0gYygncHgnKQopCgoKZml4ZWRfbnVtYmVycyA8LQogICAgbWlncmF0aW9uX3RvX2dlb3JnaWEgJT4lIGZpbHRlcihGSVBTIDwgNjApICU+JSBtdXRhdGUocmVnaW9uID0gdG9sb3dlcihyZWdpb24pKSAlPiUgZmlsdGVyKHJlZ2lvbiAhPSAnZGlzdHJpY3Qgb2YgY29sdW1iaWEnLCBGSVBTICE9IDEzKSAlPiUgbXV0YXRlKG4gPSBhcy5udW1lcmljKG4pKSAlPiUgc2VsZWN0KHJlZ2lvbiwgbikKc3RhdGVzX21hcCA8LSBtYXBfZGF0YSgnc3RhdGUnKQp0b3RhbF9tYXAgPC0gbGVmdF9qb2luKHN0YXRlc19tYXAsIGZpeGVkX251bWJlcnMsIGJ5ID0gJ3JlZ2lvbicpCnN0YXRlX25hbWUgPC0KICAgIGRhdGEuZnJhbWUoCiAgICAgICAgYWJiID0gc3RhdGUuYWJiLAogICAgICAgIHJlZ2lvbiA9IHRvbG93ZXIoc3RhdGUubmFtZSksCiAgICAgICAgeCA9IHN0YXRlLmNlbnRlciR4LAogICAgICAgIHkgPSBzdGF0ZS5jZW50ZXIkeQogICAgKSB8PiBmaWx0ZXIoYWJiICE9ICdISScsIGFiYiAhPSAnQUsnKSB8PgogICAgbGVmdF9qb2luKGZpeGVkX251bWJlcnMpIyAlPiUgbXV0YXRlKG4gPSBjYXNlX3doZW4oYWJiID09ICdHQScgfiA5NTg5ODQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gbikpCnRvX2dhIDwtIGdncGxvdCh0b3RhbF9tYXAsIGFlcyhsb25nLCBsYXQsIGdyb3VwID0gZ3JvdXApKSArCiAgICAjICAgIGFubm90YXRpb25fbWFwX3RpbGUoInN0YW1lbndhdGVyY29sb3IiKSArCiAgICBnZW9tX3BvbHlnb24oYWVzKGZpbGwgPSBuKSwgY29sb3IgPSAid2hpdGUiKSArCiAgICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb24gPSAiQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICB0cmFucyA9ICdsb2cnLAogICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gLTEpICsgZ2VvbV9zaGFkb3d0ZXh0KGRhdGEgPSBzdGF0ZV9uYW1lLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFlcygKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IHgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSB5LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbCA9ICBpZmVsc2UoYWJiID09ICdHQScsICJHQVxuICIsIHBhc3RlMChhYmIsJ1xuJywgaWZlbHNlKGlzLm5hKG4pLCAwLCBuKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncm91cCA9IDEKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAyKSArCiAgICAjICBhbm5vdGF0aW9uX3NjYWxlKCkgKwogICAjIHRoZW1lX3ZvaWQoKSArCiAgICAjdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICsgCiAgICBsYWJzKAogICAgICAgIGNvbG9yID0gJ1BvcHVsYXRpb24nLAogICAgICAgIHRpdGxlID0gJ1BvcHVsYXRpb24gTWlncmF0ZWQgdG8gR2VvcmdpYScsIAogICAgICAgIHN1YnRpdGxlID0gJ051bWJlciBvZiBjdXJyZW50IEdlb3JnaWEgcmVzaWRlbnRzIGJ5IHBsYWNlIG9mIGJpcnRoIChpZiBib3JuIG91dHNpZGUgZ2VvcmdpYSknCiAgICApICsKICAgICAgdGhlbWUoYXhpcy5saW5lPWVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aXRsZS55PWVsZW1lbnRfYmxhbmsoKSwgbGVnZW5kLnBvc2l0aW9uID0gJ25vbmUnLAogICAgICAgICAgcGFuZWwuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkscGFuZWwuYm9yZGVyPWVsZW1lbnRfYmxhbmsoKSxwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBhbmVsLmdyaWQubWlub3I9ZWxlbWVudF9ibGFuaygpLHBsb3QuYmFja2dyb3VuZD1lbGVtZW50X2JsYW5rKCkpCiAgICAgICAgIyAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oKSkKI3RoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCnRvX2dhCmdnc2F2ZSgKICAgICd0b19nYS5wbmcnLAogICAgdG9fZ2EsCiAgICB3aWR0aCA9IDI1NjAsCiAgICBoZWlnaHQgPSAxNDQwLAogICAgdW5pdHMgPSBjKCdweCcpCikKCnBhdGNod29yayA9IHRvX2dhIC8gZnJvbV9nYQpwYXRjaHdvcmsgPC0gcGF0Y2h3b3JrICsgCiAgICBwbG90X2Fubm90YXRpb24oCiAgICB0aGVtZSA9IHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJywKICAgICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjApLAogICAgICAgICAgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbih0ID0gMjUsIGIgPSAyNSwgbCA9IDI1LCByID0gMjUpKSwKICAgIHRpdGxlID0gJ01pZ3JhdGlvbiBvZiBBZnJpY2FuIEFtZXJpY2FucyB0byBhbmQgZnJvbSBHZW9yZ2lhLCAxOTAwJywKICAgIHN1YnRpdGxlID0gJ1Jlc2lkZW50cyBvZiBHZW9yZ2lhIGJvcm4gaW4gYW5vdGhlciBzdGF0ZSwgYW5kIHJlc2lkZW50cyBvZiBvdGhlciBzdGF0ZXMgYm9ybiBpbiBHZW9yZ2lhXG4gJywKICAgIGNhcHRpb24gPSAnQ3JlYXRlZCBieSBFbGl6YWJldGggR29vZHdpbiB1c2luZyB0aGUgZnVsbCAxOTAwIENlbnN1cywgSVBVTVMgVVNBJwogICAgIyBzdWJ0aXRsZSA9ICdUaGVzZSAzIHBsb3RzIHdpbGwgcmV2ZWFsIHlldC11bnRvbGQgc2VjcmV0cyBhYm91dCBvdXIgYmVsb3ZlZCBkYXRhLXNldCcsCiAgICAjICAgY2FwdGlvbiA9ICdEaXNjbGFpbWVyOiBOb25lIG9mIHRoZXNlIHBsb3RzIGFyZSBpbnNpZ2h0ZnVsJywKICAjICB0YWdfbGV2ZWxzID0gYygnQScsICcxJyksCiAgIyAgdGFnX3ByZWZpeCA9ICdGaWcuICcsCiAjICAgdGFnX3NlcCA9ICcuJywKICAjICB0YWdfc3VmZml4ID0gJzonCikgIApwYXRjaHdvcmsKCmZpbGVuYW1lID0gJ2xvdC0xMTkzMS1uby0wOC1HT09EV0lOLnBkZicKZmlsZW5hbWVwbmcgPSAnbG90LTExOTMxLW5vLTA4LUdPT0RXSU4ucG5nJwpnZ3NhdmUoZmlsZW5hbWUsIAogICAgICAgcGxvdCA9IHBhdGNod29yaywKICAgICAgIGRwaSA9IDMwMCwKICAgICAgIGhlaWdodCA9IDExLAogICAgICAgd2lkdGggPSA4LjUKICAgICAgICkKCmBgYAoKIyBNYXJpdGFsIFN0YXR1cyBGaWd1cmUKCmBgYHtyIGV2YWwgPSBGfQpkZW5zaXR5IDwtIGFjc18yMDE5XzV5ciB8PiAKICAgIGZpbHRlcihSQUNFID09IDEpIHw+IAogICAgbXV0YXRlKAogICAgICAgIGFnZV9idWNrZXQgPSBjYXNlX3doZW4oCiAgICAgICAgICAgIAogICAgICAgICAgICBBR0UgPCAxNiB+ICIwLTE1IiwKICAgICAgICAgICAgQUdFIDwgMjEgfiAiMTUtMjAiLAogICAgICAgICAgICBBR0UgPCAyNiB+ICIyMC0yNSIsCiAgICAgICAgICAgIEFHRSA8IDMxIH4gIjI1LTMwIiwKICAgICAgICAgICAgQUdFIDwgMzYgfiAiMzAtMzUiLAogICAgICAgICAgICBBR0UgPCA0NiB+ICIzNS00NSIsCiAgICAgICAgICAgIEFHRSA8IDU2IH4gIjQ1LTU1IiwKICAgICAgICAgICAgQUdFIDwgNjYgfiAiNTUtNjUiLAogICAgICAgICAgICBBR0UgPCA3NiB+ICI2NS03NSIsCiAgICAgICAgICAgIEFHRSA8IDg5IH4gIk92ZXIgNzUiLAogICAgICAgICAgICBUUlVFIH4gJ290aGVyJwogICAgICAgICksIAogICAgICAgIE1hcml0YWxfU3RhdHVzID0gY2FzZV93aGVuKAogICAgICAgICAgICBNQVJTVCA8IDMgfiAnTWFycmllZCcsIAogICAgICAgICAgICBNQVJTVCA8IDUgfiAnU2VwYXJhdGVkL1xuRGl2b3JjZWQnLCAKICAgICAgICAgICAgTUFSU1QgPT0gNSB+ICJXaWRvd2VkIiwgCiAgICAgICAgICAgIE1BUlNUID09IDYgfiAiU2luZ2xlIgogICAgICAgICkKICAgICkgfD4gCiAgICBjb3VudChTRVgsIGFnZV9idWNrZXQsIE1hcml0YWxfU3RhdHVzKSB8PiAKICAgIGlwdW1zX2NvbGxlY3QoZGRpKSB8PiAKICAgIGZpbHRlcihhZ2VfYnVja2V0ICE9ICdvdGhlcicpIHw+IAogICAgYWRkX2NvdW50KFNFWCwgYWdlX2J1Y2tldCwgd3QgPSBuLCBuYW1lID0gJ3RvdGFsJykgfD4gCiAgICBtdXRhdGUocGN0ID0gMTAwKm4gLyB0b3RhbCkgfD4gCiAgICBtdXRhdGUoU0VYID0gY2FzZV93aGVuKFNFWCA9PSAxIH4gJ01hbGUnLCBUUlVFIH4gIkZlbWFsZSIpKSB8PiAKICAgIG11dGF0ZShNYXJpdGFsX1N0YXR1cyA9IGZhY3RvcihNYXJpdGFsX1N0YXR1cywgbGV2ZWxzID0gcmV2KGMoJ1NpbmdsZScsICdNYXJyaWVkJywgIlNlcGFyYXRlZC9cbkRpdm9yY2VkIiwgJ1dpZG93ZWQnKSkpKQpgYGAKCmBgYHtyIGV2YWwgPSBGfQp0b19zd2FwID0gcmV2KGMoIiM5QThBNzYiLCAiI2RiNzM1YyIsICIjRUZBODZFIiwiIzU1NTU1NSIgKSkKbWFsZSA8LQogICAgZ2dwbG90KChkZW5zaXR5IHw+IGZpbHRlcihTRVggPT0gJ01hbGUnKSksCiAgICAgICAgICAgYWVzKHggPSBhZ2VfYnVja2V0LCB5ID0gYXMubnVtZXJpYyhwY3QpLCBmaWxsID0gTWFyaXRhbF9TdGF0dXMpKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAuMykgKyAKICAgIGNvb3JkX2ZsaXAoKSArIAogICAgCiAgICBsYWJzKHN1YnRpdGxlID0gJ01hbGUnLCAKICAgICAgICAgeSA9IGVsZW1lbnRfYmxhbmsoKSwgCiAgZmlsbCA9ICJTdGF0dXMiLAogICAgICAgICB4ID0gIkFnZSAoWWVhcnMpIikgKyAKICAjICBocmJydGhlbWVzOjp0aGVtZV9pcHN1bV9wcygpICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnYm90dG9tJwogICMgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KQogICAgICAgICAgKSArIAogICAgZ2VvbV9zaGFkb3d0ZXh0KGFlcyhsYWJlbCA9IGlmZWxzZShyb3VuZChwY3QpID4gMywgcGFzdGUwKHJvdW5kKHBjdCksICIlIiksICIiKSksIHNpemUgPSAyLjgscG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IC41KSkgKyAKICAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHM9YygxMDEsMCksIGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoc2NhbGUgPSAxKSwgZXhwYW5kID0gZXhwYW5zaW9uKG11bHQgPSBjKC4wNSwuMDI1KSkpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRvX3N3YXApCiAgICAKCmZlbWFsZSA8LQogICAgZ2dwbG90KChkZW5zaXR5IHw+IGZpbHRlcihTRVggPT0gJ0ZlbWFsZScpKSwKICAgICAgICAgICBhZXMoCiAgICAgICAgICAgICAgIHggPSBhZ2VfYnVja2V0LAogICAgICAgICAgICAgICB5ID0gYXMubnVtZXJpYyhwY3QpLAogICAgICAgICAgICAgICBmaWxsID0gTWFyaXRhbF9TdGF0dXMKICAgICAgICAgICApKSArCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5Iiwgd2lkdGggPSAxLCBjb2xvciA9ICdibGFjaycsIHNpemUgPSAuMykgKyAKICAgIGNvb3JkX2ZsaXAoKSArIAoKIAoKICAgIGxhYnMoc3VidGl0bGUgPSAnRmVtYWxlJywKICBmaWxsID0gIlN0YXR1cyIsCiAgeSA9IGVsZW1lbnRfYmxhbmsoKQogICAgICAgICkgKyAKICAjICBocmJydGhlbWVzOjp0aGVtZV9pcHN1bV9wcygpICsgCiAgICAKICBnZW9tX3NoYWRvd3RleHQoYWVzKGxhYmVsID0gaWZlbHNlKHJvdW5kKHBjdCkgPiAzLCBwYXN0ZTAocm91bmQocGN0KSwgIiUiKSwgIiIpKSwgc2l6ZSA9IDIuOCxwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gLjUpKSArIAogICAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6cGVyY2VudF9mb3JtYXQoc2NhbGUgPSAxKSwgIGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYyguMDI1LDAuMDUpKSkgKwoKICBjb29yZF9mbGlwKCkgKyAjKyBjb29yZF9mbGlwKCkgKyAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cz1jKDEwMCwtMTAwKSkrCiAgICAKICB0aGVtZSgKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAnbm9uZScsCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGlja3MueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLmxpbmUueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAjICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4obCA9IDApCiAgICApICArIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHRvX3N3YXApCgoKY29tYmluZWQgPC0gbWFsZSArIGZlbWFsZSAmIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIsIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTgpKSAgCmNvbWJpbmVkIDwtIGNvbWJpbmVkICsgcGxvdF9sYXlvdXQoZ3VpZGVzID0gImNvbGxlY3QiKSArIHBsb3RfYW5ub3RhdGlvbigKICB0aXRsZSA9ICdNYXJpdGFsIFN0YXR1cyBvZiBBZnJpY2FuIEFtZXJpY2FucycsCiAgc3VidGl0bGUgPSAnQnkgQWdlIGFuZCBTZXgsIDIwMTUtMjAxOScsCiAgY2FwdGlvbiA9IGVsZW1lbnRfdGV4dCgnTWFkZSBieSBFbGl6YWJldGggR29vZHdpblxuIFNvdXJjZTogMjAxNS0yMDE5IEFDUywgSVBVTVMgVVNBJywgc2l6ZSA9IDgpKSArCiAgcGxvdF9hbm5vdGF0aW9uKHRoZW1lID0gdGhlbWUocGxvdC5tYXJnaW4gPSBtYXJnaW4ociA9IDE1LCBsID0gMTUsIHQgPSAyMCwgYiA9IDIwLCB1bml0ID0gJ3B0JykpKQoKY29tYmluZWQKZ2dzYXZlKCdsb3QtMTE5MzEtbm8tNTMtR09PRFdJTi5wZGYnLGNvbWJpbmVkLCBkcGkgPSA0MDAsIGhlaWdodCA9IDUuODMsIHdpZHRoID0gOSkKI2dnc2F2ZSgnbG90LTExOTMxLW5vLTUzLUdPT0RXSU4ucG5nJyxjb21iaW5lZCwgZHBpID0gNDAwLCBoZWlnaHQgPSA1LjgzLCB3aWR0aCA9IDkpCmBgYAoKIyBFbXBsb3ltZW50IEZpZ3VyZSAKCmBgYHtyIGV2YWwgPSBGfQphY3Nfb2NjX3BjdCA8LSBhY3NfMjAxOV81eXIgJT4lIGNvdW50KE9DQzIwMTAsIFJBQ0UsIHd0ID0gUEVSV1QpIHw+IGFkZF9jb3VudChPQ0MyMDEwLCB3dCA9IG4sIG5hbWUgPSAndG90YWwnKSB8PiAgbXV0YXRlKHBjdCA9IDEwMCpuL3RvdGFsKSB8PiBpcHVtc19jb2xsZWN0KGRkaSkKYGBgCgpgYGB7ciBldmFsID0gRn0KCmFjc19vY2MgPC0gYWNzX29jY19wY3QgfD4gCiAgICBtdXRhdGUoT0NDMjAxMCA9IGFzLm51bWVyaWMoT0NDMjAxMCksICAKICAgIG9jYyA9IGNhc2Vfd2hlbigKICAgICAgICAoKE9DQzIwMTAgPj0gMTApICYgKE9DQzIwMTAgPD0gNDMwKSkgfiAnTWFuYWdlbWVudCwgQnVzaW5lc3MsIFNjaWVuY2UsIGFuZCBBcnRzJywKICAgICAgICAoKE9DQzIwMTAgPj0gNTAwICkgJiAoT0NDMjAxMCA8PSA3MzApKSB+ICdCdXNpbmVzcyBPcGVyYXRpb25zIFNwZWNpYWxpc3RzJywKICAgICAgICAoKE9DQzIwMTAgPj0gODAwKSAmIChPQ0MyMDEwIDw9IDk1MCkpIH4gJ0ZpbmFuY2lhbCBTcGVjaWFsaXN0cycsCiAgICAgICAgKChPQ0MyMDEwID49IDEwMDApICYgKE9DQzIwMTAgPD0gMTI0MCkpIH4gJ0NvbXB1dGVyIGFuZCBNYXRoZW1hdGljYWwnLAogICAgICAgICgoT0NDMjAxMCA+PSAxMzAwKSAmIChPQ0MyMDEwIDw9IDE1NDApKSB+ICdBcmNoaXRlY3R1cmUgYW5kIEVuZ2luZWVyaW5nJywKICAgICAgICAoKE9DQzIwMTAgPj0gMTU1MCkgJiAoT0NDMjAxMCA8PSAxNTYwKSkgfiAnVGVjaG5pY2lhbnMnLAogICAgICAgICgoT0NDMjAxMCA+PSAxNjAwKSAmIChPQ0MyMDEwIDw9IDE5ODApKSB+ICdMaWZlLCBQaHlzaWNhbCwgYW5kIFNvY2lhbCBTY2llbmNlJywKICAgICAgICAoKE9DQzIwMTAgPj0gMjAwMCkgJiAoT0NDMjAxMCA8PSAyMDYwKSkgfiAnQ29tbXVuaXR5IGFuZCBTb2NpYWwgU2VydmljZXMnLAogICAgICAgICgoT0NDMjAxMCA+PSAyMTAwKSAmIChPQ0MyMDEwIDw9IDIxNTApKSB+ICdMZWdhbCcsCiAgICAgICAgKChPQ0MyMDEwID49IDIyMDApICYgKE9DQzIwMTAgPD0gMjU1MCkpIH4gJ0VkdWNhdGlvbiwgVHJhaW5pbmcsIGFuZCBMaWJyYXJ5JywKICAgICAgICAoKE9DQzIwMTAgPj0gMjYwMCkgJiAoT0NDMjAxMCA8PSAyOTIwKSkgfiAnQXJ0cywgRGVzaWduLCBFbnRlcnRhaW5tZW50LCBTcG9ydHMsIGFuZCBNZWRpYScsCiAgICAgICAgKChPQ0MyMDEwID49IDMwMDApICYgKE9DQzIwMTAgPD0gMzU0MCkpIH4gJ0hlYWx0aGNhcmUgUHJhY3RpdGlvbmVycyBhbmQgVGVjaG5pY2lhbnMnLAogICAgICAgICgoT0NDMjAxMCA+PSAzNjAwKSAmIChPQ0MyMDEwIDw9IDM2NTApKSB+ICdIZWFsdGhjYXJlIFN1cHBvcnQnLAogICAgICAgICgoT0NDMjAxMCA+PSAzNzAwKSAmIChPQ0MyMDEwIDw9IDM5NTApKSB+ICdQcm90ZWN0aXZlIFNlcnZpY2UnLAogICAgICAgICgoT0NDMjAxMCA+PSA0MDAwKSAmIChPQ0MyMDEwIDw9IDQxNTApKSB+ICdGb29kIFByZXBhcmF0aW9uIGFuZCBTZXJ2aW5nJywKICAgICAgICAoKE9DQzIwMTAgPj0gNDIwMCkgJiAoT0NDMjAxMCA8PSA0MjUwKSkgfiAnQnVpbGRpbmcgYW5kIEdyb3VuZHMgQ2xlYW5pbmcgYW5kIE1haW50ZW5hbmNlJywKICAgICAgICAoKE9DQzIwMTAgPj0gNDMwMCkgJiAoT0NDMjAxMCA8PSA0NjUwKSkgfiAnUGVyc29uYWwgQ2FyZSBhbmQgU2VydmljZScsCiAgICAgICAgKChPQ0MyMDEwID49IDQ3MDApICYgKE9DQzIwMTAgPD0gNDk2NSkpIH4gJ1NhbGVzIGFuZCBSZWxhdGVkJywKICAgICAgICAoKE9DQzIwMTAgPj0gNTAwMCkgJiAoT0NDMjAxMCA8PSA1OTQwKSkgfiAnT2ZmaWNlIGFuZCBBZG1pbmlzdHJhdGl2ZSBTdXBwb3J0JywKICAgICAgICAoKE9DQzIwMTAgPj0gNjAwNSkgJiAoT0NDMjAxMCA8PSA2MTMwKSkgfiAnRmFybWluZywgRmlzaGluZywgYW5kIEZvcmVzdHJ5JywKICAgICAgICAoKE9DQzIwMTAgPj0gNjIwMCkgJiAoT0NDMjAxMCA8PSA2NzY1KSkgfiAnQ29uc3RydWN0aW9uJywKICAgICAgICAoKE9DQzIwMTAgPj0gNjgwMCkgJiAoT0NDMjAxMCA8PSA2OTQwKSkgfiAnRXh0cmFjdGlvbicsCiAgICAgICAgKChPQ0MyMDEwID49IDcwMDApICYgKE9DQzIwMTAgPD0gNzYzMCkpIH4gJ0luc3RhbGxhdGlvbiwgTWFpbnRlbmFuY2UsIGFuZCBSZXBhaXInLAogICAgICAgICgoT0NDMjAxMCA+PSA3NzAwKSAmIChPQ0MyMDEwIDw9IDg5NjUpKSB+ICdQcm9kdWN0aW9uJywKICAgICAgICAoKE9DQzIwMTAgPj0gOTAwMCkgJiAoT0NDMjAxMCA8PSA5NzUwKSkgfiAnVHJhbnNwb3J0YXRpb24gYW5kIE1hdGVyaWFsIE1vdmluZycsCiAgICAgICAgKChPQ0MyMDEwID49IDk4MDApICYgKE9DQzIwMTAgPD0gOTgzMCkpIH4gJ01pbGl0YXJ5IFNwZWNpZmljJywKICAgICAgICAoKE9DQzIwMTAgPj0gOTkyMCkgJiAoT0NDMjAxMCA8PSA5OTIwKSkgfiAnVW5lbXBsb3llZCBmb3IgNSsgeWVhcnMgb3IgTmV2ZXIgV29ya2VkJywKICAgICAgICBUUlVFIH4gJ090aGVyJyksCiAgICByYWNlID0gY2FzZV93aGVuKFJBQ0UgPT0gMSB+ICdXaGl0ZScsIFJBQ0UgPT0gMiB+ICdCbGFjaycsIFRSVUUgfiAnT3RoZXInKQogICAgKSB8PgogICAgdW5ncm91cCgpIHw+IAogICAgc2VsZWN0KG9jYywgcmFjZSwgbiwgdG90YWwsIHBjdCkgfD4gCiAgICBjb3VudChvY2MsIHJhY2UsIHd0ID0gbikgfD4gCiAgICBhZGRfY291bnQob2NjLCB3dCA9IG4sIG5hbWUgPSAndG90YWwnKSB8PiAKICAgIG11dGF0ZShwY3QgPSAxMDAqbi90b3RhbCkgfD4gCiAgICBmaWx0ZXIocmFjZSAhPSAnT3RoZXInKSB8PiAKICAgIHNlbGVjdChvY2MsIHJhY2UsIHBjdCwgbikgfD4gIAogICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHJhY2UsIHZhbHVlc19mcm9tID0gYyhwY3QsbikpIHw+IAogICAgbXV0YXRlKGF2Z19wY3RfYmxhY2sgPSB3ZWlnaHRlZC5tZWFuKHBjdF9CbGFjaywgbl9CbGFjayksCiAgICAgICAgICAgZGlmZl9mcm9tX21lYW4gPSBwY3RfQmxhY2sgLSBhdmdfcGN0X2JsYWNrLAogICAgICAgICAgIG9jYyA9IGZjdF9yZW9yZGVyKG9jYywgZGlmZl9mcm9tX21lYW4pLAogICAgICAgICAgIHRvdCA9IHN1bShuX0JsYWNrLCBuX1doaXRlKSwKICAgICAgICAgICBjaSA9IDE5NiAqIHNxcnQoKChuX0JsYWNrIC8gdG90KSAqICgxIC0gKG5fQmxhY2sgLyB0b3QpKSkgLyB0b3QpKQpgYGAKYGBge3IgZXZhbCA9IEZ9CmFjc19vY2NfZmlnIDwtIGFjc19vY2MgJT4lIAogICAgZ2dwbG90KGFlcyh4ID0gcGN0X0JsYWNrLCB5ID0gb2NjLCBjb2xvciA9IGRpZmZfZnJvbV9tZWFuKSkgKwogICAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBhdmdfcGN0X2JsYWNrKSwgbGluZXR5cGUgPSAyKSArIAogICAgc2NhbGVfY29sb3JfdmlyaWRpcygpICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScsCiAgICAgICAgICAgcGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwgCiAgICBwbG90LmNhcHRpb24ucG9zaXRpb24gPSAicGxvdCIsCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyPTI1LCBsPTI1LCB0PTI1LCBiPTEwKQogICAgKSArIAogICAgbGFicygKICAgICAgICB0aXRsZSA9ICdQZXJjZW50IEFmcmljYW4gQW1lcmljYW4gYnkgRW1wbG95bWVudCBTZWN0b3InLCAKICAgICAgICBzdWJ0aXRsZSA9ICdHcm91cGVkIGJ5IG92ZXJhbGwgRW1wbG95bWVudCBDYXRlZ29yeS4gRG90dGVkIGxpbmUgaXMgb3ZlcmFsbCBwZXJjZW50IG9mIHBvcHVsYXRpb24nLAogICAgICAgIHggPSAiUGVyY2VudCBBZnJpY2FuIEFtZXJpY2FuIiwKICAgICAgICB5ID0gIkVtcGxveW1lbnQgU2VjdG9yIiwKICAgICAgICBjb2xvciA9ICdEaWZmZXJlbmNlIGZyb20gb3ZlcmFsbCBwZXJjZW50JwogICAgICAgIAogICAgKSAKYWNzX29jY19maWcKYGBgCmBgYHtyIGV2YWwgPSBGfQphY3Nfb2NjXzIgPC0gYWNzX29jY19wY3QgfD4gCiAgICBtdXRhdGUob2NjID0gbGFiZWxsZWQ6OnRvX2NoYXJhY3RlcihPQ0MyMDEwKSwgIAogICAgICAgICAgICNyYWNlID0gbGFiZWxsZWQ6OnRvX2ZhY3RvcihSQUNFKQogICAgICAgICAgIHJhY2UgPSBjYXNlX3doZW4oUkFDRSA9PSAxIH4gJ1doaXRlJywgUkFDRSA9PSAyIH4gJ0JsYWNrJywgVFJVRSB+ICdPdGhlcicpCiAgICApIHw+CiAgICB1bmdyb3VwKCkgfD4gCiAgICBtdXRhdGUoCiAgICAgICAgb2NjID0gY2FzZV93aGVuKG9jYyA9PSAnUG9zdGFsIFNlcnZpY2UgTWFpbCBTb3J0ZXJzLCBQcm9jZXNzb3JzLCBhbmQgUHJvY2Vzc2luZyBNYWNoaW5lIE9wZXJhdG9ycycgfiAiUG9zdGFsIFNlcnZpY2UgTWFpbCBTb3J0ZXJzIGFuZCBQcm9jZXNzb3JzIiwKICAgICAgICAgICAgICAgICAgICAgICAgb2NjID09ICJGYXJtZXJzLCBSYW5jaGVycywgYW5kIE90aGVyIEFncmljdWx0dXJhbCBNYW5hZ2VycyIgfiAiRmFybWVycyBhbmQgUmFuY2hlcnMiLAogICAgICAgICAgICAgICAgICAgICAgICBvY2MgPT0gIlNlY3VyaXR5IEd1YXJkcyBhbmQgR2FtaW5nIFN1cnZlaWxsYW5jZSBPZmZpY2VycyIgfiAiU2VjdXJpdHkgR3VhcmRzIiwKICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IG9jYykpIHw+IAogICAgc2VsZWN0KG9jYywgcmFjZSwgbiwgdG90YWwsIHBjdCkgfD4gCiAgICBjb3VudChvY2MsIHJhY2UsIHd0ID0gbikgfD4gCiAgICBhZGRfY291bnQob2NjLCB3dCA9IG4sIG5hbWUgPSAndG90YWwnKSB8PiAKICAgIG11dGF0ZShwY3QgPSAxMDAqbi90b3RhbCkgfD4gCiAgICBmaWx0ZXIocmFjZSAhPSAnT3RoZXInKSB8PiAKICAgICNhZGRfY291bnQocmFjZSwgd3QgPSBuLCBuYW1lID0gJ3Rlc3QnKSB8PiAKICAgICMgIGZpbHRlcihyYWNlIDwgMykgfD4gCiAgICAjICBtdXRhdGUocmFjZSA9IGNhc2Vfd2hlbihSQUNFID09IDEgfiAnV2hpdGUnLCBUUlVFIH4gJ0JsYWNrJykpfD4gCiAgICBzZWxlY3Qob2NjLCByYWNlLCBwY3QsIG4pIHw+ICAKICAgIHBpdm90X3dpZGVyKG5hbWVzX2Zyb20gPSByYWNlLCB2YWx1ZXNfZnJvbSA9IGMocGN0LG4pKSB8PiAKICAgIG11dGF0ZShhdmdfcGN0X2JsYWNrID0gd2VpZ2h0ZWQubWVhbihwY3RfQmxhY2ssIG5fQmxhY2spLAogICAgICAgICAgIGRpZmZfZnJvbV9tZWFuID0gcGN0X0JsYWNrIC0gYXZnX3BjdF9ibGFjaywKICAgICAgICAgICBvY2MgPSBmY3RfcmVvcmRlcihvY2MsIGRpZmZfZnJvbV9tZWFuKSwKICAgICAgICAgICB0b3QgPSBzdW0obl9CbGFjaywgbl9XaGl0ZSksCiAgICAgICAgICAgY2kgPSAxOTYgKiBzcXJ0KCgobl9CbGFjayAvIHRvdCkgKiAoMSAtIChuX0JsYWNrIC8gdG90KSkpIC8gdG90KSkgJT4lIG11dGF0ZSh0eXBlID0gY2FzZV93aGVuKGRpZmZfZnJvbV9tZWFuIDwgMCB+ICdMb3cnLCBUUlVFIH4gJ0hpZ2gnKSkgfD4gZ3JvdXBfYnkodHlwZSkgJT4lIAogICAgc2xpY2VfbWluKGRlc2MoYWJzKGRpZmZfZnJvbV9tZWFuKSksIG49IDgpICU+JQogICAgdW5ncm91cCgpCgphY3Nfb2NjX2ZpZ18yIDwtIGFjc19vY2NfMiAlPiUgCiAgICBnZ3Bsb3QoYWVzKHggPSBwY3RfQmxhY2ssIHkgPSBvY2MsIGNvbG9yID0gZGlmZl9mcm9tX21lYW4pKSArCiAgICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogICAgZ2VvbV92bGluZShhZXMoeGludGVyY2VwdCA9IGF2Z19wY3RfYmxhY2spLCBsaW5ldHlwZSA9IDIpICsgCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzKCkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdub25lJywKICAgICAgICAgICBwbG90LnRpdGxlLnBvc2l0aW9uID0gInBsb3QiLCAjIE5FVyBwYXJhbWV0ZXIuIEFwcGx5IGZvciBzdWJ0aXRsZSB0b28uCiAgICBwbG90LmNhcHRpb24ucG9zaXRpb24gPSAicGxvdCIsCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbihyPTI1LCBsPTI1LCB0PTI1LCBiPTI1KQogICAgKSArIAogICAgbGFicygKICAgICAgICB0aXRsZSA9ICdUb3AgOCBIaWdoZXN0IGFuZCBMb3dlc3QgSm9icyBieSBBZnJpY2FuIEFtZXJpY2FuIHJlcHJlc2VudGF0aW9uJywgCiAgICAgICAgc3VidGl0bGUgPSAnR3JvdXBlZCBieSBzcGVjaWZpYyBlbXBsb3ltZW50IGNsYXNzaWZpY2F0aW9uLCBub3Qgb3ZlcmFsbCBzZWN0b3InLAogICAgICAgIHggPSAiUGVyY2VudCBBZnJpY2FuIEFtZXJpY2FuIiwKICAgICAgICB5ID0gIkVtcGxveW1lbnQgUm9sZSIsCiAgICAgICAgY29sb3IgPSAnRGlmZmVyZW5jZSBmcm9tIG92ZXJhbGwgcGVyY2VudCcKICAgICAgICAKICAgICkgKyBmYWNldF9mcmVlKHR5cGUgfiAuKQphY3Nfb2NjX2ZpZ18yIysgY29vcmRfZmxpcCgpCmBgYApgYGB7ciBldmFsID0gRn0KY29tYmluZWRfb2NjIDwtIGFjc19vY2NfZmlnIC8gYWNzX29jY19maWdfMiArIHBsb3RfbGF5b3V0KGhlaWdodHMgPSBjKDEuNSwxKSkgKyBwbG90X2Fubm90YXRpb24odGhlbWUgPSB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAnbm9uZScsIHBsb3QubWFyZ2luID0gbWFyZ2luKGIgPSAxMCkpLCBjYXB0aW9uID0gJ01hZGUgYnkgRWxpemFiZXRoIEdvb2R3aW4gfCAyMDEwIE9DQ1NDT1JFLCAyMDE1LTIwMTkgQUNTLCBJUFVNUyBVU0EnKQpnZ3NhdmUoJ29yaWdpbmFsLUdPT0RXSU4ucGRmJywgcGxvdCA9IGNvbWJpbmVkX29jYywgZHBpID0gNDAwLCBoZWlnaHQgPSAxMCwgd2lkdGggPSA4KQojZ2dzYXZlKCdvcmlnaW5hbC1HT09EV0lOLnBuZycsIHBsb3QgPSBjb21iaW5lZF9vY2MsIGRwaSA9IDQwMCwgaGVpZ2h0ID0gMTAsIHdpZHRoID0gOCkKYGBgCgo=