1. Introduction
Humanitarian needs always grossly outweigh available funding; however, it remains an industry-wide challenge to respond adequately to gaps in coverage and reallocate resources accordingly. Too often, once committed to a course of action, clusters and their humanitarian partners do not re-examine or re-evaluate their interventions. This results in responses with glaring gaps that are either not resolved in a timely manner or go completely unaddressed.
This automated reported is intended to serve as a template for a coverage and gaps analysis. It provides examples of the analyses necessary to identify populations in need who are not served by humanitarian action and provide recommendations on how partners may best reach them. This document assumes that basic reporting has already occurred; and a more generic 5W report template may be found here.
Coverage and gaps analyses are key documents, but are also rarely taken into account during operational planning or referenced during revisions of major strategic documents, such as Humanitarian Response Plans (HRPs). Neither are they mentioned in OCHA’s HRP guidance, and their usage remains quite uncommon. This document intends to show that coverage and gaps analyses are not complex, impenetrable tools; rather, they contain, and are principally concerned with, practical, actionable information.
A note on the data
- Most of the data originates from the Education, Health, Nutrition, Protection and WASH Clusters, from May to October 2019 – and any conclusions or analysis are bounded by this time period and are illustrative of the response as it was in November 2019. Partner data has been anonymised. Other data originate from the census dataset of Venezuela that was maintained by UNICEF. Unlike the document of 5W reporting and cleaning, we will not be exploring the cleaning process. But the source code of each chunk will be displayed when the
Code
button is clicked. The two chunks on the right contain code for data cleaning and preparation.
# reading and cleaning -- you really should break it into parts
ven1 <- read_csv("consolidation 191209 1636.csv") %>%
clean_names() %>%
# removing unused columns
select(-c(codigodeestablecimientoocentro, loc_id, hrp_sitre_p_indicator,
tipoderespuesta, comentarios, coordeadas_gps_x, coordeadas_gps_y,
fechade_inicio, fecha_previstade_finalizacion)) %>%
# renaming unwieldy columns
rename(ubicacion = comunidadonombredelestablecimiento_centro,
sector = sector_areade_responsabiliad,
beneficiarios_meta = beneficiarios_meta_numerodepersonas,
estatus = estatusdeprogramacion) %>%
# mutating the date to the right format
mutate(month = as.factor(recode(month,
`4` = "30/04/2019",
`5` = "31/05/2019",
`6` = "30/06/2019",
`7` = "31/07/2019",
`8` = "31/08/2019",
`9` = "30/09/2019",
`10` = "31/10/2019"))) %>%
mutate(month = as.Date(month %>% strptime(., format = "%d/%m/%Y"))) %>%
mutate(org_lider = coalesce(org_lider, org_implementadora)) %>%
# correcting sector names
mutate(sector = str_replace_all(sector, c(
"Agua_saneamiento_higiene" = "WASH",
"educacion" = "Educacion",
"Nutricion" = "Nutricion",
"protección_Niños_Niñas_Adolescentes" = "Proteccion_NNA",
"Protección_Niños_Niñas_Adolescentes" = "Proteccion_NNA",
"Protección_Violencia_Género" = "Proteccion_GBV"))) %>%
# renaming beneficiary disaggregation columns
rename(f_0_18 = f_18,
m_0_18 = m_18,
f_18plus = f_18_2,
m_18plus = m_18_2) %>%
mutate(estado = rm_accent(str_to_upper(estado)),
municipio = rm_accent(str_to_upper(municipio)),
parroquia = rm_accent(str_to_upper(parroquia)),
ubicacion = rm_accent(str_to_upper(ubicacion)),
actividad = rm_accent(str_to_upper(actividad)),
categoria = rm_accent(str_to_upper(categoriadeactividad))) %>%
# recoding the estatus column
mutate(estatus = str_replace_all(estatus,
c("En ejecucion" = "ejecucion",
"en ejecución" = "ejecucion",
"en Ejecución" = "ejecucion",
"En ejecución" = "ejecucion",
"En Ejecución" = "ejecucion",
"Enejecución" = "ejecucion",
"43741" = "ejecucion",
"finalizada" = "finalizada",
"Finalizada" = "finalizada",
"Planeada" = "planeada",
"planeada con financiamiento" = "planeada",
"planeada sin financiamiento" = "planeada"))) %>%
replace_na(list(estatus = "ejecucion")) %>%
# removing all planned activities
filter(estatus != "planeada") %>%
filter(str_detect(pcode3, "^VE")) %>% # decide if you want to do this here or later
select(-c(23:92))
# I'm kinda doubting the use of u_ben, ya I think take it out? since you're only using it once
# Am I just making these out of habit? I could make them inside the
# code chunk for parr, but maybe I can find some justification for their existence,
# maybe the disaggregations?
u_ben <- ven1 %>%
pivot_longer(f_0_18:m_18plus, names_to = "desagregacion", values_to = "beneficiarios") %>%
filter(categoria != "VACUNACION") %>% # Vaccination activities filtered out
filter(beneficiarios != 0) %>%
# for some reason, there are entries with the same ubicacion but different pcodes?
# maybe it's things like "centro municipal" or something
group_by(pcode3, ubicacion, desagregacion) %>%
slice(which.max(beneficiarios)) %>%
ungroup()
act_ben <- ven1 %>%
pivot_longer(f_0_18:m_18plus, names_to = "desagregacion", values_to = "beneficiarios") %>%
filter(categoria != "VACUNACION") %>% # Vaccination activities filtered out
filter(beneficiarios != 0) %>%
group_by(pcode3, ubicacion, desagregacion, actividad) %>%
slice(which.max(beneficiarios)) %>%
ungroup() %>%
mutate(sector = ifelse(str_detect(sector, "Proteccion_GBV|Proteccion_General|Proteccion_NNA"),
"Proteccion", sector))
# I think this is a gigantic chunk -- cannot decide if I would rather have less things in the
# environment or if I want more readable chunks. The benefit here I guess is that if I want to change something, I just have to come to this chunk
parr <- u_ben %>%
group_by(pcode3) %>%
summarise(beneficiarios = sum(beneficiarios)) %>%
ungroup() %>%
# count of organisations per pcode3
right_join(act_ben %>%
group_by(pcode3) %>%
summarise(org_count = n_distinct(org_implementadora))) %>%
# getting beneficiary frequencies, sector count and maximum multi-sector beneficiaries
right_join(
act_ben %>%
group_by(pcode3, desagregacion, sector) %>%
pivot_wider(names_from = sector, values_from = beneficiarios) %>%
rename(nutricion_ben = Nutricion, proteccion_ben = Proteccion, wash_ben = WASH,
salud_ben = Salud, educacion_ben = Educacion, sa_ben = Seguridad_Alimentaria) %>%
replace_na(list(nutricion_ben = 0, educacion_ben = 0, wash_ben = 0, salud_ben = 0,
sa_ben = 0, proteccion_ben = 0)) %>%
summarise(across(c(nutricion_ben, proteccion_ben, wash_ben,
educacion_ben, salud_ben, sa_ben), sum), .groups = "drop") %>%
mutate(ben_freq = nutricion_ben + proteccion_ben + wash_ben + salud_ben + educacion_ben + sa_ben) %>%
group_by(pcode3) %>%
summarise(across(c(nutricion_ben, proteccion_ben, wash_ben, salud_ben, educacion_ben,
salud_ben, sa_ben, ben_freq), sum)) %>%
mutate(sec_ben_max = pmax(nutricion_ben, proteccion_ben, wash_ben, salud_ben, educacion_ben, sa_ben),
ms_ben_max = ifelse(sec_ben_max >= ben_freq - sec_ben_max,
ben_freq - sec_ben_max,
sec_ben_max),
sector_count = rowSums(select(., ends_with("_ben")) != 0))) %>%
# right_join to the census data
right_join(read_excel("census data 20191122.xlsx", sheet = "data") %>%
clean_names() %>%
# selecting variables and renaming them with select
select(estado, pcode1, municipio, pcode2, parroquia, pcode3,
fo = field_office,
poblacion_2019 = x_2019_poblacion_parroquial_total,
hogares_2011 = numero_de_hogares,
ham_2019_ambitos_ge,
percent_pobre = ham_2019_xx_pobreza_env_por_parroquia,
pob_pobre = ham_2019_xx_poblacion_pobre_por_parroquia,
poblacion_total_2011,
poblacion_infantil_menor_de_12_anos, poblacion_adolescentes_de_12_a_17_anos,
poblacion_de_18_anos_y_mas,
percent_urbana = poblacion_urbana_percent,
area_km2,
densidad_ppl_km2 = densidad_poblacional_ppl_km2,
matricula_2017_educacion_inicial, matricula_2017_educacion_primaria,
matricula_2017_educacion_media, razon_de_dependencia_total,
razon_de_dependencia_de_menores_de_15_anos,
percent_sin_agua_segura = x_abast_agua2_percent_sin_agua_segura,
percent_sin_saneamiento_mejorado =
x_saneamiento_percent_sin_saneamiento_mejorado,
percent_analfabeto = percent_poblacion_10_anos_y_mas_analfabeta,
promedio_de_personas_por_vivienda,
percent_hogares_jefatura_femenina = percent_de_hogares_con_jefatura_femenina,
percent_sin_servicio_electrico =
servicio_electrico_percent_no_tiene_servicio_electrico,
ham_2019_x_violencia_envelope, ham_2019_x_mortalidad_y_salud_envelope,
ham_2019_x_pobreza_envelope, promedio_de_edad,
relacion_de_masculinidad) %>%
mutate(estado = rm_accent(str_to_upper(estado)), # just to make sure
municipio = rm_accent(str_to_upper(municipio)),
parroquia = rm_accent(str_to_upper(parroquia))) %>%
# creating new disaggregation variables
mutate(pob_menor_de_18 = (poblacion_infantil_menor_de_12_anos +
poblacion_adolescentes_de_12_a_17_anos) /poblacion_total_2011 *
poblacion_2019,
pob_18_y_mas = poblacion_de_18_anos_y_mas / poblacion_total_2011 * poblacion_2019,
hogares_2019 = hogares_2011 * poblacion_2019 / poblacion_total_2011,
matricula_total = matricula_2017_educacion_inicial +
matricula_2017_educacion_primaria +
matricula_2017_educacion_media) %>%
# dividing columns by 100 so that they're between 0 and 1
mutate_at(vars(percent_analfabeto, percent_sin_servicio_electrico,
percent_sin_agua_segura,
percent_sin_saneamiento_mejorado,
percent_hogares_jefatura_femenina, percent_urbana,
razon_de_dependencia_total), ~(. / 100)) %>%
# mutating new columns with populations
mutate(pob_analfabeto = percent_analfabeto * poblacion_2019,
pob_sin_agua_segura = percent_sin_agua_segura * poblacion_2019,
pob_sin_servicio_electrico = percent_sin_servicio_electrico * poblacion_2019,
pob_sin_saneamiento_mejorado = percent_sin_saneamiento_mejorado * poblacion_2019,
pob_urbana = percent_urbana * poblacion_2019) %>%
select(-c(matricula_2017_educacion_inicial, matricula_2017_educacion_primaria,
matricula_2017_educacion_media, poblacion_total_2011, hogares_2011,
poblacion_infantil_menor_de_12_anos, poblacion_adolescentes_de_12_a_17_anos,
poblacion_de_18_anos_y_mas)),
by = "pcode3") %>%
# mutating new variables and making sure NAs become 0s
mutate(beneficiarios = ifelse(is.na(beneficiarios), 0, beneficiarios),
org_count = ifelse(is.na(org_count), 0, org_count),
sector_count = ifelse(is.na(sector_count), 0, sector_count),
educacion_ben = ifelse(is.na(educacion_ben), 0, educacion_ben),
nutricion_ben = ifelse(is.na(nutricion_ben), 0, nutricion_ben),
proteccion_ben = ifelse(is.na(proteccion_ben), 0, proteccion_ben),
salud_ben = ifelse(is.na(salud_ben), 0, salud_ben),
sa_ben = ifelse(is.na(sa_ben), 0, sa_ben),
wash_ben = ifelse(is.na(wash_ben), 0, wash_ben),
ms_ben_max = ifelse(is.na(ms_ben_max), 0, ms_ben_max),
ben_freq = ifelse(is.na(ben_freq), 0, ben_freq),
not_reached = pob_pobre - beneficiarios,
coverage_percent = beneficiarios / pob_pobre,
percent_total_ben_u = beneficiarios / sum(beneficiarios),
multisector_percent = ms_ben_max / ben_freq,
org_present = ifelse(beneficiarios > 0, TRUE, FALSE),
pob_pobre_score = rescale(pob_pobre, to = c(0,1)),
percent_pobre_score = rescale(percent_pobre, to = c(0,1)),
poverty_score = (pob_pobre_score + percent_pobre_score) / 2)
# taking a subset of parr to only get parrishes where the
# number of beneficiaries does not exceed the number of poor persons
parr0 <- parr %>%
filter(not_reached >= 1) %>%
mutate(gap_score = (rescale(not_reached, to = c(0,1)) + percent_pobre_score) / 2)
2. Summary of coverage and gaps
2a. Map of parrishes by gaps
# parrishes with negative poor persons are recoded as "0" so they won't mess up the scale
# even though this means that their tooltips are dropped
gaps_map <- parr %>%
right_join(pcode3_shape, by = "pcode3") %>%
st_as_sf() %>%
mutate(not_reached = ifelse(not_reached < 0.1, 0, not_reached)) %>%
mutate(not_reached = round(not_reached, digits = 0)) %>%
mutate_at(vars(percent_pobre, percent_urbana), ~(round(., digits = 2))) %>%
ggplot() +
geom_sf(aes(fill = not_reached,
text = paste0(parroquia,",", "\n",
municipio, ",", "\n",
estado, "\n",
"not reached: ", not_reached, "\n",
"org count: ", org_count, "\n",
"poverty incidence: ", percent_pobre, "\n",
"percent urban: ", percent_urbana)),
size = 0.1) +
scale_fill_viridis_c(option = "turbo", trans = "log10") +
theme_void() +
theme(legend.title = element_text(size = 7),
legend.text = element_text(size = 7),
plot.title = element_text(size = 11)) +
labs(fill = "Poor persons \nnot reached") +
ggtitle("Map of parrishes by gaps in population reached")
# so are you saying that if I change the fill to viridis in the later plot, I can use hoveron = fill?
# no you can't.
ggplotly(gaps_map, tooltip = c("text")) %>%
layout(showlegend = TRUE, legend = list(font = list(size = 6))) %>%
plotly::style(hoveron = "fill") %>%
layout(title = list(text = paste0("Map of parrishes by number poor persons not reached",
"<br>",
"<sup>",
"mouse over for details; drag and click to select and zoom","</sup>")))
Nationwide, 11,614,406 poor persons have not been covered by response activities – this means that 94.5% of all poor persons in the country have yet to be reached. This population, its distribution and its characteristics are some of the main concerns of this analysis.
2b. Grouping parrishes by coverage type
As a starting point, all 1109 parrishes (admin level 3) have been split into three groups – over, where the number of unique beneficiaries reached exceeds the number of poor persons in that parrish; under, where the coverage is less than the number of poor persons; and no coverage, comprising a total of 508 parrishes, where no activities have occurred.
parr %>%
mutate(coverage_type = case_when(not_reached <= 0 ~ "over",
not_reached > 0 & beneficiarios >= 1 ~ "under",
beneficiarios == 0 ~ "no_coverage")) %>%
group_by(coverage_type) %>%
summarise(parrishes = n(),
beneficiaries = sum(beneficiarios),
not_reached = sum(not_reached),
avg_org_count = mean(org_count),
percent_poor = round(sum(pob_pobre) / sum(poblacion_2019) * 100, digits = 1),
percent_urban = round(sum(pob_urbana) /sum(poblacion_2019) * 100, digits = 1),
percent_wo_safe_water = round(sum(pob_sin_agua_segura) / sum(poblacion_2019) * 100, digits = 1),
percent_wo_improved_sanitation = round(sum(pob_sin_saneamiento_mejorado)/
sum(poblacion_2019) * 100, digits = 1),
percent_illiterate = round(sum(pob_analfabeto) / sum(poblacion_2019) * 100, digits = 1),
avg_sector_count = mean(sector_count)) %>%
pivot_longer(cols = -coverage_type, names_to = "variable") %>%
pivot_wider(names_from = coverage_type, values_from = value) %>%
relocate(no_coverage, .after = under) %>%
pander(big.mark = ",", caption = "Parrish characteristics by coverage type", style = "rmarkdown")
Parrish characteristics by coverage type
parrishes |
11 |
590 |
508 |
beneficiaries |
660,732 |
677,752 |
0 |
not_reached |
-465,811 |
8,941,939 |
2,672,468 |
avg_org_count |
7.636 |
2.278 |
0 |
percent_poor |
20.3 |
37.4 |
46.5 |
percent_urban |
99.5 |
92.9 |
66.9 |
percent_wo_safe_water |
2 |
13.2 |
23.5 |
percent_wo_improved_sanitation |
1 |
7 |
18.6 |
percent_illiterate |
2 |
4.5 |
8.7 |
avg_sector_count |
4 |
1.742 |
0 |
A total of 2,672,468 poor persons reside in the 508 parrishes that have not been reached; this is only 24% of the 11,148,595 poor persons not covered by response activities. This indicates that:
- there is much room to expand in the parrishes where we are already present and that
- sparely populated, remote and, consequently, poorer parrishes have, so far, been left out of the response.
Additionally, the 11 parrishes in the over category are much less poor and much more urban despite having 49% of all beneficiaries. As can be seen from the row not_reached
, the number beneficiaries in the over category has greatly exceeded the number of poor persons.These parrishes are shown in the table in the next section.
2c. Overallocation in the top parrishes by coverage
The 11 parrishes below (from the over category) will largely be excluded in the remainder of this report as it is clear that no further resources should be allocated to them:
parr %>%
mutate(coverage_type = case_when(not_reached <= 0 ~ "over",
not_reached > 0 & beneficiarios >= 1 ~ "under",
beneficiarios == 0 ~ "not_reached")) %>%
filter(coverage_type == "over") %>%
select(state = estado, municipality = municipio, parrish = parroquia,
beneficiaries = beneficiarios, poor_persons = pob_pobre) %>%
mutate(coverage_percent = beneficiaries / poor_persons * 100) %>%
arrange(desc(beneficiaries)) %>%
pander(big.mark = ",", caption = "Top 11 parrishes by coverage", style = "rmarkdown")
Top 11 parrishes by coverage
DISTRITO CAPITAL |
LIBERTADOR |
ALTAGRACIA |
321,597 |
6,244 |
5,151 |
MIRANDA |
SUCRE |
PETARE |
179,716 |
82,058 |
219 |
BOLIVAR |
CARONI |
ONCE DE ABRIL |
69,443 |
54,118 |
128.3 |
BOLIVAR |
HERES |
CATEDRAL |
32,319 |
14,336 |
225.4 |
BOLIVAR |
HERES |
VISTA HERMOSA |
18,477 |
13,919 |
132.7 |
MIRANDA |
CHACAO |
CHACAO |
13,780 |
5,481 |
251.4 |
TACHIRA |
ANDRES BELLO |
CAPITAL CORDERO |
8,603 |
7,766 |
110.8 |
MIRANDA |
SUCRE |
LEONCIO MARTINEZ |
7,554 |
4,792 |
157.6 |
CARABOBO |
VALENCIA |
URBANA CANDELARIA |
5,061 |
4,589 |
110.3 |
TACHIRA |
BOLIVAR |
GENERAL JUAN VICENTE GOMEZ |
2,253 |
362.1 |
622.3 |
DELTA AMACURO |
TUCUPITA |
SAN JOSE |
1,929 |
1,256 |
153.6 |
As a note, it is likely that partners have reported activities which occurred in other parts of the capital in Altagracia, as the total number of beneficaries reached in the whole of Distrito Capital is only 416,275. It is necessary to check back with partners about this; nevertheless, this is the information we have on hand.
2d. Sex ratios by cluster
act_ben %>%
mutate(sex_ben = case_when(str_detect(desagregacion, "^m") ~ "male",
str_detect(desagregacion, "^f") ~ "female")) %>%
group_by(sector) %>%
rename(cluster = sector) %>%
summarise(ben_freq = sum(beneficiarios),
male = sum(beneficiarios[sex_ben == "male"]),
female = sum(beneficiarios[sex_ben == "female"]),
sex_ratio = round(male / female, digits = 2)) %>%
mutate(`%_ben_freq` = round((ben_freq / sum(ben_freq)) * 100, digits = 1)) %>%
relocate(`%_ben_freq`, .after = ben_freq) %>%
arrange(sex_ratio) %>%
pander(caption = "Sex ratio of beneficiary frequencies by cluster")
Sex ratio of beneficiary frequencies by cluster
Salud |
54,800 |
2.6 |
12,383 |
42,417 |
0.29 |
Proteccion |
184,189 |
8.9 |
52,270 |
131,919 |
0.4 |
Nutricion |
385,665 |
18.6 |
141,675 |
243,990 |
0.58 |
Seguridad_Alimentaria |
9,338 |
0.5 |
3,865 |
5,473 |
0.71 |
Educacion |
627,985 |
30.3 |
296,053 |
331,932 |
0.89 |
WASH |
809,949 |
39.1 |
386,483 |
423,466 |
0.91 |
All of the clusters reached more women than men, with Health and Protection being particularly heavily skewed in this regard. For Health, the disproportionality is a bit more understandable as it has a focus on antenatal and obstetric care as well as preventing mother-to-child HIV transmission; Nutrition similarly has a focus on pregnant and lactating women. However, for Protection, some investigation is necessary:
act_ben %>%
mutate(sex_ben = case_when(str_detect(desagregacion, "^m") ~ "male",
str_detect(desagregacion, "^f") ~ "female"),
activity = str_to_sentence(actividad)) %>%
filter(sector == "Proteccion") %>%
group_by(activity) %>%
summarise(ben_freq = sum(beneficiarios),
male = sum(beneficiarios[sex_ben == "male"]),
female = sum(beneficiarios[sex_ben == "female"])) %>%
arrange(desc(ben_freq)) %>% select(-ben_freq) %>% head(5) %>%
pander(caption = "Top 5 Protection activities by beneficiaries",
justify = c("left", "centre", "centre"))
Top 5 Protection activities by beneficiaries
P2.27 apoyar la emision de certificados de nacimiento a nna |
180 |
56,797 |
P2.08 apoyar a nna en riesgo con asistencia legal especializada |
16,304 |
20,866 |
P3.05 sensibilizar a nna, hombres y mujeres sobre prevencion y respuesta a la violencia, abuso, explotacion de nna |
11,660 |
19,208 |
P3.04 sensibilizar a nna, hombres y mujeres sobre prevencion de separacion familiar |
3,990 |
8,813 |
P2.06 nna participan en actividades grupales estructuradas de apoyo psicosocial |
5,222 |
5,356 |
None of the top 5 – the issue of birth certificates; legal assistance; awareness raising on violence, exploitation, abuse and family separation; or psychosocial support – should be predisposed to reach females over males (and in the case of psychosocial support, it is not). The cluster needs to verify these figures and revisit its targetting and beneficiary selection strategies.
For reference, the sex ratio of the country as a whole was 0.99 in the last census – this figure should not have been affected too much by the migrants and refugees who have left the country, as IOM’s Displacement Tracking Matrix reports that population as being 49% female and 51% percent male.
3. Geographical analysis of gaps
3a. Barplot of coverage and gaps by state
# ordering the states
state_ord <- parr %>%
group_by(estado) %>%
summarise(beneficiarios = sum(beneficiarios),
total = sum(pob_pobre)) %>%
mutate(percent_reached = beneficiarios / total) %>%
arrange(percent_reached) %>% select(estado) %>% pull()
stack_text <- parr %>%
group_by(estado) %>%
summarise(beneficiarios = sum(beneficiarios),
total = sum(pob_pobre),
not_reached = sum(not_reached)) %>%
mutate(percent_reached = round(beneficiarios / total * 100, digits = 1)) %>%
arrange(percent_reached) %>%
mutate(percent_reached = paste0(percent_reached,"%"))
state_stack <- parr %>%
select(estado, beneficiarios, not_reached) %>%
group_by(estado) %>%
summarise(beneficiaries = round(sum(beneficiarios), digits = 0),
not_reached = round(sum(not_reached), digits = 0)) %>%
pivot_longer(c(beneficiaries, not_reached),
names_to = "pob_type", values_to = "total") %>%
ggplot(aes(x = total, y = estado)) +
geom_col(aes(fill = pob_type), colour = "grey70", size = 0.03) +
scale_x_continuous(label = comma, breaks = seq(0, 1800000, 200000)) +
scale_y_discrete(limits = state_ord) +
scale_fill_manual(values = c("#DE7065FF", "#403891FF")) +
geom_text(data = stack_text, aes(label = percent_reached),
size = 2.5, colour = "white", fontface = "bold",
position = position_stack(vjust = 0.5)) +
ylab("") + xlab("Number of poor persons") +
labs(fill = "", colour = "",
title = "Barplot of poor persons by state by reached/not reached") +
theme(plot.title = element_text(size = 11),
axis.text.x = element_text(size = 7, angle = 30),
axis.title.x = element_text(size = 9))
ggplotly(state_stack) %>%
layout(legend = list(font = list(size = 7))) %>%
config(displayModeBar = FALSE) %>%
layout(title = list(text = paste0(
"Barplot of poor persons by state by not reached/reached",
"<br>",
"<sup>",
"mouse over for details; figures show percent reached","</sup>")))
86.5% of all beneficiaries are from the states of Distrito Capital, Miranda, Tachira, Bolivar and Zulia, largely corresponding to the locations of UNICEF offices. These states, with the addition of Delta Amacuro, are also where the highest percentages of poor persons have been reached. Barinas has the lowest percentage of its poor population covered.
On average, after the exclusion of the top 11 parrishes, 10.7% of poor persons have been reached countrywide. However, at the state level, this average is 4.6%.
Whilst there are many poor persons yet to be reached in states where we have relatively high coverage, there is a need to ensure that our operational footprint and the consequent resources allocated are equitable and this type of overallocation is avoided – the crisis in Venezuela is nationwide, and unlike an earthquake or a typhoon where there is an epicentre or a stormpath, there is no programmatic rationale to only focus on a few areas.
Let us now move down to a lower level of granularity as state-level analysis is still too superficial. Parrishes will be the main administrative unit of reference in this analysis. Unlike in the 5W cleaning and reporting document, where we focused on municipalities to display achievements for external audiences, greater precision is needed for a coverage and gaps analysis.
3b. Scatterplot of gaps by parrish
From the scatterplot below – where each point is a parrish – we see that there is great variation both in the number of poor persons not covered (size and x-axis) as well as how concentrated they are in a given parrish (y-axis, poverty incidence); both these factors weigh heavily in programming strategies as well as in the ease of beneficiary selection.
The greatest numbers of not reached are found in parrishes between the ranges of poor persons: 10,000-100,000 and poverty incidence: 0.25-0.50 (marked by the yellow box); however, these parrishes also have a much higher than average number of organisations present (more red). This means that operational barriers are much lower in accessing these populations than the parrishes in light blue found in the middle of the plot.
parrplot <- parr0 %>%
mutate_at(vars(pob_pobre, not_reached, org_count), ~(round(.))) %>%
mutate(percent_pobre = round(percent_pobre, digits = 2))%>%
ggplot(aes(x = not_reached, y = percent_pobre,
colour = org_count,
text = paste0(parroquia,",", "\n",
municipio, ",", "\n",
estado))) +
geom_rect(aes(xmin = 10000, xmax = 100000, ymin = 0.25, ymax = 0.50),
fill = "transparent", colour = "gold", size = 0.2) +
geom_jitter(aes(size = not_reached), alpha = 0.75) +
scale_colour_gradientn(
colours = c("cornflowerblue", "tomato", "firebrick")) +
scale_x_continuous(trans = "log10", labels = comma) +
scale_size_continuous(range = c(0.3, 5)) +
xlab("Not covered poor") + ylab("Poverty incidence") +
labs(colour = "Number of \norganisations",
title = "Scatterplot of parrishes by poor persons not covered and poverty incidence") +
theme(legend.title = element_text(size = 7),
legend.text = element_text(size = 7),
plot.title = element_text(size = 11),
axis.title = element_text(size = 8.5))
ggplotly(parrplot, tooltip = c("y", "x", "size", "text", "colour")) %>%
layout(showlegend = TRUE, legend = list(font = list(size = 7))) %>%
config(displayModeBar = FALSE) %>%
layout(title = list(text = paste0(
"Scatterplot of parrishes by number poor persons not reached and poverty incidence",
"<br>",
"<sup>",
"size: number of poor persons not reached; colour: number of organisations present; drag and click to select and zoom","</sup>")))
For agencies truly unable to expand outside their current footprints, there are still many beneficiaries who are not covered or – as we will discuss in the next chapter – have only been reached with the interventions of one sector.
4. Multi-sector programming
Humanitarian emergencies are multidimensional and needs affected persons are not delineated by cluster. Phenomena such as displacement or food insecurity result from the complex interplay between numerous underlying factors and the shocks and stresses of the hazard. Multi-sector or integrated programming, consists of implementing layers of individual, household and community-level interventions to comprehensively meet the needs of a target population. It is often held up as a key marker of programme quality in strategy documents and humanitarian standards, but rarely achieved in practice.
4a. Summary table of multi-sector coverage
However, just because two Clusters operate in the same area do not mean their beneficiaries coincide. As an estimate, we calculated a theoretical maximum number of multi-sector beneficiaries, expressed below as multi_sector_ben
(explanation and calculation in the code chunk below). But, to elaborate with an example, we make the charitable assumption that that females under 18 who are beneficiaries of Nutrition and females under 18 in that same parrish who are beneficiaries of Protection are the same people – we then sum the various age and sex disaggregation subtotals by parrish to determine the maximum number of persons who could have received multi-sector support. The actual number of multi-sector beneficiaries is likely much lower.
This data has been summarised below, according to the number of sectors present in a parrish:
# Notes on calculation for multi-sector beneficiaries.
# Basically, beneficiaries per parrish are aggregated into
# sector subtotals and a beneficiary frequency total.
# The maximum value of the sector subtotals is compared against the beneficiary frequency total,
# if the maximum value is equal to the frequency total, then there is only one sector,
# if the maximum value is less than the frequency total,
# the difference between the two (or the sum of all other sector subtotals)
# becomes the theoretical maximum number of multisector beneficiaries.
# Performing this calculation at admin level 3 makes sense as a parrish is small enough
# that there it is realistic to assume that overlaps in beneficiaries between sectors exist --
# i.e. that females under 18 in a parrish who are beneficiaries of nutrition
# and females under 18 in that same parrish who are beneficiaries of WASH are the same people.
# Although I do feel this calculation to be very charitable
# We can't really do much more unless there is a beneficiary register.
# The real number of multisector beneficiaries is likely MUCH LOWER
# but that can only be verified through sampled large-scale post-distribution/post-intervention monitoring,
# which is extremely rare.
# I actually could have raised this with the third-party monitors that UNICEF,
# so it's an oversight on my part as well.
# These operations were already performed in "A note on the data" and are part of `parr` and are
# therefore, commented out here
# act_ben %>%
# group_by(pcode3, desagregacion, sector) %>%
# pivot_wider(names_from = sector, values_from = beneficiarios) %>%
# rename(nutricion_ben = Nutricion, proteccion_ben = Proteccion, wash_ben = WASH,
# salud_ben = Salud, educacion_ben = Educacion, sa_ben = Seguridad_Alimentaria) %>%
# replace_na(list(nutricion_ben = 0, educacion_ben = 0, wash_ben = 0, salud_ben = 0,
# sa_ben = 0, proteccion_ben = 0)) %>%
# summarise(across(c(nutricion_ben, proteccion_ben, wash_ben,
# educacion_ben, salud_ben, sa_ben), sum)) %>%
# mutate(ben_freq = nutricion_ben + proteccion_ben + wash_ben + salud_ben + educacion_ben + sa_ben,
# sec_ben_max = pmax(nutricion_ben, proteccion_ben, wash_ben, salud_ben, educacion_ben, sa_ben),
# ms_ben_max = ifelse(sec_ben_max >= ben_freq - sec_ben_max,
# ben_freq - sec_ben_max,
# sec_ben_max)) %>%
# group_by(pcode3) %>%
# summarise(across(c(nutricion_ben, proteccion_ben, wash_ben, salud_ben, educacion_ben,
# salud_ben, sa_ben, ben_freq, sec_ben_max, ms_ben_max), sum)) %>%
# mutate(sector_count = rowSums(select(., ends_with("_ben")) != 0))
# using parr means that all parrishes are included, but they are needed for the percentage calculations.
parr %>%
filter(ben_freq != 0) %>%
group_by(sector_count) %>%
summarise(parrishes = n(),
multi_sector_ben = sum(ms_ben_max),
one_sector_ben = sum(ben_freq) - sum(ms_ben_max),
`multisector_%` = round(sum(ms_ben_max) / sum(ben_freq) * 100, digits = 2)) %>%
pander(style = "rmarkdown", caption = "Summary of multisector coverage")
Summary of multisector coverage
1 |
365 |
0 |
242,522 |
0 |
2 |
103 |
40,938 |
148,208 |
21.64 |
3 |
64 |
49,475 |
149,788 |
24.83 |
4 |
42 |
154,723 |
625,430 |
19.83 |
5 |
21 |
163,159 |
372,180 |
30.48 |
6 |
6 |
51,743 |
68,611 |
42.99 |
Overall, the results are not encouraging – a maximum of 22.3% of beneficiaries (outside of the top 11 parrishes) could potentially covered by multi-sector support. When vaccinations are included, this percentage drops to 12.2%. But, as mentioned, vaccinations will be excluded from this analysis as government partners were not able to accurately provide records at the parrish level, many times defaulting to municipal or state-level reporting; additionally, the footprint for vaccination activities is determined by federal government priorities (that may not align with the humanitarian imperative), which UNICEF is also unable to influence.
As the leader of the Education, Nutrition, WASH and Child Protection Clusters, UNICEF supported activities that reached 81.4% of all beneficiaries. Meaning that this the low percentage of multi-sector support could largely be resolved by better internal coordination and better programmatic oversight within UNICEF – these issues will be even more apparent in sections 4c and 4d.
4b. Parrish-level gaps in multi-sector programming
A total of 961,893 beneficiaries received support from only one sector – this is 77.7% of all beneficiary frequencies. Parrishes below have been plotted according to their multi-sector coverage and their total number of beneficiary frequencies; larger sizes indicate parrishes where there are higher numbers of beneficiaries benefitting from only one sector:
ms_scatter <- parr0 %>%
mutate(multi_sector_percent = round(ms_ben_max / ben_freq * 100, digits = 1),
one_sector_percent = round((ben_freq - ms_ben_max) / ben_freq * 100, digits = 1),
multi_sector_ben = round(ms_ben_max, digits = 0),
one_sector_ben = round(ben_freq - ms_ben_max, digits = 0),
ben_freq = round(ben_freq, digits = 0)) %>%
ggplot(aes(x = ben_freq,
y = multi_sector_percent,
text = paste0(parroquia,",", "\n",
municipio, ",", "\n",
estado, ",", "\n",
"sector count: ", sector_count),
colour = estado)) +
geom_point(aes(size = one_sector_ben),
alpha = 0.8) +
scale_x_continuous(trans = "log10", labels = label_comma(accuracy = 1)) +
scale_size_continuous(range = c(0.1, 5)) +
scale_colour_manual(values = c(rep("coral",24))) +
xlab("Beneficiary frequencies") + ylab("Percentage received multi-sector support") +
labs(title = "Scatterplot of parrishes by beneficiary frequencies and multi-sector coverage",
size = "", colour = "") +
theme(plot.title = element_text(size = 11),
axis.title = element_text(size = 8.5))
ggplotly(ms_scatter, tooltip = c("x", "y", "size", "text")) %>%
layout(legend = list(font = list(size = 6))) %>%
config(displayModeBar = FALSE) %>%
layout(title = list(text = paste0(
"Scatterplot of parrishes by beneficiary frequencies and multi-sector coverage",
"<br>",
"<sup>",
"size: number of beneficiaries supported by only one sector; double-click state to toggle view; mouse over for details","</sup>")))
We note only a very loose relationship (r-squared = 0.183) between the number of beneficiary frequencies and the percentage of those beneficiary frequencies reached by interventions from multiple sectors. There is little else it is correlated with and, as can be seen above, there is no discernible pattern to multisector coverage. There are the 365 parrishes at the bottom of the plot with only one sector present in each – this is 61.9% of all parrishes we are responding in.
parr0 %>%
filter(beneficiarios != 0) %>%
select(estado, sector_count) %>%
group_by(estado) %>%
summarise(avg_sector = round(mean(sector_count), digits = 2)) %>%
arrange(desc(avg_sector)) %>%
filter(avg_sector > 2 | avg_sector < 1.15) %>%
pivot_wider(names_from = estado, values_from = avg_sector) %>%
mutate(`|` = c("|")) %>% relocate(`|`, .after = ZULIA) %>%
pander(caption = "Top 5 and bottom 5 states, average number of sectors per parrish", missing = "")
Top 5 and bottom 5 states, average number of sectors per parrish
3.38 |
2.6 |
2.43 |
2.37 |
2.36 |
| |
1.14 |
1.12 |
1.08 |
1.05 |
1.02 |
However, we do note that in the states where UNICEF has offices (Bolivar, Tachira, Zulia and Distrito Capital), there is much higher multi-sector coverage than in other states, perhaps indicating that a more decentralised approach where field offices have greater say in prioritisation might lead to more coordination in multi-sector programming. Though, that this greater multi-sector coverage has not expanded outside of these states to the other areas under their purview is indicative of the level of planning and coordination capacity field offices are capable of.
4c. Cluster combinations
This section will examine the parrishes that have multi-sector coverage and the types of inter-cluster combinations that can be found in them. Let us begin with an overview of the geographic reach of each cluster – we use frequencies here, as each individual might have benefitted from multiple combinations of clusters:
parr %>%
select(pcode3, educacion_ben, nutricion_ben, salud_ben, wash_ben, proteccion_ben) %>%
rename(Educacion = educacion_ben, Nutricion = nutricion_ben, Salud = salud_ben,
WASH = wash_ben, Proteccion = proteccion_ben) %>%
pivot_longer(cols = 2:6, names_to = "cluster", values_to = "beneficiary_frequencies") %>%
filter(beneficiary_frequencies != 0) %>%
group_by(cluster) %>%
summarise(parrishes = n(),
beneficiary_frequencies = sum(beneficiary_frequencies)) %>%
pander(caption = "Cluster coverage summary, excluding vaccination", big.mark = ",", style = "rmarkdown",
justify = c("left", "right", "right"))
Cluster coverage summary, excluding vaccination
Educacion |
187 |
623,052 |
Nutricion |
513 |
385,614 |
Proteccion |
151 |
184,084 |
Salud |
61 |
54,739 |
WASH |
126 |
809,949 |
Next, we will summarise the inter-cluster combinations according to:
- combination, referring to the various cluster-wise pairs that exist;
- parrishes, indicating the number of parrishes each combination is present in;
- cluster1 and cluster2, which show the number of beneficiary frequencies reached by both clusters in each pair, in the order that they appear in combination.
- pair_sum, which shows the total number of beneficiary frequencies in that pair i.e. the pair_sum for edu_nut would be the sum of education and nutrition beneficiaries.
- %ms_max, which shows the maximum percentage of multisector beneficiaries of each pair i.e. if the pair edu-nut has 10 education beneficiaries and 30 nutrition beneficiaries, the maximum number of beneficiaries which received support from both sectors is 10, resulting in a %ms_max of 25%. But, as mentioned in the notes for section 4a, this is just a theoretical maximum and the actual level of coincidence is likely much lower.
# creation of reference df for the cluster combinations
clust_com <- parr %>%
filter(ben_freq != 0) %>%
select(pcode3, ben_freq, educacion_ben, nutricion_ben, salud_ben, wash_ben, proteccion_ben) %>%
# mutate a new column for each combination of sectors -- if edu is the first cluster in the combination,
# only education beneficiaries will be used to fill values in the column
mutate(edu_only = ifelse(educacion_ben == ben_freq, educacion_ben, 0),
edu_nut = ifelse(educacion_ben > 0 & nutricion_ben > 0, educacion_ben + nutricion_ben, 0),
edu_sal = ifelse(educacion_ben > 0 & salud_ben > 0, educacion_ben + salud_ben, 0),
edu_wash = ifelse(educacion_ben > 0 & wash_ben > 0, educacion_ben + wash_ben, 0),
edu_prot = ifelse(educacion_ben > 0 & proteccion_ben > 0, educacion_ben + proteccion_ben, 0),
nut_only = ifelse(nutricion_ben == ben_freq, nutricion_ben, 0),
nut_sal = ifelse(nutricion_ben > 0 & salud_ben > 0, nutricion_ben + salud_ben, 0),
nut_wash = ifelse(nutricion_ben > 0 & wash_ben > 0, nutricion_ben + wash_ben, 0),
nut_prot = ifelse(nutricion_ben > 0 & proteccion_ben > 0, nutricion_ben + proteccion_ben, 0),
sal_only = ifelse(salud_ben == ben_freq, salud_ben, 0),
sal_wash = ifelse(salud_ben > 0 & wash_ben > 0, salud_ben + wash_ben, 0),
sal_prot = ifelse(proteccion_ben > 0 & salud_ben > 0, salud_ben + proteccion_ben, 0),
wash_only = ifelse(wash_ben == ben_freq, wash_ben, 0),
prot_wash = ifelse(wash_ben > 0 & proteccion_ben > 0, wash_ben + proteccion_ben, 0),
prot_only = ifelse(proteccion_ben == ben_freq, proteccion_ben, 0)) %>%
# pivot_longer to the clust_freq column
pivot_longer(names_to = "combination", values_to = "pair_sum", 8:22) %>%
filter(pair_sum != 0) %>%
group_by(pcode3, combination) %>%
summarise(educacion_ben = mean(educacion_ben),
nutricion_ben = mean(nutricion_ben),
salud_ben = mean(salud_ben),
wash_ben = mean(wash_ben),
proteccion_ben = mean(proteccion_ben),
pair_sum = sum(pair_sum)) %>%
# calculating the sum of frequencies in each pair
mutate(cluster1 =
case_when(
str_detect(combination, "edu_nut") ~ educacion_ben,
str_detect(combination, "edu_sal") ~ educacion_ben,
str_detect(combination, "edu_wash") ~ educacion_ben,
str_detect(combination, "edu_prot") ~ educacion_ben,
str_detect(combination, "nut_sal") ~ nutricion_ben,
str_detect(combination, "nut_wash") ~ nutricion_ben,
str_detect(combination, "nut_prot") ~ nutricion_ben,
str_detect(combination, "sal_wash") ~ salud_ben,
str_detect(combination, "sal_prot") ~ salud_ben,
str_detect(combination, "prot_wash") ~ proteccion_ben,
str_detect(combination, "edu_only") ~ educacion_ben,
str_detect(combination, "nut_only") ~ nutricion_ben,
str_detect(combination, "sal_only") ~ salud_ben,
str_detect(combination, "wash_only") ~ wash_ben,
str_detect(combination, "prot_only") ~ proteccion_ben)) %>%
mutate(cluster2 =
case_when(
str_detect(combination, "edu_nut") ~ nutricion_ben,
str_detect(combination, "edu_sal") ~ salud_ben,
str_detect(combination, "edu_wash") ~ wash_ben,
str_detect(combination, "edu_prot") ~ proteccion_ben,
str_detect(combination, "nut_sal") ~ salud_ben,
str_detect(combination, "nut_wash") ~ wash_ben,
str_detect(combination, "nut_prot") ~ proteccion_ben,
str_detect(combination, "sal_wash") ~ wash_ben,
str_detect(combination, "sal_prot") ~ proteccion_ben,
str_detect(combination, "prot_wash") ~ wash_ben,
str_detect(combination, "only$") ~ 0)) %>%
select(pcode3, combination, cluster1, cluster2, pair_sum)
# pander table cluster combinations
rbind(
clust_com %>%
filter(str_detect(combination, "only$")) %>%
group_by(combination) %>%
summarise(parrishes = n(),
cluster1 = round(sum(cluster1), digits = 0),
cluster2 = round(sum(cluster2), digits = 0),
pair_sum = round(sum(pair_sum), digits = 0)) %>%
mutate(`%ms_max` = pmin(cluster1, cluster2) / pair_sum * 100,
`%ms_max` = round(ifelse(is.nan(`%ms_max`), 0, `%ms_max`), digits = 1)) %>%
arrange(desc(pair_sum)) %>%
rbind(NA),
clust_com %>%
filter(!str_detect(combination, "only$")) %>%
group_by(combination) %>%
summarise(parrishes = n(),
cluster1 = round(sum(cluster1), digits = 0),
cluster2 = round(sum(cluster2), digits = 0),
pair_sum = round(sum(pair_sum), digits = 0)) %>%
mutate(`%ms_max` = pmin(cluster1, cluster2) / pair_sum * 100,
`%ms_max` = round(ifelse(is.nan(`%ms_max`), 0, `%ms_max`), digits = 1)) %>%
arrange(desc(pair_sum))
) %>%
kable(caption = "Cluster combinations, sorted by pair_sum", format.args = list(big.mark = ",")) %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Cluster combinations, sorted by pair_sum
combination
|
parrishes
|
cluster1
|
cluster2
|
pair_sum
|
%ms_max
|
nut_only
|
301
|
156,945
|
0
|
156,945
|
0.0
|
edu_only
|
34
|
75,671
|
0
|
75,671
|
0.0
|
wash_only
|
12
|
6,912
|
0
|
6,912
|
0.0
|
prot_only
|
15
|
2,852
|
0
|
2,852
|
0.0
|
sal_only
|
3
|
142
|
0
|
142
|
0.0
|
|
|
|
|
|
|
edu_wash
|
83
|
437,925
|
776,361
|
1,214,286
|
36.1
|
nut_wash
|
98
|
138,115
|
775,836
|
913,951
|
15.1
|
prot_wash
|
68
|
128,857
|
756,684
|
885,541
|
14.6
|
edu_nut
|
135
|
514,997
|
171,906
|
686,903
|
25.0
|
edu_prot
|
82
|
391,334
|
134,992
|
526,326
|
25.6
|
sal_wash
|
32
|
41,986
|
317,023
|
359,009
|
11.7
|
nut_prot
|
125
|
152,291
|
168,652
|
320,943
|
47.5
|
edu_sal
|
38
|
163,499
|
44,714
|
208,213
|
21.5
|
nut_sal
|
49
|
64,471
|
48,515
|
112,986
|
42.9
|
sal_prot
|
34
|
44,916
|
60,055
|
104,971
|
42.8
|
The most common pairing was between the Education and Nutrition clusters – they coincide in 135 parrishes, followed by Nutrition and Protection. In the next section, we will investigate whether the substantial overlap between Nutrition and Protection at the parrish level was coordinated or – as in the case with its overlap with Education, where there are no concrete programmatic links – due more to its wide operational presence.
Protection and WASH, however, both do have explicit programmatic links (in the logframe) with Education and co-occur with it in 82 and 83 parrishes respectively. A fruitful avenue of investigation would be how many beneficiaries of Education also benefitted from Protection interventions and how close it is to the 25.6% theoretical maximum.
Nutrition operates alone in 301 parrishes out of the 514 that it is present in, this is the most out of any of the other clusters – it is necessary to evaluate the extent to which other clusters can make use of the footholds established by Nutrition.
Whilst Nutrition and Health have excellent programmatic complementarity, especially with Health’s focus on obstetric, antenatal and neonatal care, this combination has the second-lowest number of beneficiary frequencies of all the combinations.
WASH overall has excellent programmatic overlap with all other clusters; and was the only cluster to programme specific multi-sector interventions – WASH in schools and WASH in health/nutrition centres. And almost none of WASH’s beneficiary frequencies occurred in parrishes where no other clusters were present. Its great reach and blanket coverage (especially water supply and other community-level activities) mean that other clusters operating in the same areas as WASH are “guaranteed” to reach beneficiaries with multi-sector programming – the challenges of these combinations being
- the intentionality of the multi-sector coverage and
- matching the scale of WASH activities.
Similar to WASH and Health, Protection has very limited beneficiary frequencies in parrishes where it operates alone. Protection coincides the most with Nutrition – this should serve as an impulse for the creation of referral pathways between the two since both carry out screening activities, made easier by the fact that both manage some form of beneficiary-level database. Protection has the most explicit progammatic links to Education in the logframe.
4d. Activity categories
To close chapter 4, the state of multi-sector programming is poor: as we have noted, there is little intentionality in deciding which areas have multi-sector coverage and which areas do not – multi-sector links do exist at the activity level, but this is a poor approximation of integrated programming. And we see the weakness of this approach in the table below, which lists the most common inter-cluster activity category combinations at the parrish level.
act_ben %>%
select(pcode3, categoria) %>%
distinct() %>%
filter(!str_detect(categoria, "OTRO")) %>%
pairwise_count(categoria, pcode3, upper = FALSE) %>%
arrange(desc(n)) %>%
left_join(act_ben %>% select(sector1 = sector, categoria) %>% distinct(),
by = c("item1" = "categoria")) %>%
left_join(act_ben %>% select(sector2 = sector, categoria) %>% distinct(),
by = c("item2" = "categoria")) %>%
filter(sector1 != sector2) %>%
mutate_at(vars(item1, item2), ~str_to_title(.)) %>%
select(actvity_category1 = item1, activity_category2 = item2, count = n) %>%
head(15) %>%
kbl(caption = "Most common inter-cluster activity category combinations") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"))
Most common inter-cluster activity category combinations
actvity_category1
|
activity_category2
|
count
|
Prevencion_desnutricion_aguda
|
Acceso_permanencia_escolar
|
114
|
Prevencion_desnutricion_aguda
|
Resilencia_educacion
|
108
|
Fortalecimiento_capacidad_educacion
|
Prevencion_desnutricion_aguda
|
102
|
Provision_de_servicios
|
Prevencion_desnutricion_aguda
|
91
|
Acceso_permanencia_escolar
|
Tratamiento_desnutricion_aguda
|
79
|
Resilencia_educacion
|
Tratamiento_desnutricion_aguda
|
75
|
Fortalecimiento_capacidad_educacion
|
Tratamiento_desnutricion_aguda
|
74
|
Prevencion_desnutricion_aguda
|
Capacitaciones_proteccion
|
69
|
Prevencion_desnutricion_aguda
|
Fortalecimiento_institucional
|
56
|
Provision_de_servicios
|
Tratamiento_desnutricion_aguda
|
54
|
Prevencion_desnutricion_aguda
|
Agua_en_comunidades
|
53
|
Provision_de_servicios
|
Acceso_permanencia_escolar
|
52
|
Prevencion_desnutricion_aguda
|
Wash_en_salud_nutricion
|
50
|
Provision_de_servicios
|
Resilencia_educacion
|
49
|
Fortalecimiento_capacidad_educacion
|
Provision_de_servicios
|
47
|
Of the 15 most common activity category combinations, we see only four combinations which might actually convey multi-sector benefits:
The 4th and 11th entries, Prevention of acute malnutrition / Provision of protection services and Provision of protection services / Treatment of acute malnutrition where referrals between the Nutrition and Protection clusters might feasibly result in vulnerable populations receiving a combination of protection services, micronutrient supplementation, de-worming, treatment and counselling that would reduce their vulnerability in a multidimensional manner; the
9th entry, Water supply in communities / Prevention of acute malnutrition, as improved water supply is a core component of preventing malnutrition; and the
11th, Access to education and student retention / Provision of protection services, as the population of children with poor access to education and are in danger of dropping out would, presumably, be more in need of protection services (which include referrals to the formal social welfare system, legal aid, support for GBV survivors and UASC).
However, as mentioned previously, these multi-sector benefits are theoretical and it has not been established that there is communication between the implementing partners of these activities. Project monitoring is required to establish this.
Combinations like Access to education and student retention / Prevention of acute malnutrition (1st) deal with almost entirely separate populations – children of schoolgoing age are outside of the target population for Nutrition; though it is feasible that Education and Nutrition could both be dealing with the same young mother who has dropped out of school.
Furthermore, combinations like Prevention of acute malnutrition / Resilience in education (2nd) and Capacity building in education / Prevention of acute malnutrition (3rd) have no overlap as malnutrition prevention has no programmatic link to safe school strategies, DRR in schools or teacher training.
As it stands, cluster footprints seem to have much more to do with opportunistic expansion strategies dependent on partners’ preferred areas than a needs-based approach which targets the most vulnerable. The next chapter is an effort to examine and correct this.
5. Decision trees
5a. Introduction to trees – organisational presence
To prioritise between the 1109 parrishes in Venezuela – that is, to determine where we should be working – it is necessary to split them up into more easily digestible groups, and we will use decision trees to do this. A prioritisation or vulnerability score is another commonly-used prioritisation tool, but, as we will see, collapsing a number of variables down into one score is not always helpful.
To understand how a decision tree functions, let us construct one to predict whether or not there is a humanitarian agency present in a parrish (org_present
– this is our dependent variable). We have supplied our model with a basket of census indicators from which it will construct a tree to predict our dependent variable – unhide the code below to see the full model. The decision tree printed below is the result:
# just to show the decision tree of how partners seem to have chosen locations.
# using full parr dataset for the tree
# no doubt there are other factors, but this is the data I have --
# looking at specific partner characteristics would be interesting.
set.seed(3000)
tree2 <- parr %>%
rpart(org_present ~ percent_pobre + percent_urbana + densidad_ppl_km2 +
razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +
percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina,
promedio_de_personas_por_vivienda, data = ., minbucket = 100)
fancyRpartPlot(tree2, digits = -3, sub = "", palettes = "Blues", type = 2)

To understand the plot above, all parrishes have been split into four groups (the terminal nodes at the bottom marked [4], [5], [6] and [7]) based on the percentage of parrishes in each node where humanitarian agencies are present. Each node has three figures – for instance, the root, at the top, and marked [1], shows that on average, 0.544 or 54.4% of all parrishes have humanitarian agencies present in them. The next numbers, “n = 1109” shows that 1109 parrishes are in that group and next to it is the percentage of parrishes it contains, which, since it is the root, is 100%.
We see that [7] (in dark blue) is the node with the highest concentration of parrishes with agencies present (84.3%); it consists of parrishes more than 79.4% urbanised and denser than 156 ppl/km2. And [4], the node with the lowest concentration of parrishes with agencies (25.6%) is less than 79.4% urbanised and less than 21.8% urbanised.
This is, of course, not to imply that this actually depicts partners’ decision-making process, just that these are the factors towards which we, as a response, are predisposed. Perhaps it is understandable that the most heavily populated parrishes are more likely to have organisations present, though population density and urban population are both negatively correlated with poverty incidence. The largest determinants of the number of beneficiaries reached per parrish are population density and urbanisation, as beneficiary numbers tend to scale in line with larger populations.
5b. Prioritisation tree
Now let us focus on future decisions:
Several trees were built and trialled to split parrishes into targetting groups. As mentioned, the independent variables come from a pool of indicators from the census dataset, with some originating from the 2019 UNICEF Municipal Prioritisation Tool, which was a Principal Components Analysis of key variables related to poverty, health and mortality and violence and insecurity. After numerous iterations, tree3
was chosen; it splits parrishes into groups according to the:
- The poverty score, which is the a rescaled average of the number of poor persons and the poverty incidence of each parrish.
To see the specific variables and formulae used for each of the major iterations, as well as additional notes on the development and application of decision trees, unhide the source code below.
# As opposed to a prioritisation score -- typically the weighted average of several
# demographic and socioeconomic indicators --
# a tree is much better at accounting for the variations across geographic areas.
# A partner might not have the capacity to work outside of urban areas or
# might have specific geographic biases and decision trees are a good tool
# to make the best possible targetting decisions within one's constraints.
# With that in mind, tree3 was developed to aid future prioritisation.
# The independent variable it strives to predict is the poverty score, which, as mentioned,
# is just the rescaled average of number of poor persons and poverty incidence.
# The performance of tree3 was considered superior to both tree1
# (whose indendepent variable is just the absolute number of poor persons)
# and tree4 (which considered parrish-level gaps) due to its ability to
# clearly distinguish its groups of parrishes and because it is not dependent on gaps data --
# meaning it will not shift when the 5Ws are updated.
set.seed(3000)
# number of not covered poor persons
tree1 <- parr0 %>%
rpart(not_reached ~ estado + percent_pobre + percent_urbana +
densidad_ppl_km2 + razon_de_dependencia_de_menores_de_15_anos +
razon_de_dependencia_total +
percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina,
promedio_de_personas_por_vivienda, data = ., cp = 0.038)
# tree based on poverty_score
tree3 <- parr0 %>%
rpart(poverty_score ~ estado + percent_urbana + densidad_ppl_km2 +
razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +
percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina,
promedio_de_personas_por_vivienda, data = ., cp = 0.044)
# tree based on gap score -- let's not use this
# as tree3 is more stable and will not change based on new 5W data
# tree4 <- parr0 %>%
# rpart(gap_score ~ estado + percent_urbana + densidad_ppl_km2 +
# razon_de_dependencia_de_menores_de_15_anos + razon_de_dependencia_total +
# percent_sin_agua_segura + percent_sin_saneamiento_mejorado +
# percent_sin_servicio_electrico + percent_analfabeto + percent_hogares_jefatura_femenina,
# promedio_de_personas_por_vivienda, data = ., cp = 0.045)
# plotcp(tree3)
# printcp(tree3)
# adding tree1 and tree3 rules to the dataset
parr0 <- parr0 %>%
mutate(rule1 = row.names(tree1$frame)[tree1$where]) %>%
left_join(rpart.rules.table(tree1) %>%
filter(Leaf == TRUE) %>%
rename(rule1 = Rule) %>%
group_by(rule1) %>%
summarise(subrules1 = paste(Subrule, collapse = ","))) %>%
mutate(rule3 = row.names(tree3$frame)[tree3$where]) %>%
left_join(rpart.rules.table(tree3) %>%
filter(Leaf == TRUE) %>%
rename(rule3 = Rule) %>%
group_by(rule3) %>%
summarise(subrules3 = paste(Subrule, collapse = ",")))
5c. Sub-groups of decision tree3
Below is a plot of tree3
– the 1098 parrishes where the number of beneficiaries does not exceed the number of poor persons (corresponding to the under and no coverage categories) have been split into four terminal nodes: [4], [5], [6] and [7]. The manner in which they have been split is meaningful for targetting decisions and this section will compare the characteristics of each. Please note that this is a different tree than in section 5a – the two models have the same numbering because they have the same number of splits.
fancyRpartPlot(tree3, digits = -3, sub = "", palettes = "Blues", type = 2)

Summary and overview of the terminal nodes of tree3
# will they be confused that the terminal nodes have the same codes?
# Should I explain in the text that this is because they have the same number of splits
# or will that just make them more confused?
parr0 %>%
group_by(rule3) %>%
summarise(parr_no_ben = n_distinct(pcode3[beneficiarios == 0]),
beneficiaries = sum(beneficiarios),
avg_beneficiaries = sum(beneficiarios) / n(),
not_reached = sum(not_reached),
avg_not_reached = sum(not_reached) / n(),
avg_org_count = mean(org_count),
avg_population = mean(poblacion_2019),
percent_poor = round(sum(pob_pobre) / sum(poblacion_2019) * 100, digits = 1),
percent_urban = round(sum(pob_urbana) / sum(poblacion_2019) * 100, digits = 1),
density_ppl_km2 = sum(poblacion_2019) / sum(area_km2, na.rm = TRUE),
parrishes = n()) %>%
gather(key = variable, value = value, 2:ncol(.)) %>%
spread_(key = names(.)[1], value = 'value') %>%
# reordering the table instead of having it be alphabetical
arrange(factor(variable, levels = c("not_reached", "avg_not_reached", "avg_population",
"beneficiaries",
"avg_beneficiaries", "avg_org_count",
"percent_poor", "percent_urban", "density_ppl_km2",
"parrishes", "parr_no_ben"))) %>%
pander(big.mark = ",", caption = "Summary table of the terminal nodes of tree3")
Summary table of the terminal nodes of tree3
not_reached |
1,087,505 |
6,361,254 |
3,644,252 |
521,395 |
avg_not_reached |
8,631 |
12,877 |
9,641 |
5,214 |
avg_population |
46,126 |
35,806 |
19,120 |
7,174 |
beneficiaries |
179,904 |
363,258 |
116,270 |
18,320 |
avg_beneficiaries |
1,428 |
735.3 |
307.6 |
183.2 |
avg_org_count |
2.286 |
1.427 |
0.8386 |
0.34 |
percent_poor |
21.8 |
38 |
52 |
75.2 |
percent_urban |
99 |
92.5 |
75.4 |
23.4 |
density_ppl_km2 |
996.1 |
147.4 |
18.07 |
1.855 |
parrishes |
126 |
494 |
378 |
100 |
parr_no_ben |
36 |
202 |
195 |
75 |
[4] consists of population centres which are easy to reach, but with only 21.8% of the population being poor, careful targetting and beneficiary selection is required – blanket coverage will only result in excessive inclusion errors. It also has the highest average number of organisations present per parrish (avg_org_count). There are 126 parrishes in this group. These parrishes should not be prioritised – resources should be allocated elsewhere.
[5] is probably the best option for expansion for most partners – it has the highest concentration of poor persons not covered per parrish (avg_not_reached), is substantially poorer than [4], with a poverty incidence of 38%. Additionally, these parrishes are still very urbanised (92.5%), meaning that access to these populations will not be challenging. The coverage of organisations is still fairly high and partners should consider expanding into parrishes to the ones they currently cover. This is the largest group, with 494 parrishes.
[6] is where access starts to get more challenging – though these parrishes have an average poverty incidence of 52%, the rate of urbanisation drops to 75.4% and the population density is only 18 ppl/km2. But there are still more poor persons not covered per parrish in this group than in [4]. There are 378 parrishes in this group.
[7] consists of the poorest, most vulnerable and most remote parrishes. Working in these areas will incur significant operational and logistical costs. However, with an average poverty incidence of 75.2%, blanket coverage will be warranted in many cases – if the challenge of reaching all of the population can be met. Additionally, they also have the lowest average number of poor persons not covered, given their extremely low population density of 1.8 ppl/km2. Humanitarian agencies have the lowest presence in these parrishes. It is advisable for donors to incentivise activities in these areas as they are very underserved. There are 100 parrishes in this group.
5d. Map of parrishes by decision tree node
# just one note for this map -- I still can't figure out how to get the tooltip to appear when
# you're hovering over the centroid instead of at the border; hoveron fill doesn't work.
# I think you should just ask stackoverflow GIS
# hex for Set2 "#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3", "#FFFFFF"
# hex for Dark2 "#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#FFFFFF"
# hex for Accent "#7FC97F", "#BEAED4", "#FDC086", "#FFFF99", "#FFFFFF"
# scale_fill_viridis_d()
# scale_fill_manual(values = c())
parrmap_org <- parr %>%
left_join(parr0 %>%
select(pcode3, rule3), by = "pcode3") %>%
right_join(pcode3_shape, by = "pcode3") %>%
st_as_sf() %>%
mutate(not_reached = round(not_reached, digits = 0),
tree_node = rule3) %>%
mutate_at(vars(percent_pobre, percent_urbana), ~(round(., digits = 2))) %>%
ggplot() +
geom_sf(size = 0.1,
aes(fill = tree_node,
text = paste0(parroquia,",", "\n",
municipio, ",", "\n",
estado, "\n",
"not covered: ", not_reached, "\n",
"poverty incidence: ", percent_pobre, "\n",
"percent urban: ", percent_urbana, "\n",
"org present :", org_present),
alpha = org_present)) +
theme_void() +
scale_fill_manual(values = c("#66C2A5", "#FC8D62", "#8DA0CB", "#E78AC3")) +
scale_alpha_discrete(range = c(1, 0.7)) +
theme(legend.title = element_text(size = 7),
legend.text = element_text(size = 7),
plot.title = element_text(size = 11)) +
guides(alpha = FALSE) +
labs(fill = "Tree node",
alpha = "") +
ggtitle('Map of parrishes by decision tree node (colour) & if organisations present (alpha)')
ggplotly(parrmap_org, tooltip = c("text", "fill")) %>%
layout(title = list(text = paste0(
"Map of parrishes by decision tree node (colour) & if organisations present (alpha)",
"<br>",
"<sup>",
"mouse over for details; drag and click to select and zoom; double-click legend select/deselect","</sup>")))
Above is a map of parrishes by their decision tree node (denoted by colour), we have also decreased the alpha for parrishes where there are already organisations present, meaning that they appear more transparent. Looking at areas with the greatest concentrations of [4] and [5], we can see that they conform to the the Venezuela Costal Range and the Venezuelan Andes, where most of the country’s population is located; as a reminder, parrishes in node [5] are excellent candidates for expansion.
We also see three large clusters of parrishes from node [7] – the poorest and most-sparsely populated areas – in Amazonas and Bolivar (at the bottom of the map), in Delta Amacuro (at the extreme right) and in Lara and Falcon (top-left). Double-click on each legend item to toggle the view.
As a final note for this chapter, the prioritisation tree was limited to four terminal nodes because they captured the vast majority of the variance amongst the parrishes – any more splits would only have diminishing returns. But, should a partner want to see a more complex tree with more nodes, it would be very easy to supply them with it. But I feel these more complex trees would mostly serve as references, rather than actual prioritisation tools – I already question partners’ ability to deal with 4 separate groups, each requiring their own strategies, much less 8 or 10.
- Chapter 5 annex: Additional notes on tree1, which was not selected – unhide code to see
# the main problem I see is that each of the leaves has little variance in terms of poverty incidence
# but let me know if you want maps or products focused on this tree, it's pretty easy to do.
# [15] is very, very attractive. Maybe I can do something with it.
# 6 is dense, urban and highest operational presence,
# 2 is just too big. 800 parrishes is just too many. The low end is distinguished much better in tree3
# 14 is just rich, urban and not a priority. It's also a really small leaf.
# 15 is actually a really good leaf -- really high nc_per_parr, few parrishes,
# very dense, very urban and 42% poor and such an immensely low coverage percent.
# Good low-hanging fruit. I almost want to keep tree1 just because of this leaf.
# Maybe I will make one map just for this. 59,508 nc_per_parr is massive.
parr0 %>%
group_by(rule1) %>%
summarise(parr_no_ben = n_distinct(pcode3[beneficiarios == 0]),
beneficiarios = sum(beneficiarios),
ben_per_parr = sum(beneficiarios) / n(),
not_reached = sum(not_reached),
nr_per_parr = sum(not_reached) / n(),
nr_per_mun = sum(not_reached) / n_distinct(pcode2),
avg_org_count = mean(org_count),
coverage_percent = sum(beneficiarios) / sum(poblacion_2019),
percent_pobre = sum(pob_pobre) / sum(poblacion_2019),
percent_urbana = sum(pob_urbana) / sum(poblacion_2019),
densidad_ppl_km2 = sum(poblacion_2019) / sum(area_km2, na.rm = TRUE),
parroquias = n(),
municipios = n_distinct(pcode2),
parr_per_mun = n() / n_distinct(pcode2)) %>%
gather(key = variable, value = value, 2:ncol(.)) %>%
spread_(key = names(.)[1], value = 'value') %>%
arrange(factor(variable, levels = c("not_reached", "nr_per_parr", "nr_per_mun", "beneficiarios",
"ben_per_parr", "avg_org_count", "coverage_percent",
"percent_pobre", "percent_urbana", "densidad_ppl_km2",
"parroquias", "parr_no_ben", "municipios",
"parr_per_mun"))) %>% pander(big.mark = ",")
7. Reference table
type or use slider to filter by categories or values; use arrows to sort; table preliminarily arranged in descending order of poor persons of not reached
parr0 %>%
mutate(educacion_only = ifelse(educacion_ben > 0, "educacion", ""),
nutricion_only = ifelse(nutricion_ben > 0, "nutricion", ""),
salud_only = ifelse(salud_ben > 0, "salud", ""),
wash_only = ifelse(wash_ben > 0, "wash", ""),
proteccion_only = ifelse(proteccion_ben > 0, "proteccion", ""),
sectors_present = str_trim(paste0(educacion_only, " ", nutricion_only, " ", proteccion_only, " ",
salud_only, " ", wash_only))) %>%
mutate_at(vars(pob_pobre, not_reached, org_count, beneficiarios), ~(round(., digits = 0))) %>%
mutate_at(vars(percent_pobre, percent_urbana, coverage_percent), ~(round(.*100, digits = 1))) %>%
mutate(rule3 = as.numeric(rule3),
sectors_present = ifelse(sectors_present == "", "none", sectors_present)) %>%
select(state = estado, municipality = municipio, parrish = parroquia,
percent_poor = percent_pobre, percent_urban = percent_urbana, not_reached,
beneficiaries = beneficiarios, coverage_percent, tree_node = rule3,
org_count, sector_count, sectors_present, pcode3) %>%
arrange(desc(not_reached)) %>%
# the js is adjusting the font size for the whole container -- there doesn't seem to be another way
datatable(filter = "top", options = list(pageLength = 10, scrollX = TRUE,
initComplete = htmlwidgets::JS(
"function(settings, json) {",
paste0("$(this.api().table().container()).css({'font-size': '", "8.5pt", "'});"),
"}")
)
)
LS0tDQp0aXRsZTogIkNvdmVyYWdlIGFuZCBnYXBzIGluIHRoZSBodW1hbml0YXJpYW4gcmVzcG9uc2UgaW4gVmVuZXp1ZWxhIGluIDIwMTkiDQphdXRob3I6ICJTZWFuIE5nIg0KZGF0ZTogIjI0LzExLzIwMjEiDQpvdXRwdXQ6IA0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHRydWUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICB0aGVtZTogcmVhZGFibGUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgY29sbGFwc2VkOiBmYWxzZQ0KICAgIA0KLS0tDQoNCjxzdHlsZT4NCiAgICBib2R5IC5tYWluLWNvbnRhaW5lciB7DQogICAgICAgIG1heC13aWR0aDogMTI4MHB4Ow0KICAgIH0NCjwvc3R5bGU+DQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCBmaWcud2lkdGg9OSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nPUZBTFNFKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShzdHJpbmdpKQ0KbGlicmFyeShzdHJpbmdyKQ0KbGlicmFyeSh0aWR5dGV4dCkNCmxpYnJhcnkod2lkeXIpDQoNCmxpYnJhcnkocGFuZGVyKQ0KbGlicmFyeShEVCkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGthYmxlRXh0cmEpDQoNCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KGdnZm9yY2UpDQpsaWJyYXJ5KGdncHVicikNCmxpYnJhcnkoZm9yY2F0cykNCmxpYnJhcnkocGF0Y2h3b3JrKQ0KDQpsaWJyYXJ5KHJhdHRsZSkNCmxpYnJhcnkocnBhcnQpDQpsaWJyYXJ5KHJwYXJ0LnBsb3QpDQpsaWJyYXJ5KHJwYXJ0LnV0aWxzKQ0KbGlicmFyeShwYXJ0eWtpdCkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KGZhY3RvZXh0cmEpDQpsaWJyYXJ5KHNoaW55KQ0KDQpsaWJyYXJ5KGdnbWFwKQ0KbGlicmFyeShzZikNCmxpYnJhcnkocm1hcHNoYXBlcikNCmxpYnJhcnkodmlyaWRpcykNCg0KIyBkaXNhYmxpbmcgc2NpZW50aWZpYyBub3RhdGlvbg0Kb3B0aW9ucyhzY2lwZW4gPSAxMDApDQoNCiMgcGFuZGVyIHRhYmxlcyBhbGwgaW4gb25lIHJvdw0KcGFuZGVyT3B0aW9ucygndGFibGUuc3BsaXQudGFibGUnLCBJbmYpDQoNCiMgcGFuZGVyIHRob3VzYW5kcyBzZXBhcmF0b3INCnBhbmRlck9wdGlvbnMoImJpZy5tYXJrIiwgIiwiKQ0KDQpgJW91dCVgIDwtIE5lZ2F0ZShgJWluJWApDQoNCiMgZnVuY3Rpb24gdG8gcmVtb3ZlIGFjY2VudHMgDQpybV9hY2NlbnQgPC0gZnVuY3Rpb24oY29sbnMpew0KICBjb2xucyA8LSBzdHJpX3RyYW5zX2dlbmVyYWwoY29sbnMsICJMYXRpbi1BU0NJSSIpDQp9DQoNCiMgZm9yIGthYmxlIHRvIHRyZWF0IE5BIGFzIGJsYW5rDQpvcHRpb25zKGtuaXRyLmthYmxlLk5BID0gJycpDQoNCmBgYA0KDQojIyAxLiBJbnRyb2R1Y3Rpb24NCg0KSHVtYW5pdGFyaWFuIG5lZWRzIGFsd2F5cyBncm9zc2x5IG91dHdlaWdoIGF2YWlsYWJsZSBmdW5kaW5nOyBob3dldmVyLCBpdCByZW1haW5zIGFuIGluZHVzdHJ5LXdpZGUgY2hhbGxlbmdlIHRvIHJlc3BvbmQgYWRlcXVhdGVseSB0byBnYXBzIGluIGNvdmVyYWdlIGFuZCByZWFsbG9jYXRlIHJlc291cmNlcyBhY2NvcmRpbmdseS4gVG9vIG9mdGVuLCBvbmNlIGNvbW1pdHRlZCB0byBhIGNvdXJzZSBvZiBhY3Rpb24sIGNsdXN0ZXJzIGFuZCB0aGVpciBodW1hbml0YXJpYW4gcGFydG5lcnMgZG8gbm90IHJlLWV4YW1pbmUgb3IgcmUtZXZhbHVhdGUgdGhlaXIgaW50ZXJ2ZW50aW9ucy4gVGhpcyByZXN1bHRzIGluIHJlc3BvbnNlcyB3aXRoIGdsYXJpbmcgZ2FwcyB0aGF0IGFyZSBlaXRoZXIgbm90IHJlc29sdmVkIGluIGEgdGltZWx5IG1hbm5lciBvciBnbyBjb21wbGV0ZWx5IHVuYWRkcmVzc2VkLg0KDQpUaGlzIGF1dG9tYXRlZCByZXBvcnRlZCBpcyBpbnRlbmRlZCB0byBzZXJ2ZSBhcyBhIHRlbXBsYXRlIGZvciBhIGNvdmVyYWdlIGFuZCBnYXBzIGFuYWx5c2lzLiBJdCBwcm92aWRlcyBleGFtcGxlcyBvZiB0aGUgYW5hbHlzZXMgbmVjZXNzYXJ5IHRvIGlkZW50aWZ5IHBvcHVsYXRpb25zIGluIG5lZWQgd2hvIGFyZSBub3Qgc2VydmVkIGJ5IGh1bWFuaXRhcmlhbiBhY3Rpb24gYW5kIHByb3ZpZGUgcmVjb21tZW5kYXRpb25zIG9uIGhvdyBwYXJ0bmVycyBtYXkgYmVzdCByZWFjaCB0aGVtLiBUaGlzIGRvY3VtZW50IGFzc3VtZXMgdGhhdCBiYXNpYyByZXBvcnRpbmcgaGFzIGFscmVhZHkgb2NjdXJyZWQ7IGFuZCBhIG1vcmUgZ2VuZXJpYyA1VyByZXBvcnQgdGVtcGxhdGUgbWF5IGJlIGZvdW5kIFtoZXJlXShodHRwczovL3NlYW55d25nLmdpdGh1Yi5pby81Vy8jQl9SZXBvcnRpbmdfb25fdGhlXzVXX2RhdGEpLiAgDQoNCkNvdmVyYWdlIGFuZCBnYXBzIGFuYWx5c2VzIGFyZSBrZXkgZG9jdW1lbnRzLCBidXQgYXJlIGFsc28gcmFyZWx5IHRha2VuIGludG8gYWNjb3VudCBkdXJpbmcgb3BlcmF0aW9uYWwgcGxhbm5pbmcgb3IgcmVmZXJlbmNlZCBkdXJpbmcgcmV2aXNpb25zIG9mIG1ham9yIHN0cmF0ZWdpYyBkb2N1bWVudHMsIHN1Y2ggYXMgSHVtYW5pdGFyaWFuIFJlc3BvbnNlIFBsYW5zIChIUlBzKS4gTmVpdGhlciBhcmUgdGhleSBtZW50aW9uZWQgaW4gT0NIQSdzIEhSUCBndWlkYW5jZSwgYW5kIHRoZWlyIHVzYWdlIHJlbWFpbnMgcXVpdGUgdW5jb21tb24uIFRoaXMgZG9jdW1lbnQgaW50ZW5kcyB0byBzaG93IHRoYXQgY292ZXJhZ2UgYW5kIGdhcHMgYW5hbHlzZXMgYXJlIG5vdCBjb21wbGV4LCBpbXBlbmV0cmFibGUgdG9vbHM7IHJhdGhlciwgdGhleSBjb250YWluLCBhbmQgYXJlIHByaW5jaXBhbGx5IGNvbmNlcm5lZCB3aXRoLCBwcmFjdGljYWwsIGFjdGlvbmFibGUgaW5mb3JtYXRpb24uIA0KDQoNCiMjIyMgQSBub3RlIG9uIHRoZSBkYXRhDQoNCiogTW9zdCBvZiB0aGUgZGF0YSBvcmlnaW5hdGVzIGZyb20gdGhlIEVkdWNhdGlvbiwgSGVhbHRoLCBOdXRyaXRpb24sIFByb3RlY3Rpb24gYW5kIFdBU0ggQ2x1c3RlcnMsIGZyb20gTWF5IHRvIE9jdG9iZXIgMjAxOSAtLSBhbmQgYW55IGNvbmNsdXNpb25zIG9yIGFuYWx5c2lzIGFyZSBib3VuZGVkIGJ5IHRoaXMgdGltZSBwZXJpb2QgYW5kIGFyZSBpbGx1c3RyYXRpdmUgb2YgdGhlIHJlc3BvbnNlIGFzIGl0IHdhcyBpbiBOb3ZlbWJlciAyMDE5LiBQYXJ0bmVyIGRhdGEgaGFzIGJlZW4gYW5vbnltaXNlZC4gT3RoZXIgZGF0YSBvcmlnaW5hdGUgZnJvbSB0aGUgY2Vuc3VzIGRhdGFzZXQgb2YgVmVuZXp1ZWxhIHRoYXQgd2FzIG1haW50YWluZWQgYnkgVU5JQ0VGLiBVbmxpa2UgdGhlIGRvY3VtZW50IG9mIDVXIHJlcG9ydGluZyBhbmQgY2xlYW5pbmcsIHdlIHdpbGwgbm90IGJlIGV4cGxvcmluZyB0aGUgY2xlYW5pbmcgcHJvY2Vzcy4gQnV0IHRoZSBzb3VyY2UgY29kZSBvZiBlYWNoIGNodW5rIHdpbGwgYmUgZGlzcGxheWVkIHdoZW4gdGhlIGBDb2RlYCBidXR0b24gaXMgY2xpY2tlZC4gVGhlIHR3byBjaHVua3Mgb24gdGhlIHJpZ2h0IGNvbnRhaW4gY29kZSBmb3IgZGF0YSBjbGVhbmluZyBhbmQgcHJlcGFyYXRpb24uIA0KDQpgYGB7ciByZWFkaW5nLWFuZC1jbGVhbmluZy1hbmQtaW50ZXJtZWRpdGUtb3VwdXRzfQ0KDQojIHJlYWRpbmcgYW5kIGNsZWFuaW5nIC0tIHlvdSByZWFsbHkgc2hvdWxkIGJyZWFrIGl0IGludG8gcGFydHMNCnZlbjEgPC0gcmVhZF9jc3YoImNvbnNvbGlkYXRpb24gMTkxMjA5IDE2MzYuY3N2IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JSANCiAgIyByZW1vdmluZyB1bnVzZWQgY29sdW1ucw0KICBzZWxlY3QoLWMoY29kaWdvZGVlc3RhYmxlY2ltaWVudG9vY2VudHJvLCBsb2NfaWQsIGhycF9zaXRyZV9wX2luZGljYXRvciwgDQogICAgICAgICAgICB0aXBvZGVyZXNwdWVzdGEsIGNvbWVudGFyaW9zLCBjb29yZGVhZGFzX2dwc194LCBjb29yZGVhZGFzX2dwc195LA0KICAgICAgICAgICAgZmVjaGFkZV9pbmljaW8sIGZlY2hhX3ByZXZpc3RhZGVfZmluYWxpemFjaW9uKSkgJT4lIA0KICAjIHJlbmFtaW5nIHVud2llbGR5IGNvbHVtbnMgDQogIHJlbmFtZSh1YmljYWNpb24gICAgICAgICAgPSBjb211bmlkYWRvbm9tYnJlZGVsZXN0YWJsZWNpbWllbnRvX2NlbnRybywgDQogICAgICAgICBzZWN0b3IgICAgICAgICAgICAgPSBzZWN0b3JfYXJlYWRlX3Jlc3BvbnNhYmlsaWFkLA0KICAgICAgICAgYmVuZWZpY2lhcmlvc19tZXRhID0gYmVuZWZpY2lhcmlvc19tZXRhX251bWVyb2RlcGVyc29uYXMsDQogICAgICAgICBlc3RhdHVzICAgICAgICAgICAgPSBlc3RhdHVzZGVwcm9ncmFtYWNpb24pICU+JSANCiAgICAgICMgbXV0YXRpbmcgdGhlIGRhdGUgdG8gdGhlIHJpZ2h0IGZvcm1hdA0KICBtdXRhdGUobW9udGggPSBhcy5mYWN0b3IocmVjb2RlKG1vbnRoLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDRgID0gIjMwLzA0LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDVgID0gIjMxLzA1LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDZgID0gIjMwLzA2LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDdgID0gIjMxLzA3LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDhgID0gIjMxLzA4LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDlgID0gIjMwLzA5LzIwMTkiLA0KICAgICAgICAgICAgICAgICAgICAgICAgYDEwYCA9ICIzMS8xMC8yMDE5IikpKSAlPiUgDQogIG11dGF0ZShtb250aCA9IGFzLkRhdGUobW9udGggJT4lIHN0cnB0aW1lKC4sIGZvcm1hdCA9ICIlZC8lbS8lWSIpKSkgJT4lIA0KICBtdXRhdGUob3JnX2xpZGVyID0gY29hbGVzY2Uob3JnX2xpZGVyLCBvcmdfaW1wbGVtZW50YWRvcmEpKSAlPiUgDQogICMgY29ycmVjdGluZyBzZWN0b3IgbmFtZXMNCiAgbXV0YXRlKHNlY3RvciA9IHN0cl9yZXBsYWNlX2FsbChzZWN0b3IsIGMoDQogICAgIkFndWFfc2FuZWFtaWVudG9faGlnaWVuZSIgICAgICAgICAgICA9ICJXQVNIIiwNCiAgICAiZWR1Y2FjaW9uIiAgICAgICAgICAgICAgICAgICAgICAgICAgID0gIkVkdWNhY2lvbiIsDQogICAgIk51dHJpY2lvbiIgICAgICAgICAgICAgICAgICAgICAgICAgICA9ICJOdXRyaWNpb24iLA0KICAgICJwcm90ZWNjacOzbl9OacOxb3NfTmnDsWFzX0Fkb2xlc2NlbnRlcyIgPSAiUHJvdGVjY2lvbl9OTkEiLA0KICAgICJQcm90ZWNjacOzbl9OacOxb3NfTmnDsWFzX0Fkb2xlc2NlbnRlcyIgPSAiUHJvdGVjY2lvbl9OTkEiLA0KICAgICJQcm90ZWNjacOzbl9WaW9sZW5jaWFfR8OpbmVybyIgICAgICAgICA9ICJQcm90ZWNjaW9uX0dCViIpKSkgJT4lIA0KICAjIHJlbmFtaW5nIGJlbmVmaWNpYXJ5IGRpc2FnZ3JlZ2F0aW9uIGNvbHVtbnMgDQogIHJlbmFtZShmXzBfMTggPSBmXzE4LA0KICAgICAgICAgbV8wXzE4ID0gbV8xOCwNCiAgICAgICAgIGZfMThwbHVzID0gZl8xOF8yLA0KICAgICAgICAgbV8xOHBsdXMgPSBtXzE4XzIpICU+JSANCiAgbXV0YXRlKGVzdGFkbyAgICA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIoZXN0YWRvKSksIA0KICAgICAgICAgbXVuaWNpcGlvID0gcm1fYWNjZW50KHN0cl90b191cHBlcihtdW5pY2lwaW8pKSwNCiAgICAgICAgIHBhcnJvcXVpYSA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIocGFycm9xdWlhKSksDQogICAgICAgICB1YmljYWNpb24gPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKHViaWNhY2lvbikpLA0KICAgICAgICAgYWN0aXZpZGFkID0gcm1fYWNjZW50KHN0cl90b191cHBlcihhY3RpdmlkYWQpKSwNCiAgICAgICAgIGNhdGVnb3JpYSA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIoY2F0ZWdvcmlhZGVhY3RpdmlkYWQpKSkgJT4lIA0KICAjIHJlY29kaW5nIHRoZSBlc3RhdHVzIGNvbHVtbiANCiAgbXV0YXRlKGVzdGF0dXMgPSBzdHJfcmVwbGFjZV9hbGwoZXN0YXR1cywgDQogICAgICAgICAgICAgICAgICBjKCJFbiBlamVjdWNpb24iID0gImVqZWN1Y2lvbiIsIA0KICAgICAgICAgICAgICAgICAgICAiZW4gZWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwgDQogICAgICAgICAgICAgICAgICAgICJlbiBFamVjdWNpw7NuIiA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiRW4gZWplY3VjacOzbiIgPSAiZWplY3VjaW9uIiwNCiAgICAgICAgICAgICAgICAgICAgIkVuIEVqZWN1Y2nDs24iID0gImVqZWN1Y2lvbiIsDQogICAgICAgICAgICAgICAgICAgICJFbmVqZWN1Y2nDs24iICA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiNDM3NDEiICAgICAgICA9ICJlamVjdWNpb24iLA0KICAgICAgICAgICAgICAgICAgICAiZmluYWxpemFkYSIgPSAiZmluYWxpemFkYSIsDQogICAgICAgICAgICAgICAgICAgICJGaW5hbGl6YWRhIiA9ICJmaW5hbGl6YWRhIiwNCiAgICAgICAgICAgICAgICAgICAgIlBsYW5lYWRhIiA9ICJwbGFuZWFkYSIsDQogICAgICAgICAgICAgICAgICAgICJwbGFuZWFkYSBjb24gZmluYW5jaWFtaWVudG8iID0gInBsYW5lYWRhIiwNCiAgICAgICAgICAgICAgICAgICAgInBsYW5lYWRhIHNpbiBmaW5hbmNpYW1pZW50byIgPSAicGxhbmVhZGEiKSkpICU+JSANCiAgcmVwbGFjZV9uYShsaXN0KGVzdGF0dXMgPSAiZWplY3VjaW9uIikpICU+JSANCiAgIyByZW1vdmluZyBhbGwgcGxhbm5lZCBhY3Rpdml0aWVzIA0KICBmaWx0ZXIoZXN0YXR1cyAhPSAicGxhbmVhZGEiKSAlPiUgDQogIGZpbHRlcihzdHJfZGV0ZWN0KHBjb2RlMywgIl5WRSIpKSAlPiUgIyBkZWNpZGUgaWYgeW91IHdhbnQgdG8gZG8gdGhpcyBoZXJlIG9yIGxhdGVyDQogIHNlbGVjdCgtYygyMzo5MikpDQoNCiMgSSdtIGtpbmRhIGRvdWJ0aW5nIHRoZSB1c2Ugb2YgdV9iZW4sIHlhIEkgdGhpbmsgdGFrZSBpdCBvdXQ/IHNpbmNlIHlvdSdyZSBvbmx5IHVzaW5nIGl0IG9uY2UNCiMgQW0gSSBqdXN0IG1ha2luZyB0aGVzZSBvdXQgb2YgaGFiaXQ/IEkgY291bGQgbWFrZSB0aGVtIGluc2lkZSB0aGUgDQojIGNvZGUgY2h1bmsgZm9yIHBhcnIsIGJ1dCBtYXliZSBJIGNhbiBmaW5kIHNvbWUganVzdGlmaWNhdGlvbiBmb3IgdGhlaXIgZXhpc3RlbmNlLCANCiMgbWF5YmUgdGhlIGRpc2FnZ3JlZ2F0aW9ucz8gDQoNCnVfYmVuIDwtIHZlbjEgJT4lIA0KICBwaXZvdF9sb25nZXIoZl8wXzE4Om1fMThwbHVzLCBuYW1lc190byA9ICJkZXNhZ3JlZ2FjaW9uIiwgdmFsdWVzX3RvID0gImJlbmVmaWNpYXJpb3MiKSAlPiUgDQogIGZpbHRlcihjYXRlZ29yaWEgIT0gIlZBQ1VOQUNJT04iKSAlPiUgIyBWYWNjaW5hdGlvbiBhY3Rpdml0aWVzIGZpbHRlcmVkIG91dA0KICBmaWx0ZXIoYmVuZWZpY2lhcmlvcyAhPSAwKSAlPiUgDQogICMgZm9yIHNvbWUgcmVhc29uLCB0aGVyZSBhcmUgZW50cmllcyB3aXRoIHRoZSBzYW1lIHViaWNhY2lvbiBidXQgZGlmZmVyZW50IHBjb2Rlcz8gDQogICMgbWF5YmUgaXQncyB0aGluZ3MgbGlrZSAiY2VudHJvIG11bmljaXBhbCIgb3Igc29tZXRoaW5nDQogIGdyb3VwX2J5KHBjb2RlMywgdWJpY2FjaW9uLCBkZXNhZ3JlZ2FjaW9uKSAlPiUgDQogIHNsaWNlKHdoaWNoLm1heChiZW5lZmljaWFyaW9zKSkgJT4lIA0KICB1bmdyb3VwKCkNCg0KYWN0X2JlbiA8LSB2ZW4xICU+JSANCiAgcGl2b3RfbG9uZ2VyKGZfMF8xODptXzE4cGx1cywgbmFtZXNfdG8gPSAiZGVzYWdyZWdhY2lvbiIsIHZhbHVlc190byA9ICJiZW5lZmljaWFyaW9zIikgJT4lIA0KICBmaWx0ZXIoY2F0ZWdvcmlhICE9ICJWQUNVTkFDSU9OIikgJT4lICMgVmFjY2luYXRpb24gYWN0aXZpdGllcyBmaWx0ZXJlZCBvdXQNCiAgZmlsdGVyKGJlbmVmaWNpYXJpb3MgIT0gMCkgJT4lIA0KICBncm91cF9ieShwY29kZTMsIHViaWNhY2lvbiwgZGVzYWdyZWdhY2lvbiwgYWN0aXZpZGFkKSAlPiUgDQogIHNsaWNlKHdoaWNoLm1heChiZW5lZmljaWFyaW9zKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBtdXRhdGUoc2VjdG9yID0gaWZlbHNlKHN0cl9kZXRlY3Qoc2VjdG9yLCAiUHJvdGVjY2lvbl9HQlZ8UHJvdGVjY2lvbl9HZW5lcmFsfFByb3RlY2Npb25fTk5BIiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICJQcm90ZWNjaW9uIiwgc2VjdG9yKSkNCg0KYGBgDQoNCmBgYHtyIHByaW50aW5nLXUtYmVuLWFjdC1iZW4tZGlmZiwgaW5jbHVkZT1GQUxTRX0NCnJiaW5kKHN1bSh1X2JlbiRiZW5lZmljaWFyaW9zKSwgDQogICAgICBzdW0oYWN0X2JlbiRiZW5lZmljaWFyaW9zKSwgDQogICAgICBzdW0odV9iZW4kYmVuZWZpY2lhcmlvcykgLSBzdW0oYWN0X2JlbiRiZW5lZmljaWFyaW9zKSkNCg0KYGBgDQoNCmBgYHtyIG1ha2luZy1hbGwtcGFyci1hbmQtcGFycjB9DQojIEkgdGhpbmsgdGhpcyBpcyBhIGdpZ2FudGljIGNodW5rIC0tIGNhbm5vdCBkZWNpZGUgaWYgSSB3b3VsZCByYXRoZXIgaGF2ZSBsZXNzIHRoaW5ncyBpbiB0aGUgDQojIGVudmlyb25tZW50IG9yIGlmIEkgd2FudCBtb3JlIHJlYWRhYmxlIGNodW5rcy4gVGhlIGJlbmVmaXQgaGVyZSBJIGd1ZXNzIGlzIHRoYXQgaWYgSSB3YW50IHRvIGNoYW5nZSBzb21ldGhpbmcsIEkganVzdCBoYXZlIHRvIGNvbWUgdG8gdGhpcyBjaHVuaw0KDQpwYXJyIDwtIHVfYmVuICU+JSANCiAgZ3JvdXBfYnkocGNvZGUzKSAlPiUgDQogIHN1bW1hcmlzZShiZW5lZmljaWFyaW9zID0gc3VtKGJlbmVmaWNpYXJpb3MpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogICMgY291bnQgb2Ygb3JnYW5pc2F0aW9ucyBwZXIgcGNvZGUzDQogIHJpZ2h0X2pvaW4oYWN0X2JlbiAlPiUNCiAgICAgICAgICAgICBncm91cF9ieShwY29kZTMpICU+JSANCiAgICAgICAgICAgICBzdW1tYXJpc2Uob3JnX2NvdW50ID0gbl9kaXN0aW5jdChvcmdfaW1wbGVtZW50YWRvcmEpKSkgJT4lIA0KICAjIGdldHRpbmcgYmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMsIHNlY3RvciBjb3VudCBhbmQgbWF4aW11bSBtdWx0aS1zZWN0b3IgYmVuZWZpY2lhcmllcw0KICByaWdodF9qb2luKA0KICAgIGFjdF9iZW4gJT4lDQogICAgICBncm91cF9ieShwY29kZTMsIGRlc2FncmVnYWNpb24sIHNlY3RvcikgJT4lIA0KICAgICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNlY3RvciwgdmFsdWVzX2Zyb20gPSBiZW5lZmljaWFyaW9zKSAlPiUgDQogICAgICByZW5hbWUobnV0cmljaW9uX2JlbiA9IE51dHJpY2lvbiwgcHJvdGVjY2lvbl9iZW4gPSBQcm90ZWNjaW9uLCB3YXNoX2JlbiA9IFdBU0gsIA0KICAgICAgICAgICAgIHNhbHVkX2JlbiA9IFNhbHVkLCBlZHVjYWNpb25fYmVuID0gRWR1Y2FjaW9uLCBzYV9iZW4gPSBTZWd1cmlkYWRfQWxpbWVudGFyaWEpICU+JSANCiAgICAgIHJlcGxhY2VfbmEobGlzdChudXRyaWNpb25fYmVuID0gMCwgZWR1Y2FjaW9uX2JlbiA9IDAsIHdhc2hfYmVuID0gMCwgc2FsdWRfYmVuID0gMCwNCiAgICAgICAgICAgICAgICAgICAgICBzYV9iZW4gPSAwLCBwcm90ZWNjaW9uX2JlbiA9IDApKSAlPiUNCiAgICAgIHN1bW1hcmlzZShhY3Jvc3MoYyhudXRyaWNpb25fYmVuLCBwcm90ZWNjaW9uX2Jlbiwgd2FzaF9iZW4sIA0KICAgICAgICAgICAgICAgICAgICAgICAgIGVkdWNhY2lvbl9iZW4sIHNhbHVkX2Jlbiwgc2FfYmVuKSwgc3VtKSwgLmdyb3VwcyA9ICJkcm9wIikgJT4lDQogICAgICBtdXRhdGUoYmVuX2ZyZXEgPSBudXRyaWNpb25fYmVuICsgcHJvdGVjY2lvbl9iZW4gKyB3YXNoX2JlbiArIHNhbHVkX2JlbiArIGVkdWNhY2lvbl9iZW4gKyBzYV9iZW4pICU+JSANCiAgICAgICAgICBncm91cF9ieShwY29kZTMpICU+JSANCiAgICAgICAgICBzdW1tYXJpc2UoYWNyb3NzKGMobnV0cmljaW9uX2JlbiwgcHJvdGVjY2lvbl9iZW4sIHdhc2hfYmVuLCBzYWx1ZF9iZW4sIGVkdWNhY2lvbl9iZW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbHVkX2Jlbiwgc2FfYmVuLCBiZW5fZnJlcSksIHN1bSkpICU+JSANCiAgICAgIG11dGF0ZShzZWNfYmVuX21heCA9IHBtYXgobnV0cmljaW9uX2JlbiwgcHJvdGVjY2lvbl9iZW4sIHdhc2hfYmVuLCBzYWx1ZF9iZW4sIGVkdWNhY2lvbl9iZW4sIHNhX2JlbiksDQogICAgICAgICAgICAgbXNfYmVuX21heCAgPSBpZmVsc2Uoc2VjX2Jlbl9tYXggPj0gYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VjX2Jlbl9tYXgpLA0KICAgICAgICAgICAgc2VjdG9yX2NvdW50ID0gcm93U3VtcyhzZWxlY3QoLiwgZW5kc193aXRoKCJfYmVuIikpICE9IDApKSkgJT4lIA0KICAjIHJpZ2h0X2pvaW4gdG8gdGhlIGNlbnN1cyBkYXRhDQogIHJpZ2h0X2pvaW4ocmVhZF9leGNlbCgiY2Vuc3VzIGRhdGEgMjAxOTExMjIueGxzeCIsIHNoZWV0ID0gImRhdGEiKSAlPiUgDQogICAgICAgIGNsZWFuX25hbWVzKCkgJT4lIA0KICAgICAgICAjIHNlbGVjdGluZyB2YXJpYWJsZXMgYW5kIHJlbmFtaW5nIHRoZW0gd2l0aCBzZWxlY3QNCiAgICAgICAgc2VsZWN0KGVzdGFkbywgcGNvZGUxLCBtdW5pY2lwaW8sIHBjb2RlMiwgcGFycm9xdWlhLCBwY29kZTMsIA0KICAgICAgICAgICAgICAgZm8gPSBmaWVsZF9vZmZpY2UsDQogICAgICAgICAgICAgICBwb2JsYWNpb25fMjAxOSA9IHhfMjAxOV9wb2JsYWNpb25fcGFycm9xdWlhbF90b3RhbCwNCiAgICAgICAgICAgICAgIGhvZ2FyZXNfMjAxMSA9IG51bWVyb19kZV9ob2dhcmVzLCANCiAgICAgICAgICAgICAgIGhhbV8yMDE5X2FtYml0b3NfZ2UsIA0KICAgICAgICAgICAgICAgcGVyY2VudF9wb2JyZSA9IGhhbV8yMDE5X3h4X3BvYnJlemFfZW52X3Bvcl9wYXJyb3F1aWEsIA0KICAgICAgICAgICAgICAgcG9iX3BvYnJlID0gaGFtXzIwMTlfeHhfcG9ibGFjaW9uX3BvYnJlX3Bvcl9wYXJyb3F1aWEsIA0KICAgICAgICAgICAgICAgcG9ibGFjaW9uX3RvdGFsXzIwMTEsDQogICAgICAgICAgICAgICBwb2JsYWNpb25faW5mYW50aWxfbWVub3JfZGVfMTJfYW5vcywgcG9ibGFjaW9uX2Fkb2xlc2NlbnRlc19kZV8xMl9hXzE3X2Fub3MsDQogICAgICAgICAgICAgICBwb2JsYWNpb25fZGVfMThfYW5vc195X21hcywgDQogICAgICAgICAgICAgICBwZXJjZW50X3VyYmFuYSA9IHBvYmxhY2lvbl91cmJhbmFfcGVyY2VudCwgDQogICAgICAgICAgICAgICBhcmVhX2ttMiwgDQogICAgICAgICAgICAgICBkZW5zaWRhZF9wcGxfa20yID0gZGVuc2lkYWRfcG9ibGFjaW9uYWxfcHBsX2ttMiwNCiAgICAgICAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9pbmljaWFsLCBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fcHJpbWFyaWEsIA0KICAgICAgICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX21lZGlhLCByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCwNCiAgICAgICAgICAgICAgIHJhem9uX2RlX2RlcGVuZGVuY2lhX2RlX21lbm9yZXNfZGVfMTVfYW5vcywgDQogICAgICAgICAgICAgICBwZXJjZW50X3Npbl9hZ3VhX3NlZ3VyYSA9IHhfYWJhc3RfYWd1YTJfcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEsDQogICAgICAgICAgICAgICBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyA9DQogICAgICAgICAgICAgICAgIHhfc2FuZWFtaWVudG9fcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8sDQogICAgICAgICAgICAgICBwZXJjZW50X2FuYWxmYWJldG8gPSBwZXJjZW50X3BvYmxhY2lvbl8xMF9hbm9zX3lfbWFzX2FuYWxmYWJldGEsDQogICAgICAgICAgICAgICBwcm9tZWRpb19kZV9wZXJzb25hc19wb3Jfdml2aWVuZGEsDQogICAgICAgICAgICAgICBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEgPSBwZXJjZW50X2RlX2hvZ2FyZXNfY29uX2plZmF0dXJhX2ZlbWVuaW5hLA0KICAgICAgICAgICAgICAgcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvID0NCiAgICAgICAgICAgICAgICAgc2VydmljaW9fZWxlY3RyaWNvX3BlcmNlbnRfbm9fdGllbmVfc2VydmljaW9fZWxlY3RyaWNvLA0KICAgICAgICAgICAgICAgaGFtXzIwMTlfeF92aW9sZW5jaWFfZW52ZWxvcGUsIGhhbV8yMDE5X3hfbW9ydGFsaWRhZF95X3NhbHVkX2VudmVsb3BlLCANCiAgICAgICAgICAgICAgIGhhbV8yMDE5X3hfcG9icmV6YV9lbnZlbG9wZSwgcHJvbWVkaW9fZGVfZWRhZCwgDQogICAgICAgICAgICAgICByZWxhY2lvbl9kZV9tYXNjdWxpbmlkYWQpICU+JSANCiAgICAgICAgbXV0YXRlKGVzdGFkbyAgICAgPSBybV9hY2NlbnQoc3RyX3RvX3VwcGVyKGVzdGFkbykpLCAjIGp1c3QgdG8gbWFrZSBzdXJlIA0KICAgICAgICAgICAgICAgbXVuaWNpcGlvICA9IHJtX2FjY2VudChzdHJfdG9fdXBwZXIobXVuaWNpcGlvKSksDQogICAgICAgICAgICAgICBwYXJyb3F1aWEgID0gcm1fYWNjZW50KHN0cl90b191cHBlcihwYXJyb3F1aWEpKSkgJT4lIA0KICAgICAgICAjIGNyZWF0aW5nIG5ldyBkaXNhZ2dyZWdhdGlvbiB2YXJpYWJsZXMgDQogICAgICAgIG11dGF0ZShwb2JfbWVub3JfZGVfMTggPSAocG9ibGFjaW9uX2luZmFudGlsX21lbm9yX2RlXzEyX2Fub3MgKw0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9ibGFjaW9uX2Fkb2xlc2NlbnRlc19kZV8xMl9hXzE3X2Fub3MpIC9wb2JsYWNpb25fdG90YWxfMjAxMSAqDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2JsYWNpb25fMjAxOSwgDQogICAgICAgICAgICAgICBwb2JfMThfeV9tYXMgICAgPSBwb2JsYWNpb25fZGVfMThfYW5vc195X21hcyAvIHBvYmxhY2lvbl90b3RhbF8yMDExICogcG9ibGFjaW9uXzIwMTksIA0KICAgICAgICAgICAgICAgaG9nYXJlc18yMDE5ICAgID0gaG9nYXJlc18yMDExICogcG9ibGFjaW9uXzIwMTkgLyBwb2JsYWNpb25fdG90YWxfMjAxMSwgDQogICAgICAgICAgICAgICBtYXRyaWN1bGFfdG90YWwgPSBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25faW5pY2lhbCArIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX3ByaW1hcmlhICsgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25fbWVkaWEpICU+JSANCiAgICAgICAgIyBkaXZpZGluZyBjb2x1bW5zIGJ5IDEwMCBzbyB0aGF0IHRoZXkncmUgYmV0d2VlbiAwIGFuZCAxDQogICAgICAgIG11dGF0ZV9hdCh2YXJzKHBlcmNlbnRfYW5hbGZhYmV0bywgcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvLCANCiAgICAgICAgICAgICAgICAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEsDQogICAgICAgICAgICAgICAgICAgICAgIHBlcmNlbnRfc2luX3NhbmVhbWllbnRvX21lam9yYWRvLA0KICAgICAgICAgICAgICAgICAgICAgICBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIHBlcmNlbnRfdXJiYW5hLA0KICAgICAgICAgICAgICAgICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCksIH4oLiAvIDEwMCkpICU+JSANCiAgICAgICAgIyBtdXRhdGluZyBuZXcgY29sdW1ucyB3aXRoIHBvcHVsYXRpb25zDQogICAgICAgIG11dGF0ZShwb2JfYW5hbGZhYmV0byAgICAgICAgICAgICAgID0gcGVyY2VudF9hbmFsZmFiZXRvICogcG9ibGFjaW9uXzIwMTksDQogICAgICAgICAgICAgICBwb2Jfc2luX2FndWFfc2VndXJhICAgICAgICAgID0gcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKiBwb2JsYWNpb25fMjAxOSwgDQogICAgICAgICAgICAgICBwb2Jfc2luX3NlcnZpY2lvX2VsZWN0cmljbyAgID0gcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvICogcG9ibGFjaW9uXzIwMTksDQogICAgICAgICAgICAgICBwb2Jfc2luX3NhbmVhbWllbnRvX21lam9yYWRvID0gcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKiBwb2JsYWNpb25fMjAxOSwNCiAgICAgICAgICAgICAgIHBvYl91cmJhbmEgICAgICAgICAgICAgICAgICAgPSBwZXJjZW50X3VyYmFuYSAqIHBvYmxhY2lvbl8yMDE5KSAlPiUgDQogICAgICAgIHNlbGVjdCgtYyhtYXRyaWN1bGFfMjAxN19lZHVjYWNpb25faW5pY2lhbCwgbWF0cmljdWxhXzIwMTdfZWR1Y2FjaW9uX3ByaW1hcmlhLCANCiAgICAgICAgICAgICAgIG1hdHJpY3VsYV8yMDE3X2VkdWNhY2lvbl9tZWRpYSwgcG9ibGFjaW9uX3RvdGFsXzIwMTEsIGhvZ2FyZXNfMjAxMSwNCiAgICAgICAgICAgICAgIHBvYmxhY2lvbl9pbmZhbnRpbF9tZW5vcl9kZV8xMl9hbm9zLCBwb2JsYWNpb25fYWRvbGVzY2VudGVzX2RlXzEyX2FfMTdfYW5vcywgDQogICAgICAgICAgICAgICBwb2JsYWNpb25fZGVfMThfYW5vc195X21hcykpLA0KICAgICAgICAgICAgYnkgPSAicGNvZGUzIikgJT4lIA0KICAjIG11dGF0aW5nIG5ldyB2YXJpYWJsZXMgYW5kIG1ha2luZyBzdXJlIE5BcyBiZWNvbWUgMHMgDQogIG11dGF0ZShiZW5lZmljaWFyaW9zICA9IGlmZWxzZShpcy5uYShiZW5lZmljaWFyaW9zKSwgMCwgYmVuZWZpY2lhcmlvcyksDQogICAgICAgICBvcmdfY291bnQgICAgICA9IGlmZWxzZShpcy5uYShvcmdfY291bnQpLCAwLCBvcmdfY291bnQpLA0KICAgICAgICAgc2VjdG9yX2NvdW50ICAgPSBpZmVsc2UoaXMubmEoc2VjdG9yX2NvdW50KSwgMCwgc2VjdG9yX2NvdW50KSwgDQogICAgICAgICBlZHVjYWNpb25fYmVuICA9IGlmZWxzZShpcy5uYShlZHVjYWNpb25fYmVuKSwgMCwgZWR1Y2FjaW9uX2JlbiksDQogICAgICAgICBudXRyaWNpb25fYmVuICA9IGlmZWxzZShpcy5uYShudXRyaWNpb25fYmVuKSwgMCwgbnV0cmljaW9uX2JlbiksDQogICAgICAgICBwcm90ZWNjaW9uX2JlbiA9IGlmZWxzZShpcy5uYShwcm90ZWNjaW9uX2JlbiksIDAsIHByb3RlY2Npb25fYmVuKSwNCiAgICAgICAgIHNhbHVkX2JlbiAgICAgID0gaWZlbHNlKGlzLm5hKHNhbHVkX2JlbiksIDAsIHNhbHVkX2JlbiksDQogICAgICAgICBzYV9iZW4gICAgICAgICA9IGlmZWxzZShpcy5uYShzYV9iZW4pLCAwLCBzYV9iZW4pLA0KICAgICAgICAgd2FzaF9iZW4gICAgICAgPSBpZmVsc2UoaXMubmEod2FzaF9iZW4pLCAwLCB3YXNoX2JlbiksDQogICAgICAgICBtc19iZW5fbWF4ICAgICA9IGlmZWxzZShpcy5uYShtc19iZW5fbWF4KSwgMCwgbXNfYmVuX21heCksDQogICAgICAgICBiZW5fZnJlcSAgICAgICA9IGlmZWxzZShpcy5uYShiZW5fZnJlcSksIDAsIGJlbl9mcmVxKSwNCiAgICAgICAgIG5vdF9yZWFjaGVkICAgICAgICAgPSBwb2JfcG9icmUgLSBiZW5lZmljaWFyaW9zLA0KICAgICAgICAgY292ZXJhZ2VfcGVyY2VudCAgICA9IGJlbmVmaWNpYXJpb3MgLyBwb2JfcG9icmUsDQogICAgICAgICBwZXJjZW50X3RvdGFsX2Jlbl91ID0gYmVuZWZpY2lhcmlvcyAvIHN1bShiZW5lZmljaWFyaW9zKSwNCiAgICAgICAgIG11bHRpc2VjdG9yX3BlcmNlbnQgPSBtc19iZW5fbWF4IC8gYmVuX2ZyZXEsIA0KICAgICAgICAgb3JnX3ByZXNlbnQgICAgICAgICA9IGlmZWxzZShiZW5lZmljaWFyaW9zID4gMCwgVFJVRSwgRkFMU0UpLA0KICAgICAgICAgcG9iX3BvYnJlX3Njb3JlICAgICA9IHJlc2NhbGUocG9iX3BvYnJlLCB0byA9IGMoMCwxKSksIA0KICAgICAgICAgcGVyY2VudF9wb2JyZV9zY29yZSA9IHJlc2NhbGUocGVyY2VudF9wb2JyZSwgdG8gPSBjKDAsMSkpLCANCiAgICAgICAgIHBvdmVydHlfc2NvcmUgICAgICAgPSAocG9iX3BvYnJlX3Njb3JlICsgcGVyY2VudF9wb2JyZV9zY29yZSkgLyAyKQ0KDQojIHRha2luZyBhIHN1YnNldCBvZiBwYXJyIHRvIG9ubHkgZ2V0IHBhcnJpc2hlcyB3aGVyZSB0aGUgDQojIG51bWJlciBvZiBiZW5lZmljaWFyaWVzIGRvZXMgbm90IGV4Y2VlZCB0aGUgbnVtYmVyIG9mIHBvb3IgcGVyc29ucw0KDQpwYXJyMCA8LSBwYXJyICU+JSANCiAgZmlsdGVyKG5vdF9yZWFjaGVkID49IDEpICU+JSANCiAgbXV0YXRlKGdhcF9zY29yZSA9IChyZXNjYWxlKG5vdF9yZWFjaGVkLCB0byA9IGMoMCwxKSkgKyBwZXJjZW50X3BvYnJlX3Njb3JlKSAvIDIpDQoNCmBgYA0KDQpgYGB7ciB3cml0ZS1jc3YtcGFycjAsIGluY2x1ZGUgPSBGQUxTRSwgZXZhbCA9IEZBTFNFfQ0KIyBldmFsbGVkIG91dCAtLSBjaGFuZ2UgdGhpcyBpZiB5b3Ugd2FudCB0aGUgY3N2IGZvciB0YWJsZWF1IG9yIHdoYXRldmVyDQp3cml0ZV9jc3YocGFycjAsICJwYXJyMC5jc3YiKQ0KYGBgDQoNCjxicj48YnI+PGJyPiAgDQoNCiMjIDIuIFN1bW1hcnkgb2YgY292ZXJhZ2UgYW5kIGdhcHMNCg0KDQojIyMgMmEuIE1hcCBvZiBwYXJyaXNoZXMgYnkgZ2Fwcw0KDQpgYGB7ciBNQVAtUkVGLCBpbmNsdWRlID0gRkFMU0V9DQojIHJlYWRpbmcgaW4gdGhlIHNoYXBlZmlsZQ0KcGNvZGUzX3NoYXBlIDwtIHN0X3JlYWQoIkM6L1VzZXJzL1NlYW4gTmcvRG9jdW1lbnRzL1IvY292ZXJhZ2VfZ2Fwc192ZW5lenVlbGEvdmVuX2FkbWJuZGFfYWRtM18yMDE4MDUwMi92ZW5fYWRtYm5kYV9hZG0zXzIwMTgwNTAyLnNocCIsDQogICAgICAgICAgICAgICAgICAgICAgICBxdWlldCA9IFRSVUUpICU+JSANCiAgcmVuYW1lKHBjb2RlMSA9IEFETTFfUENPREUsDQogICAgICAgICBwY29kZTIgPSBBRE0yX1BDT0RFLA0KICAgICAgICAgcGNvZGUzID0gQURNM19QQ09ERSkgJT4lIA0KICBtdXRhdGUocGNvZGUzID0gcmVjb2RlKHBjb2RlMywNCiAgICAgICAgICAgICAgICAgICAgICAgICAiVkUwMzAxMDIiID0gIlZFMDMwMTAxIiwgIyBvbmx5IEFuYWNvIGV4aXN0cywgYWNjb3JkaW5nIHRvIHRoZSBjZW5zdXMNCiAgICAgICAgICAgICAgICAgICAgICAgICAiVkUwMzE5MDEiID0gIlZFMDMxOTAwIiwgIyBzb21laG93IHRoZSBjZW5zdXMgYW5kIHRoZSBzaGFwZWZpbGVzIGNvbmZsaWN0DQogICAgICAgICAgICAgICAgICAgICAgICAgIlZFMDcwMzAxIiA9ICJWRTA3MDMwMCIpKSAlPiUgICMgaGVyZSB0b28NCiMgc2ltcGx5aW5nIHRvIHJlbW92ZSBzbGl2ZXJzIC0tIGxldCdzIHNlZSBpZiB0aGlzIHdvcmtzIA0KIyBpdCdzIGEgYml0IGFic3RyYWN0IGF0IDAuMDUsIGJ1dCB0aGUgc2xpdmVycyBBUkUgZ29uZSBhbmQgaXQgbG9va3Mgbm90IGJhZCANCiMgZmlndXJpbmcgdGhpcyBvdXQgd2FzIG1hZGRlbmluZywgSSBjYW4ndCBiZWxpZXZlIHlvdSBzcGVudCBzbyBsb25nIG9uIGNvc21ldGljIGl0ZW1zIA0KICBtc19zaW1wbGlmeShrZWVwID0gMC4wNSwga2VlcF9zaGFwZXMgPSBUUlVFKQ0KDQpgYGANCg0KYGBge3IgY292ZXJhZ2UtbWFwLW5vdC1jb3ZlcmVkLXBvYnJlfQ0KIyBwYXJyaXNoZXMgd2l0aCBuZWdhdGl2ZSBwb29yIHBlcnNvbnMgYXJlIHJlY29kZWQgYXMgIjAiIHNvIHRoZXkgd29uJ3QgbWVzcyB1cCB0aGUgc2NhbGUNCiMgZXZlbiB0aG91Z2ggdGhpcyBtZWFucyB0aGF0IHRoZWlyIHRvb2x0aXBzIGFyZSBkcm9wcGVkIA0KDQpnYXBzX21hcCA8LSBwYXJyICU+JSANCiAgcmlnaHRfam9pbihwY29kZTNfc2hhcGUsIGJ5ID0gInBjb2RlMyIpICU+JSANCiAgc3RfYXNfc2YoKSAlPiUgDQogIG11dGF0ZShub3RfcmVhY2hlZCA9IGlmZWxzZShub3RfcmVhY2hlZCA8IDAuMSwgMCwgbm90X3JlYWNoZWQpKSAlPiUgDQogIG11dGF0ZShub3RfcmVhY2hlZCA9IHJvdW5kKG5vdF9yZWFjaGVkLCBkaWdpdHMgPSAwKSkgJT4lDQogIG11dGF0ZV9hdCh2YXJzKHBlcmNlbnRfcG9icmUsIHBlcmNlbnRfdXJiYW5hKSwgfihyb3VuZCguLCBkaWdpdHMgPSAyKSkpICU+JSANCiAgZ2dwbG90KCkgKw0KICBnZW9tX3NmKGFlcyhmaWxsID0gbm90X3JlYWNoZWQsDQogICAgICAgICAgICAgIHRleHQgPSBwYXN0ZTAocGFycm9xdWlhLCIsIiwgIlxuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdW5pY2lwaW8sICIsIiwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGFkbywgIlxuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAibm90IHJlYWNoZWQ6ICIsIG5vdF9yZWFjaGVkLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIm9yZyBjb3VudDogIiwgb3JnX2NvdW50LCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgInBvdmVydHkgaW5jaWRlbmNlOiAiLCBwZXJjZW50X3BvYnJlLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQgdXJiYW46ICIsIHBlcmNlbnRfdXJiYW5hKSksDQogICAgICAgICAgc2l6ZSA9IDAuMSkgKw0KICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhvcHRpb24gPSAidHVyYm8iLCB0cmFucyA9ICJsb2cxMCIpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwNCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpLA0KICAgICAgICBwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMSkpICsNCiAgbGFicyhmaWxsID0gIlBvb3IgcGVyc29ucyBcbm5vdCByZWFjaGVkIikgKw0KICBnZ3RpdGxlKCJNYXAgb2YgcGFycmlzaGVzIGJ5IGdhcHMgaW4gcG9wdWxhdGlvbiByZWFjaGVkIikNCg0KIyBzbyBhcmUgeW91IHNheWluZyB0aGF0IGlmIEkgY2hhbmdlIHRoZSBmaWxsIHRvIHZpcmlkaXMgaW4gdGhlIGxhdGVyIHBsb3QsIEkgY2FuIHVzZSBob3Zlcm9uID0gZmlsbD8NCiMgbm8geW91IGNhbid0LiANCmdncGxvdGx5KGdhcHNfbWFwLCB0b29sdGlwID0gYygidGV4dCIpKSAlPiUNCiAgbGF5b3V0KHNob3dsZWdlbmQgPSBUUlVFLCBsZWdlbmQgPSBsaXN0KGZvbnQgPSBsaXN0KHNpemUgPSA2KSkpICU+JSANCiAgcGxvdGx5OjpzdHlsZShob3Zlcm9uID0gImZpbGwiKSAlPiUgDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgiTWFwIG9mIHBhcnJpc2hlcyBieSBudW1iZXIgcG9vciBwZXJzb25zIG5vdCByZWFjaGVkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8c3VwPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibW91c2Ugb3ZlciBmb3IgZGV0YWlsczsgZHJhZyBhbmQgY2xpY2sgdG8gc2VsZWN0IGFuZCB6b29tIiwiPC9zdXA+IikpKQ0KDQpgYGANCg0KTmF0aW9ud2lkZSwgKipgciBmb3JtYXQocm91bmQoc3VtKHBhcnIwJG5vdF9yZWFjaGVkKSwgZGlnaXRzID0gMCksIGJpZy5tYXJrID0gIiwiKWAqKiBwb29yIHBlcnNvbnMgaGF2ZSBub3QgYmVlbiBjb3ZlcmVkIGJ5IHJlc3BvbnNlIGFjdGl2aXRpZXMgLS0gdGhpcyBtZWFucyB0aGF0ICoqYHIgcm91bmQoc3VtKHBhcnIwJG5vdF9yZWFjaGVkKSAvIHN1bShwYXJyMCRwb2JfcG9icmUpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIHBvb3IgcGVyc29ucyBpbiB0aGUgY291bnRyeSBoYXZlIHlldCB0byBiZSByZWFjaGVkLiBUaGlzIHBvcHVsYXRpb24sIGl0cyBkaXN0cmlidXRpb24gYW5kIGl0cyBjaGFyYWN0ZXJpc3RpY3MgYXJlIHNvbWUgb2YgdGhlIG1haW4gY29uY2VybnMgb2YgdGhpcyBhbmFseXNpcy4gDQoNCjxicj48YnI+DQoNCiMjIyAyYi4gR3JvdXBpbmcgcGFycmlzaGVzIGJ5IGNvdmVyYWdlIHR5cGUNCg0KQXMgYSBzdGFydGluZyBwb2ludCwgYWxsIGByIG5yb3cocGFycilgIHBhcnJpc2hlcyAoYWRtaW4gbGV2ZWwgMykgaGF2ZSBiZWVuIHNwbGl0IGludG8gdGhyZWUgZ3JvdXBzIC0tIF9vdmVyXywgd2hlcmUgdGhlIG51bWJlciBvZiB1bmlxdWUgYmVuZWZpY2lhcmllcyByZWFjaGVkIGV4Y2VlZHMgdGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgaW4gdGhhdCBwYXJyaXNoOyBfdW5kZXJfLCB3aGVyZSB0aGUgY292ZXJhZ2UgaXMgbGVzcyB0aGFuIHRoZSBudW1iZXIgb2YgcG9vciBwZXJzb25zOyBhbmQgX25vIGNvdmVyYWdlXywgY29tcHJpc2luZyBhIHRvdGFsIG9mICoqYHIgbnJvdyhmaWx0ZXIocGFyciwgYmVuZWZpY2lhcmlvcyA9PSAwKSlgKiogcGFycmlzaGVzLCB3aGVyZSBubyBhY3Rpdml0aWVzIGhhdmUgb2NjdXJyZWQuIA0KDQoNCg0KYGBge3J9DQpwYXJyICU+JSANCiAgbXV0YXRlKGNvdmVyYWdlX3R5cGUgPSBjYXNlX3doZW4obm90X3JlYWNoZWQgPD0gMCB+ICJvdmVyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm90X3JlYWNoZWQgPiAwICYgYmVuZWZpY2lhcmlvcyA+PSAxIH4gInVuZGVyIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJlbmVmaWNpYXJpb3MgPT0gMCB+ICJub19jb3ZlcmFnZSIpKSAlPiUgDQogIGdyb3VwX2J5KGNvdmVyYWdlX3R5cGUpICU+JSANCiAgc3VtbWFyaXNlKHBhcnJpc2hlcyA9IG4oKSwNCiAgICAgICAgICAgIGJlbmVmaWNpYXJpZXMgPSBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICAgICBub3RfcmVhY2hlZCA9IHN1bShub3RfcmVhY2hlZCksIA0KICAgICAgICAgICAgYXZnX29yZ19jb3VudCA9IG1lYW4ob3JnX2NvdW50KSwNCiAgICAgICAgICAgIHBlcmNlbnRfcG9vciA9IHJvdW5kKHN1bShwb2JfcG9icmUpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSAqIDEwMCwgZGlnaXRzID0gMSksDQogICAgICAgICAgICBwZXJjZW50X3VyYmFuID0gcm91bmQoc3VtKHBvYl91cmJhbmEpIC9zdW0ocG9ibGFjaW9uXzIwMTkpICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgICAgIHBlcmNlbnRfd29fc2FmZV93YXRlciA9IHJvdW5kKHN1bShwb2Jfc2luX2FndWFfc2VndXJhKSAvIHN1bShwb2JsYWNpb25fMjAxOSkgKiAxMDAsIGRpZ2l0cyA9IDEpLA0KICAgICAgICAgICAgcGVyY2VudF93b19pbXByb3ZlZF9zYW5pdGF0aW9uID0gcm91bmQoc3VtKHBvYl9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8pLw0KICAgICAgICAgICAgICBzdW0ocG9ibGFjaW9uXzIwMTkpICAqIDEwMCwgZGlnaXRzID0gMSksDQogICAgICAgICAgICBwZXJjZW50X2lsbGl0ZXJhdGUgPSByb3VuZChzdW0ocG9iX2FuYWxmYWJldG8pIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSAqIDEwMCwgZGlnaXRzID0gMSksDQogICAgICAgICAgICBhdmdfc2VjdG9yX2NvdW50ID0gbWVhbihzZWN0b3JfY291bnQpKSAlPiUgDQogIHBpdm90X2xvbmdlcihjb2xzID0gLWNvdmVyYWdlX3R5cGUsIG5hbWVzX3RvID0gInZhcmlhYmxlIikgJT4lIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gY292ZXJhZ2VfdHlwZSwgdmFsdWVzX2Zyb20gPSB2YWx1ZSkgJT4lIA0KICANCiAgcmVsb2NhdGUobm9fY292ZXJhZ2UsIC5hZnRlciA9IHVuZGVyKSAlPiUgDQogIHBhbmRlcihiaWcubWFyayA9ICIsIiwgY2FwdGlvbiA9ICJQYXJyaXNoIGNoYXJhY3RlcmlzdGljcyBieSBjb3ZlcmFnZSB0eXBlIiwgc3R5bGUgPSAicm1hcmtkb3duIikNCg0KYGBgDQoNCkEgdG90YWwgb2YgKipgciByb3VuZChmaWx0ZXIocGFyciwgYmVuZWZpY2lhcmlvcyA9PSAwKSAlPiUge3N1bSguJHBvYl9wb2JyZSl9LCBkaWdpdHMgPSAwKSAlPiUgZm9ybWF0KGJpZy5tYXJrID0gIiwiKWAqKiBwb29yIHBlcnNvbnMgcmVzaWRlIGluIHRoZSAqKmByIG5yb3coZmlsdGVyKHBhcnIsIGJlbmVmaWNpYXJpb3MgPT0gMCkpYCoqIHBhcnJpc2hlcyB0aGF0IGhhdmUgbm90IGJlZW4gcmVhY2hlZDsgdGhpcyBpcyBvbmx5ICoqYHIgcm91bmQoZmlsdGVyKHBhcnIsIGJlbmVmaWNpYXJpb3MgPT0gMCkgJT4lIHtzdW0oLiRwb2JfcG9icmUpfSAvIHN1bShwYXJyJG5vdF9yZWFjaGVkKSAqMTAwLCBkaWdpdHMgPSAwKWAlKiogb2YgdGhlICoqYHIgcm91bmQoc3VtKHBhcnIkbm90X3JlYWNoZWQpLCBkaWdpdHMgPSAwKSAlPiUgZm9ybWF0KGJpZy5tYXJrID0gIiwiKWAqKiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgYnkgcmVzcG9uc2UgYWN0aXZpdGllcy4gVGhpcyBpbmRpY2F0ZXMgdGhhdDoNCg0KMS4gdGhlcmUgaXMgbXVjaCByb29tIHRvIGV4cGFuZCBpbiB0aGUgcGFycmlzaGVzIHdoZXJlIHdlIGFyZSBhbHJlYWR5IHByZXNlbnQgYW5kIHRoYXQgDQoyLiBzcGFyZWx5IHBvcHVsYXRlZCwgcmVtb3RlIGFuZCwgY29uc2VxdWVudGx5LCBwb29yZXIgcGFycmlzaGVzIGhhdmUsIHNvIGZhciwgYmVlbiBsZWZ0IG91dCBvZiB0aGUgcmVzcG9uc2UuDQoNCkFkZGl0aW9uYWxseSwgdGhlICoqYHIgbnJvdyhwYXJyW3BhcnIkbm90X3JlYWNoZWQgPD0gMCxdKWAqKiBwYXJyaXNoZXMgaW4gdGhlIF9vdmVyXyBjYXRlZ29yeSBhcmUgbXVjaCBsZXNzIHBvb3IgYW5kIG11Y2ggbW9yZSB1cmJhbiBkZXNwaXRlIGhhdmluZyAqKmByIHJvdW5kKGZpbHRlcihwYXJyLCBub3RfcmVhY2hlZCA8PSAwKSAlPiUge3N1bSguJGJlbmVmaWNpYXJpb3MpfSAvIHN1bShwYXJyJGJlbmVmaWNpYXJpb3MpICogMTAwLCBkaWdpdHMgPSAwKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJpZXMuIEFzIGNhbiBiZSBzZWVuIGZyb20gdGhlIHJvdyBgbm90X3JlYWNoZWRgLCB0aGUgbnVtYmVyIGJlbmVmaWNpYXJpZXMgaW4gdGhlIF9vdmVyXyBjYXRlZ29yeSBoYXMgZ3JlYXRseSBleGNlZWRlZCB0aGUgbnVtYmVyIG9mIHBvb3IgcGVyc29ucy5UaGVzZSBwYXJyaXNoZXMgYXJlIHNob3duIGluIHRoZSB0YWJsZSBpbiB0aGUgbmV4dCBzZWN0aW9uLiAgDQoNCg0KPGJyPjxicj4NCg0KIyMjIDJjLiBPdmVyYWxsb2NhdGlvbiBpbiB0aGUgdG9wIHBhcnJpc2hlcyBieSBjb3ZlcmFnZQ0KDQpUaGUgKipgciBucm93KHBhcnJbcGFyciRub3RfcmVhY2hlZCA8PSAwLF0pYCoqIHBhcnJpc2hlcyBiZWxvdyAoZnJvbSB0aGUgX292ZXJfIGNhdGVnb3J5KSB3aWxsIGxhcmdlbHkgYmUgZXhjbHVkZWQgaW4gdGhlIHJlbWFpbmRlciBvZiB0aGlzIHJlcG9ydCBhcyBpdCBpcyBjbGVhciB0aGF0IG5vIGZ1cnRoZXIgcmVzb3VyY2VzIHNob3VsZCBiZSBhbGxvY2F0ZWQgdG8gdGhlbTogDQoNCmBgYHtyfQ0KcGFyciAlPiUgDQogIG11dGF0ZShjb3ZlcmFnZV90eXBlID0gY2FzZV93aGVuKG5vdF9yZWFjaGVkIDw9IDAgfiAib3ZlciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vdF9yZWFjaGVkID4gMCAmIGJlbmVmaWNpYXJpb3MgPj0gMSB+ICJ1bmRlciIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiZW5lZmljaWFyaW9zID09IDAgfiAibm90X3JlYWNoZWQiKSkgJT4lICANCiAgZmlsdGVyKGNvdmVyYWdlX3R5cGUgPT0gIm92ZXIiKSAlPiUgDQogIHNlbGVjdChzdGF0ZSA9IGVzdGFkbywgbXVuaWNpcGFsaXR5ID0gbXVuaWNpcGlvLCBwYXJyaXNoID0gcGFycm9xdWlhLCANCiAgICAgICAgIGJlbmVmaWNpYXJpZXMgPSBiZW5lZmljaWFyaW9zLCBwb29yX3BlcnNvbnMgPSBwb2JfcG9icmUpICU+JQ0KICBtdXRhdGUoY292ZXJhZ2VfcGVyY2VudCA9IGJlbmVmaWNpYXJpZXMgLyBwb29yX3BlcnNvbnMgKiAxMDApICU+JSANCiAgYXJyYW5nZShkZXNjKGJlbmVmaWNpYXJpZXMpKSAlPiUgDQogIHBhbmRlcihiaWcubWFyayA9ICIsIiwgY2FwdGlvbiA9ICJUb3AgMTEgcGFycmlzaGVzIGJ5IGNvdmVyYWdlIiwgc3R5bGUgPSAicm1hcmtkb3duIikNCg0KYGBgDQoNCkFzIGEgbm90ZSwgaXQgaXMgbGlrZWx5IHRoYXQgcGFydG5lcnMgaGF2ZSByZXBvcnRlZCBhY3Rpdml0aWVzIHdoaWNoIG9jY3VycmVkIGluIG90aGVyIHBhcnRzIG9mIHRoZSBjYXBpdGFsIGluIEFsdGFncmFjaWEsIGFzIHRoZSB0b3RhbCBudW1iZXIgb2YgYmVuZWZpY2FyaWVzIHJlYWNoZWQgaW4gdGhlIHdob2xlIG9mIERpc3RyaXRvIENhcGl0YWwgaXMgb25seSBgciBmaWx0ZXIocGFyciwgbXVuaWNpcGlvID09ICJMSUJFUlRBRE9SIikgJT4lIHtzdW0oLiRiZW5lZmljaWFyaW9zKX0gJT4lIGZvcm1hdChiaWcubWFyayA9ICIsIilgLiBJdCBpcyBuZWNlc3NhcnkgdG8gY2hlY2sgYmFjayB3aXRoIHBhcnRuZXJzIGFib3V0IHRoaXM7IG5ldmVydGhlbGVzcywgdGhpcyBpcyB0aGUgaW5mb3JtYXRpb24gd2UgaGF2ZSBvbiBoYW5kLiANCg0KPGJyPjxicj4NCg0KIyMjIDJkLiBTZXggcmF0aW9zIGJ5IGNsdXN0ZXINCg0KYGBge3J9DQphY3RfYmVuICU+JSANCiAgbXV0YXRlKHNleF9iZW4gPSBjYXNlX3doZW4oc3RyX2RldGVjdChkZXNhZ3JlZ2FjaW9uLCAiXm0iKSB+ICJtYWxlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChkZXNhZ3JlZ2FjaW9uLCAiXmYiKSB+ICJmZW1hbGUiKSkgJT4lIA0KICBncm91cF9ieShzZWN0b3IpICU+JSANCiAgcmVuYW1lKGNsdXN0ZXIgPSBzZWN0b3IpICU+JSANCiAgc3VtbWFyaXNlKGJlbl9mcmVxID0gc3VtKGJlbmVmaWNpYXJpb3MpLA0KICAgICAgICAgICAgbWFsZSA9IHN1bShiZW5lZmljaWFyaW9zW3NleF9iZW4gPT0gIm1hbGUiXSksIA0KICAgICAgICAgICAgZmVtYWxlID0gc3VtKGJlbmVmaWNpYXJpb3Nbc2V4X2JlbiA9PSAiZmVtYWxlIl0pLA0KICAgICAgICAgICAgc2V4X3JhdGlvID0gcm91bmQobWFsZSAvIGZlbWFsZSwgZGlnaXRzID0gMikpICU+JSANCiAgbXV0YXRlKGAlX2Jlbl9mcmVxYCA9IHJvdW5kKChiZW5fZnJlcSAvIHN1bShiZW5fZnJlcSkpICogMTAwLCBkaWdpdHMgPSAxKSkgJT4lIA0KICByZWxvY2F0ZShgJV9iZW5fZnJlcWAsIC5hZnRlciA9IGJlbl9mcmVxKSAlPiUgDQogIGFycmFuZ2Uoc2V4X3JhdGlvKSAlPiUgDQogIHBhbmRlcihjYXB0aW9uID0gIlNleCByYXRpbyBvZiBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyBieSBjbHVzdGVyIikNCmBgYA0KDQpBbGwgb2YgdGhlIGNsdXN0ZXJzIHJlYWNoZWQgbW9yZSB3b21lbiB0aGFuIG1lbiwgd2l0aCBIZWFsdGggYW5kIFByb3RlY3Rpb24gYmVpbmcgcGFydGljdWxhcmx5IGhlYXZpbHkgc2tld2VkIGluIHRoaXMgcmVnYXJkLiBGb3IgSGVhbHRoLCB0aGUgZGlzcHJvcG9ydGlvbmFsaXR5IGlzIGEgYml0IG1vcmUgdW5kZXJzdGFuZGFibGUgYXMgaXQgaGFzIGEgZm9jdXMgb24gYW50ZW5hdGFsIGFuZCBvYnN0ZXRyaWMgY2FyZSBhcyB3ZWxsIGFzIHByZXZlbnRpbmcgbW90aGVyLXRvLWNoaWxkIEhJViB0cmFuc21pc3Npb247IE51dHJpdGlvbiBzaW1pbGFybHkgaGFzIGEgZm9jdXMgb24gcHJlZ25hbnQgYW5kIGxhY3RhdGluZyB3b21lbi4gSG93ZXZlciwgZm9yIFByb3RlY3Rpb24sIHNvbWUgaW52ZXN0aWdhdGlvbiBpcyBuZWNlc3Nhcnk6IA0KDQpgYGB7cn0NCmFjdF9iZW4gJT4lIA0KICBtdXRhdGUoc2V4X2JlbiA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sICJebSIpIH4gIm1hbGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KGRlc2FncmVnYWNpb24sICJeZiIpIH4gImZlbWFsZSIpLA0KICAgICAgICAgYWN0aXZpdHkgPSBzdHJfdG9fc2VudGVuY2UoYWN0aXZpZGFkKSkgJT4lIA0KICBmaWx0ZXIoc2VjdG9yID09ICJQcm90ZWNjaW9uIikgJT4lIA0KICBncm91cF9ieShhY3Rpdml0eSkgJT4lIA0KICBzdW1tYXJpc2UoYmVuX2ZyZXEgPSBzdW0oYmVuZWZpY2lhcmlvcyksIA0KICAgICAgICAgICAgbWFsZSA9IHN1bShiZW5lZmljaWFyaW9zW3NleF9iZW4gPT0gIm1hbGUiXSksIA0KICAgICAgICAgICAgZmVtYWxlID0gc3VtKGJlbmVmaWNpYXJpb3Nbc2V4X2JlbiA9PSAiZmVtYWxlIl0pKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhiZW5fZnJlcSkpICU+JSBzZWxlY3QoLWJlbl9mcmVxKSAlPiUgaGVhZCg1KSAlPiUgDQogIHBhbmRlcihjYXB0aW9uID0gIlRvcCA1IFByb3RlY3Rpb24gYWN0aXZpdGllcyBieSBiZW5lZmljaWFyaWVzIiwgDQogICAgICAgICBqdXN0aWZ5ID0gYygibGVmdCIsICJjZW50cmUiLCAiY2VudHJlIikpDQpgYGANCg0KPGJyPg0KDQpOb25lIG9mIHRoZSB0b3AgNSAtLSB0aGUgaXNzdWUgb2YgYmlydGggY2VydGlmaWNhdGVzOyBsZWdhbCBhc3Npc3RhbmNlOyBhd2FyZW5lc3MgcmFpc2luZyBvbiB2aW9sZW5jZSwgZXhwbG9pdGF0aW9uLCBhYnVzZSBhbmQgZmFtaWx5IHNlcGFyYXRpb247IG9yIHBzeWNob3NvY2lhbCBzdXBwb3J0IC0tIHNob3VsZCBiZSBwcmVkaXNwb3NlZCB0byByZWFjaCBmZW1hbGVzIG92ZXIgbWFsZXMgKGFuZCBpbiB0aGUgY2FzZSBvZiBwc3ljaG9zb2NpYWwgc3VwcG9ydCwgaXQgaXMgbm90KS4gVGhlIGNsdXN0ZXIgbmVlZHMgdG8gdmVyaWZ5IHRoZXNlIGZpZ3VyZXMgYW5kIHJldmlzaXQgaXRzIHRhcmdldHRpbmcgYW5kIGJlbmVmaWNpYXJ5IHNlbGVjdGlvbiBzdHJhdGVnaWVzLiANCg0KRm9yIHJlZmVyZW5jZSwgdGhlIHNleCByYXRpbyBvZiB0aGUgY291bnRyeSBhcyBhIHdob2xlIHdhcyAwLjk5IGluIHRoZSBsYXN0IGNlbnN1cyAtLSB0aGlzIGZpZ3VyZSBzaG91bGQgbm90IGhhdmUgYmVlbiBhZmZlY3RlZCB0b28gbXVjaCBieSB0aGUgbWlncmFudHMgYW5kIHJlZnVnZWVzIHdobyBoYXZlIGxlZnQgdGhlIGNvdW50cnksIGFzIElPTSdzIFtEaXNwbGFjZW1lbnQgVHJhY2tpbmcgTWF0cml4XShodHRwczovL3JlbGllZndlYi5pbnQvc2l0ZXMvcmVsaWVmd2ViLmludC9maWxlcy9yZXNvdXJjZXMvMS1kZW1vZ3JhcGhpYyUyOFYyJTI5TUwucGRmKSByZXBvcnRzIHRoYXQgcG9wdWxhdGlvbiBhcyBiZWluZyA0OSUgZmVtYWxlIGFuZCA1MSUgcGVyY2VudCBtYWxlLiAgDQoNCg0KPGJyPjxicj48YnI+PGJyPg0KDQojIyAzLiBHZW9ncmFwaGljYWwgYW5hbHlzaXMgb2YgZ2Fwcw0KDQojIyMgM2EuIEJhcnBsb3Qgb2YgY292ZXJhZ2UgYW5kIGdhcHMgYnkgc3RhdGUNCg0KDQpgYGB7ciBwYXJyMC1zdGF0ZS1QTE9UfQ0KIyBvcmRlcmluZyB0aGUgc3RhdGVzIA0Kc3RhdGVfb3JkIDwtIHBhcnIgJT4lIA0KICBncm91cF9ieShlc3RhZG8pICU+JSANCiAgc3VtbWFyaXNlKGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcyksIA0KICAgICAgICAgICAgdG90YWwgPSBzdW0ocG9iX3BvYnJlKSkgJT4lIA0KICBtdXRhdGUocGVyY2VudF9yZWFjaGVkID0gYmVuZWZpY2lhcmlvcyAvIHRvdGFsKSAlPiUgDQogIGFycmFuZ2UocGVyY2VudF9yZWFjaGVkKSAlPiUgc2VsZWN0KGVzdGFkbykgJT4lIHB1bGwoKQ0KICANCnN0YWNrX3RleHQgPC0gcGFyciAlPiUgDQogIGdyb3VwX2J5KGVzdGFkbykgJT4lIA0KICBzdW1tYXJpc2UoYmVuZWZpY2lhcmlvcyA9IHN1bShiZW5lZmljaWFyaW9zKSwNCiAgICAgICAgICAgIHRvdGFsID0gc3VtKHBvYl9wb2JyZSksDQogICAgICAgICAgICBub3RfcmVhY2hlZCA9IHN1bShub3RfcmVhY2hlZCkpICU+JSANCiAgbXV0YXRlKHBlcmNlbnRfcmVhY2hlZCA9IHJvdW5kKGJlbmVmaWNpYXJpb3MgLyB0b3RhbCAqIDEwMCwgZGlnaXRzID0gMSkpICU+JSANCiAgYXJyYW5nZShwZXJjZW50X3JlYWNoZWQpICU+JSANCiAgbXV0YXRlKHBlcmNlbnRfcmVhY2hlZCA9IHBhc3RlMChwZXJjZW50X3JlYWNoZWQsIiUiKSkgDQoNCnN0YXRlX3N0YWNrIDwtIHBhcnIgJT4lIA0KICBzZWxlY3QoZXN0YWRvLCBiZW5lZmljaWFyaW9zLCBub3RfcmVhY2hlZCkgJT4lIA0KICBncm91cF9ieShlc3RhZG8pICU+JQ0KICBzdW1tYXJpc2UoYmVuZWZpY2lhcmllcyA9IHJvdW5kKHN1bShiZW5lZmljaWFyaW9zKSwgZGlnaXRzID0gMCksIA0KICAgICAgICAgICAgbm90X3JlYWNoZWQgPSByb3VuZChzdW0obm90X3JlYWNoZWQpLCBkaWdpdHMgPSAwKSkgJT4lIA0KICBwaXZvdF9sb25nZXIoYyhiZW5lZmljaWFyaWVzLCBub3RfcmVhY2hlZCksDQogICAgICAgICAgICAgICBuYW1lc190byA9ICJwb2JfdHlwZSIsIHZhbHVlc190byA9ICJ0b3RhbCIpICU+JSANCiAgDQogIGdncGxvdChhZXMoeCA9IHRvdGFsLCB5ID0gZXN0YWRvKSkgKw0KICBnZW9tX2NvbChhZXMoZmlsbCA9IHBvYl90eXBlKSwgY29sb3VyID0gImdyZXk3MCIsIHNpemUgPSAwLjAzKSArDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbCA9IGNvbW1hLCBicmVha3MgPSBzZXEoMCwgMTgwMDAwMCwgMjAwMDAwKSkgKw0KICBzY2FsZV95X2Rpc2NyZXRlKGxpbWl0cyA9IHN0YXRlX29yZCkgKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjREU3MDY1RkYiLCAiIzQwMzg5MUZGIikpICsNCiAgZ2VvbV90ZXh0KGRhdGEgPSBzdGFja190ZXh0LCBhZXMobGFiZWwgPSBwZXJjZW50X3JlYWNoZWQpLCANCiAgICAgICAgICAgIHNpemUgPSAyLjUsIGNvbG91ciA9ICJ3aGl0ZSIsIGZvbnRmYWNlID0gImJvbGQiLA0KICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSkpICsNCiAgeWxhYigiIikgKyB4bGFiKCJOdW1iZXIgb2YgcG9vciBwZXJzb25zIikgKyANCiAgbGFicyhmaWxsID0gIiIsIGNvbG91ciA9ICIiLA0KICAgICAgIHRpdGxlID0gIkJhcnBsb3Qgb2YgcG9vciBwZXJzb25zIGJ5IHN0YXRlIGJ5IHJlYWNoZWQvbm90IHJlYWNoZWQiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgICA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLCANCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcsIGFuZ2xlID0gMzApLA0KICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpKSANCg0KZ2dwbG90bHkoc3RhdGVfc3RhY2spICU+JSANCiAgbGF5b3V0KGxlZ2VuZCA9IGxpc3QoZm9udCA9IGxpc3Qoc2l6ZSA9IDcpKSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkgJT4lIA0KICBsYXlvdXQodGl0bGUgPSBsaXN0KHRleHQgPSBwYXN0ZTAoDQogICAgIkJhcnBsb3Qgb2YgcG9vciBwZXJzb25zIGJ5IHN0YXRlIGJ5IG5vdCByZWFjaGVkL3JlYWNoZWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxicj4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIjxzdXA+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtb3VzZSBvdmVyIGZvciBkZXRhaWxzOyBmaWd1cmVzIHNob3cgcGVyY2VudCByZWFjaGVkIiwiPC9zdXA+IikpKQ0KDQpgYGANCg0KKipgciByb3VuZChmaWx0ZXIocGFyciwgZXN0YWRvICVpbiUgYygiRElTVFJJVE8gQ0FQSVRBTCIsICJNSVJBTkRBIiwgIlpVTElBIiwgIlRBQ0hJUkEiLCAiQk9MSVZBUiIpKSAlPiUge3N1bSguJGJlbmVmaWNpYXJpb3MpfSAvIHN1bShwYXJyJGJlbmVmaWNpYXJpb3MpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJpZXMgYXJlIGZyb20gdGhlIHN0YXRlcyBvZiBEaXN0cml0byBDYXBpdGFsLCBNaXJhbmRhLCBUYWNoaXJhLCBCb2xpdmFyIGFuZCBadWxpYSwgbGFyZ2VseSBjb3JyZXNwb25kaW5nIHRvIHRoZSBsb2NhdGlvbnMgb2YgVU5JQ0VGIG9mZmljZXMuIFRoZXNlIHN0YXRlcywgd2l0aCB0aGUgYWRkaXRpb24gb2YgRGVsdGEgQW1hY3VybywgYXJlIGFsc28gd2hlcmUgdGhlIGhpZ2hlc3QgcGVyY2VudGFnZXMgb2YgcG9vciBwZXJzb25zIGhhdmUgYmVlbiByZWFjaGVkLiBCYXJpbmFzIGhhcyB0aGUgbG93ZXN0IHBlcmNlbnRhZ2Ugb2YgaXRzIHBvb3IgcG9wdWxhdGlvbiBjb3ZlcmVkLg0KDQpPbiBhdmVyYWdlLCBhZnRlciB0aGUgZXhjbHVzaW9uIG9mIHRoZSB0b3AgYHIgbnJvdyhwYXJyW3BhcnIkbm90X3JlYWNoZWQgPD0gMCxdKWAgcGFycmlzaGVzLCAqKmByIHJvdW5kKHN1bShwYXJyJGJlbmVmaWNpYXJpb3MpIC8gc3VtKHBhcnIkcG9iX3BvYnJlKSAqIDEwMCwgZGlnaXRzID0gMSlgJSoqIG9mIHBvb3IgcGVyc29ucyBoYXZlIGJlZW4gcmVhY2hlZCBjb3VudHJ5d2lkZS4gSG93ZXZlciwgYXQgdGhlIHN0YXRlIGxldmVsLCB0aGlzIGF2ZXJhZ2UgaXMgKipgciBwYXJyMCAlPiUgZ3JvdXBfYnkoZXN0YWRvKSAlPiUgc3VtbWFyaXNlKHBlcmNlbnRfcmVhY2hlZCA9IGJlbmVmaWNpYXJpb3MgLyBwb2JfcG9icmUsIC5ncm91cHMgPSAiZHJvcCIpICU+JSB1bmdyb3VwKCkgJT4lIHN1bW1hcmlzZShhdmcgPSBtZWFuKHBlcmNlbnRfcmVhY2hlZCkgKiAxMDAsIC5ncm91cHMgPSAiZHJvcCIpICU+JSBwdWxsKCkgJT4lIHJvdW5kKGRpZ2l0cyA9IDEpYCUqKi4gDQoNCldoaWxzdCB0aGVyZSBhcmUgbWFueSBwb29yIHBlcnNvbnMgeWV0IHRvIGJlIHJlYWNoZWQgaW4gc3RhdGVzIHdoZXJlIHdlIGhhdmUgcmVsYXRpdmVseSBoaWdoIGNvdmVyYWdlLCB0aGVyZSBpcyBhIG5lZWQgdG8gZW5zdXJlIHRoYXQgb3VyIG9wZXJhdGlvbmFsIGZvb3RwcmludCBhbmQgdGhlIGNvbnNlcXVlbnQgcmVzb3VyY2VzIGFsbG9jYXRlZCBhcmUgZXF1aXRhYmxlIGFuZCB0aGlzIHR5cGUgb2Ygb3ZlcmFsbG9jYXRpb24gaXMgYXZvaWRlZCAtLSB0aGUgY3Jpc2lzIGluIFZlbmV6dWVsYSBpcyBuYXRpb253aWRlLCBhbmQgdW5saWtlIGFuIGVhcnRocXVha2Ugb3IgYSB0eXBob29uIHdoZXJlIHRoZXJlIGlzIGFuIGVwaWNlbnRyZSBvciBhIHN0b3JtcGF0aCwgdGhlcmUgaXMgbm8gcHJvZ3JhbW1hdGljIHJhdGlvbmFsZSB0byBvbmx5IGZvY3VzIG9uIGEgZmV3IGFyZWFzLiANCg0KTGV0IHVzIG5vdyBtb3ZlIGRvd24gdG8gYSBsb3dlciBsZXZlbCBvZiBncmFudWxhcml0eSBhcyBzdGF0ZS1sZXZlbCBhbmFseXNpcyBpcyBzdGlsbCB0b28gc3VwZXJmaWNpYWwuIFBhcnJpc2hlcyB3aWxsIGJlIHRoZSBtYWluIGFkbWluaXN0cmF0aXZlIHVuaXQgb2YgcmVmZXJlbmNlIGluIHRoaXMgYW5hbHlzaXMuIFVubGlrZSBpbiB0aGUgWzVXIGNsZWFuaW5nIGFuZCByZXBvcnRpbmcgZG9jdW1lbnRdKGh0dHBzOi8vc2Vhbnl3bmcuZ2l0aHViLmlvLzVXLyNCX1JlcG9ydGluZ19vbl90aGVfNVdfZGF0YSksIHdoZXJlIHdlIGZvY3VzZWQgb24gbXVuaWNpcGFsaXRpZXMgdG8gZGlzcGxheSBhY2hpZXZlbWVudHMgZm9yIGV4dGVybmFsIGF1ZGllbmNlcywgZ3JlYXRlciBwcmVjaXNpb24gaXMgbmVlZGVkIGZvciBhIGNvdmVyYWdlIGFuZCBnYXBzIGFuYWx5c2lzLg0KDQo8YnI+PGJyPg0KDQojIyMgM2IuIFNjYXR0ZXJwbG90IG9mIGdhcHMgYnkgcGFycmlzaCANCg0KRnJvbSB0aGUgc2NhdHRlcnBsb3QgYmVsb3cgLS0gd2hlcmUgZWFjaCBwb2ludCBpcyBhIHBhcnJpc2ggLS0gd2Ugc2VlIHRoYXQgdGhlcmUgaXMgZ3JlYXQgdmFyaWF0aW9uIGJvdGggaW4gdGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQgKHNpemUgYW5kIHgtYXhpcykgYXMgd2VsbCBhcyBob3cgY29uY2VudHJhdGVkIHRoZXkgYXJlIGluIGEgZ2l2ZW4gcGFycmlzaCAoeS1heGlzLCBwb3ZlcnR5IGluY2lkZW5jZSk7IGJvdGggdGhlc2UgZmFjdG9ycyB3ZWlnaCBoZWF2aWx5IGluIHByb2dyYW1taW5nIHN0cmF0ZWdpZXMgYXMgd2VsbCBhcyBpbiB0aGUgZWFzZSBvZiBiZW5lZmljaWFyeSBzZWxlY3Rpb24uICANCg0KVGhlIGdyZWF0ZXN0IG51bWJlcnMgb2Ygbm90IHJlYWNoZWQgYXJlIGZvdW5kIGluIHBhcnJpc2hlcyBiZXR3ZWVuIHRoZSByYW5nZXMgb2YgX3Bvb3IgcGVyc29uczpfIDEwLDAwMC0xMDAsMDAwIGFuZCBfcG92ZXJ0eSBpbmNpZGVuY2U6XyAwLjI1LTAuNTAgKG1hcmtlZCBieSB0aGUgeWVsbG93IGJveCk7IGhvd2V2ZXIsIHRoZXNlIHBhcnJpc2hlcyBhbHNvIGhhdmUgYSBtdWNoIGhpZ2hlciB0aGFuIGF2ZXJhZ2UgbnVtYmVyIG9mIG9yZ2FuaXNhdGlvbnMgcHJlc2VudCAobW9yZSByZWQpLiBUaGlzIG1lYW5zIHRoYXQgb3BlcmF0aW9uYWwgYmFycmllcnMgYXJlIG11Y2ggbG93ZXIgaW4gYWNjZXNzaW5nIHRoZXNlIHBvcHVsYXRpb25zIHRoYW4gdGhlIHBhcnJpc2hlcyBpbiBsaWdodCBibHVlIGZvdW5kIGluIHRoZSBtaWRkbGUgb2YgdGhlIHBsb3QuDQoNCmBgYHtyIHBhcnJwbG90LVBMT1RMWSwgZmlnLmhlaWdodD02fQ0KDQpwYXJycGxvdCA8LSBwYXJyMCAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKHBvYl9wb2JyZSwgbm90X3JlYWNoZWQsIG9yZ19jb3VudCksIH4ocm91bmQoLikpKSAlPiUgDQogIG11dGF0ZShwZXJjZW50X3BvYnJlID0gcm91bmQocGVyY2VudF9wb2JyZSwgZGlnaXRzID0gMikpJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBub3RfcmVhY2hlZCwgeSA9IHBlcmNlbnRfcG9icmUsIA0KICAgICAgICAgICAgIGNvbG91ciA9IG9yZ19jb3VudCwgDQogICAgICAgICAgICAgdGV4dCA9IHBhc3RlMChwYXJyb3F1aWEsIiwiLCAiXG4iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bmljaXBpbywgIiwiLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0YWRvKSkpICsNCiAgIGdlb21fcmVjdChhZXMoeG1pbiA9IDEwMDAwLCB4bWF4ID0gMTAwMDAwLCB5bWluID0gMC4yNSwgeW1heCA9IDAuNTApLA0KICAgICAgICAgICAgZmlsbCA9ICJ0cmFuc3BhcmVudCIsIGNvbG91ciA9ICJnb2xkIiwgc2l6ZSA9IDAuMikgKw0KICBnZW9tX2ppdHRlcihhZXMoc2l6ZSA9IG5vdF9yZWFjaGVkKSwgYWxwaGEgPSAwLjc1KSArDQogIHNjYWxlX2NvbG91cl9ncmFkaWVudG4oDQogICAgY29sb3VycyA9IGMoImNvcm5mbG93ZXJibHVlIiwgInRvbWF0byIsICJmaXJlYnJpY2siKSkgKw0KICBzY2FsZV94X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiLCBsYWJlbHMgPSBjb21tYSkgKyANCiAgc2NhbGVfc2l6ZV9jb250aW51b3VzKHJhbmdlID0gYygwLjMsIDUpKSArDQogIHhsYWIoIk5vdCBjb3ZlcmVkIHBvb3IiKSArIHlsYWIoIlBvdmVydHkgaW5jaWRlbmNlIikgKw0KICBsYWJzKGNvbG91ciA9ICJOdW1iZXIgb2YgXG5vcmdhbmlzYXRpb25zIiwgDQogICAgICAgdGl0bGUgPSAiU2NhdHRlcnBsb3Qgb2YgcGFycmlzaGVzIGJ5IHBvb3IgcGVyc29ucyBub3QgY292ZXJlZCBhbmQgcG92ZXJ0eSBpbmNpZGVuY2UiKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA4LjUpKSANCiAgDQoNCmdncGxvdGx5KHBhcnJwbG90LCB0b29sdGlwID0gYygieSIsICJ4IiwgInNpemUiLCAidGV4dCIsICJjb2xvdXIiKSkgJT4lIA0KICAgICAgICAgICBsYXlvdXQoc2hvd2xlZ2VuZCA9IFRSVUUsIGxlZ2VuZCA9IGxpc3QoZm9udCA9IGxpc3Qoc2l6ZSA9IDcpKSkgJT4lDQogICAgICAgICAgIGNvbmZpZyhkaXNwbGF5TW9kZUJhciA9IEZBTFNFKSAlPiUgDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgNCiAgICAiU2NhdHRlcnBsb3Qgb2YgcGFycmlzaGVzIGJ5IG51bWJlciBwb29yIHBlcnNvbnMgbm90IHJlYWNoZWQgYW5kIHBvdmVydHkgaW5jaWRlbmNlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8c3VwPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2l6ZTogbnVtYmVyIG9mIHBvb3IgcGVyc29ucyBub3QgcmVhY2hlZDsgY29sb3VyOiBudW1iZXIgb2Ygb3JnYW5pc2F0aW9ucyBwcmVzZW50OyBkcmFnIGFuZCBjbGljayB0byBzZWxlY3QgYW5kIHpvb20iLCI8L3N1cD4iKSkpDQoNCmBgYA0KDQpGb3IgYWdlbmNpZXMgdHJ1bHkgdW5hYmxlIHRvIGV4cGFuZCBvdXRzaWRlIHRoZWlyIGN1cnJlbnQgZm9vdHByaW50cywgdGhlcmUgYXJlIHN0aWxsIG1hbnkgYmVuZWZpY2lhcmllcyB3aG8gYXJlIG5vdCBjb3ZlcmVkIG9yIC0tIGFzIHdlIHdpbGwgZGlzY3VzcyBpbiB0aGUgbmV4dCBjaGFwdGVyIC0tIGhhdmUgb25seSBiZWVuIHJlYWNoZWQgd2l0aCB0aGUgaW50ZXJ2ZW50aW9ucyBvZiBvbmUgc2VjdG9yLg0KDQo8YnI+PGJyPjxicj48YnI+ICANCg0KIyMgNC4gTXVsdGktc2VjdG9yIHByb2dyYW1taW5nDQoNCkh1bWFuaXRhcmlhbiBlbWVyZ2VuY2llcyBhcmUgbXVsdGlkaW1lbnNpb25hbCBhbmQgbmVlZHMgYWZmZWN0ZWQgcGVyc29ucyBhcmUgbm90IGRlbGluZWF0ZWQgYnkgY2x1c3Rlci4gUGhlbm9tZW5hIHN1Y2ggYXMgZGlzcGxhY2VtZW50IG9yIGZvb2QgaW5zZWN1cml0eSByZXN1bHQgZnJvbSB0aGUgY29tcGxleCBpbnRlcnBsYXkgYmV0d2VlbiBudW1lcm91cyB1bmRlcmx5aW5nIGZhY3RvcnMgYW5kIHRoZSBzaG9ja3MgYW5kIHN0cmVzc2VzIG9mIHRoZSBoYXphcmQuIE11bHRpLXNlY3RvciBvciBpbnRlZ3JhdGVkIHByb2dyYW1taW5nLCBjb25zaXN0cyBvZiBpbXBsZW1lbnRpbmcgbGF5ZXJzIG9mIGluZGl2aWR1YWwsIGhvdXNlaG9sZCBhbmQgY29tbXVuaXR5LWxldmVsIGludGVydmVudGlvbnMgdG8gY29tcHJlaGVuc2l2ZWx5IG1lZXQgdGhlIG5lZWRzIG9mIGEgdGFyZ2V0IHBvcHVsYXRpb24uIEl0IGlzIG9mdGVuIGhlbGQgdXAgYXMgYSBrZXkgbWFya2VyIG9mIHByb2dyYW1tZSBxdWFsaXR5IGluIHN0cmF0ZWd5IGRvY3VtZW50cyBhbmQgaHVtYW5pdGFyaWFuIHN0YW5kYXJkcywgYnV0IHJhcmVseSBhY2hpZXZlZCBpbiBwcmFjdGljZS4gDQoNCg0KIyMjIDRhLiBTdW1tYXJ5IHRhYmxlIG9mIG11bHRpLXNlY3RvciBjb3ZlcmFnZSANCg0KSG93ZXZlciwganVzdCBiZWNhdXNlIHR3byBDbHVzdGVycyBvcGVyYXRlIGluIHRoZSBzYW1lIGFyZWEgZG8gbm90IG1lYW4gdGhlaXIgYmVuZWZpY2lhcmllcyBjb2luY2lkZS4gQXMgYW4gZXN0aW1hdGUsIHdlIGNhbGN1bGF0ZWQgYSB0aGVvcmV0aWNhbCBtYXhpbXVtIG51bWJlciBvZiBtdWx0aS1zZWN0b3IgYmVuZWZpY2lhcmllcywgZXhwcmVzc2VkIGJlbG93IGFzIGBtdWx0aV9zZWN0b3JfYmVuYCAoZXhwbGFuYXRpb24gYW5kIGNhbGN1bGF0aW9uIGluIHRoZSBjb2RlIGNodW5rIGJlbG93KS4gQnV0LCB0byBlbGFib3JhdGUgd2l0aCBhbiBleGFtcGxlLCB3ZSBtYWtlIHRoZSBjaGFyaXRhYmxlIGFzc3VtcHRpb24gdGhhdCB0aGF0IGZlbWFsZXMgdW5kZXIgMTggd2hvIGFyZSBiZW5lZmljaWFyaWVzIG9mIE51dHJpdGlvbiBhbmQgZmVtYWxlcyB1bmRlciAxOCBpbiB0aGF0IHNhbWUgcGFycmlzaCB3aG8gYXJlIGJlbmVmaWNpYXJpZXMgb2YgUHJvdGVjdGlvbiBhcmUgdGhlIHNhbWUgcGVvcGxlIC0tIHdlIHRoZW4gc3VtIHRoZSB2YXJpb3VzIGFnZSBhbmQgc2V4IGRpc2FnZ3JlZ2F0aW9uIHN1YnRvdGFscyBieSBwYXJyaXNoIHRvIGRldGVybWluZSB0aGUgbWF4aW11bSBudW1iZXIgb2YgcGVyc29ucyB3aG8gY291bGQgaGF2ZSByZWNlaXZlZCBtdWx0aS1zZWN0b3Igc3VwcG9ydC4gVGhlIGFjdHVhbCBudW1iZXIgb2YgbXVsdGktc2VjdG9yIGJlbmVmaWNpYXJpZXMgaXMgbGlrZWx5IG11Y2ggbG93ZXIuIA0KDQpUaGlzIGRhdGEgaGFzIGJlZW4gc3VtbWFyaXNlZCBiZWxvdywgYWNjb3JkaW5nIHRvIHRoZSBudW1iZXIgb2Ygc2VjdG9ycyBwcmVzZW50IGluIGEgcGFycmlzaDogDQoNCmBgYHtyIG11bHRpLXNlY3Rvci1iZW4tVEFCTEUtYW5kLVJFRn0NCiMgTm90ZXMgb24gY2FsY3VsYXRpb24gZm9yIG11bHRpLXNlY3RvciBiZW5lZmljaWFyaWVzLiANCg0KIyBCYXNpY2FsbHksIGJlbmVmaWNpYXJpZXMgcGVyIHBhcnJpc2ggYXJlIGFnZ3JlZ2F0ZWQgaW50byANCiMgc2VjdG9yIHN1YnRvdGFscyBhbmQgYSBiZW5lZmljaWFyeSBmcmVxdWVuY3kgdG90YWwuICANCiMgVGhlIG1heGltdW0gdmFsdWUgb2YgdGhlIHNlY3RvciBzdWJ0b3RhbHMgaXMgY29tcGFyZWQgYWdhaW5zdCB0aGUgYmVuZWZpY2lhcnkgZnJlcXVlbmN5IHRvdGFsLCANCiMgaWYgdGhlIG1heGltdW0gdmFsdWUgaXMgZXF1YWwgdG8gdGhlIGZyZXF1ZW5jeSB0b3RhbCwgdGhlbiB0aGVyZSBpcyBvbmx5IG9uZSBzZWN0b3IsDQojIGlmIHRoZSBtYXhpbXVtIHZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgZnJlcXVlbmN5IHRvdGFsLCANCiMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgdHdvIChvciB0aGUgc3VtIG9mIGFsbCBvdGhlciBzZWN0b3Igc3VidG90YWxzKSANCiMgYmVjb21lcyB0aGUgdGhlb3JldGljYWwgbWF4aW11bSBudW1iZXIgb2YgbXVsdGlzZWN0b3IgYmVuZWZpY2lhcmllcy4NCg0KIyBQZXJmb3JtaW5nIHRoaXMgY2FsY3VsYXRpb24gYXQgYWRtaW4gbGV2ZWwgMyBtYWtlcyBzZW5zZSBhcyBhIHBhcnJpc2ggaXMgc21hbGwgZW5vdWdoDQojIHRoYXQgdGhlcmUgaXQgaXMgcmVhbGlzdGljIHRvIGFzc3VtZSB0aGF0IG92ZXJsYXBzIGluIGJlbmVmaWNpYXJpZXMgYmV0d2VlbiBzZWN0b3JzIGV4aXN0IC0tDQojIGkuZS4gdGhhdCBmZW1hbGVzIHVuZGVyIDE4IGluIGEgcGFycmlzaCB3aG8gYXJlIGJlbmVmaWNpYXJpZXMgb2YgbnV0cml0aW9uIA0KIyBhbmQgZmVtYWxlcyB1bmRlciAxOCBpbiB0aGF0IHNhbWUgcGFycmlzaCB3aG8gYXJlIGJlbmVmaWNpYXJpZXMgb2YgV0FTSCBhcmUgdGhlIHNhbWUgcGVvcGxlLiANCg0KIyBBbHRob3VnaCBJIGRvIGZlZWwgdGhpcyBjYWxjdWxhdGlvbiB0byBiZSB2ZXJ5IGNoYXJpdGFibGUgDQojIFdlIGNhbid0IHJlYWxseSBkbyBtdWNoIG1vcmUgdW5sZXNzIHRoZXJlIGlzIGEgYmVuZWZpY2lhcnkgcmVnaXN0ZXIuIA0KIyBUaGUgcmVhbCBudW1iZXIgb2YgbXVsdGlzZWN0b3IgYmVuZWZpY2lhcmllcyBpcyBsaWtlbHkgTVVDSCBMT1dFUiANCiMgYnV0IHRoYXQgY2FuIG9ubHkgYmUgdmVyaWZpZWQgdGhyb3VnaCBzYW1wbGVkIGxhcmdlLXNjYWxlIHBvc3QtZGlzdHJpYnV0aW9uL3Bvc3QtaW50ZXJ2ZW50aW9uIG1vbml0b3JpbmcsDQojIHdoaWNoIGlzIGV4dHJlbWVseSByYXJlLiANCiMgSSBhY3R1YWxseSBjb3VsZCBoYXZlIHJhaXNlZCB0aGlzIHdpdGggdGhlIHRoaXJkLXBhcnR5IG1vbml0b3JzIHRoYXQgVU5JQ0VGLCANCiMgc28gaXQncyBhbiBvdmVyc2lnaHQgb24gbXkgcGFydCBhcyB3ZWxsLg0KDQojIFRoZXNlIG9wZXJhdGlvbnMgd2VyZSBhbHJlYWR5IHBlcmZvcm1lZCBpbiAiQSBub3RlIG9uIHRoZSBkYXRhIiBhbmQgYXJlIHBhcnQgb2YgYHBhcnJgIGFuZCBhcmUNCiMgdGhlcmVmb3JlLCBjb21tZW50ZWQgb3V0IGhlcmUgDQoNCiMgYWN0X2JlbiAlPiUNCiMgICAgICAgZ3JvdXBfYnkocGNvZGUzLCBkZXNhZ3JlZ2FjaW9uLCBzZWN0b3IpICU+JSANCiMgICAgICAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IHNlY3RvciwgdmFsdWVzX2Zyb20gPSBiZW5lZmljaWFyaW9zKSAlPiUgDQojICAgICAgIHJlbmFtZShudXRyaWNpb25fYmVuID0gTnV0cmljaW9uLCBwcm90ZWNjaW9uX2JlbiA9IFByb3RlY2Npb24sIHdhc2hfYmVuID0gV0FTSCwgDQojICAgICAgICAgICAgICBzYWx1ZF9iZW4gPSBTYWx1ZCwgZWR1Y2FjaW9uX2JlbiA9IEVkdWNhY2lvbiwgc2FfYmVuID0gU2VndXJpZGFkX0FsaW1lbnRhcmlhKSAlPiUgDQojICAgICAgIHJlcGxhY2VfbmEobGlzdChudXRyaWNpb25fYmVuID0gMCwgZWR1Y2FjaW9uX2JlbiA9IDAsIHdhc2hfYmVuID0gMCwgc2FsdWRfYmVuID0gMCwNCiMgICAgICAgICAgICAgICAgICAgICAgIHNhX2JlbiA9IDAsIHByb3RlY2Npb25fYmVuID0gMCkpICU+JQ0KIyAgICAgICBzdW1tYXJpc2UoYWNyb3NzKGMobnV0cmljaW9uX2JlbiwgcHJvdGVjY2lvbl9iZW4sIHdhc2hfYmVuLCANCiMgICAgICAgICAgICAgICAgICAgICAgICAgIGVkdWNhY2lvbl9iZW4sIHNhbHVkX2Jlbiwgc2FfYmVuKSwgc3VtKSkgJT4lDQojICAgICAgIG11dGF0ZShiZW5fZnJlcSAgICA9IG51dHJpY2lvbl9iZW4gKyBwcm90ZWNjaW9uX2JlbiArIHdhc2hfYmVuICsgc2FsdWRfYmVuICsgZWR1Y2FjaW9uX2JlbiArIHNhX2JlbiwNCiMgICAgICAgICAgICAgIHNlY19iZW5fbWF4ID0gcG1heChudXRyaWNpb25fYmVuLCBwcm90ZWNjaW9uX2Jlbiwgd2FzaF9iZW4sIHNhbHVkX2JlbiwgZWR1Y2FjaW9uX2Jlbiwgc2FfYmVuKSwNCiMgICAgICAgICAgICAgIG1zX2Jlbl9tYXggID0gaWZlbHNlKHNlY19iZW5fbWF4ID49IGJlbl9mcmVxIC0gc2VjX2Jlbl9tYXgsIA0KIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWNfYmVuX21heCkpICU+JQ0KIyAgICAgICAgICAgZ3JvdXBfYnkocGNvZGUzKSAlPiUgDQojICAgICAgICAgICBzdW1tYXJpc2UoYWNyb3NzKGMobnV0cmljaW9uX2JlbiwgcHJvdGVjY2lvbl9iZW4sIHdhc2hfYmVuLCBzYWx1ZF9iZW4sIGVkdWNhY2lvbl9iZW4sDQojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FsdWRfYmVuLCBzYV9iZW4sIGJlbl9mcmVxLCBzZWNfYmVuX21heCwgbXNfYmVuX21heCksIHN1bSkpICU+JSANCiMgICAgICAgICAgIG11dGF0ZShzZWN0b3JfY291bnQgPSByb3dTdW1zKHNlbGVjdCguLCBlbmRzX3dpdGgoIl9iZW4iKSkgIT0gMCkpDQoNCiMgdXNpbmcgcGFyciBtZWFucyB0aGF0IGFsbCBwYXJyaXNoZXMgYXJlIGluY2x1ZGVkLCBidXQgdGhleSBhcmUgbmVlZGVkIGZvciB0aGUgcGVyY2VudGFnZSBjYWxjdWxhdGlvbnMuIA0KDQpwYXJyICU+JQ0KICBmaWx0ZXIoYmVuX2ZyZXEgIT0gMCkgJT4lIA0KICBncm91cF9ieShzZWN0b3JfY291bnQpICU+JSANCiAgc3VtbWFyaXNlKHBhcnJpc2hlcyA9IG4oKSwNCiAgICAgICAgICAgIG11bHRpX3NlY3Rvcl9iZW4gPSBzdW0obXNfYmVuX21heCksDQogICAgICAgICAgICBvbmVfc2VjdG9yX2JlbiA9IHN1bShiZW5fZnJlcSkgLSBzdW0obXNfYmVuX21heCksDQogICAgICAgICAgICBgbXVsdGlzZWN0b3JfJWAgPSByb3VuZChzdW0obXNfYmVuX21heCkgLyBzdW0oYmVuX2ZyZXEpICogMTAwLCBkaWdpdHMgPSAyKSkgJT4lIA0KICBwYW5kZXIoc3R5bGUgPSAicm1hcmtkb3duIiwgY2FwdGlvbiA9ICJTdW1tYXJ5IG9mIG11bHRpc2VjdG9yIGNvdmVyYWdlIikNCg0KYGBgDQoNCg0KYGBge3IgUkVGLWp1c3QtZm9yLXZhY2NpbmF0aW9uLXBlcmNlbnRhZ2UsIGluY2x1ZGU9RkFMU0V9DQpwZXJjZW50X3dfdmFjIDwtIHZlbjEgJT4lIA0KICBwaXZvdF9sb25nZXIoZl8wXzE4Om1fMThwbHVzLCBuYW1lc190byA9ICJkZXNhZ3JlZ2FjaW9uIiwgdmFsdWVzX3RvID0gImJlbmVmaWNpYXJpb3MiKSAlPiUgDQogI2ZpbHRlcihjYXRlZ29yaWEgIT0gIlZBQ1VOQUNJT04iKSAlPiUgIyBWYWNjaW5hdGlvbiBhY3Rpdml0aWVzIGZpbHRlcmVkIG91dA0KICBmaWx0ZXIoYmVuZWZpY2lhcmlvcyAhPSAwKSAlPiUgDQogIGdyb3VwX2J5KHBjb2RlMywgdWJpY2FjaW9uLCBkZXNhZ3JlZ2FjaW9uLCBhY3RpdmlkYWQpICU+JSANCiAgc2xpY2Uod2hpY2gubWF4KGJlbmVmaWNpYXJpb3MpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgDQogIG11dGF0ZShzZWN0b3IgPSBpZmVsc2Uoc3RyX2RldGVjdChzZWN0b3IsICJQcm90ZWNjaW9uX0dCVnxQcm90ZWNjaW9uX0dlbmVyYWx8UHJvdGVjY2lvbl9OTkEiKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIlByb3RlY2Npb24iLCBzZWN0b3IpKSAlPiUgDQogIGdyb3VwX2J5KHBjb2RlMywgZGVzYWdyZWdhY2lvbiwgc2VjdG9yKSAlPiUgDQogICAgICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gc2VjdG9yLCB2YWx1ZXNfZnJvbSA9IGJlbmVmaWNpYXJpb3MpICU+JSANCiAgICAgIHJlbmFtZShudXRyaWNpb25fYmVuID0gTnV0cmljaW9uLCBwcm90ZWNjaW9uX2JlbiA9IFByb3RlY2Npb24sIHdhc2hfYmVuID0gV0FTSCwgDQogICAgICAgICAgICAgc2FsdWRfYmVuID0gU2FsdWQsIGVkdWNhY2lvbl9iZW4gPSBFZHVjYWNpb24sIHNhX2JlbiA9IFNlZ3VyaWRhZF9BbGltZW50YXJpYSkgJT4lIA0KICAgICAgcmVwbGFjZV9uYShsaXN0KG51dHJpY2lvbl9iZW4gPSAwLCBlZHVjYWNpb25fYmVuID0gMCwgd2FzaF9iZW4gPSAwLCBzYWx1ZF9iZW4gPSAwLA0KICAgICAgICAgICAgICAgICAgICAgIHNhX2JlbiA9IDAsIHByb3RlY2Npb25fYmVuID0gMCkpICU+JQ0KICAgICAgc3VtbWFyaXNlKGFjcm9zcyhjKG51dHJpY2lvbl9iZW4sIHByb3RlY2Npb25fYmVuLCB3YXNoX2JlbiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgZWR1Y2FjaW9uX2Jlbiwgc2FsdWRfYmVuLCBzYV9iZW4pLCBzdW0pKSAlPiUNCiAgICAgIG11dGF0ZShiZW5fZnJlcSAgICA9IG51dHJpY2lvbl9iZW4gKyBwcm90ZWNjaW9uX2JlbiArIHdhc2hfYmVuICsgc2FsdWRfYmVuICsgZWR1Y2FjaW9uX2JlbiArIHNhX2JlbiwNCiAgICAgICAgICAgICBzZWNfYmVuX21heCA9IHBtYXgobnV0cmljaW9uX2JlbiwgcHJvdGVjY2lvbl9iZW4sIHdhc2hfYmVuLCBzYWx1ZF9iZW4sIGVkdWNhY2lvbl9iZW4sIHNhX2JlbiksDQogICAgICAgICAgICAgbXNfYmVuX21heCAgPSBpZmVsc2Uoc2VjX2Jlbl9tYXggPj0gYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmVuX2ZyZXEgLSBzZWNfYmVuX21heCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VjX2Jlbl9tYXgpKSAlPiUNCiAgICAgICAgICBncm91cF9ieShwY29kZTMpICU+JSANCiAgICAgICAgICBzdW1tYXJpc2UoYWNyb3NzKGMobnV0cmljaW9uX2JlbiwgcHJvdGVjY2lvbl9iZW4sIHdhc2hfYmVuLCBzYWx1ZF9iZW4sIGVkdWNhY2lvbl9iZW4sDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbHVkX2Jlbiwgc2FfYmVuLCBiZW5fZnJlcSwgc2VjX2Jlbl9tYXgsIG1zX2Jlbl9tYXgpLCBzdW0pKSAlPiUgDQogICAgICAgICAgbXV0YXRlKHNlY3Rvcl9jb3VudCA9IHJvd1N1bXMoc2VsZWN0KC4sIGVuZHNfd2l0aCgiX2JlbiIpKSAhPSAwKSkgJT4lIA0KICBzdW1tYXJpc2UobXNfcGVyY2VudF93X3ZhYyA9IHN1bShtc19iZW5fbWF4KSAvIHN1bShiZW5fZnJlcSkpDQoNCnJvdW5kKHBlcmNlbnRfd192YWMkbXNfcGVyY2VudF93X3ZhY1sxXSAqIDEwMCwgZGlnaXRzID0gMSkNCiAgDQpgYGANCg0KDQpPdmVyYWxsLCB0aGUgcmVzdWx0cyBhcmUgbm90IGVuY291cmFnaW5nIC0tIGEgbWF4aW11bSBvZiAqKmByIHJvdW5kKHN1bShwYXJyJG1zX2Jlbl9tYXgpIC8gc3VtKHBhcnIkYmVuX2ZyZXEpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYmVuZWZpY2lhcmllcyAob3V0c2lkZSBvZiB0aGUgdG9wIDExIHBhcnJpc2hlcykgY291bGQgcG90ZW50aWFsbHkgY292ZXJlZCBieSBtdWx0aS1zZWN0b3Igc3VwcG9ydC4gV2hlbiB2YWNjaW5hdGlvbnMgYXJlIGluY2x1ZGVkLCB0aGlzIHBlcmNlbnRhZ2UgZHJvcHMgdG8gKipgciByb3VuZChwZXJjZW50X3dfdmFjJG1zX3BlcmNlbnRfd192YWNbMV0gKiAxMDAsIGRpZ2l0cyA9IDEpYCUqKi4gQnV0LCBhcyBtZW50aW9uZWQsIHZhY2NpbmF0aW9ucyB3aWxsIGJlIGV4Y2x1ZGVkIGZyb20gdGhpcyBhbmFseXNpcyBhcyBnb3Zlcm5tZW50IHBhcnRuZXJzIHdlcmUgbm90IGFibGUgdG8gYWNjdXJhdGVseSBwcm92aWRlIHJlY29yZHMgYXQgdGhlIHBhcnJpc2ggbGV2ZWwsIG1hbnkgdGltZXMgZGVmYXVsdGluZyB0byBtdW5pY2lwYWwgb3Igc3RhdGUtbGV2ZWwgcmVwb3J0aW5nOyBhZGRpdGlvbmFsbHksIHRoZSBmb290cHJpbnQgZm9yIHZhY2NpbmF0aW9uIGFjdGl2aXRpZXMgaXMgZGV0ZXJtaW5lZCBieSBmZWRlcmFsIGdvdmVybm1lbnQgcHJpb3JpdGllcyAodGhhdCBtYXkgbm90IGFsaWduIHdpdGggdGhlIGh1bWFuaXRhcmlhbiBpbXBlcmF0aXZlKSwgd2hpY2ggVU5JQ0VGIGlzIGFsc28gdW5hYmxlIHRvIGluZmx1ZW5jZS4gDQoNCkFzIHRoZSBsZWFkZXIgb2YgdGhlIEVkdWNhdGlvbiwgTnV0cml0aW9uLCBXQVNIIGFuZCBDaGlsZCBQcm90ZWN0aW9uIENsdXN0ZXJzLCBVTklDRUYgc3VwcG9ydGVkIGFjdGl2aXRpZXMgdGhhdCByZWFjaGVkICoqYHIgcm91bmQoKGZpbHRlcihhY3RfYmVuLCBvcmdfbGlkZXIgPT0gIlVOSUNFRiIpICU+JSB7c3VtKC4kYmVuZWZpY2lhcmlvcyl9KSAvIHN1bShhY3RfYmVuJGJlbmVmaWNpYXJpb3MpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJpZXMuIE1lYW5pbmcgdGhhdCB0aGlzIHRoZSBsb3cgcGVyY2VudGFnZSBvZiBtdWx0aS1zZWN0b3Igc3VwcG9ydCBjb3VsZCBsYXJnZWx5IGJlIHJlc29sdmVkIGJ5IGJldHRlciBpbnRlcm5hbCBjb29yZGluYXRpb24gYW5kIGJldHRlciBwcm9ncmFtbWF0aWMgb3ZlcnNpZ2h0IHdpdGhpbiBVTklDRUYgLS0gdGhlc2UgaXNzdWVzIHdpbGwgYmUgZXZlbiBtb3JlIGFwcGFyZW50IGluIHNlY3Rpb25zIDRjIGFuZCA0ZC4gDQoNCjxicj48YnI+DQoNCiMjIyA0Yi4gUGFycmlzaC1sZXZlbCBnYXBzIGluIG11bHRpLXNlY3RvciBwcm9ncmFtbWluZw0KDQpBIHRvdGFsIG9mICoqYHIgcm91bmQoc3VtKHBhcnIwJGJlbl9mcmVxKSAtIHN1bShwYXJyMCRtc19iZW5fbWF4KSwgZGlnaXRzID0gMCkgJT4lIGZvcm1hdChiaWcubWFyayA9ICIsIilgKiogYmVuZWZpY2lhcmllcyByZWNlaXZlZCBzdXBwb3J0IGZyb20gb25seSBvbmUgc2VjdG9yIC0tIHRoaXMgaXMgKipgciByb3VuZCgoc3VtKHBhcnIkYmVuX2ZyZXEpIC0gc3VtKHBhcnIkbXNfYmVuX21heCkpIC8gc3VtKHBhcnIkYmVuX2ZyZXEpICogMTAwLCBkaWdpdHMgPSAxKWAlKiogb2YgYWxsIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzLiBQYXJyaXNoZXMgYmVsb3cgaGF2ZSBiZWVuIHBsb3R0ZWQgYWNjb3JkaW5nIHRvIHRoZWlyIG11bHRpLXNlY3RvciBjb3ZlcmFnZSBhbmQgdGhlaXIgdG90YWwgbnVtYmVyIG9mIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzOyBsYXJnZXIgc2l6ZXMgaW5kaWNhdGUgcGFycmlzaGVzIHdoZXJlIHRoZXJlIGFyZSBoaWdoZXIgbnVtYmVycyBvZiBiZW5lZmljaWFyaWVzIGJlbmVmaXR0aW5nIGZyb20gb25seSBvbmUgc2VjdG9yOiANCg0KYGBge3J9DQptc19zY2F0dGVyIDwtIHBhcnIwICU+JSANCiAgbXV0YXRlKG11bHRpX3NlY3Rvcl9wZXJjZW50ID0gcm91bmQobXNfYmVuX21heCAvIGJlbl9mcmVxICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgIG9uZV9zZWN0b3JfcGVyY2VudCA9IHJvdW5kKChiZW5fZnJlcSAtIG1zX2Jlbl9tYXgpIC8gYmVuX2ZyZXEgKiAxMDAsIGRpZ2l0cyA9IDEpLA0KICAgICAgICAgbXVsdGlfc2VjdG9yX2JlbiA9IHJvdW5kKG1zX2Jlbl9tYXgsIGRpZ2l0cyA9IDApLA0KICAgICAgICAgb25lX3NlY3Rvcl9iZW4gPSByb3VuZChiZW5fZnJlcSAtIG1zX2Jlbl9tYXgsIGRpZ2l0cyA9IDApLA0KICAgICAgICAgYmVuX2ZyZXEgPSByb3VuZChiZW5fZnJlcSwgZGlnaXRzID0gMCkpICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gYmVuX2ZyZXEsIA0KICAgICAgICAgICAgIHkgPSBtdWx0aV9zZWN0b3JfcGVyY2VudCwgDQogICAgICAgICAgICAgdGV4dCA9IHBhc3RlMChwYXJyb3F1aWEsIiwiLCAiXG4iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bmljaXBpbywgIiwiLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgZXN0YWRvLCAiLCIsICJcbiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAic2VjdG9yIGNvdW50OiAiLCBzZWN0b3JfY291bnQpLA0KICAgICAgICAgICAgIGNvbG91ciA9IGVzdGFkbykpICsNCiAgZ2VvbV9wb2ludChhZXMoc2l6ZSA9IG9uZV9zZWN0b3JfYmVuKSwgDQogICAgICAgICAgICAgYWxwaGEgPSAwLjgpICsNCiAgc2NhbGVfeF9jb250aW51b3VzKHRyYW5zID0gImxvZzEwIiwgbGFiZWxzID0gbGFiZWxfY29tbWEoYWNjdXJhY3kgPSAxKSkgKw0KICBzY2FsZV9zaXplX2NvbnRpbnVvdXMocmFuZ2UgPSBjKDAuMSwgNSkpICsNCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBjKHJlcCgiY29yYWwiLDI0KSkpICsNCiAgeGxhYigiQmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMiKSArIHlsYWIoIlBlcmNlbnRhZ2UgcmVjZWl2ZWQgbXVsdGktc2VjdG9yIHN1cHBvcnQiKSArDQogIGxhYnModGl0bGUgPSAiU2NhdHRlcnBsb3Qgb2YgcGFycmlzaGVzIGJ5IGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIGFuZCBtdWx0aS1zZWN0b3IgY292ZXJhZ2UiLCANCiAgICAgICBzaXplID0gIiIsIGNvbG91ciA9ICIiKSArDQogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDExKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOC41KSkgDQoNCmdncGxvdGx5KG1zX3NjYXR0ZXIsIHRvb2x0aXAgPSBjKCJ4IiwgInkiLCAic2l6ZSIsICJ0ZXh0IikpICU+JSANCiAgbGF5b3V0KGxlZ2VuZCA9IGxpc3QoZm9udCA9IGxpc3Qoc2l6ZSA9IDYpKSkgJT4lIA0KICBjb25maWcoZGlzcGxheU1vZGVCYXIgPSBGQUxTRSkgJT4lIA0KICBsYXlvdXQodGl0bGUgPSBsaXN0KHRleHQgPSBwYXN0ZTAoDQogICAgIlNjYXR0ZXJwbG90IG9mIHBhcnJpc2hlcyBieSBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyBhbmQgbXVsdGktc2VjdG9yIGNvdmVyYWdlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8YnI+IiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICI8c3VwPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAic2l6ZTogbnVtYmVyIG9mIGJlbmVmaWNpYXJpZXMgc3VwcG9ydGVkIGJ5IG9ubHkgb25lIHNlY3RvcjsgZG91YmxlLWNsaWNrIHN0YXRlIHRvIHRvZ2dsZSB2aWV3OyBtb3VzZSBvdmVyIGZvciBkZXRhaWxzIiwiPC9zdXA+IikpKQ0KDQpgYGANCg0KV2Ugbm90ZSBvbmx5IGEgdmVyeSBsb29zZSByZWxhdGlvbnNoaXAgKHItc3F1YXJlZCA9IGByIGNvcihwYXJyMCRtdWx0aXNlY3Rvcl9wZXJjZW50LCBwYXJyMCRiZW5fZnJlcSwgdXNlID0gImNvbXBsZXRlLm9icyIpXjIgJT4lIHJvdW5kKGRpZ2l0cyA9IDMpYCkgYmV0d2VlbiB0aGUgbnVtYmVyIG9mIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIGFuZCB0aGUgcGVyY2VudGFnZSBvZiB0aG9zZSBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyByZWFjaGVkIGJ5IGludGVydmVudGlvbnMgZnJvbSBtdWx0aXBsZSBzZWN0b3JzLiBUaGVyZSBpcyBsaXR0bGUgZWxzZSBpdCBpcyBjb3JyZWxhdGVkIHdpdGggYW5kLCBhcyBjYW4gYmUgc2VlbiBhYm92ZSwgdGhlcmUgaXMgbm8gZGlzY2VybmlibGUgcGF0dGVybiB0byBtdWx0aXNlY3RvciBjb3ZlcmFnZS4gVGhlcmUgYXJlIHRoZSAqKmByIHBhcnIwICU+JSBmaWx0ZXIoYmVuX2ZyZXEgIT0gMCAmIG1zX2Jlbl9tYXggPT0gMCkgJT4lIG5yb3coKWAqKiBwYXJyaXNoZXMgYXQgdGhlIGJvdHRvbSBvZiB0aGUgcGxvdCB3aXRoIG9ubHkgb25lIHNlY3RvciBwcmVzZW50IGluIGVhY2ggLS0gdGhpcyBpcyAqKmByIHJvdW5kKChwYXJyMCAlPiUgZmlsdGVyKGJlbl9mcmVxICE9IDAgJiBtc19iZW5fbWF4ID09IDApICU+JSBucm93KCkpIC8gKHBhcnIwICU+JSBmaWx0ZXIoYmVuX2ZyZXEgIT0gMCkgJT4lIG5yb3coKSkgKiAxMDAsIGRpZ2l0cyA9IDEpYCUqKiBvZiBhbGwgcGFycmlzaGVzIHdlIGFyZSByZXNwb25kaW5nIGluLiANCg0KYGBge3IgYXZnLXNlYy1zdGF0ZS1UQUJMRX0NCg0KcGFycjAgJT4lIA0KICBmaWx0ZXIoYmVuZWZpY2lhcmlvcyAhPSAwKSAlPiUgDQogIHNlbGVjdChlc3RhZG8sIHNlY3Rvcl9jb3VudCkgJT4lIA0KICBncm91cF9ieShlc3RhZG8pICU+JSANCiAgc3VtbWFyaXNlKGF2Z19zZWN0b3IgPSByb3VuZChtZWFuKHNlY3Rvcl9jb3VudCksIGRpZ2l0cyA9IDIpKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhhdmdfc2VjdG9yKSkgJT4lIA0KICBmaWx0ZXIoYXZnX3NlY3RvciA+IDIgfCBhdmdfc2VjdG9yIDwgMS4xNSkgJT4lIA0KICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gZXN0YWRvLCB2YWx1ZXNfZnJvbSA9IGF2Z19zZWN0b3IpICU+JSANCiAgbXV0YXRlKGB8YCA9IGMoInwiKSkgJT4lIHJlbG9jYXRlKGB8YCwgLmFmdGVyID0gWlVMSUEpICU+JSANCiAgcGFuZGVyKGNhcHRpb24gPSAiVG9wIDUgYW5kIGJvdHRvbSA1IHN0YXRlcywgYXZlcmFnZSBudW1iZXIgb2Ygc2VjdG9ycyBwZXIgcGFycmlzaCIsIG1pc3NpbmcgPSAiIikNCg0KYGBgDQoNCkhvd2V2ZXIsIHdlIGRvIG5vdGUgdGhhdCBpbiB0aGUgc3RhdGVzIHdoZXJlIFVOSUNFRiBoYXMgb2ZmaWNlcyAoQm9saXZhciwgVGFjaGlyYSwgWnVsaWEgYW5kIERpc3RyaXRvIENhcGl0YWwpLCB0aGVyZSBpcyBtdWNoIGhpZ2hlciBtdWx0aS1zZWN0b3IgY292ZXJhZ2UgdGhhbiBpbiBvdGhlciBzdGF0ZXMsIHBlcmhhcHMgaW5kaWNhdGluZyB0aGF0IGEgbW9yZSBkZWNlbnRyYWxpc2VkIGFwcHJvYWNoIHdoZXJlIGZpZWxkIG9mZmljZXMgaGF2ZSBncmVhdGVyIHNheSBpbiBwcmlvcml0aXNhdGlvbiBtaWdodCBsZWFkIHRvIG1vcmUgY29vcmRpbmF0aW9uIGluIG11bHRpLXNlY3RvciBwcm9ncmFtbWluZy4gVGhvdWdoLCB0aGF0IHRoaXMgZ3JlYXRlciBtdWx0aS1zZWN0b3IgY292ZXJhZ2UgaGFzIG5vdCBleHBhbmRlZCBvdXRzaWRlIG9mIHRoZXNlIHN0YXRlcyB0byB0aGUgb3RoZXIgYXJlYXMgdW5kZXIgdGhlaXIgcHVydmlldyBpcyBpbmRpY2F0aXZlIG9mIHRoZSBsZXZlbCBvZiBwbGFubmluZyBhbmQgY29vcmRpbmF0aW9uIGNhcGFjaXR5IGZpZWxkIG9mZmljZXMgYXJlIGNhcGFibGUgb2YuIA0KDQo8YnI+PGJyPg0KDQojIyMgNGMuIENsdXN0ZXIgY29tYmluYXRpb25zDQoNClRoaXMgc2VjdGlvbiB3aWxsIGV4YW1pbmUgdGhlIHBhcnJpc2hlcyB0aGF0IGhhdmUgbXVsdGktc2VjdG9yIGNvdmVyYWdlIGFuZCB0aGUgdHlwZXMgb2YgaW50ZXItY2x1c3RlciBjb21iaW5hdGlvbnMgdGhhdCBjYW4gYmUgZm91bmQgaW4gdGhlbS4gTGV0IHVzIGJlZ2luIHdpdGggYW4gb3ZlcnZpZXcgb2YgdGhlIGdlb2dyYXBoaWMgcmVhY2ggb2YgZWFjaCBjbHVzdGVyIC0tIHdlIHVzZSBmcmVxdWVuY2llcyBoZXJlLCBhcyBlYWNoIGluZGl2aWR1YWwgbWlnaHQgaGF2ZSBiZW5lZml0dGVkIGZyb20gbXVsdGlwbGUgY29tYmluYXRpb25zIG9mIGNsdXN0ZXJzOiANCg0KYGBge3IgY2x1c3QtVEFCTEV9DQpwYXJyICU+JSANCiAgc2VsZWN0KHBjb2RlMywgZWR1Y2FjaW9uX2JlbiwgbnV0cmljaW9uX2Jlbiwgc2FsdWRfYmVuLCB3YXNoX2JlbiwgcHJvdGVjY2lvbl9iZW4pICU+JQ0KICByZW5hbWUoRWR1Y2FjaW9uID0gZWR1Y2FjaW9uX2JlbiwgTnV0cmljaW9uID0gbnV0cmljaW9uX2JlbiwgU2FsdWQgPSBzYWx1ZF9iZW4sDQogICAgICAgICBXQVNIID0gd2FzaF9iZW4sIFByb3RlY2Npb24gPSBwcm90ZWNjaW9uX2JlbikgJT4lIA0KICBwaXZvdF9sb25nZXIoY29scyA9IDI6NiwgbmFtZXNfdG8gPSAiY2x1c3RlciIsIHZhbHVlc190byA9ICJiZW5lZmljaWFyeV9mcmVxdWVuY2llcyIpICU+JSANCiAgZmlsdGVyKGJlbmVmaWNpYXJ5X2ZyZXF1ZW5jaWVzICE9IDApICU+JSANCiAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lIA0KICBzdW1tYXJpc2UocGFycmlzaGVzID0gbigpLA0KICAgICAgICAgICAgYmVuZWZpY2lhcnlfZnJlcXVlbmNpZXMgPSBzdW0oYmVuZWZpY2lhcnlfZnJlcXVlbmNpZXMpKSAlPiUgDQogIHBhbmRlcihjYXB0aW9uID0gIkNsdXN0ZXIgY292ZXJhZ2Ugc3VtbWFyeSwgZXhjbHVkaW5nIHZhY2NpbmF0aW9uIiwgYmlnLm1hcmsgPSAiLCIsIHN0eWxlID0gInJtYXJrZG93biIsIA0KICAgICAgICAganVzdGlmeSA9IGMoImxlZnQiLCAicmlnaHQiLCAicmlnaHQiKSkNCiAgDQpgYGANCg0KPGJyPiANCg0KTmV4dCwgd2Ugd2lsbCBzdW1tYXJpc2UgdGhlIGludGVyLWNsdXN0ZXIgY29tYmluYXRpb25zIGFjY29yZGluZyB0bzogDQoNCiogKipjb21iaW5hdGlvbioqLCByZWZlcnJpbmcgdG8gdGhlIHZhcmlvdXMgY2x1c3Rlci13aXNlIHBhaXJzIHRoYXQgZXhpc3Q7IA0KKiAqKnBhcnJpc2hlcyoqLCBpbmRpY2F0aW5nIHRoZSBudW1iZXIgb2YgcGFycmlzaGVzIGVhY2ggY29tYmluYXRpb24gaXMgcHJlc2VudCBpbjsgDQoqICoqY2x1c3RlcjEqKiBhbmQgKipjbHVzdGVyMioqLCB3aGljaCBzaG93IHRoZSBudW1iZXIgb2YgYmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMgcmVhY2hlZCBieSBib3RoIGNsdXN0ZXJzIGluIGVhY2ggcGFpciwgaW4gdGhlIG9yZGVyIHRoYXQgdGhleSBhcHBlYXIgaW4gKipjb21iaW5hdGlvbioqLiANCiogKipwYWlyX3N1bSoqLCB3aGljaCBzaG93cyB0aGUgdG90YWwgbnVtYmVyIG9mIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIGluIHRoYXQgcGFpciBpLmUuIHRoZSBwYWlyX3N1bSBmb3IgZWR1X251dCB3b3VsZCBiZSB0aGUgc3VtIG9mIGVkdWNhdGlvbiBhbmQgbnV0cml0aW9uIGJlbmVmaWNpYXJpZXMuIA0KKiAqKiVtc19tYXgqKiwgd2hpY2ggc2hvd3MgdGhlIG1heGltdW0gcGVyY2VudGFnZSBvZiBtdWx0aXNlY3RvciBiZW5lZmljaWFyaWVzIG9mIGVhY2ggcGFpciBpLmUuIGlmIHRoZSBwYWlyIGVkdS1udXQgaGFzIDEwIGVkdWNhdGlvbiBiZW5lZmljaWFyaWVzIGFuZCAzMCBudXRyaXRpb24gYmVuZWZpY2lhcmllcywgdGhlIG1heGltdW0gbnVtYmVyIG9mIGJlbmVmaWNpYXJpZXMgd2hpY2ggcmVjZWl2ZWQgc3VwcG9ydCBmcm9tIGJvdGggc2VjdG9ycyBpcyAxMCwgcmVzdWx0aW5nIGluIGEgKiolbXNfbWF4Kiogb2YgMjUlLiBCdXQsIGFzIG1lbnRpb25lZCBpbiB0aGUgbm90ZXMgZm9yIHNlY3Rpb24gNGEsIHRoaXMgaXMganVzdCBhIHRoZW9yZXRpY2FsIG1heGltdW0gYW5kIHRoZSBhY3R1YWwgbGV2ZWwgb2YgY29pbmNpZGVuY2UgaXMgbGlrZWx5IG11Y2ggbG93ZXIuDQoNCmBgYHtyIGNsdXN0LWNvbS1SRUYtYW5kLVRBQkxFfQ0KIyBjcmVhdGlvbiBvZiByZWZlcmVuY2UgZGYgZm9yIHRoZSBjbHVzdGVyIGNvbWJpbmF0aW9ucyANCmNsdXN0X2NvbSA8LSBwYXJyICU+JSANCiAgZmlsdGVyKGJlbl9mcmVxICE9IDApICU+JSANCiAgc2VsZWN0KHBjb2RlMywgYmVuX2ZyZXEsIGVkdWNhY2lvbl9iZW4sIG51dHJpY2lvbl9iZW4sIHNhbHVkX2Jlbiwgd2FzaF9iZW4sIHByb3RlY2Npb25fYmVuKSAlPiUNCiAgIyBtdXRhdGUgYSBuZXcgY29sdW1uIGZvciBlYWNoIGNvbWJpbmF0aW9uIG9mIHNlY3RvcnMgLS0gaWYgZWR1IGlzIHRoZSBmaXJzdCBjbHVzdGVyIGluIHRoZSBjb21iaW5hdGlvbiwgDQogICMgb25seSBlZHVjYXRpb24gYmVuZWZpY2lhcmllcyB3aWxsIGJlIHVzZWQgdG8gZmlsbCB2YWx1ZXMgaW4gdGhlIGNvbHVtbiANCiAgbXV0YXRlKGVkdV9vbmx5ID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPT0gYmVuX2ZyZXEsIGVkdWNhY2lvbl9iZW4sIDApLA0KICAgICAgICAgZWR1X251dCA9IGlmZWxzZShlZHVjYWNpb25fYmVuID4gMCAmIG51dHJpY2lvbl9iZW4gPiAwLCBlZHVjYWNpb25fYmVuICsgbnV0cmljaW9uX2JlbiwgMCksDQogICAgICAgICBlZHVfc2FsID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPiAwICYgc2FsdWRfYmVuID4gMCwgZWR1Y2FjaW9uX2JlbiArIHNhbHVkX2JlbiwgMCksDQogICAgICAgICBlZHVfd2FzaCA9IGlmZWxzZShlZHVjYWNpb25fYmVuID4gMCAmIHdhc2hfYmVuID4gMCwgZWR1Y2FjaW9uX2JlbiArIHdhc2hfYmVuLCAwKSwNCiAgICAgICAgIGVkdV9wcm90ID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPiAwICYgcHJvdGVjY2lvbl9iZW4gPiAwLCBlZHVjYWNpb25fYmVuICsgcHJvdGVjY2lvbl9iZW4sIDApLA0KICAgICAgICAgbnV0X29ubHkgPSBpZmVsc2UobnV0cmljaW9uX2JlbiA9PSBiZW5fZnJlcSwgbnV0cmljaW9uX2JlbiwgMCksDQogICAgICAgICBudXRfc2FsID0gaWZlbHNlKG51dHJpY2lvbl9iZW4gPiAwICYgc2FsdWRfYmVuID4gMCwgbnV0cmljaW9uX2JlbiArIHNhbHVkX2JlbiwgMCksIA0KICAgICAgICAgbnV0X3dhc2ggPSBpZmVsc2UobnV0cmljaW9uX2JlbiA+IDAgJiB3YXNoX2JlbiA+IDAsIG51dHJpY2lvbl9iZW4gKyB3YXNoX2JlbiwgMCksIA0KICAgICAgICAgbnV0X3Byb3QgPSBpZmVsc2UobnV0cmljaW9uX2JlbiA+IDAgJiBwcm90ZWNjaW9uX2JlbiA+IDAsIG51dHJpY2lvbl9iZW4gKyBwcm90ZWNjaW9uX2JlbiwgMCksDQogICAgICAgICBzYWxfb25seSA9IGlmZWxzZShzYWx1ZF9iZW4gPT0gYmVuX2ZyZXEsIHNhbHVkX2JlbiwgMCksDQogICAgICAgICBzYWxfd2FzaCA9IGlmZWxzZShzYWx1ZF9iZW4gPiAwICYgd2FzaF9iZW4gPiAwLCBzYWx1ZF9iZW4gKyB3YXNoX2JlbiwgMCksDQogICAgICAgICBzYWxfcHJvdCA9IGlmZWxzZShwcm90ZWNjaW9uX2JlbiA+IDAgJiBzYWx1ZF9iZW4gPiAwLCBzYWx1ZF9iZW4gKyBwcm90ZWNjaW9uX2JlbiwgMCksDQogICAgICAgICB3YXNoX29ubHkgPSBpZmVsc2Uod2FzaF9iZW4gPT0gYmVuX2ZyZXEsIHdhc2hfYmVuLCAwKSwNCiAgICAgICAgIHByb3Rfd2FzaCA9IGlmZWxzZSh3YXNoX2JlbiA+IDAgJiBwcm90ZWNjaW9uX2JlbiA+IDAsIHdhc2hfYmVuICsgcHJvdGVjY2lvbl9iZW4sIDApLA0KICAgICAgICAgcHJvdF9vbmx5ID0gaWZlbHNlKHByb3RlY2Npb25fYmVuID09IGJlbl9mcmVxLCBwcm90ZWNjaW9uX2JlbiwgMCkpICU+JSANCiAgIyBwaXZvdF9sb25nZXIgdG8gdGhlIGNsdXN0X2ZyZXEgY29sdW1uIA0KICBwaXZvdF9sb25nZXIobmFtZXNfdG8gPSAiY29tYmluYXRpb24iLCB2YWx1ZXNfdG8gPSAicGFpcl9zdW0iLCA4OjIyKSAlPiUNCiAgZmlsdGVyKHBhaXJfc3VtICE9IDApICU+JSANCiAgZ3JvdXBfYnkocGNvZGUzLCBjb21iaW5hdGlvbikgJT4lIA0KICBzdW1tYXJpc2UoZWR1Y2FjaW9uX2JlbiA9IG1lYW4oZWR1Y2FjaW9uX2JlbiksDQogICAgICAgICAgICBudXRyaWNpb25fYmVuID0gbWVhbihudXRyaWNpb25fYmVuKSwNCiAgICAgICAgICAgIHNhbHVkX2JlbiA9IG1lYW4oc2FsdWRfYmVuKSwNCiAgICAgICAgICAgIHdhc2hfYmVuID0gbWVhbih3YXNoX2JlbiksDQogICAgICAgICAgICBwcm90ZWNjaW9uX2JlbiA9IG1lYW4ocHJvdGVjY2lvbl9iZW4pLA0KICAgICAgICAgICAgcGFpcl9zdW0gPSBzdW0ocGFpcl9zdW0pKSAlPiUgDQogICMgY2FsY3VsYXRpbmcgdGhlIHN1bSBvZiBmcmVxdWVuY2llcyBpbiBlYWNoIHBhaXINCiAgbXV0YXRlKGNsdXN0ZXIxID0gDQogICAgICAgICAgIGNhc2Vfd2hlbigNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X251dCIpIH4gZWR1Y2FjaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3NhbCIpIH4gZWR1Y2FjaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3dhc2giKSB+IGVkdWNhY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgImVkdV9wcm90IikgfiBlZHVjYWNpb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJudXRfc2FsIikgfiBudXRyaWNpb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJudXRfd2FzaCIpIH4gbnV0cmljaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAibnV0X3Byb3QiKSB+IG51dHJpY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInNhbF93YXNoIikgfiBzYWx1ZF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInNhbF9wcm90IikgfiBzYWx1ZF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInByb3Rfd2FzaCIpIH4gcHJvdGVjY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgImVkdV9vbmx5IikgfiBlZHVjYWNpb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJudXRfb25seSIpIH4gbnV0cmljaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAic2FsX29ubHkiKSB+IHNhbHVkX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAid2FzaF9vbmx5IikgfiB3YXNoX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAicHJvdF9vbmx5IikgfiBwcm90ZWNjaW9uX2JlbikpICU+JQ0KICBtdXRhdGUoY2x1c3RlcjIgPSANCiAgICAgICAgICAgY2FzZV93aGVuKA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJlZHVfbnV0IikgfiAgbnV0cmljaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3NhbCIpIH4gIHNhbHVkX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAiZWR1X3dhc2giKSB+IHdhc2hfYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJlZHVfcHJvdCIpIH4gcHJvdGVjY2lvbl9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgIm51dF9zYWwiKSB+ICBzYWx1ZF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgIm51dF93YXNoIikgfiB3YXNoX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAibnV0X3Byb3QiKSB+IHByb3RlY2Npb25fYmVuLA0KICAgICAgICAgICAgIHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJzYWxfd2FzaCIpIH4gd2FzaF9iZW4sDQogICAgICAgICAgICAgc3RyX2RldGVjdChjb21iaW5hdGlvbiwgInNhbF9wcm90IikgfiBwcm90ZWNjaW9uX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAicHJvdF93YXNoIikgfiB3YXNoX2JlbiwNCiAgICAgICAgICAgICBzdHJfZGV0ZWN0KGNvbWJpbmF0aW9uLCAib25seSQiKSB+IDApKSAlPiUNCiAgc2VsZWN0KHBjb2RlMywgY29tYmluYXRpb24sIGNsdXN0ZXIxLCBjbHVzdGVyMiwgcGFpcl9zdW0pDQoNCiMgcGFuZGVyIHRhYmxlIGNsdXN0ZXIgY29tYmluYXRpb25zIA0KcmJpbmQoDQpjbHVzdF9jb20gJT4lICANCiAgZmlsdGVyKHN0cl9kZXRlY3QoY29tYmluYXRpb24sICJvbmx5JCIpKSAlPiUgDQogIGdyb3VwX2J5KGNvbWJpbmF0aW9uKSAlPiUgDQogIHN1bW1hcmlzZShwYXJyaXNoZXMgPSBuKCksDQogICAgICAgICAgICBjbHVzdGVyMSA9IHJvdW5kKHN1bShjbHVzdGVyMSksIGRpZ2l0cyA9IDApLA0KICAgICAgICAgICAgY2x1c3RlcjIgPSByb3VuZChzdW0oY2x1c3RlcjIpLCBkaWdpdHMgPSAwKSwNCiAgICAgICAgICAgIHBhaXJfc3VtID0gcm91bmQoc3VtKHBhaXJfc3VtKSwgZGlnaXRzID0gMCkpICU+JQ0KICBtdXRhdGUoYCVtc19tYXhgID0gcG1pbihjbHVzdGVyMSwgY2x1c3RlcjIpIC8gcGFpcl9zdW0gKiAxMDAsDQogICAgICAgICBgJW1zX21heGAgPSByb3VuZChpZmVsc2UoaXMubmFuKGAlbXNfbWF4YCksIDAsIGAlbXNfbWF4YCksIGRpZ2l0cyA9IDEpKSAlPiUNCiAgYXJyYW5nZShkZXNjKHBhaXJfc3VtKSkgJT4lIA0KICByYmluZChOQSksDQoNCmNsdXN0X2NvbSAlPiUgIA0KICBmaWx0ZXIoIXN0cl9kZXRlY3QoY29tYmluYXRpb24sICJvbmx5JCIpKSAlPiUgDQogIGdyb3VwX2J5KGNvbWJpbmF0aW9uKSAlPiUgDQogIHN1bW1hcmlzZShwYXJyaXNoZXMgPSBuKCksDQogICAgICAgICAgICBjbHVzdGVyMSA9IHJvdW5kKHN1bShjbHVzdGVyMSksIGRpZ2l0cyA9IDApLA0KICAgICAgICAgICAgY2x1c3RlcjIgPSByb3VuZChzdW0oY2x1c3RlcjIpLCBkaWdpdHMgPSAwKSwNCiAgICAgICAgICAgIHBhaXJfc3VtID0gcm91bmQoc3VtKHBhaXJfc3VtKSwgZGlnaXRzID0gMCkpICU+JSANCiAgbXV0YXRlKGAlbXNfbWF4YCA9IHBtaW4oY2x1c3RlcjEsIGNsdXN0ZXIyKSAvIHBhaXJfc3VtICogMTAwLA0KICAgICAgICAgYCVtc19tYXhgID0gcm91bmQoaWZlbHNlKGlzLm5hbihgJW1zX21heGApLCAwLCBgJW1zX21heGApLCBkaWdpdHMgPSAxKSkgJT4lDQogIGFycmFuZ2UoZGVzYyhwYWlyX3N1bSkpDQoNCikgJT4lIA0KDQogIGthYmxlKGNhcHRpb24gPSAiQ2x1c3RlciBjb21iaW5hdGlvbnMsIHNvcnRlZCBieSBwYWlyX3N1bSIsIGZvcm1hdC5hcmdzID0gbGlzdChiaWcubWFyayA9ICIsIikpICU+JSANCiAga2FibGVfc3R5bGluZyhib290c3RyYXBfb3B0aW9ucyA9IGMoInN0cmlwZWQiLCAiaG92ZXIiLCAiY29uZGVuc2VkIikpDQoNCiAgDQpgYGANCg0KPGJyPg0KDQpUaGUgbW9zdCBjb21tb24gcGFpcmluZyB3YXMgYmV0d2VlbiB0aGUgKipFZHVjYXRpb24qKiBhbmQgKipOdXRyaXRpb24qKiBjbHVzdGVycyAtLSB0aGV5IGNvaW5jaWRlIGluIGByIGNsdXN0X2NvbSAlPiUgZmlsdGVyKGNvbWJpbmF0aW9uID09ICJlZHVfbnV0IikgJT4lIG5yb3coKWAgcGFycmlzaGVzLCBmb2xsb3dlZCBieSAqKk51dHJpdGlvbioqIGFuZCAqKlByb3RlY3Rpb24qKi4gSW4gdGhlIG5leHQgc2VjdGlvbiwgd2Ugd2lsbCBpbnZlc3RpZ2F0ZSB3aGV0aGVyIHRoZSBzdWJzdGFudGlhbCBvdmVybGFwIGJldHdlZW4gTnV0cml0aW9uIGFuZCBQcm90ZWN0aW9uIGF0IHRoZSBwYXJyaXNoIGxldmVsIHdhcyBjb29yZGluYXRlZCBvciAtLSBhcyBpbiB0aGUgY2FzZSB3aXRoIGl0cyBvdmVybGFwIHdpdGggRWR1Y2F0aW9uLCB3aGVyZSB0aGVyZSBhcmUgbm8gY29uY3JldGUgcHJvZ3JhbW1hdGljIGxpbmtzIC0tIGR1ZSBtb3JlIHRvIGl0cyB3aWRlIG9wZXJhdGlvbmFsIHByZXNlbmNlLiAgDQoNCioqUHJvdGVjdGlvbioqIGFuZCAqKldBU0gqKiwgaG93ZXZlciwgYm90aCBkbyBoYXZlIGV4cGxpY2l0IHByb2dyYW1tYXRpYyBsaW5rcyAoaW4gdGhlIGxvZ2ZyYW1lKSB3aXRoICoqRWR1Y2F0aW9uKiogYW5kIGNvLW9jY3VyIHdpdGggaXQgaW4gYHIgY2x1c3RfY29tICU+JSBmaWx0ZXIoY29tYmluYXRpb24gPT0gImVkdV9wcm90IikgJT4lIG5yb3coKWAgYW5kIGByIGNsdXN0X2NvbSAlPiUgZmlsdGVyKGNvbWJpbmF0aW9uID09ICJlZHVfd2FzaCIpICU+JSBucm93KClgIHBhcnJpc2hlcyByZXNwZWN0aXZlbHkuIEEgZnJ1aXRmdWwgYXZlbnVlIG9mIGludmVzdGlnYXRpb24gd291bGQgYmUgaG93IG1hbnkgYmVuZWZpY2lhcmllcyBvZiBFZHVjYXRpb24gYWxzbyBiZW5lZml0dGVkIGZyb20gUHJvdGVjdGlvbiBpbnRlcnZlbnRpb25zIGFuZCBob3cgY2xvc2UgaXQgaXMgdG8gdGhlIGByIHJvdW5kKGNsdXN0X2NvbSAlPiUgZmlsdGVyKGNvbWJpbmF0aW9uID09ICJlZHVfcHJvdCIpICU+JSB7c3VtKC4kY2x1c3RlcjIpIC8gc3VtKC4kcGFpcl9zdW0pfSAqIDEwMCwgZGlnaXRzID0gMSlgJSB0aGVvcmV0aWNhbCBtYXhpbXVtLg0KDQoqKk51dHJpdGlvbioqIG9wZXJhdGVzIGFsb25lIGluIGByIGNsdXN0X2NvbSAlPiUgZmlsdGVyKGNvbWJpbmF0aW9uID09ICJudXRfb25seSIpICU+JSBucm93KClgIHBhcnJpc2hlcyBvdXQgb2YgdGhlIGByIGFjdF9iZW4gJT4lIGZpbHRlcihzZWN0b3IgPT0gIk51dHJpY2lvbiIpICU+JSBkaXN0aW5jdChwY29kZTMpICU+JSBucm93KClgIHRoYXQgaXQgaXMgcHJlc2VudCBpbiwgdGhpcyBpcyB0aGUgbW9zdCBvdXQgb2YgYW55IG9mIHRoZSBvdGhlciBjbHVzdGVycyAtLSBpdCBpcyBuZWNlc3NhcnkgdG8gZXZhbHVhdGUgdGhlIGV4dGVudCB0byB3aGljaCBvdGhlciBjbHVzdGVycyBjYW4gbWFrZSB1c2Ugb2YgdGhlIGZvb3Rob2xkcyBlc3RhYmxpc2hlZCBieSBOdXRyaXRpb24uIA0KDQpXaGlsc3QgKipOdXRyaXRpb24qKiBhbmQgKipIZWFsdGgqKiBoYXZlIGV4Y2VsbGVudCBwcm9ncmFtbWF0aWMgY29tcGxlbWVudGFyaXR5LCBlc3BlY2lhbGx5IHdpdGggSGVhbHRoJ3MgZm9jdXMgb24gb2JzdGV0cmljLCBhbnRlbmF0YWwgYW5kIG5lb25hdGFsIGNhcmUsIHRoaXMgY29tYmluYXRpb24gaGFzIHRoZSBzZWNvbmQtbG93ZXN0IG51bWJlciBvZiBiZW5lZmljaWFyeSBmcmVxdWVuY2llcyBvZiBhbGwgdGhlIGNvbWJpbmF0aW9ucy4gDQoNCioqV0FTSCoqIG92ZXJhbGwgaGFzIGV4Y2VsbGVudCBwcm9ncmFtbWF0aWMgb3ZlcmxhcCB3aXRoIGFsbCBvdGhlciBjbHVzdGVyczsgYW5kIHdhcyB0aGUgb25seSBjbHVzdGVyIHRvIHByb2dyYW1tZSBzcGVjaWZpYyBtdWx0aS1zZWN0b3IgaW50ZXJ2ZW50aW9ucyAtLSBXQVNIIGluIHNjaG9vbHMgYW5kIFdBU0ggaW4gaGVhbHRoL251dHJpdGlvbiBjZW50cmVzLiBBbmQgYWxtb3N0IG5vbmUgb2YgV0FTSCdzIGJlbmVmaWNpYXJ5IGZyZXF1ZW5jaWVzIG9jY3VycmVkIGluIHBhcnJpc2hlcyB3aGVyZSBubyBvdGhlciBjbHVzdGVycyB3ZXJlIHByZXNlbnQuIEl0cyBncmVhdCByZWFjaCBhbmQgYmxhbmtldCBjb3ZlcmFnZSAoZXNwZWNpYWxseSB3YXRlciBzdXBwbHkgYW5kIG90aGVyIGNvbW11bml0eS1sZXZlbCBhY3Rpdml0aWVzKSBtZWFuIHRoYXQgb3RoZXIgY2x1c3RlcnMgb3BlcmF0aW5nIGluIHRoZSBzYW1lIGFyZWFzIGFzIFdBU0ggYXJlICJndWFyYW50ZWVkIiB0byByZWFjaCBiZW5lZmljaWFyaWVzIHdpdGggbXVsdGktc2VjdG9yIHByb2dyYW1taW5nIC0tIHRoZSBjaGFsbGVuZ2VzIG9mIHRoZXNlIGNvbWJpbmF0aW9ucyBiZWluZw0KDQoxLiB0aGUgaW50ZW50aW9uYWxpdHkgb2YgdGhlIG11bHRpLXNlY3RvciBjb3ZlcmFnZSBhbmQgDQoyLiBtYXRjaGluZyB0aGUgc2NhbGUgb2YgV0FTSCBhY3Rpdml0aWVzLiANCg0KU2ltaWxhciB0byBXQVNIIGFuZCBIZWFsdGgsICoqUHJvdGVjdGlvbioqIGhhcyB2ZXJ5IGxpbWl0ZWQgYmVuZWZpY2lhcnkgZnJlcXVlbmNpZXMgaW4gcGFycmlzaGVzIHdoZXJlIGl0IG9wZXJhdGVzIGFsb25lLiBQcm90ZWN0aW9uIGNvaW5jaWRlcyB0aGUgbW9zdCB3aXRoIE51dHJpdGlvbiAtLSB0aGlzIHNob3VsZCBzZXJ2ZSBhcyBhbiBpbXB1bHNlIGZvciB0aGUgY3JlYXRpb24gb2YgcmVmZXJyYWwgcGF0aHdheXMgYmV0d2VlbiB0aGUgdHdvIHNpbmNlIGJvdGggY2Fycnkgb3V0IHNjcmVlbmluZyBhY3Rpdml0aWVzLCBtYWRlIGVhc2llciBieSB0aGUgZmFjdCB0aGF0IGJvdGggbWFuYWdlIHNvbWUgZm9ybSBvZiBiZW5lZmljaWFyeS1sZXZlbCBkYXRhYmFzZS4gUHJvdGVjdGlvbiBoYXMgdGhlIG1vc3QgZXhwbGljaXQgcHJvZ2FtbWF0aWMgbGlua3MgdG8gRWR1Y2F0aW9uIGluIHRoZSBsb2dmcmFtZS4NCg0KPGJyPjxicj4NCg0KIyMjIDRkLiBBY3Rpdml0eSBjYXRlZ29yaWVzIA0KDQpUbyBjbG9zZSBjaGFwdGVyIDQsIHRoZSBzdGF0ZSBvZiBtdWx0aS1zZWN0b3IgcHJvZ3JhbW1pbmcgaXMgcG9vcjogYXMgd2UgaGF2ZSBub3RlZCwgdGhlcmUgaXMgbGl0dGxlIGludGVudGlvbmFsaXR5IGluIGRlY2lkaW5nIHdoaWNoIGFyZWFzIGhhdmUgbXVsdGktc2VjdG9yIGNvdmVyYWdlIGFuZCB3aGljaCBhcmVhcyBkbyBub3QgLS0gbXVsdGktc2VjdG9yIGxpbmtzIGRvIGV4aXN0IGF0IHRoZSBhY3Rpdml0eSBsZXZlbCwgYnV0IHRoaXMgaXMgYSBwb29yIGFwcHJveGltYXRpb24gb2YgaW50ZWdyYXRlZCBwcm9ncmFtbWluZy4gQW5kIHdlIHNlZSB0aGUgd2Vha25lc3Mgb2YgdGhpcyBhcHByb2FjaCBpbiB0aGUgdGFibGUgYmVsb3csIHdoaWNoIGxpc3RzIHRoZSBtb3N0IGNvbW1vbiBpbnRlci1jbHVzdGVyIGFjdGl2aXR5IGNhdGVnb3J5IGNvbWJpbmF0aW9ucyBhdCB0aGUgcGFycmlzaCBsZXZlbC4gIA0KDQpgYGB7ciBjYy1jYXRlZ29yaWEtVEFCTEV9DQoNCmFjdF9iZW4gJT4lIA0KICBzZWxlY3QocGNvZGUzLCBjYXRlZ29yaWEpICU+JSANCiAgZGlzdGluY3QoKSAlPiUgDQogIGZpbHRlcighc3RyX2RldGVjdChjYXRlZ29yaWEsICJPVFJPIikpICU+JSANCiAgcGFpcndpc2VfY291bnQoY2F0ZWdvcmlhLCBwY29kZTMsIHVwcGVyID0gRkFMU0UpICU+JSANCiAgYXJyYW5nZShkZXNjKG4pKSAlPiUgDQogIGxlZnRfam9pbihhY3RfYmVuICU+JSBzZWxlY3Qoc2VjdG9yMSA9IHNlY3RvciwgY2F0ZWdvcmlhKSAlPiUgZGlzdGluY3QoKSwgDQogICAgICAgICAgICBieSA9IGMoIml0ZW0xIiA9ICJjYXRlZ29yaWEiKSkgJT4lIA0KICBsZWZ0X2pvaW4oYWN0X2JlbiAlPiUgc2VsZWN0KHNlY3RvcjIgPSBzZWN0b3IsIGNhdGVnb3JpYSkgJT4lIGRpc3RpbmN0KCksIA0KICAgICAgICAgICAgYnkgPSBjKCJpdGVtMiIgPSAiY2F0ZWdvcmlhIikpICU+JSANCiAgZmlsdGVyKHNlY3RvcjEgIT0gc2VjdG9yMikgJT4lIA0KICBtdXRhdGVfYXQodmFycyhpdGVtMSwgaXRlbTIpLCB+c3RyX3RvX3RpdGxlKC4pKSAlPiUgDQogIHNlbGVjdChhY3R2aXR5X2NhdGVnb3J5MSA9IGl0ZW0xLCBhY3Rpdml0eV9jYXRlZ29yeTIgPSBpdGVtMiwgY291bnQgPSBuKSAlPiUgDQogIGhlYWQoMTUpICU+JSANCiAga2JsKGNhcHRpb24gPSAiTW9zdCBjb21tb24gaW50ZXItY2x1c3RlciBhY3Rpdml0eSBjYXRlZ29yeSBjb21iaW5hdGlvbnMiKSAlPiUgDQogIGthYmxlX3N0eWxpbmcoYm9vdHN0cmFwX29wdGlvbnMgPSBjKCJzdHJpcGVkIiwgImhvdmVyIiwgImNvbmRlbnNlZCIpKQ0KICANCmBgYA0KPGJyPiANCg0KT2YgdGhlIDE1IG1vc3QgY29tbW9uIGFjdGl2aXR5IGNhdGVnb3J5IGNvbWJpbmF0aW9ucywgd2Ugc2VlIG9ubHkgZm91ciBjb21iaW5hdGlvbnMgd2hpY2ggbWlnaHQgYWN0dWFsbHkgY29udmV5IG11bHRpLXNlY3RvciBiZW5lZml0czogDQoNCiogVGhlIDR0aCBhbmQgMTF0aCBlbnRyaWVzLCAqKlByZXZlbnRpb24gb2YgYWN1dGUgbWFsbnV0cml0aW9uIC8gUHJvdmlzaW9uIG9mIHByb3RlY3Rpb24gc2VydmljZXMqKiBhbmQgKipQcm92aXNpb24gb2YgcHJvdGVjdGlvbiBzZXJ2aWNlcyAvIFRyZWF0bWVudCBvZiBhY3V0ZSBtYWxudXRyaXRpb24qKiB3aGVyZSByZWZlcnJhbHMgYmV0d2VlbiB0aGUgTnV0cml0aW9uIGFuZCBQcm90ZWN0aW9uIGNsdXN0ZXJzIG1pZ2h0IGZlYXNpYmx5IHJlc3VsdCBpbiB2dWxuZXJhYmxlIHBvcHVsYXRpb25zIHJlY2VpdmluZyBhIGNvbWJpbmF0aW9uIG9mIHByb3RlY3Rpb24gc2VydmljZXMsIG1pY3JvbnV0cmllbnQgc3VwcGxlbWVudGF0aW9uLCBkZS13b3JtaW5nLCB0cmVhdG1lbnQgYW5kIGNvdW5zZWxsaW5nIHRoYXQgd291bGQgcmVkdWNlIHRoZWlyIHZ1bG5lcmFiaWxpdHkgaW4gYSBtdWx0aWRpbWVuc2lvbmFsIG1hbm5lcjsgdGhlDQoNCiogOXRoIGVudHJ5LCAqKldhdGVyIHN1cHBseSBpbiBjb21tdW5pdGllcyAvIFByZXZlbnRpb24gb2YgYWN1dGUgbWFsbnV0cml0aW9uKiosIGFzIGltcHJvdmVkIHdhdGVyIHN1cHBseSBpcyBhIGNvcmUgY29tcG9uZW50IG9mIHByZXZlbnRpbmcgbWFsbnV0cml0aW9uOyBhbmQgdGhlDQoNCiogMTF0aCwgKipBY2Nlc3MgdG8gZWR1Y2F0aW9uIGFuZCBzdHVkZW50IHJldGVudGlvbiAvIFByb3Zpc2lvbiBvZiBwcm90ZWN0aW9uIHNlcnZpY2VzKiosIGFzIHRoZSBwb3B1bGF0aW9uIG9mIGNoaWxkcmVuIHdpdGggcG9vciBhY2Nlc3MgdG8gZWR1Y2F0aW9uIGFuZCBhcmUgaW4gZGFuZ2VyIG9mIGRyb3BwaW5nIG91dCB3b3VsZCwgcHJlc3VtYWJseSwgYmUgbW9yZSBpbiBuZWVkIG9mIHByb3RlY3Rpb24gc2VydmljZXMgKHdoaWNoIGluY2x1ZGUgcmVmZXJyYWxzIHRvIHRoZSBmb3JtYWwgc29jaWFsIHdlbGZhcmUgc3lzdGVtLCBsZWdhbCBhaWQsIHN1cHBvcnQgZm9yIEdCViBzdXJ2aXZvcnMgYW5kIFVBU0MpLiANCg0KSG93ZXZlciwgYXMgbWVudGlvbmVkIHByZXZpb3VzbHksIHRoZXNlIG11bHRpLXNlY3RvciBiZW5lZml0cyBhcmUgdGhlb3JldGljYWwgYW5kIGl0IGhhcyBub3QgYmVlbiBlc3RhYmxpc2hlZCB0aGF0IHRoZXJlIGlzIGNvbW11bmljYXRpb24gYmV0d2VlbiB0aGUgaW1wbGVtZW50aW5nIHBhcnRuZXJzIG9mIHRoZXNlIGFjdGl2aXRpZXMuIFByb2plY3QgbW9uaXRvcmluZyBpcyByZXF1aXJlZCB0byBlc3RhYmxpc2ggdGhpcy4gDQoNCkNvbWJpbmF0aW9ucyBsaWtlICoqQWNjZXNzIHRvIGVkdWNhdGlvbiBhbmQgc3R1ZGVudCByZXRlbnRpb24gLyBQcmV2ZW50aW9uIG9mIGFjdXRlIG1hbG51dHJpdGlvbioqICgxc3QpIGRlYWwgd2l0aCBhbG1vc3QgZW50aXJlbHkgc2VwYXJhdGUgcG9wdWxhdGlvbnMgLS0gY2hpbGRyZW4gb2Ygc2Nob29sZ29pbmcgYWdlIGFyZSBvdXRzaWRlIG9mIHRoZSB0YXJnZXQgcG9wdWxhdGlvbiBmb3IgTnV0cml0aW9uOyB0aG91Z2ggaXQgaXMgZmVhc2libGUgdGhhdCBFZHVjYXRpb24gYW5kIE51dHJpdGlvbiBjb3VsZCBib3RoIGJlIGRlYWxpbmcgd2l0aCB0aGUgc2FtZSB5b3VuZyBtb3RoZXIgd2hvIGhhcyBkcm9wcGVkIG91dCBvZiBzY2hvb2wuIA0KDQpGdXJ0aGVybW9yZSwgY29tYmluYXRpb25zIGxpa2UgKipQcmV2ZW50aW9uIG9mIGFjdXRlIG1hbG51dHJpdGlvbiAvIFJlc2lsaWVuY2UgaW4gZWR1Y2F0aW9uKiogKDJuZCkgYW5kICoqQ2FwYWNpdHkgYnVpbGRpbmcgaW4gZWR1Y2F0aW9uIC8gUHJldmVudGlvbiBvZiBhY3V0ZSBtYWxudXRyaXRpb24qKiAoM3JkKSBoYXZlIG5vIG92ZXJsYXAgYXMgbWFsbnV0cml0aW9uIHByZXZlbnRpb24gaGFzIG5vIHByb2dyYW1tYXRpYyBsaW5rIHRvIHNhZmUgc2Nob29sIHN0cmF0ZWdpZXMsIERSUiBpbiBzY2hvb2xzIG9yIHRlYWNoZXIgdHJhaW5pbmcuDQoNCkFzIGl0IHN0YW5kcywgY2x1c3RlciBmb290cHJpbnRzIHNlZW0gdG8gaGF2ZSBtdWNoIG1vcmUgdG8gZG8gd2l0aCBvcHBvcnR1bmlzdGljIGV4cGFuc2lvbiBzdHJhdGVnaWVzIGRlcGVuZGVudCBvbiBwYXJ0bmVycycgcHJlZmVycmVkIGFyZWFzIHRoYW4gYSBuZWVkcy1iYXNlZCBhcHByb2FjaCB3aGljaCB0YXJnZXRzIHRoZSBtb3N0IHZ1bG5lcmFibGUuIFRoZSBuZXh0IGNoYXB0ZXIgaXMgYW4gZWZmb3J0IHRvIGV4YW1pbmUgYW5kIGNvcnJlY3QgdGhpcy4gDQoNCjxicj48YnI+PGJyPjxicj4gIA0KDQoNCg0KIyMgNS4gRGVjaXNpb24gdHJlZXMNCg0KIyMjIDVhLiBJbnRyb2R1Y3Rpb24gdG8gdHJlZXMgLS0gb3JnYW5pc2F0aW9uYWwgcHJlc2VuY2UNCg0KVG8gcHJpb3JpdGlzZSBiZXR3ZWVuIHRoZSBgciBucm93KHBhcnIpYCBwYXJyaXNoZXMgaW4gVmVuZXp1ZWxhIC0tIHRoYXQgaXMsIHRvIGRldGVybWluZSB3aGVyZSB3ZSBzaG91bGQgYmUgd29ya2luZyAtLSBpdCBpcyBuZWNlc3NhcnkgdG8gc3BsaXQgdGhlbSB1cCBpbnRvIG1vcmUgZWFzaWx5IGRpZ2VzdGlibGUgZ3JvdXBzLCBhbmQgd2Ugd2lsbCB1c2UgZGVjaXNpb24gdHJlZXMgdG8gZG8gdGhpcy4gQSBwcmlvcml0aXNhdGlvbiBvciB2dWxuZXJhYmlsaXR5IHNjb3JlIGlzIGFub3RoZXIgY29tbW9ubHktdXNlZCBwcmlvcml0aXNhdGlvbiB0b29sLCBidXQsIGFzIHdlIHdpbGwgc2VlLCBjb2xsYXBzaW5nIGEgbnVtYmVyIG9mIHZhcmlhYmxlcyBkb3duIGludG8gb25lIHNjb3JlIGlzIG5vdCBhbHdheXMgaGVscGZ1bC4gDQoNClRvIHVuZGVyc3RhbmQgaG93IGEgZGVjaXNpb24gdHJlZSBmdW5jdGlvbnMsIGxldCB1cyBjb25zdHJ1Y3Qgb25lIHRvIHByZWRpY3Qgd2hldGhlciBvciBub3QgdGhlcmUgaXMgYSBodW1hbml0YXJpYW4gYWdlbmN5IHByZXNlbnQgaW4gYSBwYXJyaXNoIChgb3JnX3ByZXNlbnRgIC0tIHRoaXMgaXMgb3VyIGRlcGVuZGVudCB2YXJpYWJsZSkuIFdlIGhhdmUgc3VwcGxpZWQgb3VyIG1vZGVsIHdpdGggYSBiYXNrZXQgb2YgY2Vuc3VzIGluZGljYXRvcnMgZnJvbSB3aGljaCBpdCB3aWxsIGNvbnN0cnVjdCBhIHRyZWUgdG8gcHJlZGljdCBvdXIgZGVwZW5kZW50IHZhcmlhYmxlIC0tIHVuaGlkZSB0aGUgY29kZSBiZWxvdyB0byBzZWUgdGhlIGZ1bGwgbW9kZWwuIFRoZSBkZWNpc2lvbiB0cmVlIHByaW50ZWQgYmVsb3cgaXMgdGhlIHJlc3VsdDogDQoNCmBgYHtyIHRyZWUyfQ0KIyBqdXN0IHRvIHNob3cgdGhlIGRlY2lzaW9uIHRyZWUgb2YgaG93IHBhcnRuZXJzIHNlZW0gdG8gaGF2ZSBjaG9zZW4gbG9jYXRpb25zLiANCiMgdXNpbmcgZnVsbCBwYXJyIGRhdGFzZXQgZm9yIHRoZSB0cmVlDQojIG5vIGRvdWJ0IHRoZXJlIGFyZSBvdGhlciBmYWN0b3JzLCBidXQgdGhpcyBpcyB0aGUgZGF0YSBJIGhhdmUgLS0gDQojIGxvb2tpbmcgYXQgc3BlY2lmaWMgcGFydG5lciBjaGFyYWN0ZXJpc3RpY3Mgd291bGQgYmUgaW50ZXJlc3RpbmcuIA0Kc2V0LnNlZWQoMzAwMCkNCg0KdHJlZTIgPC0gcGFyciAlPiUgDQogIHJwYXJ0KG9yZ19wcmVzZW50IH4gcGVyY2VudF9wb2JyZSArIHBlcmNlbnRfdXJiYW5hICsgZGVuc2lkYWRfcHBsX2ttMiArIA0KICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCArICANCiAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKyBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyArDQogICAgICAgIHBlcmNlbnRfc2luX3NlcnZpY2lvX2VsZWN0cmljbyArIHBlcmNlbnRfYW5hbGZhYmV0byArIHBlcmNlbnRfaG9nYXJlc19qZWZhdHVyYV9mZW1lbmluYSwgDQogICAgICAgIHByb21lZGlvX2RlX3BlcnNvbmFzX3Bvcl92aXZpZW5kYSwgZGF0YSA9IC4sIG1pbmJ1Y2tldCA9IDEwMCkNCg0KZmFuY3lScGFydFBsb3QodHJlZTIsIGRpZ2l0cyA9IC0zLCBzdWIgPSAiIiwgcGFsZXR0ZXMgPSAiQmx1ZXMiLCB0eXBlID0gMikNCmBgYA0KDQpUbyB1bmRlcnN0YW5kIHRoZSBwbG90IGFib3ZlLCBhbGwgcGFycmlzaGVzIGhhdmUgYmVlbiBzcGxpdCBpbnRvIGZvdXIgZ3JvdXBzICh0aGUgdGVybWluYWwgbm9kZXMgYXQgdGhlIGJvdHRvbSBtYXJrZWQgKipbNF0qKiwgKipbNV0qKiwgKipbNl0qKiBhbmQgKipbN10qKikgYmFzZWQgb24gdGhlIHBlcmNlbnRhZ2Ugb2YgcGFycmlzaGVzIGluIGVhY2ggbm9kZSB3aGVyZSBodW1hbml0YXJpYW4gYWdlbmNpZXMgYXJlIHByZXNlbnQuIEVhY2ggbm9kZSBoYXMgdGhyZWUgZmlndXJlcyAtLSBmb3IgaW5zdGFuY2UsIHRoZSByb290LCBhdCB0aGUgdG9wLCBhbmQgbWFya2VkICoqWzFdKiosIHNob3dzIHRoYXQgb24gYXZlcmFnZSwgMC41NDQgb3IgNTQuNCUgb2YgYWxsIHBhcnJpc2hlcyBoYXZlIGh1bWFuaXRhcmlhbiBhZ2VuY2llcyBwcmVzZW50IGluIHRoZW0uIFRoZSBuZXh0IG51bWJlcnMsICJuID0gMTEwOSIgc2hvd3MgdGhhdCBgciBucm93KHBhcnIpYCBwYXJyaXNoZXMgYXJlIGluIHRoYXQgZ3JvdXAgYW5kIG5leHQgdG8gaXQgaXMgdGhlIHBlcmNlbnRhZ2Ugb2YgcGFycmlzaGVzIGl0IGNvbnRhaW5zLCB3aGljaCwgc2luY2UgaXQgaXMgdGhlIHJvb3QsIGlzIDEwMCUuIA0KDQpXZSBzZWUgdGhhdCAqKls3XSoqIChpbiBkYXJrIGJsdWUpIGlzIHRoZSBub2RlIHdpdGggdGhlIGhpZ2hlc3QgY29uY2VudHJhdGlvbiBvZiBwYXJyaXNoZXMgd2l0aCBhZ2VuY2llcyBwcmVzZW50ICg4NC4zJSk7IGl0IGNvbnNpc3RzIG9mIHBhcnJpc2hlcyBtb3JlIHRoYW4gNzkuNCUgdXJiYW5pc2VkIGFuZCBkZW5zZXIgdGhhbiAxNTYgcHBsL2ttMi4gQW5kICoqWzRdKiosIHRoZSBub2RlIHdpdGggdGhlIGxvd2VzdCBjb25jZW50cmF0aW9uIG9mIHBhcnJpc2hlcyB3aXRoIGFnZW5jaWVzICgyNS42JSkgaXMgbGVzcyB0aGFuIDc5LjQlIHVyYmFuaXNlZCBfYW5kXyBsZXNzIHRoYW4gMjEuOCUgdXJiYW5pc2VkLiANCg0KVGhpcyBpcywgb2YgY291cnNlLCBub3QgdG8gaW1wbHkgdGhhdCB0aGlzIGFjdHVhbGx5IGRlcGljdHMgcGFydG5lcnMnIGRlY2lzaW9uLW1ha2luZyBwcm9jZXNzLCBqdXN0IHRoYXQgdGhlc2UgYXJlIHRoZSBmYWN0b3JzIHRvd2FyZHMgd2hpY2ggd2UsIGFzIGEgcmVzcG9uc2UsIGFyZSBwcmVkaXNwb3NlZC4gUGVyaGFwcyBpdCBpcyB1bmRlcnN0YW5kYWJsZSB0aGF0IHRoZSBtb3N0IGhlYXZpbHkgcG9wdWxhdGVkIHBhcnJpc2hlcyBhcmUgbW9yZSBsaWtlbHkgdG8gaGF2ZSBvcmdhbmlzYXRpb25zIHByZXNlbnQsIHRob3VnaCBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHVyYmFuIHBvcHVsYXRpb24gYXJlIGJvdGggbmVnYXRpdmVseSBjb3JyZWxhdGVkIHdpdGggcG92ZXJ0eSBpbmNpZGVuY2UuIFRoZSBsYXJnZXN0IGRldGVybWluYW50cyBvZiB0aGUgX251bWJlcl8gb2YgYmVuZWZpY2lhcmllcyByZWFjaGVkIHBlciBwYXJyaXNoIGFyZSBwb3B1bGF0aW9uIGRlbnNpdHkgYW5kIHVyYmFuaXNhdGlvbiwgYXMgYmVuZWZpY2lhcnkgbnVtYmVycyB0ZW5kIHRvIHNjYWxlIGluIGxpbmUgd2l0aCBsYXJnZXIgcG9wdWxhdGlvbnMuIA0KDQo8YnI+PGJyPg0KDQojIyMgNWIuIFByaW9yaXRpc2F0aW9uIHRyZWUNCg0KTm93IGxldCB1cyBmb2N1cyBvbiBmdXR1cmUgZGVjaXNpb25zOiANCg0KU2V2ZXJhbCB0cmVlcyB3ZXJlIGJ1aWx0IGFuZCB0cmlhbGxlZCB0byBzcGxpdCBwYXJyaXNoZXMgaW50byB0YXJnZXR0aW5nIGdyb3Vwcy4gQXMgbWVudGlvbmVkLCB0aGUgaW5kZXBlbmRlbnQgdmFyaWFibGVzIGNvbWUgZnJvbSBhIHBvb2wgb2YgaW5kaWNhdG9ycyBmcm9tIHRoZSBjZW5zdXMgZGF0YXNldCwgd2l0aCBzb21lIG9yaWdpbmF0aW5nIGZyb20gdGhlIDIwMTkgVU5JQ0VGIE11bmljaXBhbCBQcmlvcml0aXNhdGlvbiBUb29sLCB3aGljaCB3YXMgYSBQcmluY2lwYWwgQ29tcG9uZW50cyBBbmFseXNpcyBvZiBrZXkgdmFyaWFibGVzIHJlbGF0ZWQgdG8gcG92ZXJ0eSwgaGVhbHRoIGFuZCBtb3J0YWxpdHkgYW5kIHZpb2xlbmNlIGFuZCBpbnNlY3VyaXR5LiBBZnRlciBudW1lcm91cyBpdGVyYXRpb25zLCAqKmB0cmVlM2AqKiB3YXMgY2hvc2VuOyBpdCBzcGxpdHMgcGFycmlzaGVzIGludG8gZ3JvdXBzIGFjY29yZGluZyB0byB0aGU6ICANCg0KKiBUaGUgcG92ZXJ0eSBzY29yZSwgd2hpY2ggaXMgdGhlIGEgcmVzY2FsZWQgYXZlcmFnZSBvZiB0aGUgbnVtYmVyIG9mIHBvb3IgcGVyc29ucyBhbmQgdGhlIHBvdmVydHkgaW5jaWRlbmNlIG9mIGVhY2ggcGFycmlzaC4gDQogIA0KVG8gc2VlIHRoZSBzcGVjaWZpYyB2YXJpYWJsZXMgYW5kIGZvcm11bGFlIHVzZWQgZm9yIGVhY2ggb2YgdGhlIG1ham9yIGl0ZXJhdGlvbnMsIGFzIHdlbGwgYXMgYWRkaXRpb25hbCBub3RlcyBvbiB0aGUgZGV2ZWxvcG1lbnQgYW5kIGFwcGxpY2F0aW9uIG9mIGRlY2lzaW9uIHRyZWVzLCB1bmhpZGUgdGhlIHNvdXJjZSBjb2RlIGJlbG93LiANCg0KYGBge3IgdHJlZXMtUkVGLXdyaXRlLWludG8tcGFycjB9DQogDQojIEFzIG9wcG9zZWQgdG8gYSBwcmlvcml0aXNhdGlvbiBzY29yZSAtLSB0eXBpY2FsbHkgdGhlIHdlaWdodGVkIGF2ZXJhZ2Ugb2Ygc2V2ZXJhbCANCiMgZGVtb2dyYXBoaWMgYW5kIHNvY2lvZWNvbm9taWMgaW5kaWNhdG9ycyAtLSANCiMgYSB0cmVlIGlzIG11Y2ggYmV0dGVyIGF0IGFjY291bnRpbmcgZm9yIHRoZSB2YXJpYXRpb25zIGFjcm9zcyBnZW9ncmFwaGljIGFyZWFzLg0KIyBBIHBhcnRuZXIgbWlnaHQgbm90IGhhdmUgdGhlIGNhcGFjaXR5IHRvIHdvcmsgb3V0c2lkZSBvZiB1cmJhbiBhcmVhcyBvciANCiMgbWlnaHQgaGF2ZSBzcGVjaWZpYyBnZW9ncmFwaGljIGJpYXNlcyBhbmQgZGVjaXNpb24gdHJlZXMgYXJlIGEgZ29vZCB0b29sIA0KIyB0byBtYWtlIHRoZSBiZXN0IHBvc3NpYmxlIHRhcmdldHRpbmcgZGVjaXNpb25zIHdpdGhpbiBvbmUncyBjb25zdHJhaW50cy4gIA0KDQojIFdpdGggdGhhdCBpbiBtaW5kLCB0cmVlMyB3YXMgZGV2ZWxvcGVkIHRvIGFpZCBmdXR1cmUgcHJpb3JpdGlzYXRpb24uIA0KIyBUaGUgaW5kZXBlbmRlbnQgdmFyaWFibGUgaXQgc3RyaXZlcyB0byBwcmVkaWN0IGlzIHRoZSBwb3ZlcnR5IHNjb3JlLCB3aGljaCwgYXMgbWVudGlvbmVkLCANCiMgaXMganVzdCB0aGUgcmVzY2FsZWQgYXZlcmFnZSBvZiBudW1iZXIgb2YgcG9vciBwZXJzb25zIGFuZCBwb3ZlcnR5IGluY2lkZW5jZS4gDQojIFRoZSBwZXJmb3JtYW5jZSBvZiB0cmVlMyB3YXMgY29uc2lkZXJlZCBzdXBlcmlvciB0byBib3RoIHRyZWUxIA0KIyAod2hvc2UgaW5kZW5kZXBlbnQgdmFyaWFibGUgaXMganVzdCB0aGUgYWJzb2x1dGUgbnVtYmVyIG9mIHBvb3IgcGVyc29ucykgDQojIGFuZCB0cmVlNCAod2hpY2ggY29uc2lkZXJlZCBwYXJyaXNoLWxldmVsIGdhcHMpIGR1ZSB0byBpdHMgYWJpbGl0eSB0byANCiMgY2xlYXJseSBkaXN0aW5ndWlzaCBpdHMgZ3JvdXBzIG9mIHBhcnJpc2hlcyBhbmQgYmVjYXVzZSBpdCBpcyBub3QgZGVwZW5kZW50IG9uIGdhcHMgZGF0YSAtLQ0KIyBtZWFuaW5nIGl0IHdpbGwgbm90IHNoaWZ0IHdoZW4gdGhlIDVXcyBhcmUgdXBkYXRlZC4NCg0Kc2V0LnNlZWQoMzAwMCkNCg0KIyBudW1iZXIgb2Ygbm90IGNvdmVyZWQgcG9vciBwZXJzb25zIA0KdHJlZTEgPC0gcGFycjAgJT4lDQogIHJwYXJ0KG5vdF9yZWFjaGVkIH4gZXN0YWRvICsgcGVyY2VudF9wb2JyZSArIHBlcmNlbnRfdXJiYW5hICsgDQogICAgICAgIGRlbnNpZGFkX3BwbF9rbTIgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyANCiAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwgKyAgDQogICAgICAgIHBlcmNlbnRfc2luX2FndWFfc2VndXJhICsgcGVyY2VudF9zaW5fc2FuZWFtaWVudG9fbWVqb3JhZG8gKw0KICAgICAgICBwZXJjZW50X3Npbl9zZXJ2aWNpb19lbGVjdHJpY28gKyBwZXJjZW50X2FuYWxmYWJldG8gKyBwZXJjZW50X2hvZ2FyZXNfamVmYXR1cmFfZmVtZW5pbmEsIA0KICAgICAgICBwcm9tZWRpb19kZV9wZXJzb25hc19wb3Jfdml2aWVuZGEsIGRhdGEgPSAuLCBjcCA9IDAuMDM4KQ0KDQojIHRyZWUgYmFzZWQgb24gcG92ZXJ0eV9zY29yZQ0KdHJlZTMgPC0gcGFycjAgJT4lDQogIHJwYXJ0KHBvdmVydHlfc2NvcmUgfiBlc3RhZG8gKyBwZXJjZW50X3VyYmFuYSArIGRlbnNpZGFkX3BwbF9rbTIgKw0KICAgICAgICByYXpvbl9kZV9kZXBlbmRlbmNpYV9kZV9tZW5vcmVzX2RlXzE1X2Fub3MgKyByYXpvbl9kZV9kZXBlbmRlbmNpYV90b3RhbCArICANCiAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKyBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyArDQogICAgICAgIHBlcmNlbnRfc2luX3NlcnZpY2lvX2VsZWN0cmljbyArIHBlcmNlbnRfYW5hbGZhYmV0byArIHBlcmNlbnRfaG9nYXJlc19qZWZhdHVyYV9mZW1lbmluYSwNCiAgICAgICAgcHJvbWVkaW9fZGVfcGVyc29uYXNfcG9yX3ZpdmllbmRhLCBkYXRhID0gLiwgY3AgPSAwLjA0NCkNCg0KIyB0cmVlIGJhc2VkIG9uIGdhcCBzY29yZSAtLSBsZXQncyBub3QgdXNlIHRoaXMgDQojIGFzIHRyZWUzIGlzIG1vcmUgc3RhYmxlIGFuZCB3aWxsIG5vdCBjaGFuZ2UgYmFzZWQgb24gbmV3IDVXIGRhdGEgDQojIHRyZWU0IDwtIHBhcnIwICU+JQ0KIyAgIHJwYXJ0KGdhcF9zY29yZSB+IGVzdGFkbyArIHBlcmNlbnRfdXJiYW5hICsgZGVuc2lkYWRfcHBsX2ttMiArDQojICAgICAgICAgcmF6b25fZGVfZGVwZW5kZW5jaWFfZGVfbWVub3Jlc19kZV8xNV9hbm9zICsgcmF6b25fZGVfZGVwZW5kZW5jaWFfdG90YWwgKyAgDQojICAgICAgICAgcGVyY2VudF9zaW5fYWd1YV9zZWd1cmEgKyBwZXJjZW50X3Npbl9zYW5lYW1pZW50b19tZWpvcmFkbyArDQojICAgICAgICAgcGVyY2VudF9zaW5fc2VydmljaW9fZWxlY3RyaWNvICsgcGVyY2VudF9hbmFsZmFiZXRvICsgcGVyY2VudF9ob2dhcmVzX2plZmF0dXJhX2ZlbWVuaW5hLCANCiMgICAgICAgICBwcm9tZWRpb19kZV9wZXJzb25hc19wb3Jfdml2aWVuZGEsIGRhdGEgPSAuLCBjcCA9IDAuMDQ1KQ0KDQojIHBsb3RjcCh0cmVlMykNCiMgcHJpbnRjcCh0cmVlMykNCg0KIyBhZGRpbmcgdHJlZTEgYW5kIHRyZWUzIHJ1bGVzIHRvIHRoZSBkYXRhc2V0IA0KcGFycjAgPC0gcGFycjAgJT4lIA0KICBtdXRhdGUocnVsZTEgPSByb3cubmFtZXModHJlZTEkZnJhbWUpW3RyZWUxJHdoZXJlXSkgJT4lDQogICAgICBsZWZ0X2pvaW4ocnBhcnQucnVsZXMudGFibGUodHJlZTEpICU+JSANCiAgICAgIGZpbHRlcihMZWFmID09IFRSVUUpICU+JSANCiAgICAgIHJlbmFtZShydWxlMSA9IFJ1bGUpICU+JSANCiAgICAgIGdyb3VwX2J5KHJ1bGUxKSAlPiUgDQogICAgICBzdW1tYXJpc2Uoc3VicnVsZXMxID0gcGFzdGUoU3VicnVsZSwgY29sbGFwc2UgPSAiLCIpKSkgICU+JSANCiAgbXV0YXRlKHJ1bGUzID0gcm93Lm5hbWVzKHRyZWUzJGZyYW1lKVt0cmVlMyR3aGVyZV0pICU+JQ0KICAgICAgbGVmdF9qb2luKHJwYXJ0LnJ1bGVzLnRhYmxlKHRyZWUzKSAlPiUgDQogICAgICBmaWx0ZXIoTGVhZiA9PSBUUlVFKSAlPiUgDQogICAgICByZW5hbWUocnVsZTMgPSBSdWxlKSAlPiUgDQogICAgICBncm91cF9ieShydWxlMykgJT4lIA0KICAgICAgc3VtbWFyaXNlKHN1YnJ1bGVzMyA9IHBhc3RlKFN1YnJ1bGUsIGNvbGxhcHNlID0gIiwiKSkpDQoNCmBgYA0KDQo8YnI+PGJyPg0KDQojIyMgNWMuIFN1Yi1ncm91cHMgb2YgZGVjaXNpb24gdHJlZTMNCg0KQmVsb3cgaXMgYSBwbG90IG9mICoqYHRyZWUzYCoqIC0tIHRoZSBgciBucm93KHBhcnIwKWAgcGFycmlzaGVzIHdoZXJlIHRoZSBudW1iZXIgb2YgYmVuZWZpY2lhcmllcyBkb2VzIG5vdCBleGNlZWQgdGhlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgKGNvcnJlc3BvbmRpbmcgdG8gdGhlIF91bmRlcl8gYW5kIF9ubyBjb3ZlcmFnZV8gY2F0ZWdvcmllcykgaGF2ZSBiZWVuIHNwbGl0IGludG8gZm91ciB0ZXJtaW5hbCBub2RlczogKipbNF0qKiwgKipbNV0qKiwgKipbNl0qKiBhbmQgKipbN10qKi4gVGhlIG1hbm5lciBpbiB3aGljaCB0aGV5IGhhdmUgYmVlbiBzcGxpdCBpcyBtZWFuaW5nZnVsIGZvciB0YXJnZXR0aW5nIGRlY2lzaW9ucyBhbmQgdGhpcyBzZWN0aW9uIHdpbGwgY29tcGFyZSB0aGUgY2hhcmFjdGVyaXN0aWNzIG9mIGVhY2guIFBsZWFzZSBub3RlIHRoYXQgdGhpcyBpcyBhIGRpZmZlcmVudCB0cmVlIHRoYW4gaW4gc2VjdGlvbiA1YSAtLSB0aGUgdHdvIG1vZGVscyBoYXZlIHRoZSBzYW1lIG51bWJlcmluZyBiZWNhdXNlIHRoZXkgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2Ygc3BsaXRzLg0KDQpgYGB7ciB0cmVlMy1ycGFydFBsb3R9DQoNCmZhbmN5UnBhcnRQbG90KHRyZWUzLCBkaWdpdHMgPSAtMywgc3ViID0gIiIsIHBhbGV0dGVzID0gIkJsdWVzIiwgdHlwZSA9IDIpDQpgYGANCiANCjxicj4NCiANCiMjIyMgU3VtbWFyeSBhbmQgb3ZlcnZpZXcgb2YgdGhlIHRlcm1pbmFsIG5vZGVzIG9mIHRyZWUzIA0KDQpgYGB7ciB0cmVlMy1ydWxlcy1UQUJMRX0NCiMgd2lsbCB0aGV5IGJlIGNvbmZ1c2VkIHRoYXQgdGhlIHRlcm1pbmFsIG5vZGVzIGhhdmUgdGhlIHNhbWUgY29kZXM/IA0KIyBTaG91bGQgSSBleHBsYWluIGluIHRoZSB0ZXh0IHRoYXQgdGhpcyBpcyBiZWNhdXNlIHRoZXkgaGF2ZSB0aGUgc2FtZSBudW1iZXIgb2Ygc3BsaXRzIA0KIyBvciB3aWxsIHRoYXQganVzdCBtYWtlIHRoZW0gbW9yZSBjb25mdXNlZD8gDQoNCnBhcnIwICU+JSANCiAgZ3JvdXBfYnkocnVsZTMpICU+JSANCiAgc3VtbWFyaXNlKHBhcnJfbm9fYmVuID0gbl9kaXN0aW5jdChwY29kZTNbYmVuZWZpY2lhcmlvcyA9PSAwXSksDQogICAgICAgICAgICBiZW5lZmljaWFyaWVzID0gc3VtKGJlbmVmaWNpYXJpb3MpLA0KICAgICAgICAgICAgYXZnX2JlbmVmaWNpYXJpZXMgPSBzdW0oYmVuZWZpY2lhcmlvcykgLyBuKCksIA0KICAgICAgICAgICAgbm90X3JlYWNoZWQgPSBzdW0obm90X3JlYWNoZWQpLA0KICAgICAgICAgICAgYXZnX25vdF9yZWFjaGVkID0gc3VtKG5vdF9yZWFjaGVkKSAvIG4oKSwNCiAgICAgICAgICAgIGF2Z19vcmdfY291bnQgPSBtZWFuKG9yZ19jb3VudCksDQogICAgICAgICAgICBhdmdfcG9wdWxhdGlvbiA9IG1lYW4ocG9ibGFjaW9uXzIwMTkpLA0KICAgICAgICAgICAgcGVyY2VudF9wb29yID0gcm91bmQoc3VtKHBvYl9wb2JyZSkgLyBzdW0ocG9ibGFjaW9uXzIwMTkpICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgICAgIHBlcmNlbnRfdXJiYW4gPSByb3VuZChzdW0ocG9iX3VyYmFuYSkgLyBzdW0ocG9ibGFjaW9uXzIwMTkpICogMTAwLCBkaWdpdHMgPSAxKSwNCiAgICAgICAgICAgIGRlbnNpdHlfcHBsX2ttMiA9IHN1bShwb2JsYWNpb25fMjAxOSkgLyBzdW0oYXJlYV9rbTIsIG5hLnJtID0gVFJVRSksDQogICAgICAgICAgICBwYXJyaXNoZXMgPSBuKCkpICU+JSANCiAgZ2F0aGVyKGtleSA9IHZhcmlhYmxlLCB2YWx1ZSA9IHZhbHVlLCAyOm5jb2woLikpICU+JSANCiAgc3ByZWFkXyhrZXkgPSBuYW1lcyguKVsxXSwgdmFsdWUgPSAndmFsdWUnKSAlPiUgDQogICMgcmVvcmRlcmluZyB0aGUgdGFibGUgaW5zdGVhZCBvZiBoYXZpbmcgaXQgYmUgYWxwaGFiZXRpY2FsDQogIGFycmFuZ2UoZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJub3RfcmVhY2hlZCIsICJhdmdfbm90X3JlYWNoZWQiLCAiYXZnX3BvcHVsYXRpb24iLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImJlbmVmaWNpYXJpZXMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYXZnX2JlbmVmaWNpYXJpZXMiLCAgImF2Z19vcmdfY291bnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGVyY2VudF9wb29yIiwgInBlcmNlbnRfdXJiYW4iLCAiZGVuc2l0eV9wcGxfa20yIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwYXJyaXNoZXMiLCAicGFycl9ub19iZW4iKSkpICU+JSAgDQogIA0KICBwYW5kZXIoYmlnLm1hcmsgPSAiLCIsIGNhcHRpb24gPSAiU3VtbWFyeSB0YWJsZSBvZiB0aGUgdGVybWluYWwgbm9kZXMgb2YgdHJlZTMiKQ0KDQpgYGANCg0KKiAqKls0XSoqIGNvbnNpc3RzIG9mIHBvcHVsYXRpb24gY2VudHJlcyB3aGljaCBhcmUgZWFzeSB0byByZWFjaCwgYnV0IHdpdGggb25seSBgciByb3VuZChmaWx0ZXIocGFycjAsIHJ1bGUzID09ICI0IikgJT4lIHtzdW0oLiRwb2JfcG9icmUpIC8gc3VtKC4kcG9ibGFjaW9uXzIwMTkpfSAqIDEwMCwgZGlnaXRzPTEpYCUgb2YgdGhlIHBvcHVsYXRpb24gYmVpbmcgcG9vciwgY2FyZWZ1bCB0YXJnZXR0aW5nIGFuZCBiZW5lZmljaWFyeSBzZWxlY3Rpb24gaXMgcmVxdWlyZWQgLS0gYmxhbmtldCBjb3ZlcmFnZSB3aWxsIG9ubHkgcmVzdWx0IGluIGV4Y2Vzc2l2ZSBpbmNsdXNpb24gZXJyb3JzLiBJdCBhbHNvIGhhcyB0aGUgaGlnaGVzdCBhdmVyYWdlIG51bWJlciBvZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgcGVyIHBhcnJpc2ggKGF2Z19vcmdfY291bnQpLiBUaGVyZSBhcmUgYHIgZmlsdGVyKHBhcnIwLCBydWxlMyA9PSAiNCIpICU+JSBucm93KClgIHBhcnJpc2hlcyBpbiB0aGlzIGdyb3VwLiBUaGVzZSBwYXJyaXNoZXMgc2hvdWxkIG5vdCBiZSBwcmlvcml0aXNlZCAtLSByZXNvdXJjZXMgc2hvdWxkIGJlIGFsbG9jYXRlZCBlbHNld2hlcmUuIA0KDQoqICoqWzVdKiogaXMgcHJvYmFibHkgdGhlIGJlc3Qgb3B0aW9uIGZvciBleHBhbnNpb24gZm9yIG1vc3QgcGFydG5lcnMgLS0gaXQgaGFzIHRoZSBoaWdoZXN0IGNvbmNlbnRyYXRpb24gb2YgcG9vciBwZXJzb25zIG5vdCBjb3ZlcmVkIHBlciBwYXJyaXNoIChhdmdfbm90X3JlYWNoZWQpLCBpcyBzdWJzdGFudGlhbGx5IHBvb3JlciB0aGFuICoqWzRdKiosIHdpdGggYSBwb3ZlcnR5IGluY2lkZW5jZSBvZiBgciByb3VuZChmaWx0ZXIocGFycjAsIHJ1bGUzID09ICI1IikgJT4lIHtzdW0oLiRwb2JfcG9icmUpIC8gc3VtKC4kcG9ibGFjaW9uXzIwMTkpfSAqIDEwMCwgZGlnaXRzPTEpYCUuIEFkZGl0aW9uYWxseSwgdGhlc2UgcGFycmlzaGVzIGFyZSBzdGlsbCB2ZXJ5IHVyYmFuaXNlZCAoYHIgcm91bmQoZmlsdGVyKHBhcnIwLCBydWxlMyA9PSAiNSIpICU+JSB7c3VtKC4kcG9iX3VyYmFuYSkgLyBzdW0oLiRwb2JsYWNpb25fMjAxOSl9ICogMTAwLCBkaWdpdHM9MSlgJSksIG1lYW5pbmcgdGhhdCBhY2Nlc3MgdG8gdGhlc2UgcG9wdWxhdGlvbnMgd2lsbCBub3QgYmUgY2hhbGxlbmdpbmcuIFRoZSBjb3ZlcmFnZSBvZiBvcmdhbmlzYXRpb25zIGlzIHN0aWxsIGZhaXJseSBoaWdoIGFuZCBwYXJ0bmVycyBzaG91bGQgY29uc2lkZXIgZXhwYW5kaW5nIGludG8gcGFycmlzaGVzIHRvIHRoZSBvbmVzIHRoZXkgY3VycmVudGx5IGNvdmVyLiBUaGlzIGlzIHRoZSBsYXJnZXN0IGdyb3VwLCB3aXRoIGByIGZpbHRlcihwYXJyMCwgcnVsZTMgPT0gIjUiKSAlPiUgbnJvdygpYCBwYXJyaXNoZXMuIA0KDQoqICoqWzZdKiogaXMgd2hlcmUgYWNjZXNzIHN0YXJ0cyB0byBnZXQgbW9yZSBjaGFsbGVuZ2luZyAtLSB0aG91Z2ggdGhlc2UgcGFycmlzaGVzIGhhdmUgYW4gYXZlcmFnZSBwb3ZlcnR5IGluY2lkZW5jZSBvZiBgciByb3VuZChmaWx0ZXIocGFycjAsIHJ1bGUzID09ICI2IikgJT4lIHtzdW0oLiRwb2JfcG9icmUpIC8gc3VtKC4kcG9ibGFjaW9uXzIwMTkpfSAqIDEwMCwgZGlnaXRzPTEpYCUsIHRoZSByYXRlIG9mIHVyYmFuaXNhdGlvbiBkcm9wcyB0byBgciByb3VuZChmaWx0ZXIocGFycjAsIHJ1bGUzID09ICI2IikgJT4lIHtzdW0oLiRwb2JfdXJiYW5hKSAvIHN1bSguJHBvYmxhY2lvbl8yMDE5KX0gKiAxMDAsIGRpZ2l0cz0xKWAlIGFuZCB0aGUgcG9wdWxhdGlvbiBkZW5zaXR5IGlzIG9ubHkgMTggcHBsL2ttMi4gQnV0IHRoZXJlIGFyZSBzdGlsbCBtb3JlIHBvb3IgcGVyc29ucyBub3QgY292ZXJlZCBwZXIgcGFycmlzaCBpbiB0aGlzIGdyb3VwIHRoYW4gaW4gKipbNF0qKi4gVGhlcmUgYXJlIGByIGZpbHRlcihwYXJyMCwgcnVsZTMgPT0gIjYiKSAlPiUgbnJvdygpYCBwYXJyaXNoZXMgaW4gdGhpcyBncm91cC4gDQoNCiogKipbN10qKiBjb25zaXN0cyBvZiB0aGUgcG9vcmVzdCwgbW9zdCB2dWxuZXJhYmxlIGFuZCBtb3N0IHJlbW90ZSBwYXJyaXNoZXMuIFdvcmtpbmcgaW4gdGhlc2UgYXJlYXMgd2lsbCBpbmN1ciBzaWduaWZpY2FudCBvcGVyYXRpb25hbCBhbmQgbG9naXN0aWNhbCBjb3N0cy4gSG93ZXZlciwgd2l0aCBhbiBhdmVyYWdlIHBvdmVydHkgaW5jaWRlbmNlIG9mIGByIHJvdW5kKGZpbHRlcihwYXJyMCwgcnVsZTMgPT0gIjciKSAlPiUge3N1bSguJHBvYl9wb2JyZSkgLyBzdW0oLiRwb2JsYWNpb25fMjAxOSl9ICogMTAwLCBkaWdpdHM9MSlgJSwgYmxhbmtldCBjb3ZlcmFnZSB3aWxsIGJlIHdhcnJhbnRlZCBpbiBtYW55IGNhc2VzIC0tIGlmIHRoZSBjaGFsbGVuZ2Ugb2YgcmVhY2hpbmcgYWxsIG9mIHRoZSBwb3B1bGF0aW9uIGNhbiBiZSBtZXQuIEFkZGl0aW9uYWxseSwgdGhleSBhbHNvIGhhdmUgdGhlIGxvd2VzdCBhdmVyYWdlIG51bWJlciBvZiBwb29yIHBlcnNvbnMgbm90IGNvdmVyZWQsIGdpdmVuIHRoZWlyIGV4dHJlbWVseSBsb3cgcG9wdWxhdGlvbiBkZW5zaXR5IG9mIDEuOCBwcGwva20yLiBIdW1hbml0YXJpYW4gYWdlbmNpZXMgaGF2ZSB0aGUgbG93ZXN0IHByZXNlbmNlIGluIHRoZXNlIHBhcnJpc2hlcy4gSXQgaXMgYWR2aXNhYmxlIGZvciBkb25vcnMgdG8gaW5jZW50aXZpc2UgYWN0aXZpdGllcyBpbiB0aGVzZSBhcmVhcyBhcyB0aGV5IGFyZSB2ZXJ5IHVuZGVyc2VydmVkLiBUaGVyZSBhcmUgYHIgZmlsdGVyKHBhcnIwLCBydWxlMyA9PSAiNyIpICU+JSBucm93KClgIHBhcnJpc2hlcyBpbiB0aGlzIGdyb3VwLg0KDQo8YnI+PGJyPg0KDQojIyMgNWQuIE1hcCBvZiBwYXJyaXNoZXMgYnkgZGVjaXNpb24gdHJlZSBub2RlDQoNCmBgYHtyIHRyZWUtMy1NQVAtb3JnLXByZXNlbnR9DQojIGp1c3Qgb25lIG5vdGUgZm9yIHRoaXMgbWFwIC0tIEkgc3RpbGwgY2FuJ3QgZmlndXJlIG91dCBob3cgdG8gZ2V0IHRoZSB0b29sdGlwIHRvIGFwcGVhciB3aGVuDQojIHlvdSdyZSBob3ZlcmluZyBvdmVyIHRoZSBjZW50cm9pZCBpbnN0ZWFkIG9mIGF0IHRoZSBib3JkZXI7IGhvdmVyb24gZmlsbCBkb2Vzbid0IHdvcmsuIA0KIyBJIHRoaW5rIHlvdSBzaG91bGQganVzdCBhc2sgc3RhY2tvdmVyZmxvdyBHSVMNCg0KIyBoZXggZm9yIFNldDIgIiM2NkMyQTUiLCAiI0ZDOEQ2MiIsICIjOERBMENCIiwgIiNFNzhBQzMiLCAiI0ZGRkZGRiINCiMgaGV4IGZvciBEYXJrMiAiIzFCOUU3NyIsICIjRDk1RjAyIiwgIiM3NTcwQjMiLCAiI0U3Mjk4QSIsICIjRkZGRkZGIg0KIyBoZXggZm9yIEFjY2VudCAiIzdGQzk3RiIsICIjQkVBRUQ0IiwgIiNGREMwODYiLCAiI0ZGRkY5OSIsICIjRkZGRkZGIg0KIyBzY2FsZV9maWxsX3ZpcmlkaXNfZCgpDQojIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoKSkNCg0KcGFycm1hcF9vcmcgPC0gcGFyciAlPiUgDQogIGxlZnRfam9pbihwYXJyMCAlPiUgDQogICAgICAgICAgICAgIHNlbGVjdChwY29kZTMsIHJ1bGUzKSwgYnkgPSAicGNvZGUzIikgJT4lIA0KICByaWdodF9qb2luKHBjb2RlM19zaGFwZSwgYnkgPSAicGNvZGUzIikgJT4lIA0KICBzdF9hc19zZigpICU+JSANCiAgbXV0YXRlKG5vdF9yZWFjaGVkID0gcm91bmQobm90X3JlYWNoZWQsIGRpZ2l0cyA9IDApLA0KICAgICAgICAgdHJlZV9ub2RlID0gcnVsZTMpICU+JSANCiAgbXV0YXRlX2F0KHZhcnMocGVyY2VudF9wb2JyZSwgcGVyY2VudF91cmJhbmEpLCB+KHJvdW5kKC4sIGRpZ2l0cyA9IDIpKSkgJT4lIA0KICBnZ3Bsb3QoKSArDQogIGdlb21fc2Yoc2l6ZSA9IDAuMSwgDQogICAgICAgICAgYWVzKGZpbGwgPSB0cmVlX25vZGUsDQogICAgICAgICAgICAgIHRleHQgPSBwYXN0ZTAocGFycm9xdWlhLCIsIiwgIlxuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICBtdW5pY2lwaW8sICIsIiwgIlxuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzdGFkbywgIlxuIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAibm90IGNvdmVyZWQ6ICIsIG5vdF9yZWFjaGVkLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgInBvdmVydHkgaW5jaWRlbmNlOiAiLCBwZXJjZW50X3BvYnJlLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgInBlcmNlbnQgdXJiYW46ICIsIHBlcmNlbnRfdXJiYW5hLCAiXG4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIm9yZyBwcmVzZW50IDoiLCBvcmdfcHJlc2VudCksDQogICAgICAgICAgICAgYWxwaGEgPSBvcmdfcHJlc2VudCkpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzY2QzJBNSIsICIjRkM4RDYyIiwgIiM4REEwQ0IiLCAiI0U3OEFDMyIpKSArDQogIHNjYWxlX2FscGhhX2Rpc2NyZXRlKHJhbmdlID0gYygxLCAwLjcpKSArDQogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gNyksDQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwNCiAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTEpKSArDQogIGd1aWRlcyhhbHBoYSA9IEZBTFNFKSArDQogIGxhYnMoZmlsbCA9ICJUcmVlIG5vZGUiLA0KICAgICAgIGFscGhhID0gIiIpICsNCiAgZ2d0aXRsZSgnTWFwIG9mIHBhcnJpc2hlcyBieSBkZWNpc2lvbiB0cmVlIG5vZGUgKGNvbG91cikgJiBpZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgKGFscGhhKScpDQogIA0KZ2dwbG90bHkocGFycm1hcF9vcmcsIHRvb2x0aXAgPSBjKCJ0ZXh0IiwgImZpbGwiKSkgJT4lDQogIGxheW91dCh0aXRsZSA9IGxpc3QodGV4dCA9IHBhc3RlMCgNCiAgICAiTWFwIG9mIHBhcnJpc2hlcyBieSBkZWNpc2lvbiB0cmVlIG5vZGUgKGNvbG91cikgJiBpZiBvcmdhbmlzYXRpb25zIHByZXNlbnQgKGFscGhhKSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPGJyPiIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiPHN1cD4iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJtb3VzZSBvdmVyIGZvciBkZXRhaWxzOyBkcmFnIGFuZCBjbGljayB0byBzZWxlY3QgYW5kIHpvb207IGRvdWJsZS1jbGljayBsZWdlbmQgc2VsZWN0L2Rlc2VsZWN0IiwiPC9zdXA+IikpKQ0KDQoNCmBgYA0KDQpBYm92ZSBpcyBhIG1hcCBvZiBwYXJyaXNoZXMgYnkgdGhlaXIgZGVjaXNpb24gdHJlZSBub2RlIChkZW5vdGVkIGJ5IGNvbG91ciksIHdlIGhhdmUgYWxzbyBkZWNyZWFzZWQgdGhlIGFscGhhIGZvciBwYXJyaXNoZXMgd2hlcmUgdGhlcmUgYXJlIGFscmVhZHkgb3JnYW5pc2F0aW9ucyBwcmVzZW50LCBtZWFuaW5nIHRoYXQgdGhleSBhcHBlYXIgbW9yZSB0cmFuc3BhcmVudC4gTG9va2luZyBhdCBhcmVhcyB3aXRoIHRoZSBncmVhdGVzdCBjb25jZW50cmF0aW9ucyBvZiAqKls0XSoqIGFuZCAqKls1XSoqLCB3ZSBjYW4gc2VlIHRoYXQgdGhleSBjb25mb3JtIHRvIHRoZSB0aGUgVmVuZXp1ZWxhIENvc3RhbCBSYW5nZSBhbmQgdGhlIFZlbmV6dWVsYW4gQW5kZXMsIHdoZXJlIG1vc3Qgb2YgdGhlIGNvdW50cnkncyBwb3B1bGF0aW9uIGlzIGxvY2F0ZWQ7IGFzIGEgcmVtaW5kZXIsIHBhcnJpc2hlcyBpbiBub2RlICoqWzVdKiogYXJlIGV4Y2VsbGVudCBjYW5kaWRhdGVzIGZvciBleHBhbnNpb24uIA0KDQpXZSBhbHNvIHNlZSB0aHJlZSBsYXJnZSBjbHVzdGVycyBvZiBwYXJyaXNoZXMgZnJvbSBub2RlICoqWzddKiogLS0gdGhlIHBvb3Jlc3QgYW5kIG1vc3Qtc3BhcnNlbHkgcG9wdWxhdGVkIGFyZWFzIC0tIGluIEFtYXpvbmFzIGFuZCBCb2xpdmFyIChhdCB0aGUgYm90dG9tIG9mIHRoZSBtYXApLCBpbiBEZWx0YSBBbWFjdXJvIChhdCB0aGUgZXh0cmVtZSByaWdodCkgYW5kIGluIExhcmEgYW5kIEZhbGNvbiAodG9wLWxlZnQpLiBEb3VibGUtY2xpY2sgb24gZWFjaCBsZWdlbmQgaXRlbSB0byB0b2dnbGUgdGhlIHZpZXcuICANCg0KQXMgYSBmaW5hbCBub3RlIGZvciB0aGlzIGNoYXB0ZXIsIHRoZSBwcmlvcml0aXNhdGlvbiB0cmVlIHdhcyBsaW1pdGVkIHRvIGZvdXIgdGVybWluYWwgbm9kZXMgYmVjYXVzZSB0aGV5IGNhcHR1cmVkIHRoZSB2YXN0IG1ham9yaXR5IG9mIHRoZSB2YXJpYW5jZSBhbW9uZ3N0IHRoZSBwYXJyaXNoZXMgLS0gYW55IG1vcmUgc3BsaXRzIHdvdWxkIG9ubHkgaGF2ZSBkaW1pbmlzaGluZyByZXR1cm5zLiBCdXQsIHNob3VsZCBhIHBhcnRuZXIgd2FudCB0byBzZWUgYSBtb3JlIGNvbXBsZXggdHJlZSB3aXRoIG1vcmUgbm9kZXMsIGl0IHdvdWxkIGJlIHZlcnkgZWFzeSB0byBzdXBwbHkgdGhlbSB3aXRoIGl0LiBCdXQgSSBmZWVsIHRoZXNlIG1vcmUgY29tcGxleCB0cmVlcyB3b3VsZCBtb3N0bHkgc2VydmUgYXMgcmVmZXJlbmNlcywgcmF0aGVyIHRoYW4gYWN0dWFsIHByaW9yaXRpc2F0aW9uIHRvb2xzIC0tIEkgYWxyZWFkeSBxdWVzdGlvbiBwYXJ0bmVycycgYWJpbGl0eSB0byBkZWFsIHdpdGggNCBzZXBhcmF0ZSBncm91cHMsIGVhY2ggcmVxdWlyaW5nIHRoZWlyIG93biBzdHJhdGVnaWVzLCBtdWNoIGxlc3MgOCBvciAxMC4NCg0KPGJyPg0KDQoqIENoYXB0ZXIgNSBhbm5leDogQWRkaXRpb25hbCBub3RlcyBvbiB0cmVlMSwgd2hpY2ggd2FzIG5vdCBzZWxlY3RlZCAtLSB1bmhpZGUgY29kZSB0byBzZWUNCg0KYGBge3IgdHJlZTEtbm90ZXMsIHJlc3VsdHM9RkFMU0V9DQojIHRoZSBtYWluIHByb2JsZW0gSSBzZWUgaXMgdGhhdCBlYWNoIG9mIHRoZSBsZWF2ZXMgaGFzIGxpdHRsZSB2YXJpYW5jZSBpbiB0ZXJtcyBvZiBwb3ZlcnR5IGluY2lkZW5jZQ0KIyBidXQgbGV0IG1lIGtub3cgaWYgeW91IHdhbnQgbWFwcyBvciBwcm9kdWN0cyBmb2N1c2VkIG9uIHRoaXMgdHJlZSwgaXQncyBwcmV0dHkgZWFzeSB0byBkby4gDQojIFsxNV0gaXMgdmVyeSwgdmVyeSBhdHRyYWN0aXZlLiBNYXliZSBJIGNhbiBkbyBzb21ldGhpbmcgd2l0aCBpdC4gIA0KDQojIDYgaXMgZGVuc2UsIHVyYmFuIGFuZCBoaWdoZXN0IG9wZXJhdGlvbmFsIHByZXNlbmNlLA0KIyAyIGlzIGp1c3QgdG9vIGJpZy4gODAwIHBhcnJpc2hlcyBpcyBqdXN0IHRvbyBtYW55LiBUaGUgbG93IGVuZCBpcyBkaXN0aW5ndWlzaGVkIG11Y2ggYmV0dGVyIGluIHRyZWUzDQojIDE0IGlzIGp1c3QgcmljaCwgdXJiYW4gYW5kIG5vdCBhIHByaW9yaXR5LiBJdCdzIGFsc28gYSByZWFsbHkgc21hbGwgbGVhZi4gIA0KIyAxNSBpcyBhY3R1YWxseSBhIHJlYWxseSBnb29kIGxlYWYgLS0gcmVhbGx5IGhpZ2ggbmNfcGVyX3BhcnIsIGZldyBwYXJyaXNoZXMsIA0KIyB2ZXJ5IGRlbnNlLCB2ZXJ5IHVyYmFuIGFuZCA0MiUgcG9vciBhbmQgc3VjaCBhbiBpbW1lbnNlbHkgbG93IGNvdmVyYWdlIHBlcmNlbnQuIA0KIyBHb29kIGxvdy1oYW5naW5nIGZydWl0LiBJIGFsbW9zdCB3YW50IHRvIGtlZXAgdHJlZTEganVzdCBiZWNhdXNlIG9mIHRoaXMgbGVhZi4gDQojIE1heWJlIEkgd2lsbCBtYWtlIG9uZSBtYXAganVzdCBmb3IgdGhpcy4gNTksNTA4IG5jX3Blcl9wYXJyIGlzIG1hc3NpdmUuIA0KDQpwYXJyMCAlPiUgDQogIGdyb3VwX2J5KHJ1bGUxKSAlPiUgDQogIHN1bW1hcmlzZShwYXJyX25vX2JlbiA9IG5fZGlzdGluY3QocGNvZGUzW2JlbmVmaWNpYXJpb3MgPT0gMF0pLCANCiAgICAgICAgICAgIGJlbmVmaWNpYXJpb3MgPSBzdW0oYmVuZWZpY2lhcmlvcyksDQogICAgICAgICAgICBiZW5fcGVyX3BhcnIgPSBzdW0oYmVuZWZpY2lhcmlvcykgLyBuKCksIA0KICAgICAgICAgICAgbm90X3JlYWNoZWQgPSBzdW0obm90X3JlYWNoZWQpLA0KICAgICAgICAgICAgbnJfcGVyX3BhcnIgPSBzdW0obm90X3JlYWNoZWQpIC8gbigpLA0KICAgICAgICAgICAgbnJfcGVyX211biA9IHN1bShub3RfcmVhY2hlZCkgLyBuX2Rpc3RpbmN0KHBjb2RlMiksIA0KICAgICAgICAgICAgYXZnX29yZ19jb3VudCA9IG1lYW4ob3JnX2NvdW50KSwNCiAgICAgICAgICAgIGNvdmVyYWdlX3BlcmNlbnQgPSBzdW0oYmVuZWZpY2lhcmlvcykgLyBzdW0ocG9ibGFjaW9uXzIwMTkpLA0KICAgICAgICAgICAgcGVyY2VudF9wb2JyZSA9IHN1bShwb2JfcG9icmUpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSwNCiAgICAgICAgICAgIHBlcmNlbnRfdXJiYW5hID0gc3VtKHBvYl91cmJhbmEpIC8gc3VtKHBvYmxhY2lvbl8yMDE5KSwNCiAgICAgICAgICAgIGRlbnNpZGFkX3BwbF9rbTIgPSBzdW0ocG9ibGFjaW9uXzIwMTkpIC8gc3VtKGFyZWFfa20yLCBuYS5ybSA9IFRSVUUpLA0KICAgICAgICAgICAgcGFycm9xdWlhcyA9IG4oKSwNCiAgICAgICAgICAgIG11bmljaXBpb3MgPSBuX2Rpc3RpbmN0KHBjb2RlMiksDQogICAgICAgICAgICBwYXJyX3Blcl9tdW4gPSBuKCkgLyBuX2Rpc3RpbmN0KHBjb2RlMikpICU+JSANCiAgZ2F0aGVyKGtleSA9IHZhcmlhYmxlLCB2YWx1ZSA9IHZhbHVlLCAyOm5jb2woLikpICU+JSANCiAgc3ByZWFkXyhrZXkgPSBuYW1lcyguKVsxXSwgdmFsdWUgPSAndmFsdWUnKSAlPiUgDQogIGFycmFuZ2UoZmFjdG9yKHZhcmlhYmxlLCBsZXZlbHMgPSBjKCJub3RfcmVhY2hlZCIsICJucl9wZXJfcGFyciIsICJucl9wZXJfbXVuIiwgImJlbmVmaWNpYXJpb3MiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiYmVuX3Blcl9wYXJyIiwgICJhdmdfb3JnX2NvdW50IiwgImNvdmVyYWdlX3BlcmNlbnQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAicGVyY2VudF9wb2JyZSIsICJwZXJjZW50X3VyYmFuYSIsICJkZW5zaWRhZF9wcGxfa20yIiwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJwYXJyb3F1aWFzIiwgInBhcnJfbm9fYmVuIiwgIm11bmljaXBpb3MiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgInBhcnJfcGVyX211biIpKSkgJT4lICBwYW5kZXIoYmlnLm1hcmsgPSAiLCIpDQoNCmBgYA0KDQoNCjxicj48YnI+PGJyPjxicj4gIA0KDQojIyA2LiBSZWNvbW1lbmRhdGlvbnMgDQoNClRvIHN1bW1hcmlzZSBzb21lIGltcG9ydGFudCBuZXh0IHN0ZXBzOg0KDQoxLiAqKlJldmlldyB0aGVzZSBmaW5kaW5ncyoqIHdpdGggYWxsIGh1bWFuaXRhcmlhbiBwYXJ0bmVyczsgcGFydG5lcnMgc2hvdWxkIGFkYXB0IGEgc2V0IG9mIHJlY29tbWVuZGF0aW9ucyBmcm9tIHNwZWNpZmljIHRvIHRoZWlyIG9yZ2FuaXNhdGlvbnMgYW5kIGRldmVsb3AgdGhlaXIgb3duIGFjdGlvbiBwbGFucy4NCg0KMi4gQ2x1c3RlcnMgbXVzdCAqKmpvaW50bHkgZXN0YWJsaXNoIHRhcmdldCBwb3B1bGF0aW9ucyBhbmQgYXJlYXMqKiBhbmQgZGVmaW5lIGEgY29tcGxlbWVudGFyeSBzdWl0ZSBvZiBhY3Rpdml0aWVzIG1lYW50IHRvIGFkZHJlc3MgdGhlaXIgc3BlY2lmaWMgbmVlZHMuIEZvciBpbnN0YW5jZSwgdnVsbmVyYWJsZSBob3VzZWhvbGRzIGluIHRhcmdldCBhcmVhcyB3aXRoIGNoaWxkcmVuIHVuZGVyIDUgc2hvdWxkIGJlIGFzc2Vzc2VkIGZvciBwcm90ZWN0aW9uIHJpc2tzIGFuZCByZWZlcnJlZCBpZiBuZWNlc3Nhcnk7IHJlY2VpdmUgbnV0cml0aW9uIHNjcmVlbmluZyBhbmQgcHJldmVudGl2ZSBjYXJlIHNlcnZpY2VzIGFuZCBjb3Vuc2VsbGluZzsgYmUgbWFkZSBhd2FyZSBvZiBhdmFpbGFibGUgRUNDRCBvcHRpb25zIGFuZCwgaWYgYXBwbGljYWJsZSwgYmUgcHJvdmlkZWQgd2l0aCBlZHVjYXRpb24ga2l0czsgcmVjZWl2ZSBoeWdpZW5lIGtpdHMgYW5kIGJlbmVmaXQgZnJvbSwgYXQgdGhlIGNvbW11bml0eSBsZXZlbCwgaW50ZXJ2ZW50aW9ucyB0byBpbXByb3ZlIHRoZSBzdXBwbHkgb2Ygc2FmZSB3YXRlci4gVGhlIGNvbW11bml0eSBhcm91bmQgdGhlbSBzaG91bGQgYWxzbyBiZSB0YXJnZXR0ZWQgd2l0aCBzY2hvb2wgcmVoYWJpbGl0YXRpb24sIGF3YXJlbmVzcy1yYWlzaW5nIGFjdGl2aXRpZXMgYW5kIGFueSBoZWFsdGggZmFjaWxpdGllcyBzaG91bGQgYmUgc3RvY2tlZCB3aXRoIGEgaG9zcGl0YWwga2l0IGFuZCBrZXkgbWVkaWNpbmVzLiBJbiBmdXR1cmUgYW5hbHlzZXMsIGl0IGlzIGhvcGVkIHRoYXQgd2UgY2FuIHRyYWNrIHNwZWNpZmljIGFjdGl2aXR5IGNvbWJpbmF0aW9ucyB0aGF0IGhhdmUgYmVlbiBpbnRlbnRpb25hbGx5IGNvbnN0cnVjdGVkIGFuZCBpbXBsZW1lbnRlZCBpbiBhIGNvb3JkaW5hdGVkIG1hbm5lci4gDQoNCjMuIEluIHBhcnRpY3VsYXIsICoqTnV0cml0aW9uIGFuZCBIZWFsdGgqKiBzaG91bGQgZW5kZWF2b3VyIHRvIG92ZXJsYXAgaW4gbW9yZSBwYXJyaXNoZXMsIGdpdmVuIHRoZSBjb21wbGVtZW50YXJpdHkgb2YgdGhlaXIgYWN0aXZpdGllczsgYWRkaXRpb25hbGx5LCBtYW55IGFnZW5jaWVzIGhhdmUgZmllbGQgb2ZmaWNlcnMgd2hvIGRvdWJsZS1oYXQgYXMgaGVhbHRoIGFuZCBudXRyaXRpb24gb2ZmaWNlcnMsIHNvIHRoaXMgbG93IGxldmVsIG9mIGNvb3JkaW5hdGlvbiBpcyB2aWV3ZWQgZG91Ymx5IHVuZmF2b3VyYWJseS4NCg0KNC4gQWdlbmNpZXMgc2hvdWxkIHVzZSB0aGUgKipSZWZlcmVuY2UgdGFibGUqKiBpbiB0aGUgbmV4dCBjaGFwdGVyIHRvIHNvcnQgdGhyb3VnaCBhbmQgZGVmaW5lIGEgcHJlbGltaW5hcnkgbGlzdCBvZiBwYXJyaXNoZXMgdGhhdCB3aWxsIHByaW9yaXRpc2VkIGZvciBjb3ZlcmFnZS4gVGhleSBzaG91bGQgYWxzbyByZXF1ZXN0IGFnZW5jeS1zcGVjaWZpYyBtYXBzIGFuZCBvdGhlciBwcm9kdWN0cyBzbyB0aGF0IGVhY2ggaW1wbGVtZW50aW5nIHBhcnRuZXIgbWF5IGV4YW1pbmUgaG93IGJlc3QgdGhleSBtYXkgY292ZXIgcG9vciBwZXJzb25zIG5vdCByZWFjaGVkLiBJbiBwYXJ0aWN1bGFyLCBhZ2VuY2llcyBzaG91bGQgZm9jdXMgb24gcGFycmlzaGVzIHdoaWNoIGhhdmUgdmVyeSBsb3cgY292ZXJhZ2UgKGBjb3ZlcmFnZV9wZXJjZW50YCksIG9uZSBvciBsZXNzIHNlY3RvcnMgKGBzZWN0b3JfY291bnRgKSwgaGlnaCBwb3ZlcnR5IGluY2lkZW5jZSAoYHBlcmNlbnRfcG9vcmApIGFuZCBoaWdoIG51bWJlcnMgb2YgcGVyc29ucyBgbm90X3JlYWNoZWRgOyBgcGVyY2VudF91cmJhbmAsIGluIGFkZGl0aW9uIHRvIGEgcGFycmlzaCdzIGxvY2F0aW9uIGFuZCB0aGUgdHJlZSBub2RlLCBjYW4gaGVscCBkZXRlcm1pbmUgdGhlIHJlbGF0aXZlIGVhc2Ugb2YgcmVhY2hpbmcgYW5kIHdvcmtpbmcgaW4gdGhhdCBhcmVhLiANCg0KNS4gKipEZXZlbG9wIG9wZXJhdGlvbnMgcGxhbnMqKiB0aGF0IGFyZSBhcmVhLWZvY3VzZWQgYW5kIG11bHRpLXNlY3RvcjsgZGVjZW50cmFsaXNlIG1vcmUgZGVjaXNpb24tbWFraW5nIHBvd2VyIHRvIGZpZWxkIG9mZmljZXMgYW5kIGluY3JlYXNlIHBlcnNvbm5lbCBhbmQgY2FwYWNpdHkgaW4gdGhlIGZpZWxkIG9mZmljZXMgdG8gaW1wbGVtZW50IHRob3NlIHBsYW5zLiBSZXF1ZXN0IGFsbCBkYXRhc2V0cyBhbmQgcHJvZHVjdHMgbmVjZXNzYXJ5IHRvIGRldmVsb3AgdGhlc2UgcGxhbnMuIENvdW50cnkgb2ZmaWNlLWxldmVsIHBsYW5uaW5nIGFsc28gbmVlZHMgdG8gYmUgbW9yZSBjb29yZGluYXRlZCBhbmQgZ3JlYXRlciBwcm9ncmFtbWF0aWMgb3ZlcnNpZ2h0IG11c3QgYmUgZXhlcmNpc2VkIG92ZXIgZWFjaCBvZiB0aGUgc2VjdGlvbnMuIA0KDQo2LiAqKlNwbGl0IGh1bWFuaXRhcmlhbiBwYXJ0bmVycyoqIGludG8gZ3JvdXBzIGJhc2VkIG9uIHRoZWlyIGNhcGFjaXR5IHRvIHdvcmsgaW4gdGhlIHZhcmlvdXMgZ3JvdXBzIGVzdGFibGlzaGVkIGJ5IHRoZSBkZWNpc2lvbiB0cmVlIC0tIHRoZXJlIGlzIG11Y2ggbG93LWhhbmdpbmcgZnJ1aXQgaW4gbm9kZSBbNV0sIGJ1dCB0aGUgbW9zdCB2dWxuZXJhYmxlIHdpbGwgYmUgZm91bmQgaW4gbm9kZSBbN10uIFRoaXMgd2lsbCBoZWxwIGNsdXN0ZXJzIHVuZGVyc3RhbmQgaWYgdGhlaXIgY3VycmVudCBwb29sIG9mIHBhcnRuZXJzIGlzIHN1ZmZpY2llbnQgdG8gY292ZXIgdGhlIGdhcHMgd2UgaGF2ZSBtZW50aW9uZWQuIEEgc2FtcGxlIHBhcnRuZXIgYW5hbHlzaXMgaGFzIGJlZW4gaW5jbHVkZWQgaW4gdGhlIGFwcGVuZGl4IG9mIHRoaXMgZG9jdW1lbnQuICAgDQoNCjcuIENsdXN0ZXJzIHNob3VsZCAqKmNvb3JkaW5hdGUgdGhlIHNlbGVjdGlvbiBvZiBuZXcgcGFycmlzaGVzKiogYW5kIGVuc3VyZSB0aGF0IHRoZXJlIGFyZSBlbm91Z2ggYWdlbmNpZXMgcHJlc2VudCBpbiBlYWNoIHRvIGVuc3VyZSB0aGF0IG5lZWRzIGFyZSBtZXQgaW4gYSBjb21wcmVoZW5zaXZlIGFuZCBpbnRlZ3JhdGVkIG1hbm5lci4gUGFydG5lcnMgc2hvdWxkIHNoYXJlIHRoZWlyIGludGVuZGVkIGFjdGlvbnMgb3Blbmx5IGFuZCBjb21tdW5pY2F0ZSB0aGVpciB0YXJnZXRzIGF0IHRoZSBwYXJyaXNoIGxldmVsLiBSZXZpZXcgY292ZXJhZ2UgYW5kIG11bHRpLXNlY3RvciBwcm9ncmFtbWluZyBpbiBpbnRlci1jbHVzdGVyIG1lZXRpbmdzLiANCg0KOC4gKipIYWx0IGFuZCByZWFsbG9jYXRlKiogYWxsIHVuY29tbWl0dGVkIHJlc291cmNlcyBpbnRlbmRlZCBmb3IgaW50ZXJ2ZW50aW9ucyBpbiBub2RlIFs0XTsgZXhwbGFpbiB0byBjb21tdW5pdGllcyB0aGUgcmVhc29ucyBiZWhpbmQgdGhlIHJlYWxsb2NhdGlvbjsgYW5kIHByZXNlbnQgdGhpcyBkb2N1bWVudCB0byBkb25vcnMgYXMgZXZpZGVuY2UgZm9yIHRoZSByZWFsbG9jYXRpb24uIFB1c2ggZG9ub3JzIHRvIGVuY291cmFnZSBleHBhbnNpb24gaW50byB1bmNvdmVyZWQgYXJlYXMuDQoNCjkuIEVuc3VyZSB0aGF0IGFsbCAqKk0mRSBhY3Rpdml0aWVzKiogc3VydmV5IG11bHRpLXNlY3RvciBjb3ZlcmFnZS4gDQoNCjEwLiBEZXZlbG9wIGFuZCBtYWludGFpbiBhICoqY29uc29saWRhdGVkIGJlbmVmaWNpYXJ5IHJlZ2lzdGVyKiogKGF0IGxlYXN0IHdpdGhpbiBVTklDRUYpLCBzbyB0aGF0IG11bHRpLXNlY3RvciBjb3ZlcmFnZSBtYXkgYmUgYWNjdXJhdGVseSB0cmFja2VkIGFuZCB0aGUgbG9uZ2l0dWRpbmFsIG1vbml0b3Jpbmcgb2YgdGFyZ2V0IHBvcHVsYXRpb25zIGZhY2lsaXRhdGVkLiANCg0KMTEuIENvbW1pc3Npb24gYSAqKm5ldyBjb3ZlcmFnZSBhbmQgZ2FwcyBhbmFseXNpcyoqIGV2ZXJ5IDYgbW9udGhzIHRvIHJldmlldyBwcm9ncmVzcyBhbmQgaWRlbnRpZnkgcGVyc2lzdGVudCBpc3N1ZXMuIA0KDQo8YnI+PGJyPjxicj48YnI+DQoNCiMjIDcuIFJlZmVyZW5jZSB0YWJsZSANCl90eXBlIG9yIHVzZSBzbGlkZXIgdG8gZmlsdGVyIGJ5IGNhdGVnb3JpZXMgb3IgdmFsdWVzO18gDQpfdXNlIGFycm93cyB0byBzb3J0OyB0YWJsZSBwcmVsaW1pbmFyaWx5IGFycmFuZ2VkIGluIGRlc2NlbmRpbmcgb3JkZXIgb2YgcG9vciBwZXJzb25zIG9mIG5vdCByZWFjaGVkXw0KDQpgYGB7cn0NCnBhcnIwICU+JSANCiAgbXV0YXRlKGVkdWNhY2lvbl9vbmx5ID0gaWZlbHNlKGVkdWNhY2lvbl9iZW4gPiAwLCAiZWR1Y2FjaW9uIiwgIiIpLA0KICAgICAgICAgbnV0cmljaW9uX29ubHkgPSBpZmVsc2UobnV0cmljaW9uX2JlbiA+IDAsICJudXRyaWNpb24iLCAiIiksDQogICAgICAgICBzYWx1ZF9vbmx5ID0gaWZlbHNlKHNhbHVkX2JlbiA+IDAsICJzYWx1ZCIsICAiIiksDQogICAgICAgICB3YXNoX29ubHkgPSBpZmVsc2Uod2FzaF9iZW4gPiAwLCAid2FzaCIsICIiKSwNCiAgICAgICAgIHByb3RlY2Npb25fb25seSA9IGlmZWxzZShwcm90ZWNjaW9uX2JlbiA+IDAsICJwcm90ZWNjaW9uIiwgIiIpLA0KICAgICAgICAgc2VjdG9yc19wcmVzZW50ID0gc3RyX3RyaW0ocGFzdGUwKGVkdWNhY2lvbl9vbmx5LCAiICIsIG51dHJpY2lvbl9vbmx5LCAiICIsIHByb3RlY2Npb25fb25seSwgIiAiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYWx1ZF9vbmx5LCAiICIsIHdhc2hfb25seSkpKSAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKHBvYl9wb2JyZSwgbm90X3JlYWNoZWQsIG9yZ19jb3VudCwgYmVuZWZpY2lhcmlvcyksIH4ocm91bmQoLiwgZGlnaXRzID0gMCkpKSAlPiUgDQogIG11dGF0ZV9hdCh2YXJzKHBlcmNlbnRfcG9icmUsIHBlcmNlbnRfdXJiYW5hLCBjb3ZlcmFnZV9wZXJjZW50KSwgfihyb3VuZCguKjEwMCwgZGlnaXRzID0gMSkpKSAlPiUgDQogIG11dGF0ZShydWxlMyA9IGFzLm51bWVyaWMocnVsZTMpLA0KICAgICAgICAgc2VjdG9yc19wcmVzZW50ID0gaWZlbHNlKHNlY3RvcnNfcHJlc2VudCA9PSAiIiwgIm5vbmUiLCBzZWN0b3JzX3ByZXNlbnQpKSAlPiUgDQogIHNlbGVjdChzdGF0ZSA9IGVzdGFkbywgbXVuaWNpcGFsaXR5ID0gbXVuaWNpcGlvLCBwYXJyaXNoID0gcGFycm9xdWlhLCAgDQogICAgICAgICBwZXJjZW50X3Bvb3IgPSBwZXJjZW50X3BvYnJlLCBwZXJjZW50X3VyYmFuID0gcGVyY2VudF91cmJhbmEsIG5vdF9yZWFjaGVkLCANCiAgICAgICAgIGJlbmVmaWNpYXJpZXMgPSBiZW5lZmljaWFyaW9zLCBjb3ZlcmFnZV9wZXJjZW50LCB0cmVlX25vZGUgPSBydWxlMywNCiAgICAgICAgIG9yZ19jb3VudCwgc2VjdG9yX2NvdW50LCBzZWN0b3JzX3ByZXNlbnQsIHBjb2RlMykgJT4lIA0KICBhcnJhbmdlKGRlc2Mobm90X3JlYWNoZWQpKSAlPiUgDQogICMgdGhlIGpzIGlzIGFkanVzdGluZyB0aGUgZm9udCBzaXplIGZvciB0aGUgd2hvbGUgY29udGFpbmVyIC0tIHRoZXJlIGRvZXNuJ3Qgc2VlbSB0byBiZSBhbm90aGVyIHdheQ0KICBkYXRhdGFibGUoZmlsdGVyID0gInRvcCIsIG9wdGlvbnMgPSBsaXN0KHBhZ2VMZW5ndGggPSAxMCwgc2Nyb2xsWCA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5pdENvbXBsZXRlID0gaHRtbHdpZGdldHM6OkpTKA0KICAgICAgICAgICJmdW5jdGlvbihzZXR0aW5ncywganNvbikgeyIsDQogICAgICAgICAgcGFzdGUwKCIkKHRoaXMuYXBpKCkudGFibGUoKS5jb250YWluZXIoKSkuY3NzKHsnZm9udC1zaXplJzogJyIsICI4LjVwdCIsICInfSk7IiksDQogICAgICAgICAgIn0iKQ0KICAgICAgICkgDQogICAgICkgDQoNCg0KYGBgDQoNCg==