TidyTuesday week 41: Registered Nurses , data from Data.World .
library(tidyverse)
library(janitor)
library(ggtext)
library(scales)
library(geofacet)
library(colorspace)
library(biscale)
library(cowplot)
nurses <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2021/2021-10-05/nurses.csv') %>% clean_names()
Rows: 1242 Columns: 22
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): State
dbl (21): Year, Total Employed RN, Employed Standard Error (%), Hourly Wage Avg, Hourly Wage Median, Annual Salary Avg,...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
range(nurses$year)
[1] 1998 2020
Tile map
nurses$st <- state.abb[match(nurses$state, state.name)]
df20 = nurses %>% filter(year==2020) %>%
mutate(st=ifelse(state=="District of Columbia","DC",st)) %>%
mutate(st=ifelse(state=="Puerto Rico","PR",st)) %>%
drop_na(st)
df1 = df20 %>%
select(state, st, year, total_employed_rn, hourly_wage_median) %>%
bi_class(x=hourly_wage_median, y=total_employed_rn, style="quantile",dim=3)
create_gradient_state_tile_map <- function(state, value, title, subtitle, caption, legend_title, state_grid='us_state_with_DC_PR_grid2') {
df <- as.tibble(data.frame(state, value))
fig <- df %>%
mutate(x = 1) %>%
mutate(label_y = .5) %>%
mutate(label_x = 1) %>%
ggplot()+
geom_bar(mapping=aes(x=x, fill=value), width=.4) +
facet_geo(~ state, grid=state_grid) +
labs(title=title, subtitle=subtitle, caption=caption) +
geom_text(aes(x=label_x, y=label_y, label=state, color=value),size=3, show.legend=F, family="sans")
return(fig)
}
# excl. Guam and Virgin Islands
p1 = create_gradient_state_tile_map(df1$st, df1$bi_class,
title='US-based Registered Nurses Employment and Wage in 2020', legend_title = "",
subtitle="<span style = 'color:#012a4a;'><b>Total employed registered nurses</b></span> and <span style = 'color:#012a4a;'><b>median hourly wage</b></span>, by US state\n",
caption="Note: Data from Guam and Virgin Islands are not presented<br>#TidyTuesday Week 41 | Data from Data.World") +
bi_scale_fill(pal="DkCyan",dim=3, guide="none") +
scale_color_manual(values=c("grey10","grey10","white","white","white","white","white","white","white")) +
theme_void(base_size=10, base_family = "sans") +
theme(strip.text.x = element_blank(),
plot.margin = unit(c(.5,4,.5,2), "cm"),
plot.title=element_text(size=14, face="bold", color="#012a4a"),
plot.subtitle=element_markdown(size=8, color="#011c31", margin=margin(t=5,b=18)),
legend.title=element_text(size=9),
plot.caption = element_markdown(size=5.6, color="#011c31",margin=margin(t=30), lineheight=1.5, hjust=0)) +
guides(fill = guide_colorbar(title="Count",
title.position = "top",
barwidth = unit(.5, "lines"),
barheight = unit(10, "lines")))
p2 = bi_legend(pal = "DkCyan",
dim = 3,
ylab = "Total employed",
xlab = "Median hourly wage",
size = 2.5) +
theme(panel.border = element_blank(),
axis.text = element_blank(),
axis.title.x = element_text(size = 6, family="sans",
color = "#011c31", margin=margin(t=-5)),
axis.title.y = element_text(size = 6, family="sans",
color = "#011c31", margin=margin(r=-5)),
legend.text = element_text(size = 6),
plot.background = element_blank(),
legend.text.align = 0)
ggdraw() +
draw_plot(p1, 0, 0, 1, 1) +
draw_plot(p2, 0.72, 0.04, 0.25, 0.25)
AlT text: Bivariate heatmap of US-based registered nurses’ median hourly rate and total employment by state (excluding Guam and Virgin Island). The visualization shows that in comparison to other states: Utah, South Dakota, West Virginia and Puerto Rico have the least total registered nurses employment and lowest median hourly rate. California, Minnesota, Massachusetts, New York, and New Jersey have the most total employment and highest median hourly rate compared to the other states.
Tile map v2
add labels for median hourly rage and total employment
# bivariate palette reference: https://nowosad.github.io/post/cbc-bp2/
library(pals)
#brewer.seqseq2()
bi_pal <- bi_pal_manual(val_1_1 = "#f3f3f3", val_1_2 = "#b4d3e1", val_1_3 = "#509dc2",
val_2_1 = "#f3e6b3", val_2_2 = "#b3b3b3",val_2_3 = "#376387",
val_3_1 = "#f3b300", val_3_2 = "#b36600",val_3_3 = "#000000")
# label colors
df2 = df1 %>%
mutate(col=case_when(str_detect(bi_class,"3")~"white",TRUE~"black")) %>%
mutate(col=case_when(bi_class=="3-1"~"black",TRUE~col))
p1b = df2 %>%
ggplot() +
geom_rect(aes(fill=bi_class), xmin=-1, xmax=1, ymin=-1, ymax=1, color="white", show.legend = F) +
geom_richtext(aes(color=col, label=glue::glue("<span style='font-size: 11px;'>{st}</span><br>{dollar(hourly_wage_median)}<br>{round(total_employed_rn/1000,1)}K")),
x=0.5, y=0.45, size=1.5, hjust=.5, fill=NA, label.color=NA, show.legend = F) +
scale_color_identity() +
facet_geo(vars(st), grid=us_state_with_DC_PR_grid2) +
bi_scale_fill(pal=bi_pal, dim=3, guide="none") +
theme_void(base_size = 9) +
theme(strip.text = element_blank(),
plot.margin = unit(c(.5, 3.2, .5, 2.5), "cm"),
plot.title=element_markdown(face="bold"),
plot.subtitle=element_markdown(margin=margin(t=4, b=15)),
plot.caption=element_text(size=6, hjust=0, margin=margin(b=0, t=30))) +
labs(title="2020 US-based Registered Nurses Wage and Employment",
subtitle="Median hourly wage and total employed, by state",
caption="Note: Data from Guam and Virgin Islands are not presented\nData source: Data.World")
p2b = bi_legend(pal = bi_pal,
dim = 3,
ylab = "Total employed",
xlab = "Median hourly wage",
size = 2.5) +
theme(panel.border = element_blank(),
axis.text = element_blank(),
axis.title.x = element_text(size = 6, family="sans",
color = "#011c31", margin=margin(t=-5)),
axis.title.y = element_text(size = 6, family="sans",
color = "#011c31", margin=margin(r=-5)),
legend.text = element_text(size = 6),
plot.background = element_blank(),
legend.text.align = 0)
ggdraw() +
draw_plot(p1b, 0, 0, 1, 1) +
draw_plot(p2b, 0.645, 0.04, 0.25, 0.25)
Western region table
library(gt)
library(gtExtras)
library(usmap)
library(patchwork)
nurses$st = state.abb[match(nurses$state, state.name)]
tab1 = df20 %>%
filter(st %in% .west_region) %>%
mutate(division= case_when(st %in% .mountain ~ "Mountain division",
st %in% .pacific ~ "Pacific division")) %>%
#group_by(state) %>%
#mutate(ratio=total_employed_rn/total_employed_healthcare_state_aggregate) %>%
#ungroup() %>%
select(state,division, annual_salary_avg, hourly_wage_avg,wage_salary_standard_error_percent,
total_employed_rn,total_employed_healthcare_state_aggregate,yearly_total_employed_state_aggregate,
location_quotient) %>%
arrange(desc(annual_salary_avg))
tab1 %>%
gt(groupname_col = "division") %>%
tab_header(title = "WESTERN U.S. REGISTERED NURSES 2020") %>%
tab_source_note(source_note="Data source: Data.World") %>%
cols_label(
annual_salary_avg = html("Annual ($)"),
hourly_wage_avg = html("Hourly ($)"),
wage_salary_standard_error_percent = html("SE (%)"),
total_employed_rn = html("RN"),
total_employed_healthcare_state_aggregate=html("Healthcare"),
yearly_total_employed_state_aggregate = html("Yearly"),
location_quotient=html("Quotient"),
state=html("State"),
) %>%
tab_spanner(
label = "Total Employed",
columns = total_employed_rn:yearly_total_employed_state_aggregate
) %>%
tab_spanner(
label = "Salary/Wage",
columns = annual_salary_avg:wage_salary_standard_error_percent
) %>%
tab_spanner(
label = "Location",
columns = location_quotient
) %>%
tab_options(table.font.size = "14px",
heading.title.font.size = "18px",column_labels.border.bottom.color = "grey",
data_row.padding = px(4),
heading.padding = px(10),
) %>%
gt_hulk_col_numeric(location_quotient) %>%
#gt_hulk_col_numeric(hourly_wage_avg) %>%
gt_hulk_col_numeric(annual_salary_avg) %>%
gt_hulk_col_numeric(total_employed_rn) %>%
cols_align(
align = "center",
columns = annual_salary_avg:location_quotient
) %>%
cols_width(annual_salary_avg:location_quotient ~ px(80)) %>%
cols_width(state ~ px(110)) %>%
fmt_number(annual_salary_avg:location_quotient, use_seps = T, drop_trailing_zeros = T) %>%
tab_footnote(
footnote = md("Total employed registered nurses"),
locations = cells_column_labels(columns = total_employed_rn)
) %>%
tab_footnote(
footnote = md("Total employed healthcare, state aggregate"),
locations = cells_column_labels(columns = total_employed_healthcare_state_aggregate)
) %>%
tab_footnote(
footnote = md("Yearly total employed, state aggregte"),
locations = cells_column_labels(columns = yearly_total_employed_state_aggregate)
) %>%
tab_style(
style = list(
cell_text(font=google_font(
name = "Libre Franklin"), weight='800',align = "left",color='#203B46')),
locations = cells_title(groups = "title")
) %>%
tab_style(style = cell_text(font = google_font("Source Sans Pro"),
weight = 400), locations = cells_body()) %>%
tab_style(style = cell_text(size = px(12.5), color = "grey30",
font = google_font("Source Sans Pro"), transform = "uppercase"),
locations = cells_column_labels(everything())) %>%
tab_style(style = cell_text(size = px(12.5), color = "grey30",
font = google_font("Source Sans Pro"), transform = "uppercase"),
locations = cells_column_spanners()) %>%
tab_style(style = cell_text(size = px(13), color = "grey20",
font = google_font("Source Sans Pro"), style="italic"),
locations = cells_footnotes()) %>%
tab_style(style = cell_text(size = px(13), color = "grey20",
font = google_font("Source Sans Pro")),
locations = cells_source_notes()) %>%
tab_style(style = cell_text(color = "#203B46",
font = google_font("Source Sans Pro"), weight=600, transform = "uppercase"),
locations = cells_row_groups())
State
Salary/Wage
Total Employed
Location
Annual ($)
Hourly ($)
SE (%)
RN
Healthcare
Yearly
Quotient
Pacific division
California
120,560
57.96
1
307,060
844,740
16,430,660
0.87
Hawaii
104,830
50.4
1.9
11,260
31,410
574,010
0.91
Oregon
96,230
46.27
1
36,840
100,230
1,806,950
0.95
Alaska
95,270
45.81
1.4
6,240
17,730
296,300
0.98
Washington
91,310
43.9
0.9
59,300
171,850
3,195,200
0.86
Mountain division
Nevada
89,750
43.15
1.9
23,420
67,590
1,250,860
0.87
Arizona
80,380
38.64
0.9
55,520
171,010
2,835,110
0.91
Colorado
77,860
37.43
0.7
52,330
144,490
2,578,000
0.95
New Mexico
75,700
36.4
1.4
17,100
47,340
785,720
1.01
Wyoming
72,600
34.9
1.1
5,010
14,010
261,690
0.89
Idaho
71,640
34.44
0.9
12,800
40,750
718,820
0.83
Montana
70,530
33.91
1.2
9,980
29,770
455,450
1.02
Utah
70,370
33.83
0.9
23,690
72,300
1,489,020
0.74
Data source: Data.World
Northeast region table
# gt_plt_bar_stack reference: https://github.com/BjnNowak/TidyTuesday/blob/main/SC_Nurse.R
bar_hourly = df20 %>% filter(st %in% .northeast_region) %>%
group_by(state) %>%
mutate(
X25=round(hourly_25th_percentile),
X50=round(hourly_wage_median),
X75=round(hourly_75th_percentile)
) %>%
arrange(-X75)%>%
summarise(Hourly = list(c(X25,X50,X75)))
bar_annual = df20 %>% filter(st %in% .northeast_region) %>%
group_by(state) %>%
mutate(
X25=round(annual_25th_percentile),
X50=round(annual_salary_median),
X75=round(annual_75th_percentile)
)%>%
arrange(-X75)%>%
summarise(Annual = list(c(X25,X50,X75)))
df20 %>% filter(st %in% .northeast_region) %>%
left_join(bar_hourly) %>%
left_join(bar_annual) %>%
arrange(desc(annual_salary_avg)) %>%
select(state, total_employed_rn, annual_salary_avg, Annual, hourly_wage_avg, Hourly) %>%
gt() %>%
gt_theme_538() %>%
#gt_merge_stack(col1 = state, col2 = st) %>%
gt_plt_dot(annual_salary_avg,state,palette = c("#6c757d", "#dee2e6")) %>%
gt_plt_bar_stack(
column=Annual, palette = c("#a4243b","#05668d","#d8973c"),
position = 'stack', labels = c("1st quartile", "Median", "3rd quartile"),
width = 60,trim=TRUE
) %>%
gt_plt_bar_stack(
column=Hourly, palette = c("#5f0f40","#e36414","#0f4c5c"),
position = 'stack', labels = c("1st quartile", "Median", "3rd quartile"),
width = 60,trim=TRUE
) %>%
cols_label(
total_employed_rn = html("Employment"),
annual_salary_avg = html("Avg"),
hourly_wage_avg = html("Avg")
) %>%
tab_spanner(
label = "Annual Salary ($)",
columns = annual_salary_avg:Annual
) %>%
tab_spanner(
label = "Hourly Wage ($)",
columns = hourly_wage_avg:Hourly
) %>%
tab_style(
style = list(cell_text(align = "center")),
locations = cells_column_labels(columns=c(annual_salary_avg,hourly_wage_avg))
) %>%
tab_style(
style = list(cell_text(align = "left")),
locations = cells_column_labels(columns=c(Annual,Hourly))
) %>%
tab_style(
style = list(
cell_text(font=google_font(
name = "Libre Franklin"), weight='800',align = "left",color='black')),
locations = cells_title(groups = "title")
) %>%
tab_options(data_row.padding = px(6),
table.font.size = "14px",
column_labels.font.size = "10.5px",
heading.padding = px(5),
column_labels.padding = px(8),
source_notes.padding = px(14),
) %>%
tab_header(title = "2020 U.S. Registered Nurses in the Northeast Region", subtitle="New York has the highest number of employed registered nurses, and Massachusetts has the highest average annual salary and hourly wage in 2020.") %>%
tab_source_note(source_note="Data source: Data.World")
state
Employment
Annual Salary ($)
Hourly Wage ($)
Avg
1st quartile ||Median ||3rd quartile
Avg
1st quartile ||Median ||3rd quartile
84030
96250
46.27
178550
89760
43.16
78590
85720
41.21
33400
84850
40.79
12150
82790
39.81
13840
75970
36.52
146640
74170
35.66
6810
72140
34.68
14160
71040
34.16
Data source: Data.World
Western region: annual salary
p3 = df20 %>% filter(st %in% .west_region) %>%
select(state, annual_salary_median,annual_10th_percentile,annual_90th_percentile,
annual_25th_percentile,annual_75th_percentile) %>%
arrange(desc(annual_salary_median)) %>%
mutate(state=fct_rev(fct_inorder(state))) %>%
ggplot() +
geom_segment(aes(y=state, yend=state, x=annual_10th_percentile, xend=annual_90th_percentile),
linetype="dotted", color="white") +
geom_segment(aes(y=state, yend=state, x=annual_25th_percentile, xend=annual_75th_percentile), color="white", size=.8) +
geom_point(aes(y=state, x=annual_salary_median), size=2.3, color="white") +
geom_point(aes(y=state, x=annual_25th_percentile), size=3, color="white", shape="|") +
geom_point(aes(y=state, x=annual_75th_percentile), size=3, color="white", shape="|") +
geom_point(aes(y=state, x=annual_10th_percentile), size=2, color="white", shape="|") +
geom_point(aes(y=state, x=annual_90th_percentile), size=2, color="white", shape="|") +
scale_x_continuous("Annual Salary", labels=dollar_format(scale = .001, suffix = "K"),
expand=c(0,0), limits=c(50000,175000)) +
coord_cartesian(clip="off") +
scale_y_discrete("",expand = expansion(mult = c(0.08, .15))) +
theme_minimal(base_size = 10) +
theme(panel.grid.major.y=element_blank(),
panel.grid.minor=element_blank(),
panel.grid=element_line(size=.2, color="#343a40"),
plot.title.position = "plot",
plot.title=element_markdown(color="white"),
plot.background = element_rect(fill="#212529",color=NA),
axis.text.y=element_text(color="white", face="bold"),
axis.text.x=element_text(color="white", size=7),
axis.title=element_text(color="white", size=8),
plot.margin = unit(c(.75, 2, .5, 1), "cm"),
plot.caption=element_text(color="white", size=5.5)
) +
labs(title="Annual Salary of **Registered Nurses** in Western US (2020)",
caption="Data from: Data.World") +
annotate(geom="text",,size=2.8, y=13.9, x=c(76180, 93970, 118410,147830,173370),
label=c("10th pctl","25th pctl","Median","75th pctl","90th pctl"), color="white")
p4 = plot_usmap(include = .west_region, color="#adb5bd", fill="#212529")
p3 | inset_element(p4, align_to = "full", clip=F, on_top=T, ignore_tag = T,
left =0.57, bottom=.2, right=1, top=.6)
Midwest region: median annual salary
plot_usmap(data=df20, values="annual_salary_median", include=.midwest_region, color="white") +
scale_fill_continuous_sequential(palette="PuBuGn", breaks=c(60000, 65000, 70000,75000,79540),label=dollar_format()) +
theme_void(base_size = 8.5) +
theme(plot.margin = unit(c(.75, 1, .55, 1), "cm"),
legend.title=element_text(size=7.7),
plot.title=element_markdown(size=12,hjust=.5, margin=margin(b=10)),
plot.caption = element_text(size=6),
legend.position = "top") +
coord_fixed() +
annotate(geom="richtext",label.color=NA, size=2.6,fill=NA,
color=c("black","black","black","black","white","black","black","white","black","black","white","white"),
x=c(-40000, -30000, 30000, 130000, 430000, 530000,660000,900000,1180000, 1450000, 1250000,780000),
y=c(270000,-50000, -400000, -720000, 250000, -300000, -720000, -500000,-450000,-380000,-100000,20000),
label=c("North Dakota<br>$68,800","South Dakota<br>$60,000","Nebraska<br>$68,010",
"Kansas<br>$62,550","Minnesota<br>$79,540","Iowa<br>$61,130",
"Missouri<br>$64,220", "Illinois<br>$72,610", "Indiana<br>$65,000",
"Ohio<br>$67,580","Michigan<br>$73,040","Wisconsin<br>$73,540")) +
labs(title="**Annual Salary of Registered Nurses in the Midwest**",
fill="Median Annual Salary in 2020", caption="Data from: Data.World") +
guides(fill = guide_colorbar(title.position = "top",
title.hjust = .5,
barwidth = unit(15, "lines"),
barheight = unit(.5, "lines")))
# north east grid
northeast_grid2 = us_state_grid2 %>% filter(code %in% .northeast_region) %>%
mutate(col = col-8,
col=ifelse(row==1,col-1,col))
# percent change (wage and total emp)
nurses %>%
filter(st %in% .northeast_region) %>%
select(year,state,hourly_wage_median, total_employed_rn) %>%
group_by(state) %>%
arrange(year, .by_group=TRUE) %>%
mutate("Hourly wage median"=(hourly_wage_median/lag(hourly_wage_median)-1),
"Total employed RN"=(total_employed_rn/lag(total_employed_rn)-1)) %>%
select(year, state, "Hourly wage median", "Total employed RN") %>%
pivot_longer("Hourly wage median":"Total employed RN") %>%
ggplot(aes(x=year, y=value, color=(name))) +
geom_hline(yintercept=0, linetype="dashed", color="#747474") +
geom_line(show.legend = F) +
scale_y_continuous(labels=scales::percent) +
scale_x_continuous(breaks=c(2000,2010,2020)) +
facet_geo(~state, grid=northeast_grid2) +
scale_color_manual(values=c("#f28f3b","#588b8b")) +
#scale_color_manual(values=c("#ff8811","#eaf8bf")) +
theme_gdocs(base_size = 5) +
theme(panel.grid.major=element_blank(),
axis.line.x=element_blank(),
strip.text=element_text(size=8, color="white"),
axis.text=element_text(color="white"),
axis.title=element_blank(),
plot.background = element_rect(fill="#212529", color=NA),
plot.margin = unit(c(.5, 2, .5, 1.5), "cm"),
panel.spacing.x = unit(2, "lines"),
plot.title.position="plot",
plot.title=element_text(color="white", size=11),
plot.subtitle=element_markdown(color="#e9ecef", size=8.5),
) +
labs(title="Northeast Region Registered Nurses (1998-2020)",
subtitle= "<span style = 'color:#f28f3b;'><b>Median hourly wage<b></span> and <span style = 'color:#588b8b;'><b>total employed<b></span>, expressed in percentage change over previous year<br>")
NA
Southern region: hourly wage
library(ggfan)
south_grid2 = us_state_grid2 %>% filter(code %in% .south_region) %>%
mutate(col=col-3, row=row-3)
fan = nurses %>%
mutate(st=ifelse(state=="District of Columbia","DC",st)) %>%
filter(st %in% .south_region) %>%
select(state, year, hourly_wage_median, contains("hourly") & contains("percentile")) %>%
rename("percentile_0" = "hourly_wage_median") %>%
pivot_longer(contains("perc")) %>%
mutate(percentile = parse_number(name) / 100)
ggplot(fan, aes(x = year, y = value, quantile = percentile)) +
geom_fan() +
geom_line(aes(group = percentile), size = 0.2, color = "white") +
scale_x_continuous(breaks = c(2000, 2010, 2020)) +
scale_y_continuous(labels=dollar_format()) +
scale_fill_stepsn(colors = c("#38a3a5", "#22577a")) +
facet_geo(~state, grid=south_grid2) +
theme_minimal(base_size = 6, base_family = "Arial Narrow") +
theme(legend.position = "none",
strip.text=element_text(size=5.5, face="bold", family="Arial Narrow"),
panel.grid.minor=element_blank(),
axis.title=element_blank(),
panel.grid=element_line(size=.2),
plot.margin = unit(c(-.5, 1, .5, 1), "cm"),
plot.title = element_text(vjust = - 16, size=11, face="bold"),
plot.subtitle = element_text(vjust = - 26, size=8, lineheight = 1.3),
plot.caption=element_text(hjust=.5, size=5)
) +
labs(title="Registered Nurses Hourly Wages in Southern US",
subtitle="From 1998 to 2020\n10th, 25th, 50th(median),75th and 90th percentile",
caption="\nData source: Data.World")
LS0tCnRpdGxlOiAiVGlkeSBUdWVzZGF5IDIwMjEgV2VlayA0MSIKZGF0ZTogIjIwMjEvMTAvMDUiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCltUaWR5VHVlc2RheV0oaHR0cHM6Ly9naXRodWIuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheSkgd2VlayA0MTogW1JlZ2lzdGVyZWQgTnVyc2VzXShodHRwczovL2dpdGh1Yi5jb20vcmZvcmRhdGFzY2llbmNlL3RpZHl0dWVzZGF5L3RyZWUvbWFzdGVyL2RhdGEvMjAyMS8yMDIxLTEwLTA1KSwgZGF0YSBmcm9tIFtEYXRhLldvcmxkXShodHRwczovL2RhdGEud29ybGQvemVuZG9sbDI3L3JlZ2lzdGVyZWQtbnVyc2luZy1sYWJvci1zdGF0cy0xOTk4LTIwMjApLgoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkoZ2d0ZXh0KQpsaWJyYXJ5KHNjYWxlcykKbGlicmFyeShnZW9mYWNldCkKbGlicmFyeShjb2xvcnNwYWNlKQpsaWJyYXJ5KGJpc2NhbGUpCmxpYnJhcnkoY293cGxvdCkKYGBgCgpgYGB7cn0KbnVyc2VzIDwtIHJlYWRyOjpyZWFkX2NzdignaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3Jmb3JkYXRhc2NpZW5jZS90aWR5dHVlc2RheS9tYXN0ZXIvZGF0YS8yMDIxLzIwMjEtMTAtMDUvbnVyc2VzLmNzdicpICU+JSBjbGVhbl9uYW1lcygpCmBgYAoKYGBge3J9CnJhbmdlKG51cnNlcyR5ZWFyKQpgYGAKCiMjIyBUaWxlIG1hcCAKKiBzaGFyZWQgb24gW1R3aXR0ZXJdKGh0dHBzOi8vdHdpdHRlci5jb20vbGVlb2xuZXkzL3N0YXR1cy8xNDQ1MTk2MzQ5ODg5MjkwMjQxKQoKYGBge3J9Cm51cnNlcyRzdCA8LSBzdGF0ZS5hYmJbbWF0Y2gobnVyc2VzJHN0YXRlLCBzdGF0ZS5uYW1lKV0KCmRmMjAgPSBudXJzZXMgJT4lIGZpbHRlcih5ZWFyPT0yMDIwKSAlPiUgCiAgbXV0YXRlKHN0PWlmZWxzZShzdGF0ZT09IkRpc3RyaWN0IG9mIENvbHVtYmlhIiwiREMiLHN0KSkgJT4lCiAgbXV0YXRlKHN0PWlmZWxzZShzdGF0ZT09IlB1ZXJ0byBSaWNvIiwiUFIiLHN0KSkgJT4lIAogIGRyb3BfbmEoc3QpIApgYGAKCmBgYHtyfQpkZjEgPSBkZjIwICU+JQogIHNlbGVjdChzdGF0ZSwgc3QsIHllYXIsIHRvdGFsX2VtcGxveWVkX3JuLCBob3VybHlfd2FnZV9tZWRpYW4pICU+JQogIGJpX2NsYXNzKHg9aG91cmx5X3dhZ2VfbWVkaWFuLCB5PXRvdGFsX2VtcGxveWVkX3JuLCBzdHlsZT0icXVhbnRpbGUiLGRpbT0zKSAKYGBgCgoKYGBge3J9CmNyZWF0ZV9ncmFkaWVudF9zdGF0ZV90aWxlX21hcCA8LSBmdW5jdGlvbihzdGF0ZSwgdmFsdWUsIHRpdGxlLCBzdWJ0aXRsZSwgY2FwdGlvbiwgbGVnZW5kX3RpdGxlLCBzdGF0ZV9ncmlkPSd1c19zdGF0ZV93aXRoX0RDX1BSX2dyaWQyJykgewogIAogIGRmIDwtIGFzLnRpYmJsZShkYXRhLmZyYW1lKHN0YXRlLCB2YWx1ZSkpCiAgCiAgZmlnIDwtIGRmICU+JSAKICAgIG11dGF0ZSh4ID0gMSkgJT4lIAogICAgbXV0YXRlKGxhYmVsX3kgPSAuNSkgJT4lICAKICAgIG11dGF0ZShsYWJlbF94ID0gMSkgJT4lIAogICAgZ2dwbG90KCkrCiAgICBnZW9tX2JhcihtYXBwaW5nPWFlcyh4PXgsIGZpbGw9dmFsdWUpLCB3aWR0aD0uNCkgICsKICAgIGZhY2V0X2dlbyh+IHN0YXRlLCBncmlkPXN0YXRlX2dyaWQpICsKICAgIGxhYnModGl0bGU9dGl0bGUsIHN1YnRpdGxlPXN1YnRpdGxlLCBjYXB0aW9uPWNhcHRpb24pICsKICAgIGdlb21fdGV4dChhZXMoeD1sYWJlbF94LCB5PWxhYmVsX3ksIGxhYmVsPXN0YXRlLCBjb2xvcj12YWx1ZSksc2l6ZT0zLCBzaG93LmxlZ2VuZD1GLCBmYW1pbHk9InNhbnMiKSAKICAKICByZXR1cm4oZmlnKQp9CmBgYAoKCmBgYHtyLCB3YXJuaW5nPUYsIG1lc3NhZ2U9Rn0KIyBleGNsLiBHdWFtIGFuZCBWaXJnaW4gSXNsYW5kcwpwMSA9IGNyZWF0ZV9ncmFkaWVudF9zdGF0ZV90aWxlX21hcChkZjEkc3QsIGRmMSRiaV9jbGFzcywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPSdVUy1iYXNlZCBSZWdpc3RlcmVkIE51cnNlcyBFbXBsb3ltZW50IGFuZCBXYWdlIGluIDIwMjAnLCBsZWdlbmRfdGl0bGUgPSAiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3VidGl0bGU9IjxzcGFuIHN0eWxlID0gJ2NvbG9yOiMwMTJhNGE7Jz48Yj5Ub3RhbCBlbXBsb3llZCByZWdpc3RlcmVkIG51cnNlczwvYj48L3NwYW4+IGFuZCA8c3BhbiBzdHlsZSA9ICdjb2xvcjojMDEyYTRhOyc+PGI+bWVkaWFuIGhvdXJseSB3YWdlPC9iPjwvc3Bhbj4sIGJ5IFVTIHN0YXRlXG4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FwdGlvbj0iTm90ZTogRGF0YSBmcm9tIEd1YW0gYW5kIFZpcmdpbiBJc2xhbmRzIGFyZSBub3QgcHJlc2VudGVkPGJyPiNUaWR5VHVlc2RheSBXZWVrIDQxIHwgRGF0YSBmcm9tIERhdGEuV29ybGQiKSArIAogIGJpX3NjYWxlX2ZpbGwocGFsPSJEa0N5YW4iLGRpbT0zLCBndWlkZT0ibm9uZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoImdyZXkxMCIsImdyZXkxMCIsIndoaXRlIiwid2hpdGUiLCJ3aGl0ZSIsIndoaXRlIiwid2hpdGUiLCJ3aGl0ZSIsIndoaXRlIikpICsKICB0aGVtZV92b2lkKGJhc2Vfc2l6ZT0xMCwgYmFzZV9mYW1pbHkgPSAic2FucyIpICsgCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBsb3QubWFyZ2luID0gdW5pdChjKC41LDQsLjUsMiksICJjbSIpLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MTQsIGZhY2U9ImJvbGQiLCBjb2xvcj0iIzAxMmE0YSIpLAogICAgICAgIHBsb3Quc3VidGl0bGU9ZWxlbWVudF9tYXJrZG93bihzaXplPTgsIGNvbG9yPSIjMDExYzMxIiwgbWFyZ2luPW1hcmdpbih0PTUsYj0xOCkpLAogICAgICAgIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT05KSwKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKHNpemU9NS42LCBjb2xvcj0iIzAxMWMzMSIsbWFyZ2luPW1hcmdpbih0PTMwKSwgbGluZWhlaWdodD0xLjUsIGhqdXN0PTApKSArIAogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3JiYXIodGl0bGU9IkNvdW50IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGUucG9zaXRpb24gPSAidG9wIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcndpZHRoID0gdW5pdCguNSwgImxpbmVzIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYXJoZWlnaHQgPSB1bml0KDEwLCAibGluZXMiKSkpIApgYGAKCmBgYHtyfQpwMiA9IGJpX2xlZ2VuZChwYWwgPSAiRGtDeWFuIiwgCiAgICAgICAgICAgIGRpbSA9IDMsCiAgICAgICAgICAgIHlsYWIgPSAiVG90YWwgZW1wbG95ZWQiLAogICAgICAgICAgICB4bGFiID0gIk1lZGlhbiBob3VybHkgd2FnZSIsCiAgICAgICAgICAgIHNpemUgPSAyLjUpICsgCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYsIGZhbWlseT0ic2FucyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMTFjMzEiLCBtYXJnaW49bWFyZ2luKHQ9LTUpKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYsIGZhbWlseT0ic2FucyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMTFjMzEiLCBtYXJnaW49bWFyZ2luKHI9LTUpKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNiksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC50ZXh0LmFsaWduID0gMCkKYGBgCgoKYGBge3IsbWVzc2FnZT1GLCB3YXJuaW5nPUZ9CmdnZHJhdygpICsKICBkcmF3X3Bsb3QocDEsIDAsIDAsIDEsIDEpICsKICBkcmF3X3Bsb3QocDIsIDAuNzIsIDAuMDQsIDAuMjUsIDAuMjUpIApgYGAKCkFsVCB0ZXh0OiBCaXZhcmlhdGUgaGVhdG1hcCBvZiBVUy1iYXNlZCByZWdpc3RlcmVkIG51cnNlcycgbWVkaWFuIGhvdXJseSByYXRlIGFuZCB0b3RhbCBlbXBsb3ltZW50IGJ5IHN0YXRlIChleGNsdWRpbmcgR3VhbSBhbmQgVmlyZ2luIElzbGFuZCkuIFRoZSB2aXN1YWxpemF0aW9uIHNob3dzIHRoYXQgaW4gY29tcGFyaXNvbiB0byBvdGhlciBzdGF0ZXM6IFV0YWgsIFNvdXRoIERha290YSwgV2VzdCBWaXJnaW5pYSBhbmQgUHVlcnRvIFJpY28gaGF2ZSB0aGUgbGVhc3QgdG90YWwgcmVnaXN0ZXJlZCBudXJzZXMgZW1wbG95bWVudCBhbmQgbG93ZXN0IG1lZGlhbiBob3VybHkgcmF0ZS4gQ2FsaWZvcm5pYSwgTWlubmVzb3RhLCBNYXNzYWNodXNldHRzLCBOZXcgWW9yaywgYW5kIE5ldyBKZXJzZXkgaGF2ZSB0aGUgbW9zdCB0b3RhbCBlbXBsb3ltZW50IGFuZCBoaWdoZXN0IG1lZGlhbiBob3VybHkgcmF0ZSBjb21wYXJlZCB0byB0aGUgb3RoZXIgc3RhdGVzLiAKCiMjIyBUaWxlIG1hcCB2MgoqIGFkZCBsYWJlbHMgZm9yIG1lZGlhbiBob3VybHkgcmFnZSBhbmQgdG90YWwgZW1wbG95bWVudCAKCmBgYHtyfQojIGJpdmFyaWF0ZSBwYWxldHRlIHJlZmVyZW5jZTogaHR0cHM6Ly9ub3dvc2FkLmdpdGh1Yi5pby9wb3N0L2NiYy1icDIvCmxpYnJhcnkocGFscykKI2JyZXdlci5zZXFzZXEyKCkKYmlfcGFsIDwtIGJpX3BhbF9tYW51YWwodmFsXzFfMSA9ICIjZjNmM2YzIiwgdmFsXzFfMiA9ICIjYjRkM2UxIiwgdmFsXzFfMyA9ICIjNTA5ZGMyIiwKICAgICAgICAgICAgICAgICAgICAgICAgdmFsXzJfMSA9ICIjZjNlNmIzIiwgdmFsXzJfMiA9ICIjYjNiM2IzIix2YWxfMl8zID0gIiMzNzYzODciLAogICAgICAgICAgICAgICAgICAgICAgICB2YWxfM18xID0gIiNmM2IzMDAiLCB2YWxfM18yID0gIiNiMzY2MDAiLHZhbF8zXzMgPSAiIzAwMDAwMCIpCiMgbGFiZWwgY29sb3JzCmRmMiA9IGRmMSAlPiUgCiAgbXV0YXRlKGNvbD1jYXNlX3doZW4oc3RyX2RldGVjdChiaV9jbGFzcywiMyIpfiJ3aGl0ZSIsVFJVRX4iYmxhY2siKSkgJT4lCiAgbXV0YXRlKGNvbD1jYXNlX3doZW4oYmlfY2xhc3M9PSIzLTEifiJibGFjayIsVFJVRX5jb2wpKQpgYGAKCmBgYHtyLCBtZXNzYWdlPUZ9CnAxYiA9IGRmMiAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9yZWN0KGFlcyhmaWxsPWJpX2NsYXNzKSwgeG1pbj0tMSwgeG1heD0xLCB5bWluPS0xLCB5bWF4PTEsIGNvbG9yPSJ3aGl0ZSIsIHNob3cubGVnZW5kID0gRikgKwogIGdlb21fcmljaHRleHQoYWVzKGNvbG9yPWNvbCwgbGFiZWw9Z2x1ZTo6Z2x1ZSgiPHNwYW4gc3R5bGU9J2ZvbnQtc2l6ZTogMTFweDsnPntzdH08L3NwYW4+PGJyPntkb2xsYXIoaG91cmx5X3dhZ2VfbWVkaWFuKX08YnI+e3JvdW5kKHRvdGFsX2VtcGxveWVkX3JuLzEwMDAsMSl9SyIpKSwKICAgICAgICAgICAgICAgIHg9MC41LCB5PTAuNDUsIHNpemU9MS41LCBoanVzdD0uNSwgZmlsbD1OQSwgbGFiZWwuY29sb3I9TkEsIHNob3cubGVnZW5kID0gRikgKwogIHNjYWxlX2NvbG9yX2lkZW50aXR5KCkgKwogIGZhY2V0X2dlbyh2YXJzKHN0KSwgZ3JpZD11c19zdGF0ZV93aXRoX0RDX1BSX2dyaWQyKSArCiAgYmlfc2NhbGVfZmlsbChwYWw9YmlfcGFsLCBkaW09MywgZ3VpZGU9Im5vbmUiKSArIAogIHRoZW1lX3ZvaWQoYmFzZV9zaXplID0gOSkgKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoLjUsIDMuMiwgLjUsIDIuNSksICJjbSIpLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF9tYXJrZG93bihmYWNlPSJib2xkIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZT1lbGVtZW50X21hcmtkb3duKG1hcmdpbj1tYXJnaW4odD00LCBiPTE1KSksCiAgICAgICAgcGxvdC5jYXB0aW9uPWVsZW1lbnRfdGV4dChzaXplPTYsIGhqdXN0PTAsIG1hcmdpbj1tYXJnaW4oYj0wLCB0PTMwKSkpICsKICBsYWJzKHRpdGxlPSIyMDIwIFVTLWJhc2VkIFJlZ2lzdGVyZWQgTnVyc2VzIFdhZ2UgYW5kIEVtcGxveW1lbnQiLAogICAgICAgc3VidGl0bGU9Ik1lZGlhbiBob3VybHkgd2FnZSBhbmQgdG90YWwgZW1wbG95ZWQsIGJ5IHN0YXRlIiwKICAgICAgIGNhcHRpb249Ik5vdGU6IERhdGEgZnJvbSBHdWFtIGFuZCBWaXJnaW4gSXNsYW5kcyBhcmUgbm90IHByZXNlbnRlZFxuRGF0YSBzb3VyY2U6IERhdGEuV29ybGQiKQoKcDJiID0gYmlfbGVnZW5kKHBhbCA9ICBiaV9wYWwsCiAgICAgICAgICAgIGRpbSA9IDMsCiAgICAgICAgICAgIHlsYWIgPSAiVG90YWwgZW1wbG95ZWQiLAogICAgICAgICAgICB4bGFiID0gIk1lZGlhbiBob3VybHkgd2FnZSIsCiAgICAgICAgICAgIHNpemUgPSAyLjUpICsgCiAgdGhlbWUocGFuZWwuYm9yZGVyID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYsIGZhbWlseT0ic2FucyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMTFjMzEiLCBtYXJnaW49bWFyZ2luKHQ9LTUpKSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDYsIGZhbWlseT0ic2FucyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMwMTFjMzEiLCBtYXJnaW49bWFyZ2luKHI9LTUpKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gNiksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGxlZ2VuZC50ZXh0LmFsaWduID0gMCkKYGBgCgoKYGBge3IsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpnZ2RyYXcoKSArCiAgZHJhd19wbG90KHAxYiwgMCwgMCwgMSwgMSkgKwogIGRyYXdfcGxvdChwMmIsIDAuNjQ1LCAwLjA0LCAwLjI1LCAwLjI1KSAKYGBgCgojIyMgV2VzdGVybiByZWdpb24gdGFibGUKYGBge3J9CmxpYnJhcnkoZ3QpCmxpYnJhcnkoZ3RFeHRyYXMpCmxpYnJhcnkodXNtYXApCmxpYnJhcnkocGF0Y2h3b3JrKQpgYGAKCmBgYHtyfQpudXJzZXMkc3QgPSBzdGF0ZS5hYmJbbWF0Y2gobnVyc2VzJHN0YXRlLCBzdGF0ZS5uYW1lKV0KCnRhYjEgPSBkZjIwICU+JQogIGZpbHRlcihzdCAlaW4lIC53ZXN0X3JlZ2lvbikgJT4lCiAgbXV0YXRlKGRpdmlzaW9uPSBjYXNlX3doZW4oc3QgJWluJSAubW91bnRhaW4gfiAiTW91bnRhaW4gZGl2aXNpb24iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0ICVpbiUgLnBhY2lmaWMgfiAiUGFjaWZpYyBkaXZpc2lvbiIpKSAlPiUKICAjZ3JvdXBfYnkoc3RhdGUpICU+JSAKICAjbXV0YXRlKHJhdGlvPXRvdGFsX2VtcGxveWVkX3JuL3RvdGFsX2VtcGxveWVkX2hlYWx0aGNhcmVfc3RhdGVfYWdncmVnYXRlKSAlPiUKICAjdW5ncm91cCgpICU+JQogIHNlbGVjdChzdGF0ZSxkaXZpc2lvbiwgIGFubnVhbF9zYWxhcnlfYXZnLCBob3VybHlfd2FnZV9hdmcsd2FnZV9zYWxhcnlfc3RhbmRhcmRfZXJyb3JfcGVyY2VudCwKICAgICAgICAgdG90YWxfZW1wbG95ZWRfcm4sdG90YWxfZW1wbG95ZWRfaGVhbHRoY2FyZV9zdGF0ZV9hZ2dyZWdhdGUseWVhcmx5X3RvdGFsX2VtcGxveWVkX3N0YXRlX2FnZ3JlZ2F0ZSwKICAgICAgICAgbG9jYXRpb25fcXVvdGllbnQpICU+JQogIGFycmFuZ2UoZGVzYyhhbm51YWxfc2FsYXJ5X2F2ZykpCmBgYAoKCgpgYGB7cn0KdGFiMSAlPiUgCiAgZ3QoZ3JvdXBuYW1lX2NvbCA9ICJkaXZpc2lvbiIpICU+JQogIHRhYl9oZWFkZXIodGl0bGUgPSAiV0VTVEVSTiBVLlMuIFJFR0lTVEVSRUQgTlVSU0VTIDIwMjAiKSAlPiUKICB0YWJfc291cmNlX25vdGUoc291cmNlX25vdGU9IkRhdGEgc291cmNlOiBEYXRhLldvcmxkIikgJT4lCiAgY29sc19sYWJlbCgKICAgIGFubnVhbF9zYWxhcnlfYXZnID0gaHRtbCgiQW5udWFsICgkKSIpLAogICAgaG91cmx5X3dhZ2VfYXZnID0gaHRtbCgiSG91cmx5ICgkKSIpLAogICAgd2FnZV9zYWxhcnlfc3RhbmRhcmRfZXJyb3JfcGVyY2VudCA9IGh0bWwoIlNFICglKSIpLAogICAgdG90YWxfZW1wbG95ZWRfcm4gPSBodG1sKCJSTiIpLAogICAgdG90YWxfZW1wbG95ZWRfaGVhbHRoY2FyZV9zdGF0ZV9hZ2dyZWdhdGU9aHRtbCgiSGVhbHRoY2FyZSIpLAogICAgeWVhcmx5X3RvdGFsX2VtcGxveWVkX3N0YXRlX2FnZ3JlZ2F0ZSA9IGh0bWwoIlllYXJseSIpLAogICAgbG9jYXRpb25fcXVvdGllbnQ9aHRtbCgiUXVvdGllbnQiKSwKICAgIHN0YXRlPWh0bWwoIlN0YXRlIiksCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIlRvdGFsIEVtcGxveWVkIiwKICAgIGNvbHVtbnMgPSB0b3RhbF9lbXBsb3llZF9ybjp5ZWFybHlfdG90YWxfZW1wbG95ZWRfc3RhdGVfYWdncmVnYXRlCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIlNhbGFyeS9XYWdlIiwKICAgIGNvbHVtbnMgPSBhbm51YWxfc2FsYXJ5X2F2Zzp3YWdlX3NhbGFyeV9zdGFuZGFyZF9lcnJvcl9wZXJjZW50CiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIkxvY2F0aW9uIiwKICAgIGNvbHVtbnMgPSBsb2NhdGlvbl9xdW90aWVudAogICkgJT4lCiAgdGFiX29wdGlvbnModGFibGUuZm9udC5zaXplID0gIjE0cHgiLAogICAgICAgICAgICAgIGhlYWRpbmcudGl0bGUuZm9udC5zaXplID0gIjE4cHgiLGNvbHVtbl9sYWJlbHMuYm9yZGVyLmJvdHRvbS5jb2xvciA9ICJncmV5IiwKICAgICAgICAgICAgICBkYXRhX3Jvdy5wYWRkaW5nID0gcHgoNCksCiAgICAgICAgICAgICAgaGVhZGluZy5wYWRkaW5nID0gcHgoMTApLAogICAgICAgICAgICAgICkgJT4lCiAgZ3RfaHVsa19jb2xfbnVtZXJpYyhsb2NhdGlvbl9xdW90aWVudCkgJT4lCiAgI2d0X2h1bGtfY29sX251bWVyaWMoaG91cmx5X3dhZ2VfYXZnKSAlPiUKICBndF9odWxrX2NvbF9udW1lcmljKGFubnVhbF9zYWxhcnlfYXZnKSAlPiUKICBndF9odWxrX2NvbF9udW1lcmljKHRvdGFsX2VtcGxveWVkX3JuKSAlPiUKICBjb2xzX2FsaWduKAogICAgYWxpZ24gPSAiY2VudGVyIiwKICAgIGNvbHVtbnMgPSBhbm51YWxfc2FsYXJ5X2F2Zzpsb2NhdGlvbl9xdW90aWVudAogICkgJT4lCiAgY29sc193aWR0aChhbm51YWxfc2FsYXJ5X2F2Zzpsb2NhdGlvbl9xdW90aWVudCB+IHB4KDgwKSkgJT4lCiAgY29sc193aWR0aChzdGF0ZSB+IHB4KDExMCkpICU+JQogIGZtdF9udW1iZXIoYW5udWFsX3NhbGFyeV9hdmc6bG9jYXRpb25fcXVvdGllbnQsIHVzZV9zZXBzID0gVCwgZHJvcF90cmFpbGluZ196ZXJvcyA9IFQpICU+JQogIHRhYl9mb290bm90ZSgKICAgIGZvb3Rub3RlID0gbWQoIlRvdGFsIGVtcGxveWVkIHJlZ2lzdGVyZWQgbnVyc2VzIiksCiAgICBsb2NhdGlvbnMgPSBjZWxsc19jb2x1bW5fbGFiZWxzKGNvbHVtbnMgPSB0b3RhbF9lbXBsb3llZF9ybikKICApICU+JQogIHRhYl9mb290bm90ZSgKICAgIGZvb3Rub3RlID0gbWQoIlRvdGFsIGVtcGxveWVkIGhlYWx0aGNhcmUsIHN0YXRlIGFnZ3JlZ2F0ZSIpLAogICAgbG9jYXRpb25zID0gY2VsbHNfY29sdW1uX2xhYmVscyhjb2x1bW5zID0gdG90YWxfZW1wbG95ZWRfaGVhbHRoY2FyZV9zdGF0ZV9hZ2dyZWdhdGUpCiAgKSAlPiUKICB0YWJfZm9vdG5vdGUoCiAgICBmb290bm90ZSA9IG1kKCJZZWFybHkgdG90YWwgZW1wbG95ZWQsIHN0YXRlIGFnZ3JlZ3RlIiksCiAgICBsb2NhdGlvbnMgPSBjZWxsc19jb2x1bW5fbGFiZWxzKGNvbHVtbnMgPSB5ZWFybHlfdG90YWxfZW1wbG95ZWRfc3RhdGVfYWdncmVnYXRlKQogICkgJT4lCiAgdGFiX3N0eWxlKAogICAgc3R5bGUgPSBsaXN0KAogICAgICBjZWxsX3RleHQoZm9udD1nb29nbGVfZm9udCgKICAgICAgICBuYW1lID0gIkxpYnJlIEZyYW5rbGluIiksIHdlaWdodD0nODAwJyxhbGlnbiA9ICJsZWZ0Iixjb2xvcj0nIzIwM0I0NicpKSwKICAgIGxvY2F0aW9ucyA9IGNlbGxzX3RpdGxlKGdyb3VwcyA9ICJ0aXRsZSIpCiAgKSAlPiUKICB0YWJfc3R5bGUoc3R5bGUgPSBjZWxsX3RleHQoZm9udCA9IGdvb2dsZV9mb250KCJTb3VyY2UgU2FucyBQcm8iKSwgCiAgICAgICAgICAgIHdlaWdodCA9IDQwMCksIGxvY2F0aW9ucyA9IGNlbGxzX2JvZHkoKSkgJT4lCiAgdGFiX3N0eWxlKHN0eWxlID0gY2VsbF90ZXh0KHNpemUgPSBweCgxMi41KSwgY29sb3IgPSAiZ3JleTMwIiwgCiAgICAgICAgZm9udCA9IGdvb2dsZV9mb250KCJTb3VyY2UgU2FucyBQcm8iKSwgdHJhbnNmb3JtID0gInVwcGVyY2FzZSIpLCAKICAgICAgICBsb2NhdGlvbnMgPSBjZWxsc19jb2x1bW5fbGFiZWxzKGV2ZXJ5dGhpbmcoKSkpICU+JQogIHRhYl9zdHlsZShzdHlsZSA9IGNlbGxfdGV4dChzaXplID0gcHgoMTIuNSksIGNvbG9yID0gImdyZXkzMCIsIAogICAgICAgIGZvbnQgPSBnb29nbGVfZm9udCgiU291cmNlIFNhbnMgUHJvIiksIHRyYW5zZm9ybSA9ICJ1cHBlcmNhc2UiKSwgCiAgICAgICAgbG9jYXRpb25zID0gY2VsbHNfY29sdW1uX3NwYW5uZXJzKCkpICU+JQogIHRhYl9zdHlsZShzdHlsZSA9IGNlbGxfdGV4dChzaXplID0gcHgoMTMpLCBjb2xvciA9ICJncmV5MjAiLCAKICAgICAgICBmb250ID0gZ29vZ2xlX2ZvbnQoIlNvdXJjZSBTYW5zIFBybyIpLCBzdHlsZT0iaXRhbGljIiksIAogICAgICAgIGxvY2F0aW9ucyA9IGNlbGxzX2Zvb3Rub3RlcygpKSAlPiUKICB0YWJfc3R5bGUoc3R5bGUgPSBjZWxsX3RleHQoc2l6ZSA9IHB4KDEzKSwgY29sb3IgPSAiZ3JleTIwIiwgCiAgICAgICAgZm9udCA9IGdvb2dsZV9mb250KCJTb3VyY2UgU2FucyBQcm8iKSksIAogICAgICAgIGxvY2F0aW9ucyA9IGNlbGxzX3NvdXJjZV9ub3RlcygpKSAlPiUKICB0YWJfc3R5bGUoc3R5bGUgPSBjZWxsX3RleHQoY29sb3IgPSAiIzIwM0I0NiIsIAogICAgICAgIGZvbnQgPSBnb29nbGVfZm9udCgiU291cmNlIFNhbnMgUHJvIiksIHdlaWdodD02MDAsIHRyYW5zZm9ybSA9ICJ1cHBlcmNhc2UiKSwgCiAgICAgICAgbG9jYXRpb25zID0gY2VsbHNfcm93X2dyb3VwcygpKSAKYGBgCgojIyMgTm9ydGhlYXN0IHJlZ2lvbiB0YWJsZQpgYGB7cn0KIyBndF9wbHRfYmFyX3N0YWNrIHJlZmVyZW5jZTogaHR0cHM6Ly9naXRodWIuY29tL0Jqbk5vd2FrL1RpZHlUdWVzZGF5L2Jsb2IvbWFpbi9TQ19OdXJzZS5SCmJhcl9ob3VybHkgPSBkZjIwICU+JSBmaWx0ZXIoc3QgJWluJSAubm9ydGhlYXN0X3JlZ2lvbikgJT4lIAogIGdyb3VwX2J5KHN0YXRlKSAlPiUKICBtdXRhdGUoCiAgICBYMjU9cm91bmQoaG91cmx5XzI1dGhfcGVyY2VudGlsZSksCiAgICBYNTA9cm91bmQoaG91cmx5X3dhZ2VfbWVkaWFuKSwKICAgIFg3NT1yb3VuZChob3VybHlfNzV0aF9wZXJjZW50aWxlKQogICAgKSAlPiUKICBhcnJhbmdlKC1YNzUpJT4lCiAgc3VtbWFyaXNlKEhvdXJseSA9IGxpc3QoYyhYMjUsWDUwLFg3NSkpKQoKYmFyX2FubnVhbCA9IGRmMjAgJT4lIGZpbHRlcihzdCAlaW4lIC5ub3J0aGVhc3RfcmVnaW9uKSAlPiUgCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQogIG11dGF0ZSgKICAgIFgyNT1yb3VuZChhbm51YWxfMjV0aF9wZXJjZW50aWxlKSwKICAgIFg1MD1yb3VuZChhbm51YWxfc2FsYXJ5X21lZGlhbiksCiAgICBYNzU9cm91bmQoYW5udWFsXzc1dGhfcGVyY2VudGlsZSkKICApJT4lCiAgYXJyYW5nZSgtWDc1KSU+JQogIHN1bW1hcmlzZShBbm51YWwgPSBsaXN0KGMoWDI1LFg1MCxYNzUpKSkKYGBgCgpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9CmRmMjAgJT4lIGZpbHRlcihzdCAlaW4lIC5ub3J0aGVhc3RfcmVnaW9uKSAlPiUgCiAgbGVmdF9qb2luKGJhcl9ob3VybHkpICU+JQogIGxlZnRfam9pbihiYXJfYW5udWFsKSAlPiUKICBhcnJhbmdlKGRlc2MoYW5udWFsX3NhbGFyeV9hdmcpKSAlPiUKICBzZWxlY3Qoc3RhdGUsIHRvdGFsX2VtcGxveWVkX3JuLCBhbm51YWxfc2FsYXJ5X2F2ZywgQW5udWFsLCBob3VybHlfd2FnZV9hdmcsIEhvdXJseSkgJT4lCiAgZ3QoKSAlPiUKICBndF90aGVtZV81MzgoKSAlPiUKICAjZ3RfbWVyZ2Vfc3RhY2soY29sMSA9IHN0YXRlLCBjb2wyID0gc3QpICU+JQogIGd0X3BsdF9kb3QoYW5udWFsX3NhbGFyeV9hdmcsc3RhdGUscGFsZXR0ZSA9IGMoIiM2Yzc1N2QiLCAiI2RlZTJlNiIpKSAlPiUKICBndF9wbHRfYmFyX3N0YWNrKAogICAgY29sdW1uPUFubnVhbCwgcGFsZXR0ZSA9IGMoIiNhNDI0M2IiLCIjMDU2NjhkIiwiI2Q4OTczYyIpLAogICAgcG9zaXRpb24gPSAnc3RhY2snLCBsYWJlbHMgPSBjKCIxc3QgcXVhcnRpbGUiLCAiTWVkaWFuIiwgIjNyZCBxdWFydGlsZSIpLAogICAgd2lkdGggPSA2MCx0cmltPVRSVUUKICApICU+JQogIGd0X3BsdF9iYXJfc3RhY2soCiAgICBjb2x1bW49SG91cmx5LCBwYWxldHRlID0gYygiIzVmMGY0MCIsIiNlMzY0MTQiLCIjMGY0YzVjIiksCiAgICBwb3NpdGlvbiA9ICdzdGFjaycsIGxhYmVscyA9IGMoIjFzdCBxdWFydGlsZSIsICJNZWRpYW4iLCAiM3JkIHF1YXJ0aWxlIiksCiAgICB3aWR0aCA9IDYwLHRyaW09VFJVRQogICkgJT4lCiAgY29sc19sYWJlbCgKICAgIHRvdGFsX2VtcGxveWVkX3JuID0gaHRtbCgiRW1wbG95bWVudCIpLAogICAgYW5udWFsX3NhbGFyeV9hdmcgPSBodG1sKCJBdmciKSwKICAgIGhvdXJseV93YWdlX2F2ZyA9IGh0bWwoIkF2ZyIpCiAgICApICU+JQogIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiQW5udWFsIFNhbGFyeSAoJCkiLAogICAgY29sdW1ucyA9IGFubnVhbF9zYWxhcnlfYXZnOkFubnVhbAogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJIb3VybHkgV2FnZSAoJCkiLAogICAgY29sdW1ucyA9IGhvdXJseV93YWdlX2F2ZzpIb3VybHkKICApICU+JQogIHRhYl9zdHlsZSgKICAgIHN0eWxlID0gbGlzdChjZWxsX3RleHQoYWxpZ24gPSAiY2VudGVyIikpLAogICAgbG9jYXRpb25zID0gY2VsbHNfY29sdW1uX2xhYmVscyhjb2x1bW5zPWMoYW5udWFsX3NhbGFyeV9hdmcsaG91cmx5X3dhZ2VfYXZnKSkKICApICU+JQogIHRhYl9zdHlsZSgKICAgIHN0eWxlID0gbGlzdChjZWxsX3RleHQoYWxpZ24gPSAibGVmdCIpKSwKICAgIGxvY2F0aW9ucyA9IGNlbGxzX2NvbHVtbl9sYWJlbHMoY29sdW1ucz1jKEFubnVhbCxIb3VybHkpKQogICkgJT4lCiAgdGFiX3N0eWxlKAogICAgc3R5bGUgPSBsaXN0KAogICAgICBjZWxsX3RleHQoZm9udD1nb29nbGVfZm9udCgKICAgICAgICBuYW1lID0gIkxpYnJlIEZyYW5rbGluIiksIHdlaWdodD0nODAwJyxhbGlnbiA9ICJsZWZ0Iixjb2xvcj0nYmxhY2snKSksCiAgICBsb2NhdGlvbnMgPSBjZWxsc190aXRsZShncm91cHMgPSAidGl0bGUiKQogICkgJT4lCiAgdGFiX29wdGlvbnMoZGF0YV9yb3cucGFkZGluZyA9IHB4KDYpLAogICAgICAgICAgICAgIHRhYmxlLmZvbnQuc2l6ZSA9ICIxNHB4IiwKICAgICAgICAgICAgICBjb2x1bW5fbGFiZWxzLmZvbnQuc2l6ZSA9ICIxMC41cHgiLAogICAgICAgICAgICAgIGhlYWRpbmcucGFkZGluZyA9IHB4KDUpLAogICAgICAgICAgICAgIGNvbHVtbl9sYWJlbHMucGFkZGluZyA9IHB4KDgpLAogICAgICAgICAgICAgIHNvdXJjZV9ub3Rlcy5wYWRkaW5nID0gcHgoMTQpLAogICAgICAgICAgICAgICkgJT4lCiAgdGFiX2hlYWRlcih0aXRsZSA9ICIyMDIwIFUuUy4gUmVnaXN0ZXJlZCBOdXJzZXMgaW4gdGhlIE5vcnRoZWFzdCBSZWdpb24iLCBzdWJ0aXRsZT0iTmV3IFlvcmsgaGFzIHRoZSBoaWdoZXN0IG51bWJlciBvZiBlbXBsb3llZCByZWdpc3RlcmVkIG51cnNlcywgYW5kIE1hc3NhY2h1c2V0dHMgaGFzIHRoZSBoaWdoZXN0IGF2ZXJhZ2UgYW5udWFsIHNhbGFyeSBhbmQgaG91cmx5IHdhZ2UgaW4gMjAyMC4iKSAlPiUKICB0YWJfc291cmNlX25vdGUoc291cmNlX25vdGU9IkRhdGEgc291cmNlOiBEYXRhLldvcmxkIikgCmBgYAoKCiMjIyBXZXN0ZXJuIHJlZ2lvbjogYW5udWFsIHNhbGFyeQpgYGB7cn0KcDMgPSBkZjIwICU+JSBmaWx0ZXIoc3QgJWluJSAud2VzdF9yZWdpb24pICU+JQogIHNlbGVjdChzdGF0ZSwgYW5udWFsX3NhbGFyeV9tZWRpYW4sYW5udWFsXzEwdGhfcGVyY2VudGlsZSxhbm51YWxfOTB0aF9wZXJjZW50aWxlLAogICAgICAgICBhbm51YWxfMjV0aF9wZXJjZW50aWxlLGFubnVhbF83NXRoX3BlcmNlbnRpbGUpICU+JSAKICBhcnJhbmdlKGRlc2MoYW5udWFsX3NhbGFyeV9tZWRpYW4pKSAlPiUKICBtdXRhdGUoc3RhdGU9ZmN0X3JldihmY3RfaW5vcmRlcihzdGF0ZSkpKSAlPiUKICBnZ3Bsb3QoKSArCiAgZ2VvbV9zZWdtZW50KGFlcyh5PXN0YXRlLCB5ZW5kPXN0YXRlLCB4PWFubnVhbF8xMHRoX3BlcmNlbnRpbGUsIHhlbmQ9YW5udWFsXzkwdGhfcGVyY2VudGlsZSksIAogICAgICAgICAgICAgICBsaW5ldHlwZT0iZG90dGVkIiwgY29sb3I9IndoaXRlIikgKwogIGdlb21fc2VnbWVudChhZXMoeT1zdGF0ZSwgeWVuZD1zdGF0ZSwgeD1hbm51YWxfMjV0aF9wZXJjZW50aWxlLCB4ZW5kPWFubnVhbF83NXRoX3BlcmNlbnRpbGUpLCBjb2xvcj0id2hpdGUiLCBzaXplPS44KSArCiAgZ2VvbV9wb2ludChhZXMoeT1zdGF0ZSwgeD1hbm51YWxfc2FsYXJ5X21lZGlhbiksIHNpemU9Mi4zLCBjb2xvcj0id2hpdGUiKSArCiAgZ2VvbV9wb2ludChhZXMoeT1zdGF0ZSwgeD1hbm51YWxfMjV0aF9wZXJjZW50aWxlKSwgc2l6ZT0zLCBjb2xvcj0id2hpdGUiLCBzaGFwZT0ifCIpICsKICBnZW9tX3BvaW50KGFlcyh5PXN0YXRlLCB4PWFubnVhbF83NXRoX3BlcmNlbnRpbGUpLCBzaXplPTMsIGNvbG9yPSJ3aGl0ZSIsIHNoYXBlPSJ8IikgKwogIGdlb21fcG9pbnQoYWVzKHk9c3RhdGUsIHg9YW5udWFsXzEwdGhfcGVyY2VudGlsZSksIHNpemU9MiwgY29sb3I9IndoaXRlIiwgc2hhcGU9InwiKSArCiAgZ2VvbV9wb2ludChhZXMoeT1zdGF0ZSwgeD1hbm51YWxfOTB0aF9wZXJjZW50aWxlKSwgc2l6ZT0yLCBjb2xvcj0id2hpdGUiLCBzaGFwZT0ifCIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoIkFubnVhbCBTYWxhcnkiLCBsYWJlbHM9ZG9sbGFyX2Zvcm1hdChzY2FsZSA9IC4wMDEsIHN1ZmZpeCA9ICJLIiksIAogICAgICAgICAgICAgICAgICAgICBleHBhbmQ9YygwLDApLCBsaW1pdHM9Yyg1MDAwMCwxNzUwMDApKSArCiAgY29vcmRfY2FydGVzaWFuKGNsaXA9Im9mZiIpICsKICBzY2FsZV95X2Rpc2NyZXRlKCIiLGV4cGFuZCA9IGV4cGFuc2lvbihtdWx0ID0gYygwLjA4LCAuMTUpKSkgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gMTApICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yLnk9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3I9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQ9ZWxlbWVudF9saW5lKHNpemU9LjIsIGNvbG9yPSIjMzQzYTQwIiksCiAgICAgICAgcGxvdC50aXRsZS5wb3NpdGlvbiA9ICJwbG90IiwKICAgICAgICBwbG90LnRpdGxlPWVsZW1lbnRfbWFya2Rvd24oY29sb3I9IndoaXRlIiksCiAgICAgICAgcGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGw9IiMyMTI1MjkiLGNvbG9yPU5BKSwKICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiwgZmFjZT0iYm9sZCIpLAogICAgICAgIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiLCBzaXplPTcpLAogICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF90ZXh0KGNvbG9yPSJ3aGl0ZSIsIHNpemU9OCksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoLjc1LCAyLCAuNSwgMSksICJjbSIpLAogICAgICAgIHBsb3QuY2FwdGlvbj1lbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiwgc2l6ZT01LjUpCiAgICAgICAgKSArCiAgbGFicyh0aXRsZT0iQW5udWFsIFNhbGFyeSBvZiAqKlJlZ2lzdGVyZWQgTnVyc2VzKiogaW4gV2VzdGVybiBVUyAoMjAyMCkiLCAKICAgICAgIGNhcHRpb249IkRhdGEgZnJvbTogRGF0YS5Xb3JsZCIpICsKICBhbm5vdGF0ZShnZW9tPSJ0ZXh0Iiwsc2l6ZT0yLjgsIHk9MTMuOSwgeD1jKDc2MTgwLCA5Mzk3MCwgMTE4NDEwLDE0NzgzMCwxNzMzNzApLCAKICAgICAgICAgICBsYWJlbD1jKCIxMHRoIHBjdGwiLCIyNXRoIHBjdGwiLCJNZWRpYW4iLCI3NXRoIHBjdGwiLCI5MHRoIHBjdGwiKSwgY29sb3I9IndoaXRlIikKCmBgYAoKYGBge3J9CnA0ID0gcGxvdF91c21hcChpbmNsdWRlID0gLndlc3RfcmVnaW9uLCBjb2xvcj0iI2FkYjViZCIsIGZpbGw9IiMyMTI1MjkiKQpgYGAKCmBgYHtyfQpwMyB8IGluc2V0X2VsZW1lbnQocDQsIGFsaWduX3RvID0gImZ1bGwiLCBjbGlwPUYsIG9uX3RvcD1ULCBpZ25vcmVfdGFnID0gVCwKICAgICAgICAgICAgICAgICAgIGxlZnQgPTAuNTcsIGJvdHRvbT0uMiwgcmlnaHQ9MSwgdG9wPS42KQpgYGAKCiMjIyBNaWR3ZXN0IHJlZ2lvbjogbWVkaWFuIGFubnVhbCBzYWxhcnkKYGBge3IsIHdhcm5pbmc9RiwgbWVzc2FnZT1GfQpwbG90X3VzbWFwKGRhdGE9ZGYyMCwgdmFsdWVzPSJhbm51YWxfc2FsYXJ5X21lZGlhbiIsIGluY2x1ZGU9Lm1pZHdlc3RfcmVnaW9uLCBjb2xvcj0id2hpdGUiKSArCiAgc2NhbGVfZmlsbF9jb250aW51b3VzX3NlcXVlbnRpYWwocGFsZXR0ZT0iUHVCdUduIiwgYnJlYWtzPWMoNjAwMDAsIDY1MDAwLCA3MDAwMCw3NTAwMCw3OTU0MCksbGFiZWw9ZG9sbGFyX2Zvcm1hdCgpKSArCiAgdGhlbWVfdm9pZChiYXNlX3NpemUgPSA4LjUpICsKICB0aGVtZShwbG90Lm1hcmdpbiA9IHVuaXQoYyguNzUsIDEsIC41NSwgMSksICJjbSIpLAogICAgICAgIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT03LjcpLAogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF9tYXJrZG93bihzaXplPTEyLGhqdXN0PS41LCBtYXJnaW49bWFyZ2luKGI9MTApKSwKICAgICAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoc2l6ZT02KSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKwogIGNvb3JkX2ZpeGVkKCkgKwogIGFubm90YXRlKGdlb209InJpY2h0ZXh0IixsYWJlbC5jb2xvcj1OQSwgc2l6ZT0yLjYsZmlsbD1OQSwKICAgICAgICAgICBjb2xvcj1jKCJibGFjayIsImJsYWNrIiwiYmxhY2siLCJibGFjayIsIndoaXRlIiwiYmxhY2siLCJibGFjayIsIndoaXRlIiwiYmxhY2siLCJibGFjayIsIndoaXRlIiwid2hpdGUiKSwKICAgICAgICAgICB4PWMoLTQwMDAwLCAtMzAwMDAsIDMwMDAwLCAxMzAwMDAsIDQzMDAwMCwgNTMwMDAwLDY2MDAwMCw5MDAwMDAsMTE4MDAwMCwgMTQ1MDAwMCwgMTI1MDAwMCw3ODAwMDApLCAKICAgICAgICAgICB5PWMoMjcwMDAwLC01MDAwMCwgLTQwMDAwMCwgLTcyMDAwMCwgMjUwMDAwLCAtMzAwMDAwLCAtNzIwMDAwLCAtNTAwMDAwLC00NTAwMDAsLTM4MDAwMCwtMTAwMDAwLDIwMDAwKSwgCiAgICAgICAgICAgbGFiZWw9YygiTm9ydGggRGFrb3RhPGJyPiQ2OCw4MDAiLCJTb3V0aCBEYWtvdGE8YnI+JDYwLDAwMCIsIk5lYnJhc2thPGJyPiQ2OCwwMTAiLAogICAgICAgICAgICAgICAgICAgIkthbnNhczxicj4kNjIsNTUwIiwiTWlubmVzb3RhPGJyPiQ3OSw1NDAiLCJJb3dhPGJyPiQ2MSwxMzAiLAogICAgICAgICAgICAgICAgICAgIk1pc3NvdXJpPGJyPiQ2NCwyMjAiLCAiSWxsaW5vaXM8YnI+JDcyLDYxMCIsICJJbmRpYW5hPGJyPiQ2NSwwMDAiLAogICAgICAgICAgICAgICAgICAgIk9oaW88YnI+JDY3LDU4MCIsIk1pY2hpZ2FuPGJyPiQ3MywwNDAiLCJXaXNjb25zaW48YnI+JDczLDU0MCIpKSArCiAgbGFicyh0aXRsZT0iKipBbm51YWwgU2FsYXJ5IG9mIFJlZ2lzdGVyZWQgTnVyc2VzIGluIHRoZSBNaWR3ZXN0KioiLAogICAgICAgZmlsbD0iTWVkaWFuIEFubnVhbCBTYWxhcnkgaW4gMjAyMCIsIGNhcHRpb249IkRhdGEgZnJvbTogRGF0YS5Xb3JsZCIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG9yYmFyKHRpdGxlLnBvc2l0aW9uID0gInRvcCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlLmhqdXN0ID0gLjUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcndpZHRoID0gdW5pdCgxNSwgImxpbmVzIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhcmhlaWdodCA9IHVuaXQoLjUsICJsaW5lcyIpKSkKYGBgCgpgYGB7ciwgd2FybmluZz1GLCBtZXNzYWdlPUZ9CiMgbm9ydGggZWFzdCBncmlkIApub3J0aGVhc3RfZ3JpZDIgPSB1c19zdGF0ZV9ncmlkMiAlPiUgZmlsdGVyKGNvZGUgJWluJSAubm9ydGhlYXN0X3JlZ2lvbikgJT4lCiAgbXV0YXRlKGNvbCA9IGNvbC04LAogICAgICAgICBjb2w9aWZlbHNlKHJvdz09MSxjb2wtMSxjb2wpKQoKIyBwZXJjZW50IGNoYW5nZSAod2FnZSBhbmQgdG90YWwgZW1wKQpudXJzZXMgJT4lIAogIGZpbHRlcihzdCAlaW4lIC5ub3J0aGVhc3RfcmVnaW9uKSAlPiUgCiAgc2VsZWN0KHllYXIsc3RhdGUsaG91cmx5X3dhZ2VfbWVkaWFuLCB0b3RhbF9lbXBsb3llZF9ybikgJT4lCiAgZ3JvdXBfYnkoc3RhdGUpICU+JQogIGFycmFuZ2UoeWVhciwgLmJ5X2dyb3VwPVRSVUUpICU+JQogIG11dGF0ZSgiSG91cmx5IHdhZ2UgbWVkaWFuIj0oaG91cmx5X3dhZ2VfbWVkaWFuL2xhZyhob3VybHlfd2FnZV9tZWRpYW4pLTEpLAogICAgICAgICAiVG90YWwgZW1wbG95ZWQgUk4iPSh0b3RhbF9lbXBsb3llZF9ybi9sYWcodG90YWxfZW1wbG95ZWRfcm4pLTEpKSAlPiUKICBzZWxlY3QoeWVhciwgc3RhdGUsICJIb3VybHkgd2FnZSBtZWRpYW4iLCAiVG90YWwgZW1wbG95ZWQgUk4iKSAlPiUKICBwaXZvdF9sb25nZXIoIkhvdXJseSB3YWdlIG1lZGlhbiI6IlRvdGFsIGVtcGxveWVkIFJOIikgJT4lCiAgZ2dwbG90KGFlcyh4PXllYXIsIHk9dmFsdWUsIGNvbG9yPShuYW1lKSkpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MCwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSIjNzQ3NDc0IikgKwogIGdlb21fbGluZShzaG93LmxlZ2VuZCA9IEYpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPXNjYWxlczo6cGVyY2VudCkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3M9YygyMDAwLDIwMTAsMjAyMCkpICsKICBmYWNldF9nZW8ofnN0YXRlLCBncmlkPW5vcnRoZWFzdF9ncmlkMikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiI2YyOGYzYiIsIiM1ODhiOGIiKSkgKwogICNzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzPWMoIiNmZjg4MTEiLCIjZWFmOGJmIikpICsKICB0aGVtZV9nZG9jcyhiYXNlX3NpemUgPSA1KSArCiAgdGhlbWUocGFuZWwuZ3JpZC5tYWpvcj1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy5saW5lLng9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHN0cmlwLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OCwgY29sb3I9IndoaXRlIiksCiAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfdGV4dChjb2xvcj0id2hpdGUiKSwKICAgICAgICBheGlzLnRpdGxlPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0iIzIxMjUyOSIsIGNvbG9yPU5BKSwKICAgICAgICBwbG90Lm1hcmdpbiA9IHVuaXQoYyguNSwgMiwgLjUsIDEuNSksICJjbSIpLAogICAgICAgIHBhbmVsLnNwYWNpbmcueCA9IHVuaXQoMiwgImxpbmVzIiksCiAgICAgICAgcGxvdC50aXRsZS5wb3NpdGlvbj0icGxvdCIsCiAgICAgICAgcGxvdC50aXRsZT1lbGVtZW50X3RleHQoY29sb3I9IndoaXRlIiwgc2l6ZT0xMSksCiAgICAgICAgcGxvdC5zdWJ0aXRsZT1lbGVtZW50X21hcmtkb3duKGNvbG9yPSIjZTllY2VmIiwgc2l6ZT04LjUpLAogICAgICAgICkgKwogIGxhYnModGl0bGU9Ik5vcnRoZWFzdCBSZWdpb24gUmVnaXN0ZXJlZCBOdXJzZXMgKDE5OTgtMjAyMCkiLAogICAgICAgc3VidGl0bGU9ICI8c3BhbiBzdHlsZSA9ICdjb2xvcjojZjI4ZjNiOyc+PGI+TWVkaWFuIGhvdXJseSB3YWdlPGI+PC9zcGFuPiBhbmQgPHNwYW4gc3R5bGUgPSAnY29sb3I6IzU4OGI4YjsnPjxiPnRvdGFsIGVtcGxveWVkPGI+PC9zcGFuPiwgZXhwcmVzc2VkIGluIHBlcmNlbnRhZ2UgY2hhbmdlIG92ZXIgcHJldmlvdXMgeWVhcjxicj4iKQogIApgYGAKCiMjIyBTb3V0aGVybiByZWdpb246IGhvdXJseSB3YWdlCgpgYGB7cn0KbGlicmFyeShnZ2ZhbikKYGBgCgpgYGB7cn0Kc291dGhfZ3JpZDIgPSB1c19zdGF0ZV9ncmlkMiAlPiUgZmlsdGVyKGNvZGUgJWluJSAuc291dGhfcmVnaW9uKSAlPiUKICBtdXRhdGUoY29sPWNvbC0zLCByb3c9cm93LTMpIApgYGAKCmBgYHtyfQojIHBsb3QgcmVmZXJlbmNlOiBodHRwczovL3R3aXR0ZXIuY29tL2dlb2thcmFtYW5pcy9zdGF0dXMvMTQ0NTc0MTYwNjI4ODU2MDEyOApmYW4gPSBudXJzZXMgJT4lIAogIG11dGF0ZShzdD1pZmVsc2Uoc3RhdGU9PSJEaXN0cmljdCBvZiBDb2x1bWJpYSIsIkRDIixzdCkpICU+JQogIGZpbHRlcihzdCAlaW4lIC5zb3V0aF9yZWdpb24pICU+JQogIHNlbGVjdChzdGF0ZSwgeWVhciwgaG91cmx5X3dhZ2VfbWVkaWFuLCBjb250YWlucygiaG91cmx5IikgJiBjb250YWlucygicGVyY2VudGlsZSIpKSAlPiUgCiAgcmVuYW1lKCJwZXJjZW50aWxlXzAiID0gImhvdXJseV93YWdlX21lZGlhbiIpICU+JSAgCiAgcGl2b3RfbG9uZ2VyKGNvbnRhaW5zKCJwZXJjIikpICU+JSAKICBtdXRhdGUocGVyY2VudGlsZSA9IHBhcnNlX251bWJlcihuYW1lKSAvIDEwMCkKYGBgCgoKYGBge3IsIG1lc3NhZ2U9Riwgd2FybmluZz1GfQpnZ3Bsb3QoZmFuLCBhZXMoeCA9IHllYXIsIHkgPSB2YWx1ZSwgcXVhbnRpbGUgPSBwZXJjZW50aWxlKSkgKwogIGdlb21fZmFuKCkgKwogIGdlb21fbGluZShhZXMoZ3JvdXAgPSBwZXJjZW50aWxlKSwgc2l6ZSA9IDAuMiwgY29sb3IgPSAid2hpdGUiKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMjAwMCwgMjAxMCwgMjAyMCkpICsKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPWRvbGxhcl9mb3JtYXQoKSkgKwogIHNjYWxlX2ZpbGxfc3RlcHNuKGNvbG9ycyA9IGMoIiMzOGEzYTUiLCAiIzIyNTc3YSIpKSArCiAgZmFjZXRfZ2VvKH5zdGF0ZSwgZ3JpZD1zb3V0aF9ncmlkMikgKwogIHRoZW1lX21pbmltYWwoYmFzZV9zaXplID0gNiwgYmFzZV9mYW1pbHkgPSAiQXJpYWwgTmFycm93IikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwKICAgICAgICBzdHJpcC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTUuNSwgZmFjZT0iYm9sZCIsIGZhbWlseT0iQXJpYWwgTmFycm93IiksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZD1lbGVtZW50X2xpbmUoc2l6ZT0uMiksCiAgICAgICAgcGxvdC5tYXJnaW4gPSB1bml0KGMoLS41LCAxLCAuNSwgMSksICJjbSIpLAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQodmp1c3QgPSAtIDE2LCBzaXplPTExLCBmYWNlPSJib2xkIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfdGV4dCh2anVzdCA9IC0gMjYsIHNpemU9OCwgbGluZWhlaWdodCA9IDEuMyksCiAgICAgICAgcGxvdC5jYXB0aW9uPWVsZW1lbnRfdGV4dChoanVzdD0uNSwgc2l6ZT01KQogICAgICAgICkgKwogIGxhYnModGl0bGU9IlJlZ2lzdGVyZWQgTnVyc2VzIEhvdXJseSBXYWdlcyBpbiBTb3V0aGVybiBVUyIsCiAgICAgICBzdWJ0aXRsZT0iRnJvbSAxOTk4IHRvIDIwMjBcbjEwdGgsIDI1dGgsIDUwdGgobWVkaWFuKSw3NXRoIGFuZCA5MHRoIHBlcmNlbnRpbGUiLAogICAgICAgY2FwdGlvbj0iXG5EYXRhIHNvdXJjZTogRGF0YS5Xb3JsZCIpCmBgYAoKCgoKCg==