Restarting with the addition of ILNH data

Introduction

Objectives

  1. Compare the number and area of wetlands mapped by 3-factor and NWI wetlands across study sites

  2. Evaluate correlates of differences in mapping outcomes

Methods

Map comparison metrics

Total area mapped:

The simple sum of all wetland polygons for a given mapping protocol.

For 3-factor wetlands: \[{A_{3f}} = \sum_{i=1}^{n}A_{i}\]

For NWI wetlands: \[{A_{NWI}} = \sum_{i=1}^{n}A_{i}\]

Total polygons mapped:

The count of all wetland polygons for a given mapping protocol.

The formulation for 3-factor wetlands: \[{n_{3f poly}} = \sum_{i=1}^{n}n_{i}\]

The formulation for NWI wetlands: \[{A_{NWI poly}} = \sum_{i=1}^{n}n_{i}\]

Normalized Difference Area Index:

\[NDAI = \frac{({A_{3f}} - {A_{NWI}})}{({A_{3f}} + A_{NWI})}\]

Goodness of Fit [add citation]

\[G_{fit} = \frac{({A_{union}})}{({A_{3f.only}} + A_{union})} * \frac{({A_{union}})}{({A_{NWI.only}} + A_{union})}\]

Results

Assessment Area characterstics

Total area and number of AA

OGR data source with driver: ESRI Shapefile 
Source: "data/Final_shapefile/v15_data", layer: "polyAAidv15fin_centroid"
with 1751 features
It has 8 fields
[1] "OBJECTID"   "AAv14id"    "Shape_Leng" "Shape_Area" "AAidAcre"  
[6] "AAareaHa"   "CenLat"     "CenLon"    
## add the lookup table...
v15_centroid_EcoregDistDiv_LU <- read_csv("D:/Dropbox/PROJECTS/CORPS_NWI3P/RStudio_Projects/NWI_Analysis2016/data/Final_shapefile/V15_data/v15_centroid_EcoregDistDiv_LU.csv")
# and add the nwi meta lookup
## import the NWI metadata
AAv15centrNWImeta_LU <- read_csv("D:/Dropbox/PROJECTS/CORPS_NWI3P/RStudio_Projects/NWI_Analysis2016/data/Final_shapefile/V15_data/AAv15centrNWImeta_LU.csv")
nwi.meta <- AAv15centrNWImeta_LU %>% 
  # names()
  dplyr::select(c(AAv14id,IMAGE_YR, EMULSION))
#---------
# View(v15_centroid_EcoregDistDiv_LU)
# v15_centroid_EcoregDistDiv_LU %>%
#   names() %>%
#   as_tibble()
# unique(v15_centroid_EcoregDistDiv_LU$STATE)
## select the fields I want
ecoreg.lu <- v15_centroid_EcoregDistDiv_LU %>% 
  dplyr::select(AAv14id, 
District,
DIVISION,
US_L4CODE,              
US_L4NAME,          
US_L3NAME,              
NA_L3NAME,              
NA_L2NAME,
BlyDOMAIN,              
BlyDIVISION,
PROVINCE,               
SECTION,
STATE,
isoBioCli
)
  
# datatable(ecoreg.lu)
## Left join the ecoregion etc. lu with the AA
aaCtrd.ecoreg <- left_join(aacentr.tbl, ecoreg.lu, by = "AAv14id")
# Now join the NWI metadata 
aaCtrd.ecoreg <- left_join(aaCtrd.ecoreg, nwi.meta, by = "AAv14id")
## just a check to see I wave one poly per AAv14id
# aaCtrd.ecoreg %>% 
#   group_by(AAv14id) %>%
#   summarize(cnt= n()) %>% 
#   filter(cnt==1)

Summary datatabe for AA

aaCtrd.ecoreg %>% 
  datatable(filter = 'top')

AA area summary by STATE

aaCtrd.ecoreg %>%
  group_by(STATE) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  arrange(desc(sum.sqmiles)) %>% 
  datatable()

aaCtrd.ecoreg %>%
  group_by(STATE) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  filter(sum.sqmiles > 35) %>% 
  ggplot(aes(x= reorder(STATE,-sum.sqmiles), y = sum.sqmiles)) +
  geom_bar(stat='identity') +
  labs(x="",y="Sum AA area (square miles)") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) 

AA area summary by USACE DIVISION

aaCtrd.ecoreg %>%
  group_by(DIVISION) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  arrange(desc(sum.sqmiles)) %>% 
  datatable()

USACE Division: Sum acres

# Graphs
# plot 1: sum of acres in AA by Division
pl01 <- aaCtrd.ecoreg %>% 
  group_by(DIVISION) %>% 
  summarise(sum.Acres = sum(AAidAcre)) %>% 
  ggplot(aes(reorder(x=DIVISION, sum.Acres),y = sum.Acres)) +
  geom_bar(stat='identity') +
  labs(x = "", y = "AA area (acres)", title = "Sum AA area") +
  coord_flip() +
  scale_y_log10(labels = scales::comma)
  # scale_y_log10()
# pl01
######## horizontal boxplot via ggstance
## # In ggstance, you supply aesthetics in their natural order:
# Horizontal with ggstance
# ggplot(mpg, aes(hwy, class, fill = factor(cyl))) +
#   geom_boxploth() 
# boxplot
pl02 <- aaCtrd.ecoreg %>%
  # filter()
  ggplot(aes(x=AAidAcre,y = DIVISION)) +
  geom_boxploth() +
  labs(x = "AA area (acres)", y = "", title = "Individual AA area") +
  # coord_flip() +
  scale_x_log10(labels = scales::comma)
  # scale_x_continuous(labels=fancy_scientific) ## this uses the function at the head of the doc
  # scale_x_continuous(labels=function(n){format(n, scientific = FALSE)}) # this also works but log
# pl02
## save as a grid
# plot_grid(pl01, pl02, labels = c("A", "B"))
p3 <- cowplot::plot_grid(pl01, pl02, labels = c("A", "B"), nrow = 2, align = "V")
# save_plot("v15_AA_boplots_totalarea_indi.png", p3, ncol = 2)
p3

## plot the AA area
# med.div <- aaCtrd.ecoreg %>% 
#   group_by(DIVISION, District) %>% 
#   summarise(med.AAha = median(AAareaHa), mean.areaHa = mean(AAareaHa), med.AAacre = median(AAidAcre), mean.AAacre = mean(AAidAcre))
# 
# med.div %>% 
#   ggplot(aes(x = reorder(District, med.AAacre), y = med.AAacre)) +
#   geom_point() +
#   facet_wrap(~DIVISION, scales = 'free') +
#   scale_y_log10()

AA area summary by USACE District

aaCtrd.ecoreg %>%
  group_by(District) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  arrange(desc(sum.sqmiles)) %>% 
  datatable()

USACE Division: Boxplot individual AA acres

# aaCtrd.ecoreg %>% 
#   group_by(District) %>% 
#   summarise(sum.Acres = sum(AAidAcre)) %>% 
#   ggplot(aes(reorder(x=District, sum.Acres),y = sum.Acres)) +
#   geom_bar(stat='identity') +
#   labs(x = "", y = "AA area (acres)", title = "Sum AA area") +
#   # coord_flip() +
#   scale_y_log10()
pl04 <- aaCtrd.ecoreg %>% 
  ggplot(aes(x=AAidAcre,y = District, fill= District)) +
  geom_boxploth() +
  labs(x = "Area (acres)", y = "", title = "Individual AA area by USACE District") +
  facet_wrap(~DIVISION, scales='free_y', ncol=2)+
  guides(fill=FALSE) +
  scale_x_log10(labels = scales::comma)
# if want to hide ALL legends: theme(legend.postion = "none")
pl04

# ggsave(filename = "v15_AAdistAreaBox.png",plot = pl04, width = 8, height = 8, dpi = 300)

AA area summary by PROVINCE

aaCtrd.ecoreg %>%
  group_by(PROVINCE) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  arrange(desc(sum.sqmiles)) %>% 
  datatable()

Analysis of AA NWI metadata

Image year for all AA

######
nwi.AAv15.summary <- aaCtrd.ecoreg %>%
  group_by(IMAGE_YR) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  filter(IMAGE_YR != "0") %>% 
  arrange(desc(IMAGE_YR))
datatable(nwi.AAv15.summary)

img.pl1 <- nwi.AAv15.summary %>% 
  ggplot(aes(x = IMAGE_YR, y = sum.aaAcre)) +
  geom_bar(stat='identity', color = 'black', fill = "ivory2") +
  labs(x = "NWI image year", y = "Area (acres)", title = "")
# img.pl1
img.pl2 <- nwi.AAv15.summary %>% 
  ggplot(aes(x = IMAGE_YR, y = cnt)) +
  geom_bar(stat='identity', color = 'black', fill = "ivory2") +
  labs(x = "NWI image year", y = "AA count", title = "")
# img.pl2
## save as a grid
# plot_grid(pl01, pl02, labels = c("A", "B"))
img.pl3 <- cowplot::plot_grid(img.pl1, img.pl2, labels = c("A", "B"), nrow = 1, align = "H")
img.pl3

# save_plot("v15_NWImeta_2panel.png", img.pl3, ncol = 2)

Image year by Division AA

# **Image year for all AA**
nwi.ImgYr.DIV.summary <- aaCtrd.ecoreg %>%
  group_by(IMAGE_YR, DIVISION) %>%
  summarize(cnt = n(), sum.aaAcre = sum(AAidAcre), sum.aaHa = sum(AAareaHa)) %>%
  mutate(sum.sqmiles = 0.00386102*sum.aaHa) %>% 
  filter(IMAGE_YR != "0") %>% 
  arrange(desc(IMAGE_YR))
datatable(nwi.ImgYr.DIV.summary)

imgDiv.pl1 <- nwi.ImgYr.DIV.summary %>% 
  ggplot(aes(x = IMAGE_YR, y = sum.aaAcre)) +
  geom_bar(stat='identity', color = 'black', fill = "ivory2") +
  labs(x = "NWI image year", y = "Area (acres)", title = "") +
  facet_wrap(~DIVISION, scales = 'free_y', ncol=2) +
  theme_smFacet
imgDiv.pl1

# ggsave("NWIimgYr_Divis_Acres.png", width = 6, height = 5, dpi = 300)
imgDiv.pl2 <- nwi.ImgYr.DIV.summary %>% 
  ggplot(aes(x = IMAGE_YR, y = cnt)) +
  geom_bar(stat='identity', color = 'black', fill = "ivory2") +
  labs(x = "NWI image year", y = "AA count", title = "") +
  facet_wrap(~DIVISION, scales = 'free_y', ncol=2) +
  theme_smFacet
imgDiv.pl2

# ggsave("NWIimgYr_Divis_Cnt.png", width = 6.5, height = 6, dpi = 300)
# ## save as a grid
# # plot_grid(pl01, pl02, labels = c("A", "B"))
# imgDiv.pl3 <- cowplot::plot_grid(imgDiv.pl1, imgDiv.pl2, labels = c("A", "B"), nrow = 1, align = "H")
# imgDiv.pl3
# # save_plot("v15_NWImeta_2panel.png", img.pl3, ncol = 2)

Analysis of wetland area: 3 factor and full NWI

Summary of wetland area across AA

v15NWIallType_3F_UNI <- read_csv("D:/Dropbox/PROJECTS/CORPS_NWI3P/RStudio_Projects/NWI_Analysis2016/data/Final_shapefile/V15_data/v15NWIallType_3F_UNI.csv")
Parsed with column specification:
cols(
  OBJECTID = col_integer(),
  AAv14id = col_character(),
  PolyAreaHa = col_double(),
  Shape_Length = col_double(),
  Shape_Area = col_double(),
  PolyTyUni = col_character()
)
# View(v15NWIallType_3F_UNI)
# join the aa
wetl.uni01 <- left_join(v15NWIallType_3F_UNI, aaCtrd.ecoreg, by = "AAv14id")
## quick check
# wetl.uni01 %>% 
#   names()
#  [1] "OBJECTID.x"   "AAv14id"      "PolyAreaHa"   "Shape_Length" "Shape_Area.x"
#  [6] "PolyTyUni"    "OBJECTID.y"   "Shape_Leng"   "Shape_Area.y" "AAidAcre"    
# [11] "AAareaHa"     "CenLat"       "CenLon"       "District"     "DIVISION"    
# [16] "US_L4CODE"    "US_L4NAME"    "US_L3NAME"    "NA_L3NAME"    "NA_L2NAME"   
# [21] "BlyDOMAIN"    "BlyDIVISION"  "PROVINCE"     "SECTION"      "STATE"       
# [26] "isoBioCli"
## total wetland area
# wetl.uni01 %>% 
#   names()
# unique(wetl.uni01$PolyTyUni)

Summarize area across all sites

###
uni.all <- wetl.uni01 %>% 
  # names() %>%
  group_by(PolyTyUni) %>%
  summarize(sum.areaHa = sum(PolyAreaHa)) %>%  
  mutate(Acres = sum.areaHa*2.47105) %>% 
  mutate(SqMile = Acres*0.0015625)
uni.all %>% datatable()

uni.all %>% 
  ggplot(aes(x = Acres, y = PolyTyUni)) +
  geom_barh(stat='identity') +
  labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "All mapped Cowardin types") +
  theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma)

# ggsave("AllCowTypeNWI_3F_union_Bar.png", width = 5.5, height = 4, dpi = 300)
###
AAv15.uni_wide1 <- wetl.uni01 %>% 
  group_by(AAv14id, PolyTyUni) %>%
  summarize(sum.areaHa = sum(PolyAreaHa)) %>%
  spread(key = PolyTyUni, value = sum.areaHa) %>% 
  rename(Wet3FonlyHa = Wet3Fonly) %>% 
  rename(WetNWIonlyHa = WetNWIonly) %>% 
  rename(WetUnionHa = WetUnion)
# this is only 1538 aaid. are the others with no area? need to check
# join with the AA centroid and ecoregion
AAv15.uni_wide1 <- left_join(aaCtrd.ecoreg, AAv15.uni_wide1, by = "AAv14id")
### replace NA with 0
AAv15.uni_wide1[is.na(AAv15.uni_wide1)] <- 0 # this replaces NA with 0 for all Columns
# ## SO example of changing for specific columns...
# x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
## GOF mapcurves
AAv15.uni_wide1 <- AAv15.uni_wide1 %>% 
  mutate(gof = ((WetUnionHa)/(WetUnionHa + WetNWIonlyHa))*((WetUnionHa)/(WetUnionHa + Wet3FonlyHa)))
## KEY calculations: 
AAv15.uni_wide1 <- AAv15.uni_wide1 %>% 
  # names() %>% 
  mutate(TotWetHa.nwi = WetNWIonlyHa + WetUnionHa) %>%
  mutate(TotWetHa.3f = Wet3FonlyHa + WetUnionHa) %>% 
  mutate(PercWetNWI = 100*TotWetHa.nwi/AAareaHa) %>% 
  mutate(PercWet3f = 100*TotWetHa.3f/AAareaHa) %>% 
  mutate(NDAI = (TotWetHa.3f-TotWetHa.nwi)/(TotWetHa.3f+TotWetHa.nwi))
AAv15.uni_wide1 %>% 
  # names() %>% 
  datatable() %>% 
  formatRound(columns=c("TotWetHa.nwi","TotWetHa.3f","PercWetNWI","PercWet3f", "NDAI","gof"), digits=2)

Division tidy

### Calcualte acres an tidy and plot
div.Acres <- AAv15.uni_wide1 %>% 
  dplyr::select(WetUnionHa, Wet3FonlyHa, WetNWIonlyHa, DIVISION) %>% 
  rename(Union = WetUnionHa, Only3F = Wet3FonlyHa, OnlyNWI = WetNWIonlyHa) %>% 
  gather(key = uniType, value = AreaHa, -DIVISION) %>% 
  mutate(AreaAcre = AreaHa*2.47105) %>% 
  group_by(uniType, DIVISION) %>%
  summarise(sum.Acre = sum(AreaAcre))
datatable(div.Acres)

###
div.Acres %>% 
  ggplot(aes(x= sum.Acre, y = uniType)) +
  geom_barh(stat='identity') +
  facet_wrap(~DIVISION, scales = "free") +
  labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "All mapped Cowardin types") +
  theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma)

div.Acres %>% 
  ggplot(aes(x= sum.Acre, y = DIVISION, fill = uniType)) +
  geom_barh(stat='identity', color = 'black') +
  facet_wrap(~DIVISION, scales = "free", ncol = 1) +
  labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "All mapped Cowardin types") +
  theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma) +
  theme(axis.ticks = element_blank(), axis.text.y = element_blank())

# ggsave("DivisionUniType.png", width = 6.5, height = 6, dpi = 300)
# uni.all %>% 
#   ggplot(aes(x = Acres, y = PolyTyUni)) +
#   geom_barh(stat='identity') +
#   labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "All mapped Cowardin types") +
#   theme_bw() +
#   # scale_x_log10(labels = scales::comma)
#   scale_x_continuous(labels = scales::comma)
### Calcualte acres an tidy and plot
## Baily provinces
Prov.Acres <- AAv15.uni_wide1 %>% 
  dplyr::select(WetUnionHa, Wet3FonlyHa, WetNWIonlyHa, PROVINCE) %>% 
  rename(Union = WetUnionHa, Only3F = Wet3FonlyHa, OnlyNWI = WetNWIonlyHa) %>% 
  gather(key = uniType, value = AreaHa, -PROVINCE) %>% 
  mutate(AreaAcre = AreaHa*2.47105) %>% 
  group_by(uniType, PROVINCE) %>%
  summarise(sum.Acre = sum(AreaAcre))
datatable(Prov.Acres)

###
Prov.Acres %>% 
  ggplot(aes(x= sum.Acre, y = uniType)) +
  geom_barh(stat='identity') +
  facet_wrap(~PROVINCE, scales = "free") +
  labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "All mapped Cowardin types") +
  theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma)

### filter out sites >50 acreas in AA size
Prov.Acres %>% 
  group_by(PROVINCE) %>% 
  mutate(sumAllPRovinceArea = sum(sum.Acre)) %>% 
  filter(sumAllPRovinceArea > 50) %>% 
  ggplot(aes(x= sum.Acre, y = PROVINCE, fill = uniType)) +
  geom_barh(stat='identity', color = 'black') +
  facet_wrap(~PROVINCE, scales = "free", ncol = 2) +
  labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "All mapped Cowardin types", fill="") +
  theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma) +
  theme(axis.ticks = element_blank(), axis.text.y = element_blank()) 

# ggsave("PROVINCWUniType.png", width = 12.5, height = 10, dpi = 300)

Percent of AA as NWI (all C types) and 3 factor

Summary: percent AA as NWI

## NWI
summary(AAv15.uni_wide1$PercWetNWI)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  0.000   0.000   2.911  14.020  17.280 100.000 
# dir()
# AAv15.uni_wide1 %>% 
#   summarise_at(.cols = PercWet3f,.funs = summary)

Summary: percent AA as 3F

summary(AAv15.uni_wide1$PercWet3f)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  0.0000   0.1669   3.0570  12.8500  13.6100 100.0000 
## all AA
AAv15.uni_wide1 %>% 
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.05, color = "blue") +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "All NWI Cowardin types") +
  theme_bw()

  # geom_hex()
# ggsave("AllNWICowardinTy_AllAA_percentAAWet.png", width = 5, height = 5, dpi = 300)

% AA full NWI by DIVISION

## AA by Division full NWI
AAv15.uni_wide1 %>% 
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.05, color = "blue") +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "Full NWI") +
  facet_wrap(~DIVISION, ncol = 4) +
  xlim(0,100) +
  ylim(0,100) +
  theme(strip.text.x = element_text(size = 8))

      
# ggsave(filename = "PercentAA_NWIallType.png", width = 5, height = 10, dpi = 300)
# ggsave(filename = "PercentAA_NWIallTypeW.png", width = 10, height = 5, dpi = 300)
AAv15.uni_wide1 %>%
  group_by(IMAGE_YR) %>% 
  summarize(mean.PercWetNWI = mean(PercWetNWI), sd.PercWetNWI = sd(PercWetNWI), mean.PercWet3f = mean(PercWet3f), sd.PercWet3f = sd(PercWet3f)) %>% 
  filter(IMAGE_YR != 0) %>% 
  mutate(YrBin = ifelse(IMAGE_YR <= 1979, "1970's",
               ifelse(IMAGE_YR >= 1980 & IMAGE_YR < 1990, "1980's",ifelse(IMAGE_YR >= 1990 & IMAGE_YR <2000, "1990's", "2000's")))) %>%
  ggplot(aes(x = mean.PercWetNWI, y = mean.PercWet3f)) + 
  geom_point(alpha = 0.25, color = "blue", size = 6) +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "") +
  facet_wrap(~YrBin, ncol = 2, scales = "free") +
  # xlim(0,100) +
  # ylim(0,100) +
  theme(strip.text.x = element_text(size = 8)) +
  theme_smFacet

####
AAv15.uni_wide1 %>%
  # group_by(IMAGE_YR) %>% 
  # summarize(mean.PercWetNWI = mean(PercWetNWI), sd.PercWetNWI = sd(PercWetNWI), mean.PercWet3f = mean(PercWet3f), sd.PercWet3f = sd(PercWet3f)) %>% 
  filter(IMAGE_YR != 0) %>% 
  mutate(YrBin = ifelse(IMAGE_YR <= 1979, "1970's",
               ifelse(IMAGE_YR >= 1980 & IMAGE_YR < 1990, "1980's",ifelse(IMAGE_YR >= 1990 & IMAGE_YR <2000, "1990's", "2000's")))) %>%
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.085, color = "blue", size = 3) +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "") +
  facet_wrap(~YrBin, ncol = 2, scales = "free") +
  # xlim(0,100) +
  # ylim(0,100) +
  theme(strip.text.x = element_text(size = 8)) +
  theme_smFacet

# ggsave("NWI_ImgBin_scatterPercent.png", width = 6, height = 5, dpi = 300)

Percent of AA as NWI (REDUCED C types) and 3 factor

This ihas been rduced by eliminating NWI polygons in the followong Cowardin classes: 1. Riverine 1. Lacustrine 1. Other 1. Marine Deep Water

t1 <- gsub("\\.shp$","", list.files("data/Final_shapefile/v15_data", pattern="shp$", full.names=TRUE, recursive = FALSE))
# t2 <- gsub("\\.shp$","", dir("data/Final_shapefile/v15_data", pattern="shp$", full.names=TRUE, recursive = FALSE)) # Note list.files and dir seem to do the exact smae thing...
nwiRed01.tbl <- map2(.x = "data/Final_shapefile/v15_data", .y = "FinNWI_noPoLacRiv_3Funi", .f =  readOGR) 
OGR data source with driver: ESRI Shapefile 
Source: "data/Final_shapefile/v15_data", layer: "FinNWI_noPoLacRiv_3Funi"
with 49274 features
It has 14 fields
Z-dimension discarded
nwiRed01.tbl <- as_tibble(nwiRed01.tbl[[1]]@data) 
names(nwiRed01.tbl)
 [1] "OBJECTID"   "FID_FinNWI" "AAv14id"    "WETLAND_TY" "PolyAreaM2"
 [6] "PolyAreaHa" "PolyType"   "FID_Fin3F_" "AAv14id_1"  "PolyType_1"
[11] "Shape_Leng" "Shape_Area" "PolyTyUni"  "UniClass"  
# aacentr.tbl %>% datatable()
## summarize total AA area
nwiRed01.tbl %>% 
  # names() %>%
  summarize(sum.areaHa = sum(PolyAreaHa), cnt.AApoly = n()) %>%
  mutate(sum.Acres = 2.47105*sum.areaHa) %>% 
  mutate(sum.sqmiles = 0.00386102*sum.areaHa) %>% 
  datatable()
# join the aa, eroregion stuff
wetl.uni01red <- left_join(nwiRed01.tbl, aaCtrd.ecoreg, by = "AAv14id")
joining character vector and factor, coercing into character vector
## reduced NWI
uni.all.red <- wetl.uni01red %>% 
  # names() %>%
  group_by(PolyTyUni) %>%
  summarize(sum.areaHa = sum(PolyAreaHa)) %>%  
  mutate(Acres = sum.areaHa*2.47105) %>% 
  mutate(SqMile = Acres*0.0015625)
uni.all.red %>% datatable()

uni.all.red  %>% 
  ggplot(aes(x = Acres, y = PolyTyUni)) +
  geom_barh(stat='identity') +
  labs(y = "", x = "Area (acres)", fill = "", title = "Mapped area by geometric union", subtitle = "Reduced set of Cowardin types") +
  # theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma) +
  theme_CowsMod1

wetl.uni01red %>% 
  # names() %>%
  group_by(PolyTyUni) %>%
  summarize(sum.areaHa = sum(PolyAreaHa)) %>%  
  mutate(WetAcres = sum.areaHa*2.47105) %>% 
  mutate(WetSqMile = WetAcres*0.0015625)

DIVISION: NWI reduced Acreas stacked bar

### reduced wetland type
## DIVSION sum 
red.tdy <- left_join(aaCtrd.ecoreg, nwiRed01.tbl, by = "AAv14id")
joining factor and character vector, coercing into character vector
red.tdy %>% 
  group_by(PolyTyUni) %>% 
  summarise(sum.areaHa = sum(PolyAreaHa)) %>% 
  mutate(sum.acre = sum.areaHa*2.47105)
div.Acres.red <- red.tdy %>% 
  dplyr::select(PolyTyUni, DIVISION, PolyAreaHa) %>% 
  mutate(AreaAcre = PolyAreaHa*2.47105) %>% 
  na.omit() %>% 
  group_by(PolyTyUni, DIVISION) %>%
  summarise(sum.Acre = sum(AreaAcre))
# datatable(div.Acres)
###
div.Acres.red %>%
  ggplot(aes(x= sum.Acre, y = PolyTyUni)) +
  geom_barh(stat='identity') +
  facet_wrap(~DIVISION, scales = "free", ncol = 4)

div.Acres.red %>% 
  ggplot(aes(x= sum.Acre, y = DIVISION, fill = PolyTyUni)) +
  geom_barh(stat='identity', color = 'black') +
  facet_wrap(~DIVISION, scales = "free", ncol = 1) +
  labs(y = "", x = "Area (acres)",fill = "") +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma) +
  theme(axis.ticks = element_blank(), axis.text.y = element_blank())

# ggsave("DivisionUniType_Reduced.png", width = 6.5, height = 6, dpi = 300)
# reduced nwi
wetl.uni01red_wide1 <- wetl.uni01red %>% 
  group_by(AAv14id, PolyTyUni) %>%
  summarize(sum.areaHa = sum(PolyAreaHa)) %>%
  spread(key = PolyTyUni, value = sum.areaHa) %>% 
  rename(Wet3FonlyHa = Wet3Fonly) %>% 
  rename(WetNWIonlyHa = WetNWIonly) %>% 
  rename(WetUnionHa = WetUnion)
# this is only 1499 (from 1538 aaid for the nwi full 3f uni layer). 
# Need to check
# join with the AA centroid and ecoregion
wetl.uni01red_wide1 <- left_join(aaCtrd.ecoreg, wetl.uni01red_wide1, by = "AAv14id")
### replace NA with 0
wetl.uni01red_wide1[is.na(wetl.uni01red_wide1)] <- 0 # this replaces NA with 0 for all Columns
# ## SO example of changing for specific columns...
# x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
## GOF mapcurves
wetl.uni01red_wide1 <- wetl.uni01red_wide1 %>% 
  mutate(gof = ((WetUnionHa)/(WetUnionHa + WetNWIonlyHa))*((WetUnionHa)/(WetUnionHa + Wet3FonlyHa)))
## KEY calculations: 
wetl.uni01red_wide1 <- wetl.uni01red_wide1 %>% 
  # names() %>% 
  mutate(TotWetHa.nwi = WetNWIonlyHa + WetUnionHa) %>%
  mutate(TotWetHa.3f = Wet3FonlyHa + WetUnionHa) %>% 
  mutate(PercWetNWI = 100*TotWetHa.nwi/AAareaHa) %>% 
  mutate(PercWet3f = 100*TotWetHa.3f/AAareaHa) %>% 
  mutate(NDAI = (TotWetHa.3f-TotWetHa.nwi)/(TotWetHa.3f+TotWetHa.nwi))
wetl.uni01red_wide1 %>% 
  # names() %>% 
  datatable() %>% 
  formatRound(columns=c("TotWetHa.nwi","TotWetHa.3f","PercWetNWI","PercWet3f", "NDAI","gof"), digits=2)
## all AA: comparison of reduced and full nwi
b1 <- AAv15.uni_wide1 %>% 
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.05, color = "blue") +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "All NWI Cowardin types") +
  theme_bw()
  # geom_hex()
b2 <- wetl.uni01red_wide1 %>% 
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.05, color = "blue") +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "Reduced NWI Cowardin types") +
  theme_bw()
  # geom_hex()
# ggsave("ReducedNWICowardinTy_AllAA_percentAAWet.png", width = 5, height = 5, dpi = 300)
b3 <- plot_grid(b1, b2, labels = c("A", "B"), align = "h")
# save_plot("v15_NWIred.png", b3, ncol = 2)

Reduced: difference in %AA

  • Summary of the %AA for all sites*
## calc the diff
wetl.uni01red_wide1 <- wetl.uni01red_wide1 %>% 
  mutate(diff.AApercWet = PercWet3f-PercWetNWI)
Some.wet.aa <- wetl.uni01red_wide1 %>%
  mutate(combined_WetArea = TotWetHa.3f + TotWetHa.nwi) %>% 
  filter(combined_WetArea >0)
summary(Some.wet.aa$diff.AApercWet)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
-100.0000   -3.4770    0.7392    1.6750    6.5000  100.0000 
##
areaZ.wide <- wetl.uni01red_wide1 %>% 
  dplyr::select(AAv14id, AAareaHa, PercWet3f, PercWetNWI,TotWetHa.nwi, TotWetHa.3f)
areaZ.tidy <- areaZ.wide %>% 
  gather(key = PropVar, value = Prop, PercWet3f:PercWetNWI) %>% 
  gather(key = AreaHaVar, value = AreaHa, TotWetHa.nwi:TotWetHa.3f)
areaZ.tidy %>% 
  ggplot(aes(x=AreaHaVar, y = AreaHa)) +
  geom_boxplot()

areaZ.tidy %>% 
  ggplot(aes(x=PropVar, y = Prop)) +
  geom_boxplot()

## AA by Division: REDUCED
wetl.uni01red_wide1 %>% 
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.05, color = "blue") +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "Proportion of AA mapped by 3F and NWI (reduced Cowardin types)") +
  facet_wrap(~DIVISION, ncol = 4) +
  xlim(0,100) +
  ylim(0,100) +
  # theme(strip.text.x = element_text(size = 8))
  theme_smFacet

  # theme_CowsMod1
      
# ggsave(filename = "PercentAA_NWIreducedTypeN.png", width = 5, height = 10, dpi = 300)
# ggsave(filename = "PercentAA_NWIreducedTypeW.png", width = 10, height = 5, dpi = 300)
wetl.uni01red_wide1 %>%
  group_by(IMAGE_YR) %>% 
  summarize(mean.PercWetNWI = mean(PercWetNWI), sd.PercWetNWI = sd(PercWetNWI), mean.PercWet3f = mean(PercWet3f), sd.PercWet3f = sd(PercWet3f)) %>% 
  filter(IMAGE_YR != 0) %>% 
  mutate(YrBin = ifelse(IMAGE_YR <= 1979, "1970's",
               ifelse(IMAGE_YR >= 1980 & IMAGE_YR < 1990, "1980's",ifelse(IMAGE_YR >= 1990 & IMAGE_YR <2000, "1990's", "2000's")))) %>%
  ggplot(aes(x = mean.PercWetNWI, y = mean.PercWet3f)) + 
  geom_point(alpha = 0.25, color = "blue", size = 6) +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "") +
  facet_wrap(~YrBin, ncol = 2, scales = "free") +
  # xlim(0,100) +
  # ylim(0,100) +
  theme(strip.text.x = element_text(size = 8)) +
  theme_smFacet

####
wetl.uni01red_wide1 %>%
  # group_by(IMAGE_YR) %>% 
  # summarize(mean.PercWetNWI = mean(PercWetNWI), sd.PercWetNWI = sd(PercWetNWI), mean.PercWet3f = mean(PercWet3f), sd.PercWet3f = sd(PercWet3f)) %>% 
  filter(IMAGE_YR != 0) %>% 
  mutate(YrBin = ifelse(IMAGE_YR <= 1979, "1970's",
               ifelse(IMAGE_YR >= 1980 & IMAGE_YR < 1990, "1980's",ifelse(IMAGE_YR >= 1990 & IMAGE_YR <2000, "1990's", "2000's")))) %>%
  ggplot(aes(x = PercWetNWI, y = PercWet3f)) + 
  geom_point(alpha = 0.085, color = "blue", size = 3) +
  geom_smooth(color = "red", method = "lm") +
  geom_abline(slope = 1, intercept = 0, lty = 'dashed', size = 1.1, alpha = .4) +
  # geom_density_2d() +
  labs(x = "% AA mapped as NWI", y = "% AA mapped as 3 factor", title = "Reduced Cowardin types") +
  facet_wrap(~YrBin, ncol = 2, scales = "free") +
  # xlim(0,100) +
  # ylim(0,100) +
  theme(strip.text.x = element_text(size = 8)) +
  theme_smFacet

# ggsave("NWI_ImgBin_scatterPercent_reduced.png", width = 6, height = 5, dpi = 300)

Division: NDAI reduced NWI

pl06 <- wetl.uni01red_wide1 %>%
  group_by(DIVISION) %>% 
  mutate(mean.NDAI = mean(NDAI, na.rm = TRUE)) %>% 
  # names() %>% 
  ggplot(aes(x=NDAI, y = reorder(DIVISION, mean.NDAI))) +
  geom_boxploth(fill = "ivory2") +
  # geom_jitter(color = "blue", alpha=0.05, size = 2) +
  geom_vline(xintercept = 0, size=1.5, color = "red", lty = "dashed", alpha = 0.5) +
  labs(y="", title = "Normalized Difference Area Index", subtitle = "Reduced set of Cowardin types") +
  theme_CowsMod1
# # save_plot(plot = pl06, filename = "DIVISION_NDAI_boxplot_Red.png")
# ggsave(filename = "Division_NDAI_boxplotNoJit_red.png", plot = pl06, dpi = 300, width = 7.5, height = 4)
pl06

District: NDAI

pl07 <- wetl.uni01red_wide1 %>% 
  # mutate(mean.NDAI = mean(NDAI, na.rm = TRUE)) %>%
  group_by(District) %>% 
  mutate(med.NDAI = median(NDAI, na.rm = TRUE)) %>%
  mutate(cnt = n()) %>% 
  filter(cnt >= 15) %>% 
  # names() %>% 
  ggplot(aes(x=NDAI, y = reorder(District,med.NDAI))) +
  geom_boxploth(fill = "ivory2") +
  # geom_jitter(color = "blue", alpha=0.05, size = 2) +
  geom_vline(xintercept = 0, size=1.5, color = "red", lty = "dashed", alpha = 0.5) +
  labs(y="", title = "Normalized Difference Area Index", subtitle = "Reduced set of Cowardin types") +
  theme_CowsMod1
# ggsave(filename = "District_NDAI_boxplotNojitter_red.png", plot = pl07, dpi = 300, width = 7.5, height = 6)
pl07

Province: NDAI (#fail)

## can't get this shit to work...

pl08 <- wetl.uni01red_wide1 %>% 
  # mutate(mean.NDAI = mean(NDAI, na.rm = TRUE)) %>%
  group_by(PROVINCE) %>% 
  mutate(med.NDAI = median(NDAI, na.rm = TRUE)) %>%
  mutate(cnt = n()) %>% 
  filter(cnt >= 15) %>% 
  # names() %>% 
  ggplot(aes(x=NDAI, y = reorder(PROVINCE,med.NDAI))) +
  geom_boxploth(fill = "ivory2") +
  # geom_jitter(color = "blue", alpha=0.05, size = 2) +
  geom_vline(xintercept = 0, size=1.5, color = "red", lty = "dashed", alpha = 0.5) +
  labs(y="", title = "Normalized Difference Area Index", subtitle = "Reduced set of Cowardin types") +
  theme_smFacet +
  theme(axis.ticks.y = element_blank(), axis.text.y = element_blank()) +
  # theme_CowsMod1
  facet_wrap(~PROVINCE, ncol = 1)


ggsave(filename = "BlyProvince_NDAI_boxplot_red.png", plot = pl08, dpi = 300, width = 8.5, height = 15)

pl08
####
disti.ndai.sum <- wetl.uni01red_wide1 %>% 
  group_by(District) %>% 
  summarise(cnt = n(), mean.ndai = mean(NDAI, na.rm=TRUE), med.ndai = median(NDAI, na.rm=TRUE), q25.ndai = quantile(NDAI,prob = .25, na.rm=TRUE), q75.ndai = quantile(NDAI,prob = .75, na.rm=TRUE))
disti.ndai.sum %>% 
  datatable() %>% 
  formatRound(~mean.ndai + med.ndai + q25.ndai + q75.ndai, 2)

## error bar with median NDAI
disti.ndai.sum %>% 
  filter(cnt >= 30) %>%
  ggplot(aes(x=med.ndai, y = reorder(District, med.ndai))) +
  geom_errorbarh(aes(xmin= q25.ndai, xmax = q75.ndai)) +
  geom_point(size = 4.5, color = "red")

########
## Note cool use of summarize_at
########
wetl.uni01red_wide1 %>% 
  summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd', 'median'))
## DIVISION
wetl.uni01red_wide1 %>% 
  group_by(DIVISION) %>%
  summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd')) %>% 
  datatable() %>% 
  formatRound(~AAareaHa_mean + PercWet3f_mean + PercWetNWI_mean + AAareaHa_sd + PercWet3f_sd + PercWetNWI_sd, 2)

## DISTRICT
wetl.uni01red_wide1 %>% 
  group_by(District) %>%
  summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd')) %>% 
  # names() %>% 
  datatable() %>% 
  formatRound(~AAareaHa_mean + PercWet3f_mean + PercWetNWI_mean + AAareaHa_sd + PercWet3f_sd + PercWetNWI_sd, 2)

  
## US_L3NAME
wetl.uni01red_wide1 %>% 
  group_by(US_L3NAME) %>%
  summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd')) %>% 
  # names() %>% 
  datatable() %>% 
  formatRound(~AAareaHa_mean + PercWet3f_mean + PercWetNWI_mean + AAareaHa_sd + PercWet3f_sd + PercWetNWI_sd, 3)

Difference in the %AA mapped as wetland

## historgram of the $ diff in % AA mapped
# wetl.uni01red_wide1 %>% 
#   ggplot(aes(x=diff.AApercWet)) +
#   geom_histogram()
wetl.uni01red_wide1 %>% 
  ggplot(aes(x=diff.AApercWet)) +
  geom_density(fill = 'ivory2') +
  geom_vline(xintercept = 0, size = 1.2, lty = "dashed", color = "red", alpha = .2) +
  labs(x = "Difference in %AA mapped", y = "Density")

# ggsave("DiffInPercAAasWet.png", width = 5.5, height = 5, dpi = 300)
## DIVISION
wetl.uni01red_wide1 %>% 
  group_by(DIVISION) %>%
  summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd')) %>% 
  ggplot(aes(x = diff.AApercWet_mean
, y = reorder(DIVISION,diff.AApercWet_mean))) +
geom_point()

## plot faceted version of graph
wetl.uni01red_wide1 %>% 
  ggplot(aes(x=diff.AApercWet)) +
  geom_density(fill = 'ivory2') +
  geom_vline(xintercept = 0, size = 1.2, lty = "dashed", color = "red", alpha = .2) +
  labs(x = "Difference in %AA mapped", y = "Density") +
  facet_wrap(~DIVISION, ncol = 2, scales = 'free_y') +
  theme_smFacet

# ggsave("DiffInPercAAasWet_DIVden.png", width = 7.5, height = 6, dpi = 300)
# ## DISTRICT
# wetl.uni01red_wide1 %>% 
#   group_by(District) %>%
#   summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd')) %>% 
#   # names() %>% 
#   datatable() %>% 
#   formatRound(~AAareaHa_mean + PercWet3f_mean + PercWetNWI_mean + AAareaHa_sd + PercWet3f_sd + PercWetNWI_sd, 2)
#   
# 
# ## US_L3NAME
# wetl.uni01red_wide1 %>% 
#   group_by(US_L3NAME) %>%
#   summarise_at(c('AAareaHa','PercWet3f','PercWetNWI','diff.AApercWet'),c('mean','sd')) %>% 
#   # names() %>% 
#   datatable() %>% 
#   formatRound(~AAareaHa_mean + PercWet3f_mean + PercWetNWI_mean + AAareaHa_sd + PercWet3f_sd + PercWetNWI_sd, 3)
## NDAI 
## plot: reduced NWI
wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  ggplot(aes(x=NDAI)) +
  geom_density(alpha = 0.4, fill = 'ivory2', color = "black") +
  geom_vline(xintercept = 0, color = 'red', size = 1.15, lty = "dashed") +
  facet_wrap(~DIVISION, ncol = 2, scale = 'free_y') +
  labs(x="NDAI", y = "Density", title = "NDAI by USACE Division") +
  theme(legend.position = "none")

# ggsave(file="NDAI_Division_Density_red.png", width = 7.5, height = 6, dpi = 300)
## histogram: reduced NWI
wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  ggplot(aes(x=NDAI)) +
  geom_histogram(alpha = 0.4, fill = 'ivory2', color = "black") +
  geom_vline(xintercept = 0, color = 'red', size = 1.15, lty = "dashed") +
  facet_wrap(~DIVISION, ncol = 2, scale = 'free_y') +
  labs(x="NDAI", y = "AA count", title = "NDAI by USACE Division") +
  theme(legend.position = "none")

# ggsave(file="NDAI_Division_histogram_red.png", width = 7.5, height = 6, dpi = 300)

USACE Division – Mapcurves GOF

gof.div.plot <- wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  ggplot(aes(x=gof)) +
  geom_density(color = "black", alpha = 0.45, fill = "ivory2") +
  # geom_vline(xintercept = 0, color = 'red', size = 1.15, lty = "dashed") +
  facet_wrap(~DIVISION, ncol = 2, scale = 'free') +
  labs(x="Goodness of fit", y = "Density", title = "Mapcurves goodness of fit by USACE Division") +
  theme(legend.position = "none")
# gof.div.plot %>% 
#   ggsave(file = "GOF_Division_red.png", width = 7, height = 7, dpi = 300)
## histgram
gof.div.hist <- wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  ggplot(aes(x=gof)) +
  geom_histogram(color = "black", alpha = 0.45, fill = "ivory2") +
  # geom_vline(xintercept = 0, color = 'red', size = 1.15, lty = "dashed") +
  facet_wrap(~DIVISION, ncol = 2, scale = 'free_y') +
  labs(x="Goodness of fit", y = "AA count", title = "Mapcurves goodness of fit by USACE Division") +
  theme(legend.position = "none")
# ggsave(file="GOF_Division_histogram_red2.png", width = 6.85, height = 6, dpi = 300)
gof.div.hist

## boxplots
wetl.uni01red_wide1 %>% 
  geom_histogram(color = "black", alpha = 0.45, fill = "ivory2") +
  # geom_vline(xintercept = 0, color = 'red', size = 1.15, lty = "dashed") +
  facet_wrap(~DIVISION, ncol = 2, scale = 'free_y') +
  labs(x="Goodness of fit", y = "AA count", title = "Mapcurves goodness of fit by USACE Division") +
  theme(legend.position = "none") +
  coord_flip()

# ggsave(file="GOF_Division_histogram_redalt.png", width = 7.5, height = 6, dpi = 300)
gof.div.hist

Baily province

Prov.Acres.red <- wetl.uni01red_wide1  %>% 
  dplyr::select(WetUnionHa, Wet3FonlyHa, WetNWIonlyHa, PROVINCE) %>% 
  rename(Union = WetUnionHa, Only3F = Wet3FonlyHa, OnlyNWI = WetNWIonlyHa) %>% 
  gather(key = uniType, value = AreaHa, -PROVINCE) %>% 
  mutate(AreaAcre = AreaHa*2.47105) %>% 
  group_by(uniType, PROVINCE) %>%
  summarise(sum.Acre = sum(AreaAcre))
datatable(Prov.Acres.red)

###
# Prov.Acres.red %>% 
#   ggplot(aes(x= sum.Acre, y = uniType)) +
#   geom_barh(stat='identity') +
#   facet_wrap(~PROVINCE, scales = "free") +
#   labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "Subset Cowardin types") +
#   theme_bw() +
#   # scale_x_log10(labels = scales::comma)
#   scale_x_continuous(labels = scales::comma)
### filter out sites >50 acreas in AA size
Prov.Acres.red %>% 
  group_by(PROVINCE) %>% 
  mutate(sumAllPRovinceArea = sum(sum.Acre)) %>% 
  filter(sumAllPRovinceArea > 50) %>% 
  ggplot(aes(x= sum.Acre, y = PROVINCE, fill = uniType)) +
  geom_barh(stat='identity', color = 'black') +
  facet_wrap(~PROVINCE, scales = "free", ncol = 2) +
  labs(y = "", x = "Area (acres)", title = "Mapped area by geometric union", subtitle = "Subset of Cowardin types", fill="") +
  theme_bw() +
  # scale_x_log10(labels = scales::comma)
  scale_x_continuous(labels = scales::comma) +
  theme(axis.ticks = element_blank(), axis.text.y = element_blank()) 

# ggsave("DivisionUniType.png", width = 9.5, height = 10, dpi = 300)

Bailey Section – Mapcurves GOF

gof.BlyProvince.plot <- wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(PROVINCE) %>% 
  mutate(cnt_by_prov  = n()) %>% 
  filter(cnt_by_prov >= 30) %>% 
  ggplot(aes(x=gof)) +
  geom_density(color = "black", alpha = 0.45, fill = "ivory2") +
  # geom_vline(xintercept = 0, color = 'red', size = 1.15, lty = "dashed") +
  facet_wrap(~PROVINCE, ncol = 1) +
  labs(x="Goodness of fit", y = "Density", title = "Mapcurves goodness of fit by Bailey Province") +
  theme(legend.position = "none") +
  theme_CowsMod1
gof.BlyProvince.plot
gof.BlyProvince.plot %>%
  ggsave(file = "GOF_BlyProvince_red.png", width = 7, height = 10, dpi = 300)

## Datatble
wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(PROVINCE) %>% 
  mutate(cnt_by_prov  = n()) %>% 
  datatable(caption = "GOF reduced NWI Baily Province")

Difference in % mapped by NWI

wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(IMAGE_YR) %>% 
  summarize(cnt_by_prov  = n(), mean.PercWetNWI = mean(PercWetNWI), mean.PercWet3f = mean(PercWet3f),sum.AAv15Acre = sum(AAidAcre)) %>% 
  mutate(dif.PercAA3F_NWI = mean.PercWet3f-mean.PercWetNWI) %>% 
  mutate(wt.mn = map2_dbl(.x = dif.PercAA3F_NWI, .y = sum.AAv15Acre, .f=weighted.mean)) %>% 
  filter(IMAGE_YR >0) %>% 
  ggplot(aes(x=IMAGE_YR, y = dif.PercAA3F_NWI)) +
  geom_hline(yintercept = 0, color='red', size=1.2, alpha=0.5) +
  geom_point(aes(size=sum.AAv15Acre), color = "blue", alpha = .3) +
  labs(x = "NWI image year", y = "Difference in % AA mapped", title = "All AA - Reduced NWI") +
  # theme_CowsMod1
  theme_smFacet +
  theme(legend.position="none") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ylim(-100,100) 
  # geom_smooth(method = "lm", se = FALSE, lty = "dashed", color = 'black')
ggsave("DiffernceMappedNWIred_AllAA_reduced.png", width = 5.5, height = 3.5, dpi = 300)

## datatable
wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(IMAGE_YR) %>% 
  summarize(cnt_by_prov  = n(), mean.PercWetNWI = mean(PercWetNWI), mean.PercWet3f = mean(PercWet3f),sum.AAv15Acre = sum(AAidAcre)) %>% 
  mutate(dif.PercAA3F_NWI = mean.PercWet3f-mean.PercWetNWI) %>% 
  filter(IMAGE_YR >0) %>% 
  datatable(filter = 'top',caption = "mean_AAdiff")

Difference in percent AA mapped by 3f and reduced NWI DISTRICT

wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(District, IMAGE_YR) %>% 
  summarize(cnt_by_prov  = n(), mean.PercWetNWI = mean(PercWetNWI), mean.PercWet3f = mean(PercWet3f),sum.AAv15Acre = sum(AAidAcre)) %>% 
  mutate(dif.PercAA3F_NWI = mean.PercWet3f-mean.PercWetNWI) %>% 
  mutate(wt.mn = map2_dbl(.x = dif.PercAA3F_NWI, .y = sum.AAv15Acre, .f=weighted.mean)) %>% 
  filter(IMAGE_YR >0) %>% 
  ggplot(aes(x=IMAGE_YR, y = dif.PercAA3F_NWI)) +
  geom_hline(yintercept = 0, color='red', size=1.2, alpha=0.5) +
  geom_point(aes(size=sum.AAv15Acre), color = "blue", alpha = .3) +
  labs(x = "NWI image year", y = "Difference in % AA mapped", title = "Reduced NWI") +
  facet_wrap(~District) +
  # theme_CowsMod1
  theme_smFacet +
  theme(legend.position="none") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ylim(-100,100)

# ggsave("DiffernceMappedNWIred_District.png", width = 7.5, height = 5.5, dpi = 300)

Difference in percent AA mapped by 3f and reduced NWI DIVISION

wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(DIVISION, IMAGE_YR) %>% 
  summarize(cnt_by_prov  = n(), mean.PercWetNWI = mean(PercWetNWI), mean.PercWet3f = mean(PercWet3f),sum.AAv15Acre = sum(AAidAcre)) %>% 
  mutate(dif.PercAA3F_NWI = mean.PercWet3f-mean.PercWetNWI) %>% 
  mutate(wt.mn = map2_dbl(.x = dif.PercAA3F_NWI, .y = sum.AAv15Acre, .f=weighted.mean)) %>% 
  filter(IMAGE_YR >0) %>% 
  ggplot(aes(x=IMAGE_YR, y = dif.PercAA3F_NWI)) +
  geom_hline(yintercept = 0, color='red', size=1.2, alpha=0.5) +
  geom_point(aes(size=sum.AAv15Acre), color = "blue", alpha = .3) +
  labs(x = "NWI image year", y = "Difference in % AA mapped", title = "Reduced NWI") +
  facet_wrap(~DIVISION, ncol = 4) +
  # theme_CowsMod1
  theme_smFacet +
  theme(legend.position="none") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
  ylim(-100,100) +
  geom_smooth(method = "lm", se = FALSE, lty = "dashed", size = 1, color = 'black')

# ggsave("DiffernceMappedNWIred_Division.png", width = 8, height = 3.75, dpi = 300)
wetl.uni01red_wide1 %>% 
  # filter(cnt >= 7) %>% 
  group_by(DIVISION, IMAGE_YR) %>% 
  summarize(cnt_by_prov  = n(), mean.PercWetNWI = mean(PercWetNWI), mean.PercWet3f = mean(PercWet3f),sum.AAv15Acre = sum(AAidAcre)) %>% 
  mutate(dif.PercAA3F_NWI = mean.PercWet3f-mean.PercWetNWI) %>% 
  mutate(wt.mn = map2_dbl(.x = dif.PercAA3F_NWI, .y = sum.AAv15Acre, .f=weighted.mean)) %>% 
  filter(IMAGE_YR >0) %>% 
  datatable(filter = 'top')
# export a version of the wide AA with all the stuff for jpining in Arc
# wetl.uni01red_wide1 %>% 
#   write_csv("Wide_NWIred_3F_uni_CALCs_for_AAv15join.csv")

Regression modeling

Reduced NWI by DIVISION

uni.red.DIV.nDF <- wetl.uni01red_wide1 %>%
  group_by(DIVISION) %>% 
  nest()
  
uni.red.DIV.nDF <- uni.red.DIV.nDF %>% 
  mutate(model01 = purrr::map(data, ~ lm(TotWetHa.nwi ~ TotWetHa.3f, data = .))
)  
# Extract model summaries:
uni.red.DIV.nDF <- uni.red.DIV.nDF %>% unnest(model01 %>% purrr::map(broom::glance))
uni.red.DIV.nDF %>% 
  ggplot(aes(x = adj.r.squared, y= reorder(DIVISION,adj.r.squared))) +
  # geom_barh(stat = 'identity', aes(fill = p.value)) +
  geom_barh(stat = 'identity', fill = 'ivory2', color = 'ivory3') +
  labs(x=expression('adjusted R'^{2}), y = "", title = "Linear models: 3F area ~ NWI area") +
  theme_CowsMod1

# ggsave("LinerModels_Division_red.png", dpi = 300, width = 7.5, height = 3)
# # Extract model summaries:
# by_country %>% unnest(model %>% purrr::map(broom::glance))
## data table
uni.red.DIV.nDF %>% 
  datatable(filter='top')

NWI image year: adjust R2 lm

uni.red.ImgYr.nDF <- wetl.uni01red_wide1 %>%
  filter(IMAGE_YR >0) %>% 
  group_by(IMAGE_YR) %>% 
  mutate(cnt = n()) %>%
  filter(cnt>=25) %>% # note need to filter to have >1 record. I'm going for minimum n of 25 AA in that particular 
  nest() %>% 
  mutate(model01 = purrr::map(data, ~ lm(TotWetHa.nwi ~ TotWetHa.3f, data = .)))
  
# uni.red.ImgYr.nDF <- uni.red.ImgYr.nDF %>% 
#   mutate(model02 = purrr::map(data, ~ lm(TotWetHa.nwi ~ TotWetHa.3f, data = .)))  
# Extract model summaries:
uni.red.ImgYr.nDF <- uni.red.ImgYr.nDF %>% unnest(model01 %>% purrr::map(broom::glance))
uni.red.ImgYr.nDF %>% 
  # ggplot(aes(x = adj.r.squared, y= reorder(IMAGE_YR,adj.r.squared))) +
  # ggplot(aes(x = IMAGE_YR, y = adj.r.squared)) +
  ggplot(aes(x = IMAGE_YR, y = adj.r.squared)) +
  # geom_barh(stat = 'identity', aes(fill = p.value)) +
  geom_bar(stat = 'identity', fill = 'ivory2', color = 'ivory3') +
  geom_point() +
  xlim(1970,2010) +
  labs(y=expression('adjusted r'^{2}), x = "NWI image year", title = "Linear models: 3F area ~ NWI area")

## data table
uni.red.ImgYr.nDF %>% 
  datatable(filter='top')

NA

Climate modeling:

# wetl.uni01red_wide1
vpd.aa <- read_csv("data/Final_shapefile/V15_data/v15centrPRISMNormal_LU.csv")
vpd.aa <- vpd.aa %>% 
  dplyr::select(AAv14id, vpdMx30yr, PrismPPT, PrismTMean) %>% 
  na.omit()
#join with the tabulated full data set
vpd.aa <- left_join(vpd.aa, wetl.uni01red_wide1, by = "AAv14id")
vpd.aa %>% 
  mutate(PercAAWetDiff3f.redNWI = PercWet3f-PercWetNWI) %>% 
  mutate(vpdInt = as.integer(vpdMx30yr)) %>% 
  ggplot(aes(x = vpdMx30yr, y = PercAAWetDiff3f.redNWI)) +
  # geom_point(alpha = 0.05) +
  # geom_density_2d() +
  geom_smooth(method = 'lm') +
  geom_hline(yintercept = 0, color = 'red', alpha=0.41, lty = 'dashed', size = 1.2) +
  scale_y_continuous(limits = quantile(vpd.aa$PercAAWetDiff3f.redNWI, c(0.05, 0.95)))
Unknown column 'PercAAWetDiff3f.redNWI'

### boxplots!
pp1 <- vpd.aa %>% 
  mutate(PercAAWetDiff3f.redNWI = PercWet3f-PercWetNWI) %>% 
  mutate(vpdInt = as.factor(as.integer(vpdMx30yr))) %>% 
  ggplot(aes(x = vpdMx30yr, y = PercAAWetDiff3f.redNWI)) +
  geom_boxplot(aes(group=vpdInt), outlier.shape = NA, fill = "ivory2") +
  labs(x = "Maximum vapor pressure deficit (hPa)", y = "Difference in % AA mapped", title = "VPD") +
  # geom_smooth(method = "lm", se = FALSE) +
  geom_hline(yintercept = 0, color = 'red', alpha=0.41, lty = 'dashed', size = 1.2) +
  theme_smFacet
# ggsave("vpd_AllAA_boxplot.png",width = 6, height = 4.5, dpi = 300)
  
  
## boxplot: ppt
pp2 <- vpd.aa %>% 
  mutate(PercAAWetDiff3f.redNWI = PercWet3f-PercWetNWI) %>% 
  mutate(PPTInt = as.factor(as.integer(PrismPPT))) %>%
  mutate(quartile.PPT = ntile(PrismPPT, 10)) %>% 
  # mutate(t = map_int(.x=.$PrismPPT, .f = cut_equal_ranges))
  # ggplot(aes(x = quartile.PPT, y = PercAAWetDiff3f.redNWI)) +
  ggplot(aes(x = PrismPPT, y = PercAAWetDiff3f.redNWI)) +
  # geom_point(alpha = .051, color = 'darkgrey', size = 2.5) +
  # geom_boxplot(aes(group=t), outlier.shape = NA, fill = "ivory2") +
  labs(x = "Precipitation (mm)", y = "Difference in % AA mapped", title = "Precipitation") +
  geom_smooth(method = "lm", se = FALSE) +
  geom_hline(yintercept = 0, color = 'red', alpha=0.6, lty = 'dashed', size = 1.2) +
  geom_smooth(method = "lm", se = TRUE) +
  theme_smFacet
# ggsave("PrimsPPT_AllAA_boxplot.png",width = 6, height = 4.5, dpi = 300)
## boxplot: temp
pp3 <- vpd.aa %>% 
  mutate(PercAAWetDiff3f.redNWI = PercWet3f-PercWetNWI) %>% 
  mutate(TempInt = as.factor(as.integer(PrismTMean))) %>%
  mutate(quartile.PrismTMean = ntile(PrismTMean, 10)) %>% 
  # mutate(t = map_int(.x=.$PrismPPT, .f = cut_equal_ranges))
  # ggplot(aes(x = quartile.PPT, y = PercAAWetDiff3f.redNWI)) +
  ggplot(aes(x = PrismTMean, y = PercAAWetDiff3f.redNWI)) +
  # geom_point(alpha = .051, color = 'darkgrey', size = 2.5) +
  geom_boxplot(aes(group=TempInt), outlier.shape = NA, fill = "ivory2") +
  labs(x = "Temperature (C)", y = "Difference in % AA mapped", title = "Mean temperature") +
  geom_smooth(method = "lm", se = FALSE) +
  geom_hline(yintercept = 0, color = 'red', alpha=0.6, lty = 'dashed', size = 1.2) +
  geom_smooth(method = "lm", se = TRUE) +
  theme_smFacet
# ggsave("PrimsTEMP_AllAA_boxplot.png",width = 6, height = 4.5, dpi = 300)
# pp3 <- cowplot::plot_grid(pp1, pp2, labels = c("A", "B"), nrow = 2, align = "V")
# save_plot(pp3, filename = "2panel_plot.png",ncol = 1, base_height = 6, base_width = 7.5)
# ### Ternaryplot ... interstingb but not now
# library(ggtern)
# data('Feldspar')
# ggtern(Feldspar,aes(Ab,An,Or)) + 
#  geom_density_tern(aes(color=..level..),bins=5) +
#  geom_point()
# 
# ggtern(vpd.aa,aes(PrismPPT,PrismTMean,vpdMx30yr)) + 
#  geom_density_tern(aes(color=..level..),bins=5) +
#  geom_point()
# 
# # ### hex plot
# # vpd.aa %>% 
# #   mutate(PercAAWetDiff3f.redNWI = PercWet3f-PercWetNWI) %>% 
# #   mutate(vpdInt = as.factor(as.integer(vpdMx30yr))) %>% 
# #   ggplot(aes(x = vpdMx30yr, y = PercAAWetDiff3f.redNWI)) +
# #   geom_hex(bins=35, alpha = 0.95) +
# #   scale_fill_viridis(direction = -1) +
# #   geom_quantile() 

Climatevars scatterplots

plot01 <- vpd.aa %>%
  ggplot(aes(x = PrismPPT, y = diff.AApercWet)) +
  geom_point(alpha = 0.08) +
  geom_smooth() +
  geom_hline(yintercept = 0, lty = 'dashed',color='red',size=1.2) +
  labs(x="Precipitation (mm)", y = "Difference in %AA mapped")
plot01

# save_plot(plot = plot01,filename = "ppt_vs_DiffAA.png")

Looking at 3f polygon ditribution

F3poly <- map2(.x = "data/Final_shapefile/v15_data", .y = "Fin3F_AAv14DIS", .f =  readOGR) ### Note: this also works
OGR data source with driver: ESRI Shapefile 
Source: "data/Final_shapefile/v15_data", layer: "Fin3F_AAv14DIS"
with 29490 features
It has 6 fields
Z-dimension discarded
# ### View attribute data
F3poly.tbl <- as_tibble(F3poly[[1]]@data) 
# names(F3poly.tbl)
F3poly.tbl <- left_join(F3poly.tbl,ecoreg.lu,by="AAv14id")
joining character vector and factor, coercing into character vector
# F3poly.tbl %>% datatable()
## summarize total AA area
F3poly.tbl %>% 
  # names() %>% 
  summarize(sum.polyHa = sum(PolyAreaHa), mean.polyHa = mean(PolyAreaHa, na.rm = TRUE), med.polyHa = median(PolyAreaHa), cnt.poly = n(), min.polyHa = min(PolyAreaHa), max.polyHa = max(PolyAreaHa)) %>%
  mutate(sum.polyAcres = 2.47105*sum.polyHa) %>% 
  mutate(mean.polyAcres = 2.47105*mean.polyHa) %>% 
  mutate(med.polyAcres = 2.47105*med.polyHa) %>% 
  mutate(min.polyAcres = 2.47105*min.polyHa) %>% 
  mutate(max.polyAcres = 2.47105*max.polyHa)
F3poly.tbl <- F3poly.tbl %>%
  mutate(PolyAreaAcre = PolyAreaHa*2.47105) 
  
F3poly.tbl %>% datatable()
It seems your data is too big for client-side DataTables. You may consider server-side processing: http://rstudio.github.io/DT/server.htmlIt seems your data is too big for client-side DataTables. You may consider server-side processing: http://rstudio.github.io/DT/server.html
LS0tDQp0aXRsZTogIkFBdjE1IGFuYWx5c2lzIg0Kb3V0cHV0OiANCiAgaHRtbF9ub3RlYm9vazogDQogICAgdGhlbWU6IGNlcnVsZWFuDQotLS0NCg0KDQoqKlJlc3RhcnRpbmcgd2l0aCB0aGUgYWRkaXRpb24gb2YgSUxOSCBkYXRhKioNCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQpsaWJyYXJ5KHRpbnQpDQojIGludmFsaWRhdGUgY2FjaGUgd2hlbiB0aGUgcGFja2FnZSB2ZXJzaW9uIGNoYW5nZXMNCmtuaXRyOjpvcHRzX2NodW5rJHNldCh0aWR5ID0gRkFMU0UsIGNhY2hlLmV4dHJhID0gcGFja2FnZVZlcnNpb24oJ3RpbnQnKSwgZWNobyA9IEZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIGNvbW1lbnQgPSBGQUxTRSkNCm9wdGlvbnMoaHRtbHRvb2xzLmRpci52ZXJzaW9uID0gRkFMU0UpDQpgYGANCg0KYGBge3IsIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSwgY29tbWVudD1GQUxTRX0NCmxpYnJhcnkoRFQpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkocmdkYWwpDQpsaWJyYXJ5KGdkYWxVdGlscykNCmxpYnJhcnkocmFzdGVyKQ0KbGlicmFyeShyYXN0ZXJWaXMpDQpsaWJyYXJ5KG1hcHZpZXcpDQpsaWJyYXJ5KFJDb2xvckJyZXdlcikNCmxpYnJhcnkoZ2dyZXBlbCkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGQzaGVhdG1hcCkNCmxpYnJhcnkoZ2dzdGFuY2UpDQpsaWJyYXJ5KHZpcmlkaXMpDQpsaWJyYXJ5KGdndmlzKQ0KbGlicmFyeShzY2FsZXMpDQpsaWJyYXJ5KGNvd3Bsb3QpDQpsaWJyYXJ5KHRtYXApDQpsaWJyYXJ5KGRldnRvb2xzKQ0KIyBpbnN0YWxsLnBhY2thZ2VzKCJkZXZ0b29scyIpDQojIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiY2FyZGlvbW9vbi9nZ2lyYXBoRXh0cmEiKQ0KbGlicmFyeShnZ2lyYXBoKQ0KbGlicmFyeShnZ2lyYXBoRXh0cmEpDQoNCiMjIyBsb29rcyB1c2VmdWwsIGJ1dCB1cCBhbmQgcnVubmluZyBhcyBvZiAxMi81LzE2DQojIGluc3RhbGwucGFja2FnZXMoImJhbm5lckNvbW1lbnRlciIpDQojIGxpYnJhcnkoYmFubmVyQ29tbWVudGVyKQ0KDQojIHRpZHl2ZXJzZV91cGRhdGUoKQ0KDQojIyMjIEFuYWx5c2lzIHBhY2thZ2VzDQojIGluc3RhbGwucGFja2FnZXMoImRpZmZlUiIpDQojIGxpYnJhcnkoZGlmZmVSKQ0KDQoNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsIGNvbW1lbnQ9RkFMU0V9DQojIHNvbWUgZnVuY3Rpb25zLi4uDQoNCg0KIy0tLS0tLS0tLS0tLS0tLS0tLS0tDQojIFNPOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzExNjEwMzc3L2hvdy1kby1pLWNoYW5nZS10aGUtZm9ybWF0dGluZy1vZi1udW1iZXJzLW9uLWFuLWF4aXMtd2l0aC1nZ3Bsb3QNCiMgLi4uZ2l2ZXMgcHJvcGVyICd4MTAoc3VwZXJzY3JpcHQpNScgbm90YXRpb24gb24gdGhlIGF4ZXMuIA0KDQpmYW5jeV9zY2llbnRpZmljIDwtIGZ1bmN0aW9uKGwpIHsNCiAgICAgIyB0dXJuIGluIHRvIGNoYXJhY3RlciBzdHJpbmcgaW4gc2NpZW50aWZpYyBub3RhdGlvbg0KICAgICBsIDwtIGZvcm1hdChsLCBzY2llbnRpZmljID0gVFJVRSkNCiAgICAgIyBxdW90ZSB0aGUgcGFydCBiZWZvcmUgdGhlIGV4cG9uZW50IHRvIGtlZXAgYWxsIHRoZSBkaWdpdHMNCiAgICAgbCA8LSBnc3ViKCJeKC4qKWUiLCAiJ1xcMSdlIiwgbCkNCiAgICAgIyB0dXJuIHRoZSAnZSsnIGludG8gcGxvdG1hdGggZm9ybWF0DQogICAgIGwgPC0gZ3N1YigiZSIsICIlKiUxMF4iLCBsKQ0KICAgICAjIHJldHVybiB0aGlzIGFzIGFuIGV4cHJlc3Npb24NCiAgICAgcGFyc2UodGV4dD1sKQ0KfQ0KDQojIFdoaWNoIHlvdSBjYW4gdGhlbiB1c2UgYXMNCg0KIyBnZ3Bsb3QoZGF0YT1kZiwgYWVzKHg9eCwgeT15KSkgKw0KIyAgICBnZW9tX3BvaW50KCkgKw0KIyAgICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzPWZhbmN5X3NjaWVudGlmaWMpIA0KDQoNCiMjIGZ1biB0byBhZGQgcjINCiMgR0VUIEVRVUFUSU9OIEFORCBSLVNRVUFSRUQgQVMgU1RSSU5HDQojIFNPVVJDRTogaHR0cDovL2dvby5nbC9LNHloDQoNCmxtX2VxbiA8LSBmdW5jdGlvbihkZil7DQogICAgbSA8LSBsbSh5IH4geCwgZGYpOw0KICAgIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKHkpID09IGEgKyBiICUuJSBpdGFsaWMoeCkqIiwifn5pdGFsaWMocileMn4iPSJ+cjIsIA0KICAgICAgICAgbGlzdChhID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLCANCiAgICAgICAgICAgICAgYiA9IGZvcm1hdChjb2VmKG0pWzJdLCBkaWdpdHMgPSAyKSwgDQogICAgICAgICAgICAgcjIgPSBmb3JtYXQoc3VtbWFyeShtKSRyLnNxdWFyZWQsIGRpZ2l0cyA9IDMpKSkNCiAgICBhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpOyAgICAgICAgICAgICAgICAgDQp9DQoNCiMgcDEgPC0gcCArIGdlb21fdGV4dCh4ID0gMjUsIHkgPSAzMDAsIGxhYmVsID0gbG1fZXFuKGRmKSwgcGFyc2UgPSBUUlVFKQ0KDQoNCiMjIyMjIyMjDQojIyBmcm9tIGh0dHBzOi8vd3d3LnItYmxvZ2dlcnMuY29tL3VzaW5nLXB1cnJyLXdpdGgtZHBseXIvDQpjdXRfZXF1YWxfc2l6ZXMgPC0gZnVuY3Rpb24oeCwgbiA9IDMsIC4uLikgew0KICBnZ3Bsb3QyOjpjdXRfbnVtYmVyKHgsIG4sIC4uLikNCn0NCg0KY3V0X2VxdWFsX3JhbmdlcyA8LSBmdW5jdGlvbih4LCBuID0gMTAsIC4uLikgew0KICBjdXQoeCwgbiwgaW5jbHVkZS5sb3dlc3QgPSBUUlVFLCAuLi4pDQp9DQoNCg0KYGBgDQoNCmBgYHtyLCBlY2hvPUZBTFNFLCB3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UsIGNvbW1lbnQ9RkFMU0V9DQojIHNvbWUgdGhlbWVzDQp0aGVtZV9zbUZhY2V0IDwtIHRoZW1lX2J3KCkgKyB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDcpKQ0KdGhlbWVfQ293c01vZDEgPC0gdGhlbWVfY293cGxvdCgpICsgDQogIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gNykpICsNCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDApKSANCg0KYGBgDQoNCiMjIEludHJvZHVjdGlvbg0KDQojIyMgT2JqZWN0aXZlcw0KDQoxLiBDb21wYXJlIHRoZSBudW1iZXIgYW5kIGFyZWEgb2Ygd2V0bGFuZHMgbWFwcGVkIGJ5IDMtZmFjdG9yIGFuZCBOV0kgd2V0bGFuZHMgYWNyb3NzIHN0dWR5IHNpdGVzDQoNCjEuIEV2YWx1YXRlIGNvcnJlbGF0ZXMgb2YgZGlmZmVyZW5jZXMgaW4gbWFwcGluZyBvdXRjb21lcw0KDQoNCiMjIE1ldGhvZHMNCg0KIyMjIE1hcCBjb21wYXJpc29uIG1ldHJpY3MNCg0KKipUb3RhbCBhcmVhIG1hcHBlZDoqKg0KDQoqVGhlIHNpbXBsZSBzdW0gb2YgYWxsIHdldGxhbmQgcG9seWdvbnMgZm9yIGEgZ2l2ZW4gbWFwcGluZyBwcm90b2NvbC4gKg0KDQpGb3IgMy1mYWN0b3Igd2V0bGFuZHM6ICQke0FfezNmfX0gPSBcc3VtX3tpPTF9XntufUFfe2l9JCQgDQoNCkZvciBOV0kgd2V0bGFuZHM6ICQke0Ffe05XSX19ID0gXHN1bV97aT0xfV57bn1BX3tpfSQkIA0KDQoNCioqVG90YWwgcG9seWdvbnMgbWFwcGVkOioqDQoNClRoZSBjb3VudCBvZiBhbGwgd2V0bGFuZCBwb2x5Z29ucyBmb3IgYSBnaXZlbiBtYXBwaW5nIHByb3RvY29sLiANCg0KVGhlIGZvcm11bGF0aW9uIGZvciAzLWZhY3RvciB3ZXRsYW5kczogJCR7bl97M2YgcG9seX19ID0gXHN1bV97aT0xfV57bn1uX3tpfSQkIA0KDQpUaGUgZm9ybXVsYXRpb24gZm9yIE5XSSB3ZXRsYW5kczogJCR7QV97TldJIHBvbHl9fSA9IFxzdW1fe2k9MX1ee259bl97aX0kJCANCg0KIyMgKipOb3JtYWxpemVkIERpZmZlcmVuY2UgQXJlYSBJbmRleDoqKg0KDQokJE5EQUkgPSBcZnJhY3soe0FfezNmfX0gLSB7QV97TldJfX0pfXsoe0FfezNmfX0gKyBBX3tOV0l9KX0kJA0KDQojIyAqKkdvb2RuZXNzIG9mIEZpdCBbYWRkIGNpdGF0aW9uXSoqDQoNCiQkR197Zml0fSA9IFxmcmFjeyh7QV97dW5pb259fSl9eyh7QV97M2Yub25seX19ICsgQV97dW5pb259KX0gKiBcZnJhY3soe0Ffe3VuaW9ufX0pfXsoe0Ffe05XSS5vbmx5fX0gKyBBX3t1bmlvbn0pfSQkDQoNCg0KDQoNCiMgUmVzdWx0cw0KDQojIyBBc3Nlc3NtZW50IEFyZWEgY2hhcmFjdGVyc3RpY3MNCg0KIyMjIFRvdGFsIGFyZWEgYW5kIG51bWJlciBvZiBBQQ0KDQpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCiMgbGlzdC5maWxlcyhwYXR0ZXJuID0gIl9pbnB1dC50eHQkIiwgcmVjdXJzaXZlID0gVFJVRSkNCg0KIyAjIHJlYWQgaW4gdGhlIGRhdGEgZnJvbSAuLg0KIyBTaGFwZS5saXN0IDwtZ3N1YigiXFwuc2hwJCIsIiIsIGxpc3QuZmlsZXMoImRhdGEvRmluYWxfc2hhcGVmaWxlL3YxNV9kYXRhIiwgcGF0dGVybj0ic2hwJCIsIGZ1bGwubmFtZXM9VFJVRSwgcmVjdXJzaXZlID0gRkFMU0UpKQ0KIyANCiMgIyMgY3JlYXRlIGEgZGF0YWZyYW1lLCBzZXBhcmF0ZSB0aGUgcGFydHMgYW5kIHByZXAgZm9yIHNoYXBlZmlsZQ0KIyAjIGltcG9ydCBieSBjcmVhdGluZyBhIHBhdGggYW5kIGJhcmUgZmlsZSBuYW1lDQojIEFBdjE1Y2VudCA8LSBTaGFwZS5saXN0W1s3XV0gJT4lICMgdGhpcyBpcyB0aGUgdnVsbmVyYWJsZSBwYXJ0LiBUaGUgaW5kZXggY2hhbmdlcyBpZiBpIGFkZCBuZXcgc2hwIHRvIGRpcmVjdG9yeSENCiMgICBhc19kYXRhX2ZyYW1lKCkgJT4lIA0KIyAgIHNlcGFyYXRlKGNvbCA9IHZhbHVlLHNlcCA9ICIvIiwgaW50byA9IGMoInAxIiwicDIiLCJwMyIsIkZpbGVOYW1lIiksIHJlbW92ZSA9IEZBTFNFLCBleHRyYSA9ICJtZXJnZSIpICU+JSANCiMgdW5pdGUocGF0aCwgcDEsIHAyLHAzLHNlcCA9ICIvIixyZW1vdmUgPSBGQUxTRSkgJT4lIA0KIyAgIGRwbHlyOjpyZW5hbWUoRnVsbFNoYXBlUGF0aCA9IHZhbHVlKQ0KIyAjIyMjIHJlYWQgaW4gdGhlIGFjdHVhbCBzaGFwZWZpbGUNCiMgYWFjZW50ciA8LSBtYXAyKC54ID0gQUF2MTVjZW50JHBhdGgsIC55ID0gQUF2MTVjZW50JEZpbGVOYW1lLCAuZiA9ICByZWFkT0dSKSANCg0KIy0tLS0tLS0tLS0tLS0tLSBOb3RlOiB0aGUgYWJvdmUgaXMgbW9yZSBnZW5lcmFsIGJ1dCByZXF1aXJlcyBpbmRleGluZy4gV2hhdCBmb2xsb3dzIGlzIG1vcmUgZGlyZWN0IGFuZCB1c2VkDQoNCiMgYWFjZW50ciA8LSByZWFkT0dSKGRzbiA9ICJkYXRhL0ZpbmFsX3NoYXBlZmlsZS92MTVfZGF0YSIsbGF5ZXIgPSAicG9seUFBaWR2MTVmaW5fY2VudHJvaWQiKQ0KDQphYWNlbnRyLnRibCA8LSBtYXAyKC54ID0gImRhdGEvRmluYWxfc2hhcGVmaWxlL3YxNV9kYXRhIiwgLnkgPSAicG9seUFBaWR2MTVmaW5fY2VudHJvaWQiLCAuZiA9ICByZWFkT0dSKSAjIyMgTm90ZTogdGhpcyBhbHNvIHdvcmtzDQojICMjIyBWaWV3IGF0dHJpYnV0ZSBkYXRhDQoNCmFhY2VudHIudGJsIDwtIGFzX3RpYmJsZShhYWNlbnRyLnRibFtbMV1dQGRhdGEpIA0KbmFtZXMoYWFjZW50ci50YmwpDQoNCg0KDQojIGFhY2VudHIudGJsICU+JSBkYXRhdGFibGUoKQ0KDQojIyBzdW1tYXJpemUgdG90YWwgQUEgYXJlYQ0KYWFjZW50ci50YmwgJT4lIA0KICAjIG5hbWVzKCkgJT4lIA0KICBzdW1tYXJpemUoc3VtLkFBYWNyZSA9IHN1bShBQWlkQWNyZSksIHN1bS5hcmVhSGEgPSBzdW0oQUFhcmVhSGEpLCBjbnQuQUFwb2x5ID0gbigpKSAlPiUNCiAgbXV0YXRlKHN1bS5BY3JlcyA9IDIuNDcxMDUqc3VtLmFyZWFIYSkgJT4lIA0KICBtdXRhdGUoc3VtLnNxbWlsZXMgPSAwLjAwMzg2MTAyKnN1bS5hcmVhSGEpICU+JSANCiAgZGF0YXRhYmxlKCkNCg0KDQpgYGANCg0KDQoNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0UsIGNvbW1lbnQ9RkFMU0V9DQoNCiMjIGFkZCB0aGUgbG9va3VwIHRhYmxlLi4uDQp2MTVfY2VudHJvaWRfRWNvcmVnRGlzdERpdl9MVSA8LSByZWFkX2NzdigiRDovRHJvcGJveC9QUk9KRUNUUy9DT1JQU19OV0kzUC9SU3R1ZGlvX1Byb2plY3RzL05XSV9BbmFseXNpczIwMTYvZGF0YS9GaW5hbF9zaGFwZWZpbGUvVjE1X2RhdGEvdjE1X2NlbnRyb2lkX0Vjb3JlZ0Rpc3REaXZfTFUuY3N2IikNCg0KIyBhbmQgYWRkIHRoZSBud2kgbWV0YSBsb29rdXANCiMjIGltcG9ydCB0aGUgTldJIG1ldGFkYXRhDQpBQXYxNWNlbnRyTldJbWV0YV9MVSA8LSByZWFkX2NzdigiRDovRHJvcGJveC9QUk9KRUNUUy9DT1JQU19OV0kzUC9SU3R1ZGlvX1Byb2plY3RzL05XSV9BbmFseXNpczIwMTYvZGF0YS9GaW5hbF9zaGFwZWZpbGUvVjE1X2RhdGEvQUF2MTVjZW50ck5XSW1ldGFfTFUuY3N2IikNCg0KbndpLm1ldGEgPC0gQUF2MTVjZW50ck5XSW1ldGFfTFUgJT4lIA0KICAjIG5hbWVzKCkNCiAgZHBseXI6OnNlbGVjdChjKEFBdjE0aWQsSU1BR0VfWVIsIEVNVUxTSU9OKSkNCg0KIy0tLS0tLS0tLQ0KDQojIFZpZXcodjE1X2NlbnRyb2lkX0Vjb3JlZ0Rpc3REaXZfTFUpDQoNCiMgdjE1X2NlbnRyb2lkX0Vjb3JlZ0Rpc3REaXZfTFUgJT4lDQojICAgbmFtZXMoKSAlPiUNCiMgICBhc190aWJibGUoKQ0KDQojIHVuaXF1ZSh2MTVfY2VudHJvaWRfRWNvcmVnRGlzdERpdl9MVSRTVEFURSkNCg0KDQojIyBzZWxlY3QgdGhlIGZpZWxkcyBJIHdhbnQNCmVjb3JlZy5sdSA8LSB2MTVfY2VudHJvaWRfRWNvcmVnRGlzdERpdl9MVSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoQUF2MTRpZCwgDQpEaXN0cmljdCwNCkRJVklTSU9OLA0KVVNfTDRDT0RFLAkJCQkNClVTX0w0TkFNRSwJCQkNClVTX0wzTkFNRSwJCQkJDQpOQV9MM05BTUUsCQkJCQ0KTkFfTDJOQU1FLA0KQmx5RE9NQUlOLAkJCQkNCkJseURJVklTSU9OLA0KUFJPVklOQ0UsCQkJCQ0KU0VDVElPTiwNClNUQVRFLA0KaXNvQmlvQ2xpDQopDQogIA0KIyBkYXRhdGFibGUoZWNvcmVnLmx1KQ0KDQojIyBMZWZ0IGpvaW4gdGhlIGVjb3JlZ2lvbiBldGMuIGx1IHdpdGggdGhlIEFBDQphYUN0cmQuZWNvcmVnIDwtIGxlZnRfam9pbihhYWNlbnRyLnRibCwgZWNvcmVnLmx1LCBieSA9ICJBQXYxNGlkIikNCg0KIyBOb3cgam9pbiB0aGUgTldJIG1ldGFkYXRhIA0KYWFDdHJkLmVjb3JlZyA8LSBsZWZ0X2pvaW4oYWFDdHJkLmVjb3JlZywgbndpLm1ldGEsIGJ5ID0gIkFBdjE0aWQiKQ0KDQojIyBqdXN0IGEgY2hlY2sgdG8gc2VlIEkgd2F2ZSBvbmUgcG9seSBwZXIgQUF2MTRpZA0KIyBhYUN0cmQuZWNvcmVnICU+JSANCiMgICBncm91cF9ieShBQXYxNGlkKSAlPiUNCiMgICBzdW1tYXJpemUoY250PSBuKCkpICU+JSANCiMgICBmaWx0ZXIoY250PT0xKQ0KDQoNCg0KYGBgDQojIyMgU3VtbWFyeSBkYXRhdGFiZSBmb3IgQUENCmBgYHtyfQ0KYWFDdHJkLmVjb3JlZyAlPiUgDQogIGRhdGF0YWJsZShmaWx0ZXIgPSAndG9wJykNCg0KYGBgDQoNCiMjIyBBQSBhcmVhIHN1bW1hcnkgYnkgU1RBVEUNCmBgYHtyfQ0KYWFDdHJkLmVjb3JlZyAlPiUNCiAgZ3JvdXBfYnkoU1RBVEUpICU+JQ0KICBzdW1tYXJpemUoY250ID0gbigpLCBzdW0uYWFBY3JlID0gc3VtKEFBaWRBY3JlKSwgc3VtLmFhSGEgPSBzdW0oQUFhcmVhSGEpKSAlPiUNCiAgbXV0YXRlKHN1bS5zcW1pbGVzID0gMC4wMDM4NjEwMipzdW0uYWFIYSkgJT4lIA0KICBhcnJhbmdlKGRlc2Moc3VtLnNxbWlsZXMpKSAlPiUgDQogIGRhdGF0YWJsZSgpDQoNCmFhQ3RyZC5lY29yZWcgJT4lDQogIGdyb3VwX2J5KFNUQVRFKSAlPiUNCiAgc3VtbWFyaXplKGNudCA9IG4oKSwgc3VtLmFhQWNyZSA9IHN1bShBQWlkQWNyZSksIHN1bS5hYUhhID0gc3VtKEFBYXJlYUhhKSkgJT4lDQogIG11dGF0ZShzdW0uc3FtaWxlcyA9IDAuMDAzODYxMDIqc3VtLmFhSGEpICU+JSANCiAgZmlsdGVyKHN1bS5zcW1pbGVzID4gMzUpICU+JSANCiAgZ2dwbG90KGFlcyh4PSByZW9yZGVyKFNUQVRFLC1zdW0uc3FtaWxlcyksIHkgPSBzdW0uc3FtaWxlcykpICsNCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknKSArDQogIGxhYnMoeD0iIix5PSJTdW0gQUEgYXJlYSAoc3F1YXJlIG1pbGVzKSIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgDQoNCmBgYA0KDQojIyMgQUEgYXJlYSBzdW1tYXJ5IGJ5IFVTQUNFIERJVklTSU9ODQpgYGB7cn0NCmFhQ3RyZC5lY29yZWcgJT4lDQogIGdyb3VwX2J5KERJVklTSU9OKSAlPiUNCiAgc3VtbWFyaXplKGNudCA9IG4oKSwgc3VtLmFhQWNyZSA9IHN1bShBQWlkQWNyZSksIHN1bS5hYUhhID0gc3VtKEFBYXJlYUhhKSkgJT4lDQogIG11dGF0ZShzdW0uc3FtaWxlcyA9IDAuMDAzODYxMDIqc3VtLmFhSGEpICU+JSANCiAgYXJyYW5nZShkZXNjKHN1bS5zcW1pbGVzKSkgJT4lIA0KICBkYXRhdGFibGUoKQ0KDQpgYGANCg0KIyMjIFVTQUNFIERpdmlzaW9uOiBTdW0gYWNyZXMNCg0KYGBge3J9DQojIEdyYXBocw0KIyBwbG90IDE6IHN1bSBvZiBhY3JlcyBpbiBBQSBieSBEaXZpc2lvbg0KcGwwMSA8LSBhYUN0cmQuZWNvcmVnICU+JSANCiAgZ3JvdXBfYnkoRElWSVNJT04pICU+JSANCiAgc3VtbWFyaXNlKHN1bS5BY3JlcyA9IHN1bShBQWlkQWNyZSkpICU+JSANCiAgZ2dwbG90KGFlcyhyZW9yZGVyKHg9RElWSVNJT04sIHN1bS5BY3JlcykseSA9IHN1bS5BY3JlcykpICsNCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknKSArDQogIGxhYnMoeCA9ICIiLCB5ID0gIkFBIGFyZWEgKGFjcmVzKSIsIHRpdGxlID0gIlN1bSBBQSBhcmVhIikgKw0KICBjb29yZF9mbGlwKCkgKw0KICBzY2FsZV95X2xvZzEwKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpDQogICMgc2NhbGVfeV9sb2cxMCgpDQoNCiMgcGwwMQ0KDQojIyMjIyMjIyBob3Jpem9udGFsIGJveHBsb3QgdmlhIGdnc3RhbmNlDQojIyAjIEluIGdnc3RhbmNlLCB5b3Ugc3VwcGx5IGFlc3RoZXRpY3MgaW4gdGhlaXIgbmF0dXJhbCBvcmRlcjoNCiMgSG9yaXpvbnRhbCB3aXRoIGdnc3RhbmNlDQojIGdncGxvdChtcGcsIGFlcyhod3ksIGNsYXNzLCBmaWxsID0gZmFjdG9yKGN5bCkpKSArDQojICAgZ2VvbV9ib3hwbG90aCgpIA0KDQojIGJveHBsb3QNCnBsMDIgPC0gYWFDdHJkLmVjb3JlZyAlPiUNCiAgIyBmaWx0ZXIoKQ0KICBnZ3Bsb3QoYWVzKHg9QUFpZEFjcmUseSA9IERJVklTSU9OKSkgKw0KICBnZW9tX2JveHBsb3RoKCkgKw0KICBsYWJzKHggPSAiQUEgYXJlYSAoYWNyZXMpIiwgeSA9ICIiLCB0aXRsZSA9ICJJbmRpdmlkdWFsIEFBIGFyZWEiKSArDQogICMgY29vcmRfZmxpcCgpICsNCiAgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKQ0KICAjIHNjYWxlX3hfY29udGludW91cyhsYWJlbHM9ZmFuY3lfc2NpZW50aWZpYykgIyMgdGhpcyB1c2VzIHRoZSBmdW5jdGlvbiBhdCB0aGUgaGVhZCBvZiB0aGUgZG9jDQogICMgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscz1mdW5jdGlvbihuKXtmb3JtYXQobiwgc2NpZW50aWZpYyA9IEZBTFNFKX0pICMgdGhpcyBhbHNvIHdvcmtzIGJ1dCBsb2cNCg0KIyBwbDAyDQoNCiMjIHNhdmUgYXMgYSBncmlkDQojIHBsb3RfZ3JpZChwbDAxLCBwbDAyLCBsYWJlbHMgPSBjKCJBIiwgIkIiKSkNCnAzIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChwbDAxLCBwbDAyLCBsYWJlbHMgPSBjKCJBIiwgIkIiKSwgbnJvdyA9IDIsIGFsaWduID0gIlYiKQ0KIyBzYXZlX3Bsb3QoInYxNV9BQV9ib3Bsb3RzX3RvdGFsYXJlYV9pbmRpLnBuZyIsIHAzLCBuY29sID0gMikNCg0KcDMNCg0KYGBgDQoNCmBgYHtyfQ0KIyMgcGxvdCB0aGUgQUEgYXJlYQ0KIyBtZWQuZGl2IDwtIGFhQ3RyZC5lY29yZWcgJT4lIA0KIyAgIGdyb3VwX2J5KERJVklTSU9OLCBEaXN0cmljdCkgJT4lIA0KIyAgIHN1bW1hcmlzZShtZWQuQUFoYSA9IG1lZGlhbihBQWFyZWFIYSksIG1lYW4uYXJlYUhhID0gbWVhbihBQWFyZWFIYSksIG1lZC5BQWFjcmUgPSBtZWRpYW4oQUFpZEFjcmUpLCBtZWFuLkFBYWNyZSA9IG1lYW4oQUFpZEFjcmUpKQ0KIyANCiMgbWVkLmRpdiAlPiUgDQojICAgZ2dwbG90KGFlcyh4ID0gcmVvcmRlcihEaXN0cmljdCwgbWVkLkFBYWNyZSksIHkgPSBtZWQuQUFhY3JlKSkgKw0KIyAgIGdlb21fcG9pbnQoKSArDQojICAgZmFjZXRfd3JhcCh+RElWSVNJT04sIHNjYWxlcyA9ICdmcmVlJykgKw0KIyAgIHNjYWxlX3lfbG9nMTAoKQ0KDQpgYGANCg0KDQojIyMgQUEgYXJlYSBzdW1tYXJ5IGJ5IFVTQUNFIERpc3RyaWN0DQpgYGB7cn0NCmFhQ3RyZC5lY29yZWcgJT4lDQogIGdyb3VwX2J5KERpc3RyaWN0KSAlPiUNCiAgc3VtbWFyaXplKGNudCA9IG4oKSwgc3VtLmFhQWNyZSA9IHN1bShBQWlkQWNyZSksIHN1bS5hYUhhID0gc3VtKEFBYXJlYUhhKSkgJT4lDQogIG11dGF0ZShzdW0uc3FtaWxlcyA9IDAuMDAzODYxMDIqc3VtLmFhSGEpICU+JSANCiAgYXJyYW5nZShkZXNjKHN1bS5zcW1pbGVzKSkgJT4lIA0KICBkYXRhdGFibGUoKQ0KDQpgYGANCg0KIyMjIFVTQUNFIERpdmlzaW9uOiBCb3hwbG90IGluZGl2aWR1YWwgQUEgYWNyZXMNCmBgYHtyfQ0KIyBhYUN0cmQuZWNvcmVnICU+JSANCiMgICBncm91cF9ieShEaXN0cmljdCkgJT4lIA0KIyAgIHN1bW1hcmlzZShzdW0uQWNyZXMgPSBzdW0oQUFpZEFjcmUpKSAlPiUgDQojICAgZ2dwbG90KGFlcyhyZW9yZGVyKHg9RGlzdHJpY3QsIHN1bS5BY3JlcykseSA9IHN1bS5BY3JlcykpICsNCiMgICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpICsNCiMgICBsYWJzKHggPSAiIiwgeSA9ICJBQSBhcmVhIChhY3JlcykiLCB0aXRsZSA9ICJTdW0gQUEgYXJlYSIpICsNCiMgICAjIGNvb3JkX2ZsaXAoKSArDQojICAgc2NhbGVfeV9sb2cxMCgpDQoNCnBsMDQgPC0gYWFDdHJkLmVjb3JlZyAlPiUgDQogIGdncGxvdChhZXMoeD1BQWlkQWNyZSx5ID0gRGlzdHJpY3QsIGZpbGw9IERpc3RyaWN0KSkgKw0KICBnZW9tX2JveHBsb3RoKCkgKw0KICBsYWJzKHggPSAiQXJlYSAoYWNyZXMpIiwgeSA9ICIiLCB0aXRsZSA9ICJJbmRpdmlkdWFsIEFBIGFyZWEgYnkgVVNBQ0UgRGlzdHJpY3QiKSArDQogIGZhY2V0X3dyYXAofkRJVklTSU9OLCBzY2FsZXM9J2ZyZWVfeScsIG5jb2w9MikrDQogIGd1aWRlcyhmaWxsPUZBTFNFKSArDQogIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCg0KIyBpZiB3YW50IHRvIGhpZGUgQUxMIGxlZ2VuZHM6IHRoZW1lKGxlZ2VuZC5wb3N0aW9uID0gIm5vbmUiKQ0KDQpwbDA0DQojIGdnc2F2ZShmaWxlbmFtZSA9ICJ2MTVfQUFkaXN0QXJlYUJveC5wbmciLHBsb3QgPSBwbDA0LCB3aWR0aCA9IDgsIGhlaWdodCA9IDgsIGRwaSA9IDMwMCkNCg0KYGBgDQoNCg0KIyMjIEFBIGFyZWEgc3VtbWFyeSBieSBQUk9WSU5DRQ0KYGBge3J9DQphYUN0cmQuZWNvcmVnICU+JQ0KICBncm91cF9ieShQUk9WSU5DRSkgJT4lDQogIHN1bW1hcml6ZShjbnQgPSBuKCksIHN1bS5hYUFjcmUgPSBzdW0oQUFpZEFjcmUpLCBzdW0uYWFIYSA9IHN1bShBQWFyZWFIYSkpICU+JQ0KICBtdXRhdGUoc3VtLnNxbWlsZXMgPSAwLjAwMzg2MTAyKnN1bS5hYUhhKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhzdW0uc3FtaWxlcykpICU+JSANCiAgZGF0YXRhYmxlKCkNCg0KYGBgDQoNCiMjIEFuYWx5c2lzIG9mIEFBIE5XSSBtZXRhZGF0YQ0KDQoqKkltYWdlIHllYXIgZm9yIGFsbCBBQSoqDQpgYGB7cn0NCiMjIyMjIw0KbndpLkFBdjE1LnN1bW1hcnkgPC0gYWFDdHJkLmVjb3JlZyAlPiUNCiAgZ3JvdXBfYnkoSU1BR0VfWVIpICU+JQ0KICBzdW1tYXJpemUoY250ID0gbigpLCBzdW0uYWFBY3JlID0gc3VtKEFBaWRBY3JlKSwgc3VtLmFhSGEgPSBzdW0oQUFhcmVhSGEpKSAlPiUNCiAgbXV0YXRlKHN1bS5zcW1pbGVzID0gMC4wMDM4NjEwMipzdW0uYWFIYSkgJT4lIA0KICBmaWx0ZXIoSU1BR0VfWVIgIT0gIjAiKSAlPiUgDQogIGFycmFuZ2UoZGVzYyhJTUFHRV9ZUikpDQpkYXRhdGFibGUobndpLkFBdjE1LnN1bW1hcnkpDQoNCmltZy5wbDEgPC0gbndpLkFBdjE1LnN1bW1hcnkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBJTUFHRV9ZUiwgeSA9IHN1bS5hYUFjcmUpKSArDQogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5JywgY29sb3IgPSAnYmxhY2snLCBmaWxsID0gIml2b3J5MiIpICsNCiAgbGFicyh4ID0gIk5XSSBpbWFnZSB5ZWFyIiwgeSA9ICJBcmVhIChhY3JlcykiLCB0aXRsZSA9ICIiKQ0KIyBpbWcucGwxDQoNCmltZy5wbDIgPC0gbndpLkFBdjE1LnN1bW1hcnkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBJTUFHRV9ZUiwgeSA9IGNudCkpICsNCiAgZ2VvbV9iYXIoc3RhdD0naWRlbnRpdHknLCBjb2xvciA9ICdibGFjaycsIGZpbGwgPSAiaXZvcnkyIikgKw0KICBsYWJzKHggPSAiTldJIGltYWdlIHllYXIiLCB5ID0gIkFBIGNvdW50IiwgdGl0bGUgPSAiIikNCiMgaW1nLnBsMg0KDQojIyBzYXZlIGFzIGEgZ3JpZA0KIyBwbG90X2dyaWQocGwwMSwgcGwwMiwgbGFiZWxzID0gYygiQSIsICJCIikpDQppbWcucGwzIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChpbWcucGwxLCBpbWcucGwyLCBsYWJlbHMgPSBjKCJBIiwgIkIiKSwgbnJvdyA9IDEsIGFsaWduID0gIkgiKQ0KaW1nLnBsMw0KIyBzYXZlX3Bsb3QoInYxNV9OV0ltZXRhXzJwYW5lbC5wbmciLCBpbWcucGwzLCBuY29sID0gMikNCg0KDQpgYGANCioqSW1hZ2UgeWVhciBieSBEaXZpc2lvbiBBQSoqDQoNCmBgYHtyfQ0KIyAqKkltYWdlIHllYXIgZm9yIGFsbCBBQSoqDQpud2kuSW1nWXIuRElWLnN1bW1hcnkgPC0gYWFDdHJkLmVjb3JlZyAlPiUNCiAgZ3JvdXBfYnkoSU1BR0VfWVIsIERJVklTSU9OKSAlPiUNCiAgc3VtbWFyaXplKGNudCA9IG4oKSwgc3VtLmFhQWNyZSA9IHN1bShBQWlkQWNyZSksIHN1bS5hYUhhID0gc3VtKEFBYXJlYUhhKSkgJT4lDQogIG11dGF0ZShzdW0uc3FtaWxlcyA9IDAuMDAzODYxMDIqc3VtLmFhSGEpICU+JSANCiAgZmlsdGVyKElNQUdFX1lSICE9ICIwIikgJT4lIA0KICBhcnJhbmdlKGRlc2MoSU1BR0VfWVIpKQ0KZGF0YXRhYmxlKG53aS5JbWdZci5ESVYuc3VtbWFyeSkNCg0KaW1nRGl2LnBsMSA8LSBud2kuSW1nWXIuRElWLnN1bW1hcnkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBJTUFHRV9ZUiwgeSA9IHN1bS5hYUFjcmUpKSArDQogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5JywgY29sb3IgPSAnYmxhY2snLCBmaWxsID0gIml2b3J5MiIpICsNCiAgbGFicyh4ID0gIk5XSSBpbWFnZSB5ZWFyIiwgeSA9ICJBcmVhIChhY3JlcykiLCB0aXRsZSA9ICIiKSArDQogIGZhY2V0X3dyYXAofkRJVklTSU9OLCBzY2FsZXMgPSAnZnJlZV95JywgbmNvbD0yKSArDQogIHRoZW1lX3NtRmFjZXQNCmltZ0Rpdi5wbDENCiMgZ2dzYXZlKCJOV0lpbWdZcl9EaXZpc19BY3Jlcy5wbmciLCB3aWR0aCA9IDYsIGhlaWdodCA9IDUsIGRwaSA9IDMwMCkNCg0KDQppbWdEaXYucGwyIDwtIG53aS5JbWdZci5ESVYuc3VtbWFyeSAlPiUgDQogIGdncGxvdChhZXMoeCA9IElNQUdFX1lSLCB5ID0gY250KSkgKw0KICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScsIGNvbG9yID0gJ2JsYWNrJywgZmlsbCA9ICJpdm9yeTIiKSArDQogIGxhYnMoeCA9ICJOV0kgaW1hZ2UgeWVhciIsIHkgPSAiQUEgY291bnQiLCB0aXRsZSA9ICIiKSArDQogIGZhY2V0X3dyYXAofkRJVklTSU9OLCBzY2FsZXMgPSAnZnJlZV95JywgbmNvbD0yKSArDQogIHRoZW1lX3NtRmFjZXQNCmltZ0Rpdi5wbDINCiMgZ2dzYXZlKCJOV0lpbWdZcl9EaXZpc19DbnQucG5nIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCg0KIyAjIyBzYXZlIGFzIGEgZ3JpZA0KIyAjIHBsb3RfZ3JpZChwbDAxLCBwbDAyLCBsYWJlbHMgPSBjKCJBIiwgIkIiKSkNCiMgaW1nRGl2LnBsMyA8LSBjb3dwbG90OjpwbG90X2dyaWQoaW1nRGl2LnBsMSwgaW1nRGl2LnBsMiwgbGFiZWxzID0gYygiQSIsICJCIiksIG5yb3cgPSAxLCBhbGlnbiA9ICJIIikNCiMgaW1nRGl2LnBsMw0KIyAjIHNhdmVfcGxvdCgidjE1X05XSW1ldGFfMnBhbmVsLnBuZyIsIGltZy5wbDMsIG5jb2wgPSAyKQ0KDQpgYGANCg0KIyMgQW5hbHlzaXMgb2Ygd2V0bGFuZCBhcmVhOiAzIGZhY3RvciBhbmQgZnVsbCBOV0kNCg0KIyMjIFN1bW1hcnkgb2Ygd2V0bGFuZCBhcmVhIGFjcm9zcyBBQQ0KDQoNCg0KYGBge3J9DQoNCnYxNU5XSWFsbFR5cGVfM0ZfVU5JIDwtIHJlYWRfY3N2KCJEOi9Ecm9wYm94L1BST0pFQ1RTL0NPUlBTX05XSTNQL1JTdHVkaW9fUHJvamVjdHMvTldJX0FuYWx5c2lzMjAxNi9kYXRhL0ZpbmFsX3NoYXBlZmlsZS9WMTVfZGF0YS92MTVOV0lhbGxUeXBlXzNGX1VOSS5jc3YiKQ0KDQojIFZpZXcodjE1TldJYWxsVHlwZV8zRl9VTkkpDQoNCiMgam9pbiB0aGUgYWENCndldGwudW5pMDEgPC0gbGVmdF9qb2luKHYxNU5XSWFsbFR5cGVfM0ZfVU5JLCBhYUN0cmQuZWNvcmVnLCBieSA9ICJBQXYxNGlkIikNCg0KIyMgcXVpY2sgY2hlY2sNCiMgd2V0bC51bmkwMSAlPiUgDQojICAgbmFtZXMoKQ0KIyAgWzFdICJPQkpFQ1RJRC54IiAgICJBQXYxNGlkIiAgICAgICJQb2x5QXJlYUhhIiAgICJTaGFwZV9MZW5ndGgiICJTaGFwZV9BcmVhLngiDQojICBbNl0gIlBvbHlUeVVuaSIgICAgIk9CSkVDVElELnkiICAgIlNoYXBlX0xlbmciICAgIlNoYXBlX0FyZWEueSIgIkFBaWRBY3JlIiAgICANCiMgWzExXSAiQUFhcmVhSGEiICAgICAiQ2VuTGF0IiAgICAgICAiQ2VuTG9uIiAgICAgICAiRGlzdHJpY3QiICAgICAiRElWSVNJT04iICAgIA0KIyBbMTZdICJVU19MNENPREUiICAgICJVU19MNE5BTUUiICAgICJVU19MM05BTUUiICAgICJOQV9MM05BTUUiICAgICJOQV9MMk5BTUUiICAgDQojIFsyMV0gIkJseURPTUFJTiIgICAgIkJseURJVklTSU9OIiAgIlBST1ZJTkNFIiAgICAgIlNFQ1RJT04iICAgICAgIlNUQVRFIiAgICAgICANCiMgWzI2XSAiaXNvQmlvQ2xpIg0KDQojIyB0b3RhbCB3ZXRsYW5kIGFyZWENCg0KIyB3ZXRsLnVuaTAxICU+JSANCiMgICBuYW1lcygpDQojIHVuaXF1ZSh3ZXRsLnVuaTAxJFBvbHlUeVVuaSkNCg0KYGBgDQojIyBTdW1tYXJpemUgYXJlYSBhY3Jvc3MgYWxsIHNpdGVzDQoNCmBgYHtyfQ0KDQojIyMNCnVuaS5hbGwgPC0gd2V0bC51bmkwMSAlPiUgDQogICMgbmFtZXMoKSAlPiUNCiAgZ3JvdXBfYnkoUG9seVR5VW5pKSAlPiUNCiAgc3VtbWFyaXplKHN1bS5hcmVhSGEgPSBzdW0oUG9seUFyZWFIYSkpICU+JSAgDQogIG11dGF0ZShBY3JlcyA9IHN1bS5hcmVhSGEqMi40NzEwNSkgJT4lIA0KICBtdXRhdGUoU3FNaWxlID0gQWNyZXMqMC4wMDE1NjI1KQ0KdW5pLmFsbCAlPiUgZGF0YXRhYmxlKCkNCg0KdW5pLmFsbCAlPiUgDQogIGdncGxvdChhZXMoeCA9IEFjcmVzLCB5ID0gUG9seVR5VW5pKSkgKw0KICBnZW9tX2Jhcmgoc3RhdD0naWRlbnRpdHknKSArDQogIGxhYnMoeSA9ICIiLCB4ID0gIkFyZWEgKGFjcmVzKSIsIHRpdGxlID0gIk1hcHBlZCBhcmVhIGJ5IGdlb21ldHJpYyB1bmlvbiIsIHN1YnRpdGxlID0gIkFsbCBtYXBwZWQgQ293YXJkaW4gdHlwZXMiKSArDQogIHRoZW1lX2J3KCkgKw0KICAjIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpDQojIGdnc2F2ZSgiQWxsQ293VHlwZU5XSV8zRl91bmlvbl9CYXIucG5nIiwgd2lkdGggPSA1LjUsIGhlaWdodCA9IDQsIGRwaSA9IDMwMCkNCg0KYGBgDQpgYGB7cn0NCiMjIw0KQUF2MTUudW5pX3dpZGUxIDwtIHdldGwudW5pMDEgJT4lIA0KICBncm91cF9ieShBQXYxNGlkLCBQb2x5VHlVbmkpICU+JQ0KICBzdW1tYXJpemUoc3VtLmFyZWFIYSA9IHN1bShQb2x5QXJlYUhhKSkgJT4lDQogIHNwcmVhZChrZXkgPSBQb2x5VHlVbmksIHZhbHVlID0gc3VtLmFyZWFIYSkgJT4lIA0KICByZW5hbWUoV2V0M0Zvbmx5SGEgPSBXZXQzRm9ubHkpICU+JSANCiAgcmVuYW1lKFdldE5XSW9ubHlIYSA9IFdldE5XSW9ubHkpICU+JSANCiAgcmVuYW1lKFdldFVuaW9uSGEgPSBXZXRVbmlvbikNCg0KIyB0aGlzIGlzIG9ubHkgMTUzOCBhYWlkLiBhcmUgdGhlIG90aGVycyB3aXRoIG5vIGFyZWE/IG5lZWQgdG8gY2hlY2sNCg0KIyBqb2luIHdpdGggdGhlIEFBIGNlbnRyb2lkIGFuZCBlY29yZWdpb24NCkFBdjE1LnVuaV93aWRlMSA8LSBsZWZ0X2pvaW4oYWFDdHJkLmVjb3JlZywgQUF2MTUudW5pX3dpZGUxLCBieSA9ICJBQXYxNGlkIikNCg0KIyMjIHJlcGxhY2UgTkEgd2l0aCAwDQpBQXYxNS51bmlfd2lkZTFbaXMubmEoQUF2MTUudW5pX3dpZGUxKV0gPC0gMCAjIHRoaXMgcmVwbGFjZXMgTkEgd2l0aCAwIGZvciBhbGwgQ29sdW1ucw0KDQojICMjIFNPIGV4YW1wbGUgb2YgY2hhbmdpbmcgZm9yIHNwZWNpZmljIGNvbHVtbnMuLi4NCiMgeFtjKCJhIiwgImIiKV1baXMubmEoeFtjKCJhIiwgImIiKV0pXSA8LSAwDQoNCiMjIEdPRiBtYXBjdXJ2ZXMNCkFBdjE1LnVuaV93aWRlMSA8LSBBQXYxNS51bmlfd2lkZTEgJT4lIA0KICBtdXRhdGUoZ29mID0gKChXZXRVbmlvbkhhKS8oV2V0VW5pb25IYSArIFdldE5XSW9ubHlIYSkpKigoV2V0VW5pb25IYSkvKFdldFVuaW9uSGEgKyBXZXQzRm9ubHlIYSkpKQ0KDQojIyBLRVkgY2FsY3VsYXRpb25zOiANCkFBdjE1LnVuaV93aWRlMSA8LSBBQXYxNS51bmlfd2lkZTEgJT4lIA0KICAjIG5hbWVzKCkgJT4lIA0KICBtdXRhdGUoVG90V2V0SGEubndpID0gV2V0TldJb25seUhhICsgV2V0VW5pb25IYSkgJT4lDQogIG11dGF0ZShUb3RXZXRIYS4zZiA9IFdldDNGb25seUhhICsgV2V0VW5pb25IYSkgJT4lIA0KICBtdXRhdGUoUGVyY1dldE5XSSA9IDEwMCpUb3RXZXRIYS5ud2kvQUFhcmVhSGEpICU+JSANCiAgbXV0YXRlKFBlcmNXZXQzZiA9IDEwMCpUb3RXZXRIYS4zZi9BQWFyZWFIYSkgJT4lIA0KICBtdXRhdGUoTkRBSSA9IChUb3RXZXRIYS4zZi1Ub3RXZXRIYS5ud2kpLyhUb3RXZXRIYS4zZitUb3RXZXRIYS5ud2kpKQ0KDQpBQXYxNS51bmlfd2lkZTEgJT4lIA0KICAjIG5hbWVzKCkgJT4lIA0KICBkYXRhdGFibGUoKSAlPiUgDQogIGZvcm1hdFJvdW5kKGNvbHVtbnM9YygiVG90V2V0SGEubndpIiwiVG90V2V0SGEuM2YiLCJQZXJjV2V0TldJIiwiUGVyY1dldDNmIiwgIk5EQUkiLCJnb2YiKSwgZGlnaXRzPTIpDQoNCg0KYGBgDQojIyMgRGl2aXNpb24gdGlkeQ0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQojIyMgQ2FsY3VhbHRlIGFjcmVzIGFuIHRpZHkgYW5kIHBsb3QNCg0KZGl2LkFjcmVzIDwtIEFBdjE1LnVuaV93aWRlMSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoV2V0VW5pb25IYSwgV2V0M0Zvbmx5SGEsIFdldE5XSW9ubHlIYSwgRElWSVNJT04pICU+JSANCiAgcmVuYW1lKFVuaW9uID0gV2V0VW5pb25IYSwgT25seTNGID0gV2V0M0Zvbmx5SGEsIE9ubHlOV0kgPSBXZXROV0lvbmx5SGEpICU+JSANCiAgZ2F0aGVyKGtleSA9IHVuaVR5cGUsIHZhbHVlID0gQXJlYUhhLCAtRElWSVNJT04pICU+JSANCiAgbXV0YXRlKEFyZWFBY3JlID0gQXJlYUhhKjIuNDcxMDUpICU+JSANCiAgZ3JvdXBfYnkodW5pVHlwZSwgRElWSVNJT04pICU+JQ0KICBzdW1tYXJpc2Uoc3VtLkFjcmUgPSBzdW0oQXJlYUFjcmUpKQ0KDQoNCmRhdGF0YWJsZShkaXYuQWNyZXMpDQoNCiMjIw0KZGl2LkFjcmVzICU+JSANCiAgZ2dwbG90KGFlcyh4PSBzdW0uQWNyZSwgeSA9IHVuaVR5cGUpKSArDQogIGdlb21fYmFyaChzdGF0PSdpZGVudGl0eScpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIHNjYWxlcyA9ICJmcmVlIikgKw0KICBsYWJzKHkgPSAiIiwgeCA9ICJBcmVhIChhY3JlcykiLCB0aXRsZSA9ICJNYXBwZWQgYXJlYSBieSBnZW9tZXRyaWMgdW5pb24iLCBzdWJ0aXRsZSA9ICJBbGwgbWFwcGVkIENvd2FyZGluIHR5cGVzIikgKw0KICB0aGVtZV9idygpICsNCiAgIyBzY2FsZV94X2xvZzEwKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKQ0KDQpkaXYuQWNyZXMgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9IHN1bS5BY3JlLCB5ID0gRElWSVNJT04sIGZpbGwgPSB1bmlUeXBlKSkgKw0KICBnZW9tX2Jhcmgoc3RhdD0naWRlbnRpdHknLCBjb2xvciA9ICdibGFjaycpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDEpICsNCiAgbGFicyh5ID0gIiIsIHggPSAiQXJlYSAoYWNyZXMpIiwgdGl0bGUgPSAiTWFwcGVkIGFyZWEgYnkgZ2VvbWV0cmljIHVuaW9uIiwgc3VidGl0bGUgPSAiQWxsIG1hcHBlZCBDb3dhcmRpbiB0eXBlcyIpICsNCiAgdGhlbWVfYncoKSArDQogICMgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKQ0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkNCiMgZ2dzYXZlKCJEaXZpc2lvblVuaVR5cGUucG5nIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCg0KIyB1bmkuYWxsICU+JSANCiMgICBnZ3Bsb3QoYWVzKHggPSBBY3JlcywgeSA9IFBvbHlUeVVuaSkpICsNCiMgICBnZW9tX2Jhcmgoc3RhdD0naWRlbnRpdHknKSArDQojICAgbGFicyh5ID0gIiIsIHggPSAiQXJlYSAoYWNyZXMpIiwgdGl0bGUgPSAiTWFwcGVkIGFyZWEgYnkgZ2VvbWV0cmljIHVuaW9uIiwgc3VidGl0bGUgPSAiQWxsIG1hcHBlZCBDb3dhcmRpbiB0eXBlcyIpICsNCiMgICB0aGVtZV9idygpICsNCiMgICAjIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCiMgICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCg0KYGBgDQoNCmBgYHtyfQ0KIyMjIENhbGN1YWx0ZSBhY3JlcyBhbiB0aWR5IGFuZCBwbG90DQojIyBCYWlseSBwcm92aW5jZXMNClByb3YuQWNyZXMgPC0gQUF2MTUudW5pX3dpZGUxICU+JSANCiAgZHBseXI6OnNlbGVjdChXZXRVbmlvbkhhLCBXZXQzRm9ubHlIYSwgV2V0TldJb25seUhhLCBQUk9WSU5DRSkgJT4lIA0KICByZW5hbWUoVW5pb24gPSBXZXRVbmlvbkhhLCBPbmx5M0YgPSBXZXQzRm9ubHlIYSwgT25seU5XSSA9IFdldE5XSW9ubHlIYSkgJT4lIA0KICBnYXRoZXIoa2V5ID0gdW5pVHlwZSwgdmFsdWUgPSBBcmVhSGEsIC1QUk9WSU5DRSkgJT4lIA0KICBtdXRhdGUoQXJlYUFjcmUgPSBBcmVhSGEqMi40NzEwNSkgJT4lIA0KICBncm91cF9ieSh1bmlUeXBlLCBQUk9WSU5DRSkgJT4lDQogIHN1bW1hcmlzZShzdW0uQWNyZSA9IHN1bShBcmVhQWNyZSkpDQoNCg0KZGF0YXRhYmxlKFByb3YuQWNyZXMpDQoNCiMjIw0KUHJvdi5BY3JlcyAlPiUgDQogIGdncGxvdChhZXMoeD0gc3VtLkFjcmUsIHkgPSB1bmlUeXBlKSkgKw0KICBnZW9tX2Jhcmgoc3RhdD0naWRlbnRpdHknKSArDQogIGZhY2V0X3dyYXAoflBST1ZJTkNFLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgbGFicyh5ID0gIiIsIHggPSAiQXJlYSAoYWNyZXMpIiwgdGl0bGUgPSAiTWFwcGVkIGFyZWEgYnkgZ2VvbWV0cmljIHVuaW9uIiwgc3VidGl0bGUgPSAiQWxsIG1hcHBlZCBDb3dhcmRpbiB0eXBlcyIpICsNCiAgdGhlbWVfYncoKSArDQogICMgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKQ0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCg0KIyMjIGZpbHRlciBvdXQgc2l0ZXMgPjUwIGFjcmVhcyBpbiBBQSBzaXplDQpQcm92LkFjcmVzICU+JSANCiAgZ3JvdXBfYnkoUFJPVklOQ0UpICU+JSANCiAgbXV0YXRlKHN1bUFsbFBSb3ZpbmNlQXJlYSA9IHN1bShzdW0uQWNyZSkpICU+JSANCiAgZmlsdGVyKHN1bUFsbFBSb3ZpbmNlQXJlYSA+IDUwKSAlPiUgDQogIGdncGxvdChhZXMoeD0gc3VtLkFjcmUsIHkgPSBQUk9WSU5DRSwgZmlsbCA9IHVuaVR5cGUpKSArDQogIGdlb21fYmFyaChzdGF0PSdpZGVudGl0eScsIGNvbG9yID0gJ2JsYWNrJykgKw0KICBmYWNldF93cmFwKH5QUk9WSU5DRSwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMikgKw0KICBsYWJzKHkgPSAiIiwgeCA9ICJBcmVhIChhY3JlcykiLCB0aXRsZSA9ICJNYXBwZWQgYXJlYSBieSBnZW9tZXRyaWMgdW5pb24iLCBzdWJ0aXRsZSA9ICJBbGwgbWFwcGVkIENvd2FyZGluIHR5cGVzIiwgZmlsbD0iIikgKw0KICB0aGVtZV9idygpICsNCiAgIyBzY2FsZV94X2xvZzEwKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpDQogIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKSArDQogIHRoZW1lKGF4aXMudGlja3MgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKSANCiMgZ2dzYXZlKCJQUk9WSU5DV1VuaVR5cGUucG5nIiwgd2lkdGggPSAxMi41LCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KDQpgYGANCg0KDQojIyMgUGVyY2VudCBvZiBBQSBhcyBOV0kgKGFsbCBDIHR5cGVzKSBhbmQgMyBmYWN0b3INCg0KX1N1bW1hcnk6IHBlcmNlbnQgQUEgYXMgTldJXw0KYGBge3J9DQojIyBOV0kNCnN1bW1hcnkoQUF2MTUudW5pX3dpZGUxJFBlcmNXZXROV0kpDQojIGRpcigpDQoNCiMgQUF2MTUudW5pX3dpZGUxICU+JSANCiMgICBzdW1tYXJpc2VfYXQoLmNvbHMgPSBQZXJjV2V0M2YsLmZ1bnMgPSBzdW1tYXJ5KQ0KDQpgYGANCl9TdW1tYXJ5OiBwZXJjZW50IEFBIGFzIDNGXw0KYGBge3J9DQpzdW1tYXJ5KEFBdjE1LnVuaV93aWRlMSRQZXJjV2V0M2YpDQpgYGANCg0KYGBge3J9DQojIyBhbGwgQUENCkFBdjE1LnVuaV93aWRlMSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFBlcmNXZXROV0ksIHkgPSBQZXJjV2V0M2YpKSArIA0KICBnZW9tX3BvaW50KGFscGhhID0gMC4wNSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIkFsbCBOV0kgQ293YXJkaW4gdHlwZXMiKSArDQogIHRoZW1lX2J3KCkNCiAgIyBnZW9tX2hleCgpDQojIGdnc2F2ZSgiQWxsTldJQ293YXJkaW5UeV9BbGxBQV9wZXJjZW50QUFXZXQucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSA1LCBkcGkgPSAzMDApDQoNCg0KYGBgDQoNCioqJSBBQSBmdWxsIE5XSSBieSBESVZJU0lPTioqDQoNCmBgYHtyfQ0KIyMgQUEgYnkgRGl2aXNpb24gZnVsbCBOV0kNCkFBdjE1LnVuaV93aWRlMSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFBlcmNXZXROV0ksIHkgPSBQZXJjV2V0M2YpKSArIA0KICBnZW9tX3BvaW50KGFscGhhID0gMC4wNSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIkZ1bGwgTldJIikgKw0KICBmYWNldF93cmFwKH5ESVZJU0lPTiwgbmNvbCA9IDQpICsNCiAgeGxpbSgwLDEwMCkgKw0KICB5bGltKDAsMTAwKSArDQogIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpDQogICAgICANCiMgZ2dzYXZlKGZpbGVuYW1lID0gIlBlcmNlbnRBQV9OV0lhbGxUeXBlLnBuZyIsIHdpZHRoID0gNSwgaGVpZ2h0ID0gMTAsIGRwaSA9IDMwMCkNCiMgZ2dzYXZlKGZpbGVuYW1lID0gIlBlcmNlbnRBQV9OV0lhbGxUeXBlVy5wbmciLCB3aWR0aCA9IDEwLCBoZWlnaHQgPSA1LCBkcGkgPSAzMDApDQoNCmBgYA0KDQpgYGB7cn0NCkFBdjE1LnVuaV93aWRlMSAlPiUNCiAgZ3JvdXBfYnkoSU1BR0VfWVIpICU+JSANCiAgc3VtbWFyaXplKG1lYW4uUGVyY1dldE5XSSA9IG1lYW4oUGVyY1dldE5XSSksIHNkLlBlcmNXZXROV0kgPSBzZChQZXJjV2V0TldJKSwgbWVhbi5QZXJjV2V0M2YgPSBtZWFuKFBlcmNXZXQzZiksIHNkLlBlcmNXZXQzZiA9IHNkKFBlcmNXZXQzZikpICU+JSANCiAgZmlsdGVyKElNQUdFX1lSICE9IDApICU+JSANCiAgbXV0YXRlKFlyQmluID0gaWZlbHNlKElNQUdFX1lSIDw9IDE5NzksICIxOTcwJ3MiLA0KICAgICAgICAgICAgICAgaWZlbHNlKElNQUdFX1lSID49IDE5ODAgJiBJTUFHRV9ZUiA8IDE5OTAsICIxOTgwJ3MiLGlmZWxzZShJTUFHRV9ZUiA+PSAxOTkwICYgSU1BR0VfWVIgPDIwMDAsICIxOTkwJ3MiLCAiMjAwMCdzIikpKSkgJT4lDQogIGdncGxvdChhZXMoeCA9IG1lYW4uUGVyY1dldE5XSSwgeSA9IG1lYW4uUGVyY1dldDNmKSkgKyANCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMjUsIGNvbG9yID0gImJsdWUiLCBzaXplID0gNikgKw0KICBnZW9tX3Ntb290aChjb2xvciA9ICJyZWQiLCBtZXRob2QgPSAibG0iKSArDQogIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgaW50ZXJjZXB0ID0gMCwgbHR5ID0gJ2Rhc2hlZCcsIHNpemUgPSAxLjEsIGFscGhhID0gLjQpICsNCiAgIyBnZW9tX2RlbnNpdHlfMmQoKSArDQogIGxhYnMoeCA9ICIlIEFBIG1hcHBlZCBhcyBOV0kiLCB5ID0gIiUgQUEgbWFwcGVkIGFzIDMgZmFjdG9yIiwgdGl0bGUgPSAiIikgKw0KICBmYWNldF93cmFwKH5ZckJpbiwgbmNvbCA9IDIsIHNjYWxlcyA9ICJmcmVlIikgKw0KICAjIHhsaW0oMCwxMDApICsNCiAgIyB5bGltKDAsMTAwKSArDQogIHRoZW1lKHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICsNCiAgdGhlbWVfc21GYWNldA0KDQoNCiMjIyMNCkFBdjE1LnVuaV93aWRlMSAlPiUNCiAgIyBncm91cF9ieShJTUFHRV9ZUikgJT4lIA0KICAjIHN1bW1hcml6ZShtZWFuLlBlcmNXZXROV0kgPSBtZWFuKFBlcmNXZXROV0kpLCBzZC5QZXJjV2V0TldJID0gc2QoUGVyY1dldE5XSSksIG1lYW4uUGVyY1dldDNmID0gbWVhbihQZXJjV2V0M2YpLCBzZC5QZXJjV2V0M2YgPSBzZChQZXJjV2V0M2YpKSAlPiUgDQogIGZpbHRlcihJTUFHRV9ZUiAhPSAwKSAlPiUgDQogIG11dGF0ZShZckJpbiA9IGlmZWxzZShJTUFHRV9ZUiA8PSAxOTc5LCAiMTk3MCdzIiwNCiAgICAgICAgICAgICAgIGlmZWxzZShJTUFHRV9ZUiA+PSAxOTgwICYgSU1BR0VfWVIgPCAxOTkwLCAiMTk4MCdzIixpZmVsc2UoSU1BR0VfWVIgPj0gMTk5MCAmIElNQUdFX1lSIDwyMDAwLCAiMTk5MCdzIiwgIjIwMDAncyIpKSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBQZXJjV2V0TldJLCB5ID0gUGVyY1dldDNmKSkgKyANCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMDg1LCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDMpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIiIpICsNCiAgZmFjZXRfd3JhcCh+WXJCaW4sIG5jb2wgPSAyLCBzY2FsZXMgPSAiZnJlZSIpICsNCiAgIyB4bGltKDAsMTAwKSArDQogICMgeWxpbSgwLDEwMCkgKw0KICB0aGVtZShzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArDQogIHRoZW1lX3NtRmFjZXQNCiMgZ2dzYXZlKCJOV0lfSW1nQmluX3NjYXR0ZXJQZXJjZW50LnBuZyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSwgZHBpID0gMzAwKQ0KDQoNCmBgYA0KDQoNCiMjIFBlcmNlbnQgb2YgQUEgYXMgTldJIChSRURVQ0VEIEMgdHlwZXMpIGFuZCAzIGZhY3Rvcg0KDQpUaGlzIGloYXMgYmVlbiByZHVjZWQgYnkgZWxpbWluYXRpbmcgTldJIHBvbHlnb25zIGluIHRoZSBmb2xsb3dvbmcgQ293YXJkaW4gY2xhc3NlczoNCjEuIFJpdmVyaW5lDQoxLiBMYWN1c3RyaW5lDQoxLiBPdGhlcg0KMS4gTWFyaW5lIERlZXAgV2F0ZXINCg0KYGBge3J9DQp0MSA8LSBnc3ViKCJcXC5zaHAkIiwiIiwgbGlzdC5maWxlcygiZGF0YS9GaW5hbF9zaGFwZWZpbGUvdjE1X2RhdGEiLCBwYXR0ZXJuPSJzaHAkIiwgZnVsbC5uYW1lcz1UUlVFLCByZWN1cnNpdmUgPSBGQUxTRSkpDQojIHQyIDwtIGdzdWIoIlxcLnNocCQiLCIiLCBkaXIoImRhdGEvRmluYWxfc2hhcGVmaWxlL3YxNV9kYXRhIiwgcGF0dGVybj0ic2hwJCIsIGZ1bGwubmFtZXM9VFJVRSwgcmVjdXJzaXZlID0gRkFMU0UpKSAjIE5vdGUgbGlzdC5maWxlcyBhbmQgZGlyIHNlZW0gdG8gZG8gdGhlIGV4YWN0IHNtYWUgdGhpbmcuLi4NCg0KDQpud2lSZWQwMS50YmwgPC0gbWFwMigueCA9ICJkYXRhL0ZpbmFsX3NoYXBlZmlsZS92MTVfZGF0YSIsIC55ID0gIkZpbk5XSV9ub1BvTGFjUml2XzNGdW5pIiwgLmYgPSAgcmVhZE9HUikgDQoNCm53aVJlZDAxLnRibCA8LSBhc190aWJibGUobndpUmVkMDEudGJsW1sxXV1AZGF0YSkgDQpuYW1lcyhud2lSZWQwMS50YmwpDQoNCiMgYWFjZW50ci50YmwgJT4lIGRhdGF0YWJsZSgpDQoNCiMjIHN1bW1hcml6ZSB0b3RhbCBBQSBhcmVhDQpud2lSZWQwMS50YmwgJT4lIA0KICAjIG5hbWVzKCkgJT4lDQogIHN1bW1hcml6ZShzdW0uYXJlYUhhID0gc3VtKFBvbHlBcmVhSGEpLCBjbnQuQUFwb2x5ID0gbigpKSAlPiUNCiAgbXV0YXRlKHN1bS5BY3JlcyA9IDIuNDcxMDUqc3VtLmFyZWFIYSkgJT4lIA0KICBtdXRhdGUoc3VtLnNxbWlsZXMgPSAwLjAwMzg2MTAyKnN1bS5hcmVhSGEpICU+JSANCiAgZGF0YXRhYmxlKCkNCg0KDQpgYGANCg0KYGBge3J9DQojIGpvaW4gdGhlIGFhLCBlcm9yZWdpb24gc3R1ZmYNCndldGwudW5pMDFyZWQgPC0gbGVmdF9qb2luKG53aVJlZDAxLnRibCwgYWFDdHJkLmVjb3JlZywgYnkgPSAiQUF2MTRpZCIpDQoNCg0KYGBgDQoNCmBgYHtyfQ0KIyMgcmVkdWNlZCBOV0kNCnVuaS5hbGwucmVkIDwtIHdldGwudW5pMDFyZWQgJT4lIA0KICAjIG5hbWVzKCkgJT4lDQogIGdyb3VwX2J5KFBvbHlUeVVuaSkgJT4lDQogIHN1bW1hcml6ZShzdW0uYXJlYUhhID0gc3VtKFBvbHlBcmVhSGEpKSAlPiUgIA0KICBtdXRhdGUoQWNyZXMgPSBzdW0uYXJlYUhhKjIuNDcxMDUpICU+JSANCiAgbXV0YXRlKFNxTWlsZSA9IEFjcmVzKjAuMDAxNTYyNSkNCnVuaS5hbGwucmVkICU+JSBkYXRhdGFibGUoKQ0KDQp1bmkuYWxsLnJlZCAgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBBY3JlcywgeSA9IFBvbHlUeVVuaSkpICsNCiAgZ2VvbV9iYXJoKHN0YXQ9J2lkZW50aXR5JykgKw0KICBsYWJzKHkgPSAiIiwgeCA9ICJBcmVhIChhY3JlcykiLCBmaWxsID0gIiIsIHRpdGxlID0gIk1hcHBlZCBhcmVhIGJ5IGdlb21ldHJpYyB1bmlvbiIsIHN1YnRpdGxlID0gIlJlZHVjZWQgc2V0IG9mIENvd2FyZGluIHR5cGVzIikgKw0KICAjIHRoZW1lX2J3KCkgKw0KICAjIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgdGhlbWVfQ293c01vZDENCg0KYGBgDQoNCmBgYHtyfQ0Kd2V0bC51bmkwMXJlZCAlPiUgDQogICMgbmFtZXMoKSAlPiUNCiAgZ3JvdXBfYnkoUG9seVR5VW5pKSAlPiUNCiAgc3VtbWFyaXplKHN1bS5hcmVhSGEgPSBzdW0oUG9seUFyZWFIYSkpICU+JSAgDQogIG11dGF0ZShXZXRBY3JlcyA9IHN1bS5hcmVhSGEqMi40NzEwNSkgJT4lIA0KICBtdXRhdGUoV2V0U3FNaWxlID0gV2V0QWNyZXMqMC4wMDE1NjI1KQ0KDQpgYGANCg0KDQoNCiMjIyBESVZJU0lPTjogTldJIHJlZHVjZWQgQWNyZWFzIHN0YWNrZWQgYmFyIA0KYGBge3J9DQojIyMgcmVkdWNlZCB3ZXRsYW5kIHR5cGUNCiMjIERJVlNJT04gc3VtIA0KcmVkLnRkeSA8LSBsZWZ0X2pvaW4oYWFDdHJkLmVjb3JlZywgbndpUmVkMDEudGJsLCBieSA9ICJBQXYxNGlkIikNCg0KcmVkLnRkeSAlPiUgDQogIGdyb3VwX2J5KFBvbHlUeVVuaSkgJT4lIA0KICBzdW1tYXJpc2Uoc3VtLmFyZWFIYSA9IHN1bShQb2x5QXJlYUhhKSkgJT4lIA0KICBtdXRhdGUoc3VtLmFjcmUgPSBzdW0uYXJlYUhhKjIuNDcxMDUpDQoNCmRpdi5BY3Jlcy5yZWQgPC0gcmVkLnRkeSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoUG9seVR5VW5pLCBESVZJU0lPTiwgUG9seUFyZWFIYSkgJT4lIA0KICBtdXRhdGUoQXJlYUFjcmUgPSBQb2x5QXJlYUhhKjIuNDcxMDUpICU+JSANCiAgbmEub21pdCgpICU+JSANCiAgZ3JvdXBfYnkoUG9seVR5VW5pLCBESVZJU0lPTikgJT4lDQogIHN1bW1hcmlzZShzdW0uQWNyZSA9IHN1bShBcmVhQWNyZSkpDQoNCg0KIyBkYXRhdGFibGUoZGl2LkFjcmVzKQ0KDQojIyMNCmRpdi5BY3Jlcy5yZWQgJT4lDQogIGdncGxvdChhZXMoeD0gc3VtLkFjcmUsIHkgPSBQb2x5VHlVbmkpKSArDQogIGdlb21fYmFyaChzdGF0PSdpZGVudGl0eScpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpDQoNCmRpdi5BY3Jlcy5yZWQgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9IHN1bS5BY3JlLCB5ID0gRElWSVNJT04sIGZpbGwgPSBQb2x5VHlVbmkpKSArDQogIGdlb21fYmFyaChzdGF0PSdpZGVudGl0eScsIGNvbG9yID0gJ2JsYWNrJykgKw0KICBmYWNldF93cmFwKH5ESVZJU0lPTiwgc2NhbGVzID0gImZyZWUiLCBuY29sID0gMSkgKw0KICBsYWJzKHkgPSAiIiwgeCA9ICJBcmVhIChhY3JlcykiLGZpbGwgPSAiIikgKw0KICAjIHNjYWxlX3hfbG9nMTAobGFiZWxzID0gc2NhbGVzOjpjb21tYSkNCiAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpICsNCiAgdGhlbWUoYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCkpDQojIGdnc2F2ZSgiRGl2aXNpb25VbmlUeXBlX1JlZHVjZWQucG5nIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCiMgcmVkdWNlZCBud2kNCndldGwudW5pMDFyZWRfd2lkZTEgPC0gd2V0bC51bmkwMXJlZCAlPiUgDQogIGdyb3VwX2J5KEFBdjE0aWQsIFBvbHlUeVVuaSkgJT4lDQogIHN1bW1hcml6ZShzdW0uYXJlYUhhID0gc3VtKFBvbHlBcmVhSGEpKSAlPiUNCiAgc3ByZWFkKGtleSA9IFBvbHlUeVVuaSwgdmFsdWUgPSBzdW0uYXJlYUhhKSAlPiUgDQogIHJlbmFtZShXZXQzRm9ubHlIYSA9IFdldDNGb25seSkgJT4lIA0KICByZW5hbWUoV2V0TldJb25seUhhID0gV2V0TldJb25seSkgJT4lIA0KICByZW5hbWUoV2V0VW5pb25IYSA9IFdldFVuaW9uKQ0KDQojIHRoaXMgaXMgb25seSAxNDk5IChmcm9tIDE1MzggYWFpZCBmb3IgdGhlIG53aSBmdWxsIDNmIHVuaSBsYXllcikuIA0KIyBOZWVkIHRvIGNoZWNrDQoNCiMgam9pbiB3aXRoIHRoZSBBQSBjZW50cm9pZCBhbmQgZWNvcmVnaW9uDQp3ZXRsLnVuaTAxcmVkX3dpZGUxIDwtIGxlZnRfam9pbihhYUN0cmQuZWNvcmVnLCB3ZXRsLnVuaTAxcmVkX3dpZGUxLCBieSA9ICJBQXYxNGlkIikNCg0KIyMjIHJlcGxhY2UgTkEgd2l0aCAwDQp3ZXRsLnVuaTAxcmVkX3dpZGUxW2lzLm5hKHdldGwudW5pMDFyZWRfd2lkZTEpXSA8LSAwICMgdGhpcyByZXBsYWNlcyBOQSB3aXRoIDAgZm9yIGFsbCBDb2x1bW5zDQoNCiMgIyMgU08gZXhhbXBsZSBvZiBjaGFuZ2luZyBmb3Igc3BlY2lmaWMgY29sdW1ucy4uLg0KIyB4W2MoImEiLCAiYiIpXVtpcy5uYSh4W2MoImEiLCAiYiIpXSldIDwtIDANCg0KIyMgR09GIG1hcGN1cnZlcw0Kd2V0bC51bmkwMXJlZF93aWRlMSA8LSB3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgbXV0YXRlKGdvZiA9ICgoV2V0VW5pb25IYSkvKFdldFVuaW9uSGEgKyBXZXROV0lvbmx5SGEpKSooKFdldFVuaW9uSGEpLyhXZXRVbmlvbkhhICsgV2V0M0Zvbmx5SGEpKSkNCg0KIyMgS0VZIGNhbGN1bGF0aW9uczogDQp3ZXRsLnVuaTAxcmVkX3dpZGUxIDwtIHdldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIG5hbWVzKCkgJT4lIA0KICBtdXRhdGUoVG90V2V0SGEubndpID0gV2V0TldJb25seUhhICsgV2V0VW5pb25IYSkgJT4lDQogIG11dGF0ZShUb3RXZXRIYS4zZiA9IFdldDNGb25seUhhICsgV2V0VW5pb25IYSkgJT4lIA0KICBtdXRhdGUoUGVyY1dldE5XSSA9IDEwMCpUb3RXZXRIYS5ud2kvQUFhcmVhSGEpICU+JSANCiAgbXV0YXRlKFBlcmNXZXQzZiA9IDEwMCpUb3RXZXRIYS4zZi9BQWFyZWFIYSkgJT4lIA0KICBtdXRhdGUoTkRBSSA9IChUb3RXZXRIYS4zZi1Ub3RXZXRIYS5ud2kpLyhUb3RXZXRIYS4zZitUb3RXZXRIYS5ud2kpKQ0KDQp3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgIyBuYW1lcygpICU+JSANCiAgZGF0YXRhYmxlKCkgJT4lIA0KICBmb3JtYXRSb3VuZChjb2x1bW5zPWMoIlRvdFdldEhhLm53aSIsIlRvdFdldEhhLjNmIiwiUGVyY1dldE5XSSIsIlBlcmNXZXQzZiIsICJOREFJIiwiZ29mIiksIGRpZ2l0cz0yKQ0KDQpgYGANCg0KYGBge3J9DQojIyBhbGwgQUE6IGNvbXBhcmlzb24gb2YgcmVkdWNlZCBhbmQgZnVsbCBud2kNCmIxIDwtIEFBdjE1LnVuaV93aWRlMSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFBlcmNXZXROV0ksIHkgPSBQZXJjV2V0M2YpKSArIA0KICBnZW9tX3BvaW50KGFscGhhID0gMC4wNSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIkFsbCBOV0kgQ293YXJkaW4gdHlwZXMiKSArDQogIHRoZW1lX2J3KCkNCiAgIyBnZW9tX2hleCgpDQoNCg0KYjIgPC0gd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFBlcmNXZXROV0ksIHkgPSBQZXJjV2V0M2YpKSArIA0KICBnZW9tX3BvaW50KGFscGhhID0gMC4wNSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIlJlZHVjZWQgTldJIENvd2FyZGluIHR5cGVzIikgKw0KICB0aGVtZV9idygpDQogICMgZ2VvbV9oZXgoKQ0KIyBnZ3NhdmUoIlJlZHVjZWROV0lDb3dhcmRpblR5X0FsbEFBX3BlcmNlbnRBQVdldC5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDUsIGRwaSA9IDMwMCkNCg0KYjMgPC0gcGxvdF9ncmlkKGIxLCBiMiwgbGFiZWxzID0gYygiQSIsICJCIiksIGFsaWduID0gImgiKQ0KIyBzYXZlX3Bsb3QoInYxNV9OV0lyZWQucG5nIiwgYjMsIG5jb2wgPSAyKQ0KDQpgYGANCiMjIyBSZWR1Y2VkOiBkaWZmZXJlbmNlIGluICVBQQ0KDQoqIFN1bW1hcnkgb2YgdGhlICVBQSBmb3IgYWxsIHNpdGVzKg0KYGBge3J9DQojIyBjYWxjIHRoZSBkaWZmDQp3ZXRsLnVuaTAxcmVkX3dpZGUxIDwtIHdldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICBtdXRhdGUoZGlmZi5BQXBlcmNXZXQgPSBQZXJjV2V0M2YtUGVyY1dldE5XSSkNCg0KU29tZS53ZXQuYWEgPC0gd2V0bC51bmkwMXJlZF93aWRlMSAlPiUNCiAgbXV0YXRlKGNvbWJpbmVkX1dldEFyZWEgPSBUb3RXZXRIYS4zZiArIFRvdFdldEhhLm53aSkgJT4lIA0KICBmaWx0ZXIoY29tYmluZWRfV2V0QXJlYSA+MCkNCg0Kc3VtbWFyeShTb21lLndldC5hYSRkaWZmLkFBcGVyY1dldCkNCg0KYGBgDQoNCmBgYHtyfQ0KIyMNCmFyZWFaLndpZGUgPC0gd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIGRwbHlyOjpzZWxlY3QoQUF2MTRpZCwgQUFhcmVhSGEsIFBlcmNXZXQzZiwgUGVyY1dldE5XSSxUb3RXZXRIYS5ud2ksIFRvdFdldEhhLjNmKQ0KDQoNCmFyZWFaLnRpZHkgPC0gYXJlYVoud2lkZSAlPiUgDQogIGdhdGhlcihrZXkgPSBQcm9wVmFyLCB2YWx1ZSA9IFByb3AsIFBlcmNXZXQzZjpQZXJjV2V0TldJKSAlPiUgDQogIGdhdGhlcihrZXkgPSBBcmVhSGFWYXIsIHZhbHVlID0gQXJlYUhhLCBUb3RXZXRIYS5ud2k6VG90V2V0SGEuM2YpDQoNCmFyZWFaLnRpZHkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9QXJlYUhhVmFyLCB5ID0gQXJlYUhhKSkgKw0KICBnZW9tX2JveHBsb3QoKQ0KDQphcmVhWi50aWR5ICU+JSANCiAgZ2dwbG90KGFlcyh4PVByb3BWYXIsIHkgPSBQcm9wKSkgKw0KICBnZW9tX2JveHBsb3QoKQ0KDQoNCmBgYA0KDQoNCg0KYGBge3J9DQojIyBBQSBieSBEaXZpc2lvbjogUkVEVUNFRA0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIGdncGxvdChhZXMoeCA9IFBlcmNXZXROV0ksIHkgPSBQZXJjV2V0M2YpKSArIA0KICBnZW9tX3BvaW50KGFscGhhID0gMC4wNSwgY29sb3IgPSAiYmx1ZSIpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIlByb3BvcnRpb24gb2YgQUEgbWFwcGVkIGJ5IDNGIGFuZCBOV0kgKHJlZHVjZWQgQ293YXJkaW4gdHlwZXMpIikgKw0KICBmYWNldF93cmFwKH5ESVZJU0lPTiwgbmNvbCA9IDQpICsNCiAgeGxpbSgwLDEwMCkgKw0KICB5bGltKDAsMTAwKSArDQogICMgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkNCiAgdGhlbWVfc21GYWNldA0KICAjIHRoZW1lX0Nvd3NNb2QxDQoNCiAgICAgIA0KIyBnZ3NhdmUoZmlsZW5hbWUgPSAiUGVyY2VudEFBX05XSXJlZHVjZWRUeXBlTi5wbmciLCB3aWR0aCA9IDUsIGhlaWdodCA9IDEwLCBkcGkgPSAzMDApDQojIGdnc2F2ZShmaWxlbmFtZSA9ICJQZXJjZW50QUFfTldJcmVkdWNlZFR5cGVXLnBuZyIsIHdpZHRoID0gMTAsIGhlaWdodCA9IDUsIGRwaSA9IDMwMCkNCmBgYA0KDQoNCg0KYGBge3J9DQp3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JQ0KICBncm91cF9ieShJTUFHRV9ZUikgJT4lIA0KICBzdW1tYXJpemUobWVhbi5QZXJjV2V0TldJID0gbWVhbihQZXJjV2V0TldJKSwgc2QuUGVyY1dldE5XSSA9IHNkKFBlcmNXZXROV0kpLCBtZWFuLlBlcmNXZXQzZiA9IG1lYW4oUGVyY1dldDNmKSwgc2QuUGVyY1dldDNmID0gc2QoUGVyY1dldDNmKSkgJT4lIA0KICBmaWx0ZXIoSU1BR0VfWVIgIT0gMCkgJT4lIA0KICBtdXRhdGUoWXJCaW4gPSBpZmVsc2UoSU1BR0VfWVIgPD0gMTk3OSwgIjE5NzAncyIsDQogICAgICAgICAgICAgICBpZmVsc2UoSU1BR0VfWVIgPj0gMTk4MCAmIElNQUdFX1lSIDwgMTk5MCwgIjE5ODAncyIsaWZlbHNlKElNQUdFX1lSID49IDE5OTAgJiBJTUFHRV9ZUiA8MjAwMCwgIjE5OTAncyIsICIyMDAwJ3MiKSkpKSAlPiUNCiAgZ2dwbG90KGFlcyh4ID0gbWVhbi5QZXJjV2V0TldJLCB5ID0gbWVhbi5QZXJjV2V0M2YpKSArIA0KICBnZW9tX3BvaW50KGFscGhhID0gMC4yNSwgY29sb3IgPSAiYmx1ZSIsIHNpemUgPSA2KSArDQogIGdlb21fc21vb3RoKGNvbG9yID0gInJlZCIsIG1ldGhvZCA9ICJsbSIpICsNCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwLCBsdHkgPSAnZGFzaGVkJywgc2l6ZSA9IDEuMSwgYWxwaGEgPSAuNCkgKw0KICAjIGdlb21fZGVuc2l0eV8yZCgpICsNCiAgbGFicyh4ID0gIiUgQUEgbWFwcGVkIGFzIE5XSSIsIHkgPSAiJSBBQSBtYXBwZWQgYXMgMyBmYWN0b3IiLCB0aXRsZSA9ICIiKSArDQogIGZhY2V0X3dyYXAofllyQmluLCBuY29sID0gMiwgc2NhbGVzID0gImZyZWUiKSArDQogICMgeGxpbSgwLDEwMCkgKw0KICAjIHlsaW0oMCwxMDApICsNCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKw0KICB0aGVtZV9zbUZhY2V0DQoNCg0KIyMjIw0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUNCiAgIyBncm91cF9ieShJTUFHRV9ZUikgJT4lIA0KICAjIHN1bW1hcml6ZShtZWFuLlBlcmNXZXROV0kgPSBtZWFuKFBlcmNXZXROV0kpLCBzZC5QZXJjV2V0TldJID0gc2QoUGVyY1dldE5XSSksIG1lYW4uUGVyY1dldDNmID0gbWVhbihQZXJjV2V0M2YpLCBzZC5QZXJjV2V0M2YgPSBzZChQZXJjV2V0M2YpKSAlPiUgDQogIGZpbHRlcihJTUFHRV9ZUiAhPSAwKSAlPiUgDQogIG11dGF0ZShZckJpbiA9IGlmZWxzZShJTUFHRV9ZUiA8PSAxOTc5LCAiMTk3MCdzIiwNCiAgICAgICAgICAgICAgIGlmZWxzZShJTUFHRV9ZUiA+PSAxOTgwICYgSU1BR0VfWVIgPCAxOTkwLCAiMTk4MCdzIixpZmVsc2UoSU1BR0VfWVIgPj0gMTk5MCAmIElNQUdFX1lSIDwyMDAwLCAiMTk5MCdzIiwgIjIwMDAncyIpKSkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBQZXJjV2V0TldJLCB5ID0gUGVyY1dldDNmKSkgKyANCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuMDg1LCBjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDMpICsNCiAgZ2VvbV9zbW9vdGgoY29sb3IgPSAicmVkIiwgbWV0aG9kID0gImxtIikgKw0KICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4xLCBhbHBoYSA9IC40KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBsYWJzKHggPSAiJSBBQSBtYXBwZWQgYXMgTldJIiwgeSA9ICIlIEFBIG1hcHBlZCBhcyAzIGZhY3RvciIsIHRpdGxlID0gIlJlZHVjZWQgQ293YXJkaW4gdHlwZXMiKSArDQogIGZhY2V0X3dyYXAofllyQmluLCBuY29sID0gMiwgc2NhbGVzID0gImZyZWUiKSArDQogICMgeGxpbSgwLDEwMCkgKw0KICAjIHlsaW0oMCwxMDApICsNCiAgdGhlbWUoc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKw0KICB0aGVtZV9zbUZhY2V0DQojIGdnc2F2ZSgiTldJX0ltZ0Jpbl9zY2F0dGVyUGVyY2VudF9yZWR1Y2VkLnBuZyIsIHdpZHRoID0gNiwgaGVpZ2h0ID0gNSwgZHBpID0gMzAwKQ0KDQpgYGANCg0KDQoNCiMjIyBEaXZpc2lvbjogTkRBSSByZWR1Y2VkIE5XSQ0KYGBge3J9DQpwbDA2IDwtIHdldGwudW5pMDFyZWRfd2lkZTEgJT4lDQogIGdyb3VwX2J5KERJVklTSU9OKSAlPiUgDQogIG11dGF0ZShtZWFuLk5EQUkgPSBtZWFuKE5EQUksIG5hLnJtID0gVFJVRSkpICU+JSANCiAgIyBuYW1lcygpICU+JSANCiAgZ2dwbG90KGFlcyh4PU5EQUksIHkgPSByZW9yZGVyKERJVklTSU9OLCBtZWFuLk5EQUkpKSkgKw0KICBnZW9tX2JveHBsb3RoKGZpbGwgPSAiaXZvcnkyIikgKw0KICAjIGdlb21faml0dGVyKGNvbG9yID0gImJsdWUiLCBhbHBoYT0wLjA1LCBzaXplID0gMikgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBzaXplPTEuNSwgY29sb3IgPSAicmVkIiwgbHR5ID0gImRhc2hlZCIsIGFscGhhID0gMC41KSArDQogIGxhYnMoeT0iIiwgdGl0bGUgPSAiTm9ybWFsaXplZCBEaWZmZXJlbmNlIEFyZWEgSW5kZXgiLCBzdWJ0aXRsZSA9ICJSZWR1Y2VkIHNldCBvZiBDb3dhcmRpbiB0eXBlcyIpICsNCiAgdGhlbWVfQ293c01vZDENCg0KDQojICMgc2F2ZV9wbG90KHBsb3QgPSBwbDA2LCBmaWxlbmFtZSA9ICJESVZJU0lPTl9OREFJX2JveHBsb3RfUmVkLnBuZyIpDQojIGdnc2F2ZShmaWxlbmFtZSA9ICJEaXZpc2lvbl9OREFJX2JveHBsb3ROb0ppdF9yZWQucG5nIiwgcGxvdCA9IHBsMDYsIGRwaSA9IDMwMCwgd2lkdGggPSA3LjUsIGhlaWdodCA9IDQpDQoNCnBsMDYNCg0KYGBgDQoNCiMjIyBEaXN0cmljdDogTkRBSQ0KYGBge3IsIGZpZy5oZWlnaHQ9OH0NCnBsMDcgPC0gd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogICMgbXV0YXRlKG1lYW4uTkRBSSA9IG1lYW4oTkRBSSwgbmEucm0gPSBUUlVFKSkgJT4lDQogIGdyb3VwX2J5KERpc3RyaWN0KSAlPiUgDQogIG11dGF0ZShtZWQuTkRBSSA9IG1lZGlhbihOREFJLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgbXV0YXRlKGNudCA9IG4oKSkgJT4lIA0KICBmaWx0ZXIoY250ID49IDE1KSAlPiUgDQogICMgbmFtZXMoKSAlPiUgDQogIGdncGxvdChhZXMoeD1OREFJLCB5ID0gcmVvcmRlcihEaXN0cmljdCxtZWQuTkRBSSkpKSArDQogIGdlb21fYm94cGxvdGgoZmlsbCA9ICJpdm9yeTIiKSArDQogICMgZ2VvbV9qaXR0ZXIoY29sb3IgPSAiYmx1ZSIsIGFscGhhPTAuMDUsIHNpemUgPSAyKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIHNpemU9MS41LCBjb2xvciA9ICJyZWQiLCBsdHkgPSAiZGFzaGVkIiwgYWxwaGEgPSAwLjUpICsNCiAgbGFicyh5PSIiLCB0aXRsZSA9ICJOb3JtYWxpemVkIERpZmZlcmVuY2UgQXJlYSBJbmRleCIsIHN1YnRpdGxlID0gIlJlZHVjZWQgc2V0IG9mIENvd2FyZGluIHR5cGVzIikgKw0KICB0aGVtZV9Db3dzTW9kMQ0KDQojIGdnc2F2ZShmaWxlbmFtZSA9ICJEaXN0cmljdF9OREFJX2JveHBsb3ROb2ppdHRlcl9yZWQucG5nIiwgcGxvdCA9IHBsMDcsIGRwaSA9IDMwMCwgd2lkdGggPSA3LjUsIGhlaWdodCA9IDYpDQoNCnBsMDcNCg0KDQoNCg0KYGBgDQojIyMgUHJvdmluY2U6IE5EQUkgKCNmYWlsKQ0KYGBge3IsIGV2YWw9RkFMU0V9DQojIyBjYW4ndCBnZXQgdGhpcyBzaGl0IHRvIHdvcmsuLi4NCg0KcGwwOCA8LSB3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgIyBtdXRhdGUobWVhbi5OREFJID0gbWVhbihOREFJLCBuYS5ybSA9IFRSVUUpKSAlPiUNCiAgZ3JvdXBfYnkoUFJPVklOQ0UpICU+JSANCiAgbXV0YXRlKG1lZC5OREFJID0gbWVkaWFuKE5EQUksIG5hLnJtID0gVFJVRSkpICU+JQ0KICBtdXRhdGUoY250ID0gbigpKSAlPiUgDQogIGZpbHRlcihjbnQgPj0gMTUpICU+JSANCiAgIyBuYW1lcygpICU+JSANCiAgZ2dwbG90KGFlcyh4PU5EQUksIHkgPSByZW9yZGVyKFBST1ZJTkNFLG1lZC5OREFJKSkpICsNCiAgZ2VvbV9ib3hwbG90aChmaWxsID0gIml2b3J5MiIpICsNCiAgIyBnZW9tX2ppdHRlcihjb2xvciA9ICJibHVlIiwgYWxwaGE9MC4wNSwgc2l6ZSA9IDIpICsNCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gMCwgc2l6ZT0xLjUsIGNvbG9yID0gInJlZCIsIGx0eSA9ICJkYXNoZWQiLCBhbHBoYSA9IDAuNSkgKw0KICBsYWJzKHk9IiIsIHRpdGxlID0gIk5vcm1hbGl6ZWQgRGlmZmVyZW5jZSBBcmVhIEluZGV4Iiwgc3VidGl0bGUgPSAiUmVkdWNlZCBzZXQgb2YgQ293YXJkaW4gdHlwZXMiKSArDQogIHRoZW1lX3NtRmFjZXQgKw0KICB0aGVtZShheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGV4dC55ID0gZWxlbWVudF9ibGFuaygpKSArDQogICMgdGhlbWVfQ293c01vZDENCiAgZmFjZXRfd3JhcCh+UFJPVklOQ0UsIG5jb2wgPSAxKQ0KDQoNCmdnc2F2ZShmaWxlbmFtZSA9ICJCbHlQcm92aW5jZV9OREFJX2JveHBsb3RfcmVkLnBuZyIsIHBsb3QgPSBwbDA4LCBkcGkgPSAzMDAsIHdpZHRoID0gOC41LCBoZWlnaHQgPSAxNSkNCg0KcGwwOA0KYGBgDQoNCg0KYGBge3J9DQojIyMjDQpkaXN0aS5uZGFpLnN1bSA8LSB3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgZ3JvdXBfYnkoRGlzdHJpY3QpICU+JSANCiAgc3VtbWFyaXNlKGNudCA9IG4oKSwgbWVhbi5uZGFpID0gbWVhbihOREFJLCBuYS5ybT1UUlVFKSwgbWVkLm5kYWkgPSBtZWRpYW4oTkRBSSwgbmEucm09VFJVRSksIHEyNS5uZGFpID0gcXVhbnRpbGUoTkRBSSxwcm9iID0gLjI1LCBuYS5ybT1UUlVFKSwgcTc1Lm5kYWkgPSBxdWFudGlsZShOREFJLHByb2IgPSAuNzUsIG5hLnJtPVRSVUUpKQ0KDQpkaXN0aS5uZGFpLnN1bSAlPiUgDQogIGRhdGF0YWJsZSgpICU+JSANCiAgZm9ybWF0Um91bmQofm1lYW4ubmRhaSArIG1lZC5uZGFpICsgcTI1Lm5kYWkgKyBxNzUubmRhaSwgMikNCg0KIyMgZXJyb3IgYmFyIHdpdGggbWVkaWFuIE5EQUkNCmRpc3RpLm5kYWkuc3VtICU+JSANCiAgZmlsdGVyKGNudCA+PSAzMCkgJT4lDQogIGdncGxvdChhZXMoeD1tZWQubmRhaSwgeSA9IHJlb3JkZXIoRGlzdHJpY3QsIG1lZC5uZGFpKSkpICsNCiAgZ2VvbV9lcnJvcmJhcmgoYWVzKHhtaW49IHEyNS5uZGFpLCB4bWF4ID0gcTc1Lm5kYWkpKSArDQogIGdlb21fcG9pbnQoc2l6ZSA9IDQuNSwgY29sb3IgPSAicmVkIikNCg0KYGBgDQpgYGB7cn0NCiMjIyMjIyMjDQojIyBOb3RlIGNvb2wgdXNlIG9mIHN1bW1hcml6ZV9hdA0KIyMjIyMjIyMNCg0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIHN1bW1hcmlzZV9hdChjKCdBQWFyZWFIYScsJ1BlcmNXZXQzZicsJ1BlcmNXZXROV0knLCdkaWZmLkFBcGVyY1dldCcpLGMoJ21lYW4nLCdzZCcsICdtZWRpYW4nKSkNCg0KDQojIyBESVZJU0lPTg0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIGdyb3VwX2J5KERJVklTSU9OKSAlPiUNCiAgc3VtbWFyaXNlX2F0KGMoJ0FBYXJlYUhhJywnUGVyY1dldDNmJywnUGVyY1dldE5XSScsJ2RpZmYuQUFwZXJjV2V0JyksYygnbWVhbicsJ3NkJykpICU+JSANCiAgZGF0YXRhYmxlKCkgJT4lIA0KICBmb3JtYXRSb3VuZCh+QUFhcmVhSGFfbWVhbiArIFBlcmNXZXQzZl9tZWFuICsgUGVyY1dldE5XSV9tZWFuICsgQUFhcmVhSGFfc2QgKyBQZXJjV2V0M2Zfc2QgKyBQZXJjV2V0TldJX3NkLCAyKQ0KDQojIyBESVNUUklDVA0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIGdyb3VwX2J5KERpc3RyaWN0KSAlPiUNCiAgc3VtbWFyaXNlX2F0KGMoJ0FBYXJlYUhhJywnUGVyY1dldDNmJywnUGVyY1dldE5XSScsJ2RpZmYuQUFwZXJjV2V0JyksYygnbWVhbicsJ3NkJykpICU+JSANCiAgIyBuYW1lcygpICU+JSANCiAgZGF0YXRhYmxlKCkgJT4lIA0KICBmb3JtYXRSb3VuZCh+QUFhcmVhSGFfbWVhbiArIFBlcmNXZXQzZl9tZWFuICsgUGVyY1dldE5XSV9tZWFuICsgQUFhcmVhSGFfc2QgKyBQZXJjV2V0M2Zfc2QgKyBQZXJjV2V0TldJX3NkLCAyKQ0KICANCg0KIyMgVVNfTDNOQU1FDQp3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgZ3JvdXBfYnkoVVNfTDNOQU1FKSAlPiUNCiAgc3VtbWFyaXNlX2F0KGMoJ0FBYXJlYUhhJywnUGVyY1dldDNmJywnUGVyY1dldE5XSScsJ2RpZmYuQUFwZXJjV2V0JyksYygnbWVhbicsJ3NkJykpICU+JSANCiAgIyBuYW1lcygpICU+JSANCiAgZGF0YXRhYmxlKCkgJT4lIA0KICBmb3JtYXRSb3VuZCh+QUFhcmVhSGFfbWVhbiArIFBlcmNXZXQzZl9tZWFuICsgUGVyY1dldE5XSV9tZWFuICsgQUFhcmVhSGFfc2QgKyBQZXJjV2V0M2Zfc2QgKyBQZXJjV2V0TldJX3NkLCAzKQ0KDQpgYGANCiMjI0RpZmZlcmVuY2UgaW4gdGhlICVBQSBtYXBwZWQgYXMgd2V0bGFuZA0KYGBge3J9DQojIyBoaXN0b3JncmFtIG9mIHRoZSAkIGRpZmYgaW4gJSBBQSBtYXBwZWQNCiMgd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQojICAgZ2dwbG90KGFlcyh4PWRpZmYuQUFwZXJjV2V0KSkgKw0KIyAgIGdlb21faGlzdG9ncmFtKCkNCg0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogIGdncGxvdChhZXMoeD1kaWZmLkFBcGVyY1dldCkpICsNCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAnaXZvcnkyJykgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBzaXplID0gMS4yLCBsdHkgPSAiZGFzaGVkIiwgY29sb3IgPSAicmVkIiwgYWxwaGEgPSAuMikgKw0KICBsYWJzKHggPSAiRGlmZmVyZW5jZSBpbiAlQUEgbWFwcGVkIiwgeSA9ICJEZW5zaXR5IikNCiMgZ2dzYXZlKCJEaWZmSW5QZXJjQUFhc1dldC5wbmciLCB3aWR0aCA9IDUuNSwgaGVpZ2h0ID0gNSwgZHBpID0gMzAwKQ0KDQoNCiMjIERJVklTSU9ODQp3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgZ3JvdXBfYnkoRElWSVNJT04pICU+JQ0KICBzdW1tYXJpc2VfYXQoYygnQUFhcmVhSGEnLCdQZXJjV2V0M2YnLCdQZXJjV2V0TldJJywnZGlmZi5BQXBlcmNXZXQnKSxjKCdtZWFuJywnc2QnKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBkaWZmLkFBcGVyY1dldF9tZWFuDQosIHkgPSByZW9yZGVyKERJVklTSU9OLGRpZmYuQUFwZXJjV2V0X21lYW4pKSkgKw0KZ2VvbV9wb2ludCgpDQoNCiMjIHBsb3QgZmFjZXRlZCB2ZXJzaW9uIG9mIGdyYXBoDQp3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgZ2dwbG90KGFlcyh4PWRpZmYuQUFwZXJjV2V0KSkgKw0KICBnZW9tX2RlbnNpdHkoZmlsbCA9ICdpdm9yeTInKSArDQogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIHNpemUgPSAxLjIsIGx0eSA9ICJkYXNoZWQiLCBjb2xvciA9ICJyZWQiLCBhbHBoYSA9IC4yKSArDQogIGxhYnMoeCA9ICJEaWZmZXJlbmNlIGluICVBQSBtYXBwZWQiLCB5ID0gIkRlbnNpdHkiKSArDQogIGZhY2V0X3dyYXAofkRJVklTSU9OLCBuY29sID0gMiwgc2NhbGVzID0gJ2ZyZWVfeScpICsNCiAgdGhlbWVfc21GYWNldA0KIyBnZ3NhdmUoIkRpZmZJblBlcmNBQWFzV2V0X0RJVmRlbi5wbmciLCB3aWR0aCA9IDcuNSwgaGVpZ2h0ID0gNiwgZHBpID0gMzAwKQ0KDQoNCiMgIyMgRElTVFJJQ1QNCiMgd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQojICAgZ3JvdXBfYnkoRGlzdHJpY3QpICU+JQ0KIyAgIHN1bW1hcmlzZV9hdChjKCdBQWFyZWFIYScsJ1BlcmNXZXQzZicsJ1BlcmNXZXROV0knLCdkaWZmLkFBcGVyY1dldCcpLGMoJ21lYW4nLCdzZCcpKSAlPiUgDQojICAgIyBuYW1lcygpICU+JSANCiMgICBkYXRhdGFibGUoKSAlPiUgDQojICAgZm9ybWF0Um91bmQofkFBYXJlYUhhX21lYW4gKyBQZXJjV2V0M2ZfbWVhbiArIFBlcmNXZXROV0lfbWVhbiArIEFBYXJlYUhhX3NkICsgUGVyY1dldDNmX3NkICsgUGVyY1dldE5XSV9zZCwgMikNCiMgICANCiMgDQojICMjIFVTX0wzTkFNRQ0KIyB3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiMgICBncm91cF9ieShVU19MM05BTUUpICU+JQ0KIyAgIHN1bW1hcmlzZV9hdChjKCdBQWFyZWFIYScsJ1BlcmNXZXQzZicsJ1BlcmNXZXROV0knLCdkaWZmLkFBcGVyY1dldCcpLGMoJ21lYW4nLCdzZCcpKSAlPiUgDQojICAgIyBuYW1lcygpICU+JSANCiMgICBkYXRhdGFibGUoKSAlPiUgDQojICAgZm9ybWF0Um91bmQofkFBYXJlYUhhX21lYW4gKyBQZXJjV2V0M2ZfbWVhbiArIFBlcmNXZXROV0lfbWVhbiArIEFBYXJlYUhhX3NkICsgUGVyY1dldDNmX3NkICsgUGVyY1dldE5XSV9zZCwgMykNCg0KYGBgDQoNCg0KYGBge3J9DQojIyBOREFJIA0KIyMgcGxvdDogcmVkdWNlZCBOV0kNCndldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9TkRBSSkpICsNCiAgZ2VvbV9kZW5zaXR5KGFscGhhID0gMC40LCBmaWxsID0gJ2l2b3J5MicsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBzaXplID0gMS4xNSwgbHR5ID0gImRhc2hlZCIpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIG5jb2wgPSAyLCBzY2FsZSA9ICdmcmVlX3knKSArDQogIGxhYnMoeD0iTkRBSSIsIHkgPSAiRGVuc2l0eSIsIHRpdGxlID0gIk5EQUkgYnkgVVNBQ0UgRGl2aXNpb24iKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCiMgZ2dzYXZlKGZpbGU9Ik5EQUlfRGl2aXNpb25fRGVuc2l0eV9yZWQucG5nIiwgd2lkdGggPSA3LjUsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCg0KDQojIyBoaXN0b2dyYW06IHJlZHVjZWQgTldJDQp3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgIyBmaWx0ZXIoY250ID49IDcpICU+JSANCiAgZ2dwbG90KGFlcyh4PU5EQUkpKSArDQogIGdlb21faGlzdG9ncmFtKGFscGhhID0gMC40LCBmaWxsID0gJ2l2b3J5MicsIGNvbG9yID0gImJsYWNrIikgKw0KICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBzaXplID0gMS4xNSwgbHR5ID0gImRhc2hlZCIpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIG5jb2wgPSAyLCBzY2FsZSA9ICdmcmVlX3knKSArDQogIGxhYnMoeD0iTkRBSSIsIHkgPSAiQUEgY291bnQiLCB0aXRsZSA9ICJOREFJIGJ5IFVTQUNFIERpdmlzaW9uIikgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQojIGdnc2F2ZShmaWxlPSJOREFJX0RpdmlzaW9uX2hpc3RvZ3JhbV9yZWQucG5nIiwgd2lkdGggPSA3LjUsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCg0KYGBgDQoNCg0KIyMgVVNBQ0UgRGl2aXNpb24gLS0gTWFwY3VydmVzIEdPRg0KDQpgYGB7cn0NCmdvZi5kaXYucGxvdCA8LSB3ZXRsLnVuaTAxcmVkX3dpZGUxICU+JSANCiAgIyBmaWx0ZXIoY250ID49IDcpICU+JSANCiAgZ2dwbG90KGFlcyh4PWdvZikpICsNCiAgZ2VvbV9kZW5zaXR5KGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjQ1LCBmaWxsID0gIml2b3J5MiIpICsNCiAgIyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBzaXplID0gMS4xNSwgbHR5ID0gImRhc2hlZCIpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIG5jb2wgPSAyLCBzY2FsZSA9ICdmcmVlJykgKw0KICBsYWJzKHg9Ikdvb2RuZXNzIG9mIGZpdCIsIHkgPSAiRGVuc2l0eSIsIHRpdGxlID0gIk1hcGN1cnZlcyBnb29kbmVzcyBvZiBmaXQgYnkgVVNBQ0UgRGl2aXNpb24iKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCg0KIyBnb2YuZGl2LnBsb3QgJT4lIA0KIyAgIGdnc2F2ZShmaWxlID0gIkdPRl9EaXZpc2lvbl9yZWQucG5nIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA3LCBkcGkgPSAzMDApDQoNCiMjIGhpc3RncmFtDQpnb2YuZGl2Lmhpc3QgPC0gd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogICMgZmlsdGVyKGNudCA+PSA3KSAlPiUgDQogIGdncGxvdChhZXMoeD1nb2YpKSArDQogIGdlb21faGlzdG9ncmFtKGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjQ1LCBmaWxsID0gIml2b3J5MiIpICsNCiAgIyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBzaXplID0gMS4xNSwgbHR5ID0gImRhc2hlZCIpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIG5jb2wgPSAyLCBzY2FsZSA9ICdmcmVlX3knKSArDQogIGxhYnMoeD0iR29vZG5lc3Mgb2YgZml0IiwgeSA9ICJBQSBjb3VudCIsIHRpdGxlID0gIk1hcGN1cnZlcyBnb29kbmVzcyBvZiBmaXQgYnkgVVNBQ0UgRGl2aXNpb24iKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikNCiMgZ2dzYXZlKGZpbGU9IkdPRl9EaXZpc2lvbl9oaXN0b2dyYW1fcmVkMi5wbmciLCB3aWR0aCA9IDYuODUsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCmdvZi5kaXYuaGlzdA0KDQojIyBib3hwbG90cw0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogICMgZmlsdGVyKGNudCA+PSA3KSAlPiUgDQogIGdncGxvdChhZXMoeD1nb2YpKSArDQogIGdlb21faGlzdG9ncmFtKGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjQ1LCBmaWxsID0gIml2b3J5MiIpICsNCiAgIyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBzaXplID0gMS4xNSwgbHR5ID0gImRhc2hlZCIpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIG5jb2wgPSAyLCBzY2FsZSA9ICdmcmVlX3knKSArDQogIGxhYnMoeD0iR29vZG5lc3Mgb2YgZml0IiwgeSA9ICJBQSBjb3VudCIsIHRpdGxlID0gIk1hcGN1cnZlcyBnb29kbmVzcyBvZiBmaXQgYnkgVVNBQ0UgRGl2aXNpb24iKSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKw0KICBjb29yZF9mbGlwKCkNCiMgZ2dzYXZlKGZpbGU9IkdPRl9EaXZpc2lvbl9oaXN0b2dyYW1fcmVkYWx0LnBuZyIsIHdpZHRoID0gNy41LCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQpnb2YuZGl2Lmhpc3QNCg0KDQpgYGANCg0KIyMjIEJhaWx5IHByb3ZpbmNlIA0KDQoNCmBgYHtyfQ0KUHJvdi5BY3Jlcy5yZWQgPC0gd2V0bC51bmkwMXJlZF93aWRlMSAgJT4lIA0KICBkcGx5cjo6c2VsZWN0KFdldFVuaW9uSGEsIFdldDNGb25seUhhLCBXZXROV0lvbmx5SGEsIFBST1ZJTkNFKSAlPiUgDQogIHJlbmFtZShVbmlvbiA9IFdldFVuaW9uSGEsIE9ubHkzRiA9IFdldDNGb25seUhhLCBPbmx5TldJID0gV2V0TldJb25seUhhKSAlPiUgDQogIGdhdGhlcihrZXkgPSB1bmlUeXBlLCB2YWx1ZSA9IEFyZWFIYSwgLVBST1ZJTkNFKSAlPiUgDQogIG11dGF0ZShBcmVhQWNyZSA9IEFyZWFIYSoyLjQ3MTA1KSAlPiUgDQogIGdyb3VwX2J5KHVuaVR5cGUsIFBST1ZJTkNFKSAlPiUNCiAgc3VtbWFyaXNlKHN1bS5BY3JlID0gc3VtKEFyZWFBY3JlKSkNCg0KDQpkYXRhdGFibGUoUHJvdi5BY3Jlcy5yZWQpDQoNCiMjIw0KIyBQcm92LkFjcmVzLnJlZCAlPiUgDQojICAgZ2dwbG90KGFlcyh4PSBzdW0uQWNyZSwgeSA9IHVuaVR5cGUpKSArDQojICAgZ2VvbV9iYXJoKHN0YXQ9J2lkZW50aXR5JykgKw0KIyAgIGZhY2V0X3dyYXAoflBST1ZJTkNFLCBzY2FsZXMgPSAiZnJlZSIpICsNCiMgICBsYWJzKHkgPSAiIiwgeCA9ICJBcmVhIChhY3JlcykiLCB0aXRsZSA9ICJNYXBwZWQgYXJlYSBieSBnZW9tZXRyaWMgdW5pb24iLCBzdWJ0aXRsZSA9ICJTdWJzZXQgQ293YXJkaW4gdHlwZXMiKSArDQojICAgdGhlbWVfYncoKSArDQojICAgIyBzY2FsZV94X2xvZzEwKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpDQojICAgc2NhbGVfeF9jb250aW51b3VzKGxhYmVscyA9IHNjYWxlczo6Y29tbWEpDQoNCiMjIyBmaWx0ZXIgb3V0IHNpdGVzID41MCBhY3JlYXMgaW4gQUEgc2l6ZQ0KUHJvdi5BY3Jlcy5yZWQgJT4lIA0KICBncm91cF9ieShQUk9WSU5DRSkgJT4lIA0KICBtdXRhdGUoc3VtQWxsUFJvdmluY2VBcmVhID0gc3VtKHN1bS5BY3JlKSkgJT4lIA0KICBmaWx0ZXIoc3VtQWxsUFJvdmluY2VBcmVhID4gNTApICU+JSANCiAgZ2dwbG90KGFlcyh4PSBzdW0uQWNyZSwgeSA9IFBST1ZJTkNFLCBmaWxsID0gdW5pVHlwZSkpICsNCiAgZ2VvbV9iYXJoKHN0YXQ9J2lkZW50aXR5JywgY29sb3IgPSAnYmxhY2snKSArDQogIGZhY2V0X3dyYXAoflBST1ZJTkNFLCBzY2FsZXMgPSAiZnJlZSIsIG5jb2wgPSAyKSArDQogIGxhYnMoeSA9ICIiLCB4ID0gIkFyZWEgKGFjcmVzKSIsIHRpdGxlID0gIk1hcHBlZCBhcmVhIGJ5IGdlb21ldHJpYyB1bmlvbiIsIHN1YnRpdGxlID0gIlN1YnNldCBvZiBDb3dhcmRpbiB0eXBlcyIsIGZpbGw9IiIpICsNCiAgdGhlbWVfYncoKSArDQogICMgc2NhbGVfeF9sb2cxMChsYWJlbHMgPSBzY2FsZXM6OmNvbW1hKQ0KICBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICB0aGVtZShheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSkgDQojIGdnc2F2ZSgiRGl2aXNpb25VbmlUeXBlLnBuZyIsIHdpZHRoID0gOS41LCBoZWlnaHQgPSAxMCwgZHBpID0gMzAwKQ0KDQpgYGANCg0KIyMgQmFpbGV5IFNlY3Rpb24gLS0gTWFwY3VydmVzIEdPRg0KDQpgYGB7cn0NCmdvZi5CbHlQcm92aW5jZS5wbG90IDwtIHdldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBncm91cF9ieShQUk9WSU5DRSkgJT4lIA0KICBtdXRhdGUoY250X2J5X3Byb3YgID0gbigpKSAlPiUgDQogIGZpbHRlcihjbnRfYnlfcHJvdiA+PSAzMCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9Z29mKSkgKw0KICBnZW9tX2RlbnNpdHkoY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNDUsIGZpbGwgPSAiaXZvcnkyIikgKw0KICAjIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDAsIGNvbG9yID0gJ3JlZCcsIHNpemUgPSAxLjE1LCBsdHkgPSAiZGFzaGVkIikgKw0KICBmYWNldF93cmFwKH5QUk9WSU5DRSwgbmNvbCA9IDEpICsNCiAgbGFicyh4PSJHb29kbmVzcyBvZiBmaXQiLCB5ID0gIkRlbnNpdHkiLCB0aXRsZSA9ICJNYXBjdXJ2ZXMgZ29vZG5lc3Mgb2YgZml0IGJ5IEJhaWxleSBQcm92aW5jZSIpICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArDQogIHRoZW1lX0Nvd3NNb2QxDQoNCmdvZi5CbHlQcm92aW5jZS5wbG90DQoNCmdvZi5CbHlQcm92aW5jZS5wbG90ICU+JQ0KICBnZ3NhdmUoZmlsZSA9ICJHT0ZfQmx5UHJvdmluY2VfcmVkLnBuZyIsIHdpZHRoID0gNywgaGVpZ2h0ID0gMTAsIGRwaSA9IDMwMCkNCg0KDQojIyBEYXRhdGJsZQ0Kd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQogICMgZmlsdGVyKGNudCA+PSA3KSAlPiUgDQogIGdyb3VwX2J5KFBST1ZJTkNFKSAlPiUgDQogIG11dGF0ZShjbnRfYnlfcHJvdiAgPSBuKCkpICU+JSANCiAgZGF0YXRhYmxlKGNhcHRpb24gPSAiR09GIHJlZHVjZWQgTldJIEJhaWx5IFByb3ZpbmNlIikNCg0KYGBgDQoNCiMjIyBEaWZmZXJlbmNlIGluICUgbWFwcGVkIGJ5IE5XSQ0KYGBge3J9DQoNCndldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBncm91cF9ieShJTUFHRV9ZUikgJT4lIA0KICBzdW1tYXJpemUoY250X2J5X3Byb3YgID0gbigpLCBtZWFuLlBlcmNXZXROV0kgPSBtZWFuKFBlcmNXZXROV0kpLCBtZWFuLlBlcmNXZXQzZiA9IG1lYW4oUGVyY1dldDNmKSxzdW0uQUF2MTVBY3JlID0gc3VtKEFBaWRBY3JlKSkgJT4lIA0KICBtdXRhdGUoZGlmLlBlcmNBQTNGX05XSSA9IG1lYW4uUGVyY1dldDNmLW1lYW4uUGVyY1dldE5XSSkgJT4lIA0KICBtdXRhdGUod3QubW4gPSBtYXAyX2RibCgueCA9IGRpZi5QZXJjQUEzRl9OV0ksIC55ID0gc3VtLkFBdjE1QWNyZSwgLmY9d2VpZ2h0ZWQubWVhbikpICU+JSANCiAgZmlsdGVyKElNQUdFX1lSID4wKSAlPiUgDQogIGdncGxvdChhZXMoeD1JTUFHRV9ZUiwgeSA9IGRpZi5QZXJjQUEzRl9OV0kpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yPSdyZWQnLCBzaXplPTEuMiwgYWxwaGE9MC41KSArDQogIGdlb21fcG9pbnQoYWVzKHNpemU9c3VtLkFBdjE1QWNyZSksIGNvbG9yID0gImJsdWUiLCBhbHBoYSA9IC4zKSArDQogIGxhYnMoeCA9ICJOV0kgaW1hZ2UgeWVhciIsIHkgPSAiRGlmZmVyZW5jZSBpbiAlIEFBIG1hcHBlZCIsIHRpdGxlID0gIkFsbCBBQSAtIFJlZHVjZWQgTldJIikgKw0KICAjIHRoZW1lX0Nvd3NNb2QxDQogIHRoZW1lX3NtRmFjZXQgKw0KICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSArDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNDUsIGhqdXN0ID0gMSkpICsNCiAgeWxpbSgtMTAwLDEwMCkgDQogICMgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgbHR5ID0gImRhc2hlZCIsIGNvbG9yID0gJ2JsYWNrJykNCmdnc2F2ZSgiRGlmZmVybmNlTWFwcGVkTldJcmVkX0FsbEFBX3JlZHVjZWQucG5nIiwgd2lkdGggPSA1LjUsIGhlaWdodCA9IDMuNSwgZHBpID0gMzAwKQ0KDQojIyBkYXRhdGFibGUNCndldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBncm91cF9ieShJTUFHRV9ZUikgJT4lIA0KICBzdW1tYXJpemUoY250X2J5X3Byb3YgID0gbigpLCBtZWFuLlBlcmNXZXROV0kgPSBtZWFuKFBlcmNXZXROV0kpLCBtZWFuLlBlcmNXZXQzZiA9IG1lYW4oUGVyY1dldDNmKSxzdW0uQUF2MTVBY3JlID0gc3VtKEFBaWRBY3JlKSkgJT4lIA0KICBtdXRhdGUoZGlmLlBlcmNBQTNGX05XSSA9IG1lYW4uUGVyY1dldDNmLW1lYW4uUGVyY1dldE5XSSkgJT4lIA0KICBmaWx0ZXIoSU1BR0VfWVIgPjApICU+JSANCiAgZGF0YXRhYmxlKGZpbHRlciA9ICd0b3AnLGNhcHRpb24gPSAibWVhbl9BQWRpZmYiKQ0KDQpgYGANCg0KDQojIyMgRGlmZmVyZW5jZSBpbiBwZXJjZW50IEFBIG1hcHBlZCBieSAzZiBhbmQgcmVkdWNlZCBOV0kgRElTVFJJQ1QNCg0KYGBge3J9DQoNCndldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBncm91cF9ieShEaXN0cmljdCwgSU1BR0VfWVIpICU+JSANCiAgc3VtbWFyaXplKGNudF9ieV9wcm92ICA9IG4oKSwgbWVhbi5QZXJjV2V0TldJID0gbWVhbihQZXJjV2V0TldJKSwgbWVhbi5QZXJjV2V0M2YgPSBtZWFuKFBlcmNXZXQzZiksc3VtLkFBdjE1QWNyZSA9IHN1bShBQWlkQWNyZSkpICU+JSANCiAgbXV0YXRlKGRpZi5QZXJjQUEzRl9OV0kgPSBtZWFuLlBlcmNXZXQzZi1tZWFuLlBlcmNXZXROV0kpICU+JSANCiAgbXV0YXRlKHd0Lm1uID0gbWFwMl9kYmwoLnggPSBkaWYuUGVyY0FBM0ZfTldJLCAueSA9IHN1bS5BQXYxNUFjcmUsIC5mPXdlaWdodGVkLm1lYW4pKSAlPiUgDQogIGZpbHRlcihJTUFHRV9ZUiA+MCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9SU1BR0VfWVIsIHkgPSBkaWYuUGVyY0FBM0ZfTldJKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvcj0ncmVkJywgc2l6ZT0xLjIsIGFscGhhPTAuNSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplPXN1bS5BQXYxNUFjcmUpLCBjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAuMykgKw0KICBsYWJzKHggPSAiTldJIGltYWdlIHllYXIiLCB5ID0gIkRpZmZlcmVuY2UgaW4gJSBBQSBtYXBwZWQiLCB0aXRsZSA9ICJSZWR1Y2VkIE5XSSIpICsNCiAgZmFjZXRfd3JhcCh+RGlzdHJpY3QpICsNCiAgIyB0aGVtZV9Db3dzTW9kMQ0KICB0aGVtZV9zbUZhY2V0ICsNCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgKw0KICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKSArDQogIHlsaW0oLTEwMCwxMDApDQoNCiMgZ2dzYXZlKCJEaWZmZXJuY2VNYXBwZWROV0lyZWRfRGlzdHJpY3QucG5nIiwgd2lkdGggPSA3LjUsIGhlaWdodCA9IDUuNSwgZHBpID0gMzAwKQ0KDQoNCmBgYA0KIyMgRGlmZmVyZW5jZSBpbiBwZXJjZW50IEFBIG1hcHBlZCBieSAzZiBhbmQgcmVkdWNlZCBOV0kgRElWSVNJT04NCg0KYGBge3J9DQoNCndldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBncm91cF9ieShESVZJU0lPTiwgSU1BR0VfWVIpICU+JSANCiAgc3VtbWFyaXplKGNudF9ieV9wcm92ICA9IG4oKSwgbWVhbi5QZXJjV2V0TldJID0gbWVhbihQZXJjV2V0TldJKSwgbWVhbi5QZXJjV2V0M2YgPSBtZWFuKFBlcmNXZXQzZiksc3VtLkFBdjE1QWNyZSA9IHN1bShBQWlkQWNyZSkpICU+JSANCiAgbXV0YXRlKGRpZi5QZXJjQUEzRl9OV0kgPSBtZWFuLlBlcmNXZXQzZi1tZWFuLlBlcmNXZXROV0kpICU+JSANCiAgbXV0YXRlKHd0Lm1uID0gbWFwMl9kYmwoLnggPSBkaWYuUGVyY0FBM0ZfTldJLCAueSA9IHN1bS5BQXYxNUFjcmUsIC5mPXdlaWdodGVkLm1lYW4pKSAlPiUgDQogIGZpbHRlcihJTUFHRV9ZUiA+MCkgJT4lIA0KICBnZ3Bsb3QoYWVzKHg9SU1BR0VfWVIsIHkgPSBkaWYuUGVyY0FBM0ZfTldJKSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvcj0ncmVkJywgc2l6ZT0xLjIsIGFscGhhPTAuNSkgKw0KICBnZW9tX3BvaW50KGFlcyhzaXplPXN1bS5BQXYxNUFjcmUpLCBjb2xvciA9ICJibHVlIiwgYWxwaGEgPSAuMykgKw0KICBsYWJzKHggPSAiTldJIGltYWdlIHllYXIiLCB5ID0gIkRpZmZlcmVuY2UgaW4gJSBBQSBtYXBwZWQiLCB0aXRsZSA9ICJSZWR1Y2VkIE5XSSIpICsNCiAgZmFjZXRfd3JhcCh+RElWSVNJT04sIG5jb2wgPSA0KSArDQogICMgdGhlbWVfQ293c01vZDENCiAgdGhlbWVfc21GYWNldCArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpICsNCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkgKw0KICB5bGltKC0xMDAsMTAwKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGx0eSA9ICJkYXNoZWQiLCBzaXplID0gMSwgY29sb3IgPSAnYmxhY2snKQ0KDQojIGdnc2F2ZSgiRGlmZmVybmNlTWFwcGVkTldJcmVkX0RpdmlzaW9uLnBuZyIsIHdpZHRoID0gOCwgaGVpZ2h0ID0gMy43NSwgZHBpID0gMzAwKQ0KDQoNCndldGwudW5pMDFyZWRfd2lkZTEgJT4lIA0KICAjIGZpbHRlcihjbnQgPj0gNykgJT4lIA0KICBncm91cF9ieShESVZJU0lPTiwgSU1BR0VfWVIpICU+JSANCiAgc3VtbWFyaXplKGNudF9ieV9wcm92ICA9IG4oKSwgbWVhbi5QZXJjV2V0TldJID0gbWVhbihQZXJjV2V0TldJKSwgbWVhbi5QZXJjV2V0M2YgPSBtZWFuKFBlcmNXZXQzZiksc3VtLkFBdjE1QWNyZSA9IHN1bShBQWlkQWNyZSkpICU+JSANCiAgbXV0YXRlKGRpZi5QZXJjQUEzRl9OV0kgPSBtZWFuLlBlcmNXZXQzZi1tZWFuLlBlcmNXZXROV0kpICU+JSANCiAgbXV0YXRlKHd0Lm1uID0gbWFwMl9kYmwoLnggPSBkaWYuUGVyY0FBM0ZfTldJLCAueSA9IHN1bS5BQXYxNUFjcmUsIC5mPXdlaWdodGVkLm1lYW4pKSAlPiUgDQogIGZpbHRlcihJTUFHRV9ZUiA+MCkgJT4lIA0KICBkYXRhdGFibGUoZmlsdGVyID0gJ3RvcCcpDQoNCmBgYA0KDQpgYGB7cn0NCiMgZXhwb3J0IGEgdmVyc2lvbiBvZiB0aGUgd2lkZSBBQSB3aXRoIGFsbCB0aGUgc3R1ZmYgZm9yIGpwaW5pbmcgaW4gQXJjDQoNCiMgd2V0bC51bmkwMXJlZF93aWRlMSAlPiUgDQojICAgd3JpdGVfY3N2KCJXaWRlX05XSXJlZF8zRl91bmlfQ0FMQ3NfZm9yX0FBdjE1am9pbi5jc3YiKQ0KDQpgYGANCg0KIyMgUmVncmVzc2lvbiBtb2RlbGluZyANCg0KIyMjIFJlZHVjZWQgTldJIGJ5IERJVklTSU9OIA0KDQpgYGB7cn0NCg0KdW5pLnJlZC5ESVYubkRGIDwtIHdldGwudW5pMDFyZWRfd2lkZTEgJT4lDQogIGdyb3VwX2J5KERJVklTSU9OKSAlPiUgDQogIG5lc3QoKQ0KICANCnVuaS5yZWQuRElWLm5ERiA8LSB1bmkucmVkLkRJVi5uREYgJT4lIA0KICBtdXRhdGUobW9kZWwwMSA9IHB1cnJyOjptYXAoZGF0YSwgfiBsbShUb3RXZXRIYS5ud2kgfiBUb3RXZXRIYS4zZiwgZGF0YSA9IC4pKQ0KKSAgDQoNCiMgRXh0cmFjdCBtb2RlbCBzdW1tYXJpZXM6DQp1bmkucmVkLkRJVi5uREYgPC0gdW5pLnJlZC5ESVYubkRGICU+JSB1bm5lc3QobW9kZWwwMSAlPiUgcHVycnI6Om1hcChicm9vbTo6Z2xhbmNlKSkNCg0KdW5pLnJlZC5ESVYubkRGICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gYWRqLnIuc3F1YXJlZCwgeT0gcmVvcmRlcihESVZJU0lPTixhZGouci5zcXVhcmVkKSkpICsNCiAgIyBnZW9tX2Jhcmgoc3RhdCA9ICdpZGVudGl0eScsIGFlcyhmaWxsID0gcC52YWx1ZSkpICsNCiAgZ2VvbV9iYXJoKHN0YXQgPSAnaWRlbnRpdHknLCBmaWxsID0gJ2l2b3J5MicsIGNvbG9yID0gJ2l2b3J5MycpICsNCiAgbGFicyh4PWV4cHJlc3Npb24oJ2FkanVzdGVkIFInXnsyfSksIHkgPSAiIiwgdGl0bGUgPSAiTGluZWFyIG1vZGVsczogM0YgYXJlYSB+IE5XSSBhcmVhIikgKw0KICB0aGVtZV9Db3dzTW9kMQ0KIyBnZ3NhdmUoIkxpbmVyTW9kZWxzX0RpdmlzaW9uX3JlZC5wbmciLCBkcGkgPSAzMDAsIHdpZHRoID0gNy41LCBoZWlnaHQgPSAzKQ0KDQojICMgRXh0cmFjdCBtb2RlbCBzdW1tYXJpZXM6DQojIGJ5X2NvdW50cnkgJT4lIHVubmVzdChtb2RlbCAlPiUgcHVycnI6Om1hcChicm9vbTo6Z2xhbmNlKSkNCg0KIyMgZGF0YSB0YWJsZQ0KdW5pLnJlZC5ESVYubkRGICU+JSANCiAgZGF0YXRhYmxlKGZpbHRlcj0ndG9wJykNCg0KYGBgDQoNCiMjIyBOV0kgaW1hZ2UgeWVhcjogYWRqdXN0IFIyIGxtDQpgYGB7cn0NCnVuaS5yZWQuSW1nWXIubkRGIDwtIHdldGwudW5pMDFyZWRfd2lkZTEgJT4lDQogIGZpbHRlcihJTUFHRV9ZUiA+MCkgJT4lIA0KICBncm91cF9ieShJTUFHRV9ZUikgJT4lIA0KICBtdXRhdGUoY250ID0gbigpKSAlPiUNCiAgZmlsdGVyKGNudD49MjUpICU+JSAjIG5vdGUgbmVlZCB0byBmaWx0ZXIgdG8gaGF2ZSA+MSByZWNvcmQuIEknbSBnb2luZyBmb3IgbWluaW11bSBuIG9mIDI1IEFBIGluIHRoYXQgcGFydGljdWxhciANCiAgbmVzdCgpICU+JSANCiAgbXV0YXRlKG1vZGVsMDEgPSBwdXJycjo6bWFwKGRhdGEsIH4gbG0oVG90V2V0SGEubndpIH4gVG90V2V0SGEuM2YsIGRhdGEgPSAuKSkpDQogIA0KIyB1bmkucmVkLkltZ1lyLm5ERiA8LSB1bmkucmVkLkltZ1lyLm5ERiAlPiUgDQojICAgbXV0YXRlKG1vZGVsMDIgPSBwdXJycjo6bWFwKGRhdGEsIH4gbG0oVG90V2V0SGEubndpIH4gVG90V2V0SGEuM2YsIGRhdGEgPSAuKSkpICANCg0KIyBFeHRyYWN0IG1vZGVsIHN1bW1hcmllczoNCnVuaS5yZWQuSW1nWXIubkRGIDwtIHVuaS5yZWQuSW1nWXIubkRGICU+JSB1bm5lc3QobW9kZWwwMSAlPiUgcHVycnI6Om1hcChicm9vbTo6Z2xhbmNlKSkNCg0KDQoNCnVuaS5yZWQuSW1nWXIubkRGICU+JSANCiAgIyBnZ3Bsb3QoYWVzKHggPSBhZGouci5zcXVhcmVkLCB5PSByZW9yZGVyKElNQUdFX1lSLGFkai5yLnNxdWFyZWQpKSkgKw0KICAjIGdncGxvdChhZXMoeCA9IElNQUdFX1lSLCB5ID0gYWRqLnIuc3F1YXJlZCkpICsNCiAgZ2dwbG90KGFlcyh4ID0gSU1BR0VfWVIsIHkgPSBhZGouci5zcXVhcmVkKSkgKw0KICAjIGdlb21fYmFyaChzdGF0ID0gJ2lkZW50aXR5JywgYWVzKGZpbGwgPSBwLnZhbHVlKSkgKw0KICBnZW9tX2JhcihzdGF0ID0gJ2lkZW50aXR5JywgZmlsbCA9ICdpdm9yeTInLCBjb2xvciA9ICdpdm9yeTMnKSArDQogIGdlb21fcG9pbnQoKSArDQogIHhsaW0oMTk3MCwyMDEwKSArDQogIGxhYnMoeT1leHByZXNzaW9uKCdhZGp1c3RlZCByJ157Mn0pLCB4ID0gIk5XSSBpbWFnZSB5ZWFyIiwgdGl0bGUgPSAiTGluZWFyIG1vZGVsczogM0YgYXJlYSB+IE5XSSBhcmVhIikNCg0KIyMgZGF0YSB0YWJsZQ0KdW5pLnJlZC5JbWdZci5uREYgJT4lIA0KICBkYXRhdGFibGUoZmlsdGVyPSd0b3AnKQ0KICANCmBgYA0KDQoNCiMjIENsaW1hdGUgbW9kZWxpbmc6DQoNCg0KYGBge3IsIG1lc3NhZ2U9RkFMU0V9DQoNCiMgd2V0bC51bmkwMXJlZF93aWRlMQ0KDQp2cGQuYWEgPC0gcmVhZF9jc3YoImRhdGEvRmluYWxfc2hhcGVmaWxlL1YxNV9kYXRhL3YxNWNlbnRyUFJJU01Ob3JtYWxfTFUuY3N2IikNCnZwZC5hYSA8LSB2cGQuYWEgJT4lIA0KICBkcGx5cjo6c2VsZWN0KEFBdjE0aWQsIHZwZE14MzB5ciwgUHJpc21QUFQsIFByaXNtVE1lYW4pICU+JSANCiAgbmEub21pdCgpDQoNCiNqb2luIHdpdGggdGhlIHRhYnVsYXRlZCBmdWxsIGRhdGEgc2V0DQp2cGQuYWEgPC0gbGVmdF9qb2luKHZwZC5hYSwgd2V0bC51bmkwMXJlZF93aWRlMSwgYnkgPSAiQUF2MTRpZCIpDQoNCnZwZC5hYSAlPiUgDQogIG11dGF0ZShQZXJjQUFXZXREaWZmM2YucmVkTldJID0gUGVyY1dldDNmLVBlcmNXZXROV0kpICU+JSANCiAgbXV0YXRlKHZwZEludCA9IGFzLmludGVnZXIodnBkTXgzMHlyKSkgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSB2cGRNeDMweXIsIHkgPSBQZXJjQUFXZXREaWZmM2YucmVkTldJKSkgKw0KICAjIGdlb21fcG9pbnQoYWxwaGEgPSAwLjA1KSArDQogICMgZ2VvbV9kZW5zaXR5XzJkKCkgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAnbG0nKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gJ3JlZCcsIGFscGhhPTAuNDEsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4yKSArDQogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBxdWFudGlsZSh2cGQuYWEkUGVyY0FBV2V0RGlmZjNmLnJlZE5XSSwgYygwLjA1LCAwLjk1KSkpDQoNCg0KDQoNCmBgYA0KDQpgYGB7cn0NCg0KIyMjIGJveHBsb3RzIQ0KcHAxIDwtIHZwZC5hYSAlPiUgDQogIG11dGF0ZShQZXJjQUFXZXREaWZmM2YucmVkTldJID0gUGVyY1dldDNmLVBlcmNXZXROV0kpICU+JSANCiAgbXV0YXRlKHZwZEludCA9IGFzLmZhY3Rvcihhcy5pbnRlZ2VyKHZwZE14MzB5cikpKSAlPiUgDQogIGdncGxvdChhZXMoeCA9IHZwZE14MzB5ciwgeSA9IFBlcmNBQVdldERpZmYzZi5yZWROV0kpKSArDQogIGdlb21fYm94cGxvdChhZXMoZ3JvdXA9dnBkSW50KSwgb3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gIml2b3J5MiIpICsNCiAgbGFicyh4ID0gIk1heGltdW0gdmFwb3IgcHJlc3N1cmUgZGVmaWNpdCAoaFBhKSIsIHkgPSAiRGlmZmVyZW5jZSBpbiAlIEFBIG1hcHBlZCIsIHRpdGxlID0gIlZQRCIpICsNCiAgIyBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGNvbG9yID0gJ3JlZCcsIGFscGhhPTAuNDEsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4yKSArDQogIHRoZW1lX3NtRmFjZXQNCiMgZ2dzYXZlKCJ2cGRfQWxsQUFfYm94cGxvdC5wbmciLHdpZHRoID0gNiwgaGVpZ2h0ID0gNC41LCBkcGkgPSAzMDApDQogIA0KICANCiMjIGJveHBsb3Q6IHBwdA0KcHAyIDwtIHZwZC5hYSAlPiUgDQogIG11dGF0ZShQZXJjQUFXZXREaWZmM2YucmVkTldJID0gUGVyY1dldDNmLVBlcmNXZXROV0kpICU+JSANCiAgbXV0YXRlKFBQVEludCA9IGFzLmZhY3Rvcihhcy5pbnRlZ2VyKFByaXNtUFBUKSkpICU+JQ0KICBtdXRhdGUocXVhcnRpbGUuUFBUID0gbnRpbGUoUHJpc21QUFQsIDEwKSkgJT4lIA0KICAjIG11dGF0ZSh0ID0gbWFwX2ludCgueD0uJFByaXNtUFBULCAuZiA9IGN1dF9lcXVhbF9yYW5nZXMpKQ0KICAjIGdncGxvdChhZXMoeCA9IHF1YXJ0aWxlLlBQVCwgeSA9IFBlcmNBQVdldERpZmYzZi5yZWROV0kpKSArDQogIGdncGxvdChhZXMoeCA9IFByaXNtUFBULCB5ID0gUGVyY0FBV2V0RGlmZjNmLnJlZE5XSSkpICsNCiAgIyBnZW9tX3BvaW50KGFscGhhID0gLjA1MSwgY29sb3IgPSAnZGFya2dyZXknLCBzaXplID0gMi41KSArDQogICMgZ2VvbV9ib3hwbG90KGFlcyhncm91cD10KSwgb3V0bGllci5zaGFwZSA9IE5BLCBmaWxsID0gIml2b3J5MiIpICsNCiAgbGFicyh4ID0gIlByZWNpcGl0YXRpb24gKG1tKSIsIHkgPSAiRGlmZmVyZW5jZSBpbiAlIEFBIG1hcHBlZCIsIHRpdGxlID0gIlByZWNpcGl0YXRpb24iKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgY29sb3IgPSAncmVkJywgYWxwaGE9MC42LCBsdHkgPSAnZGFzaGVkJywgc2l6ZSA9IDEuMikgKw0KICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IFRSVUUpICsNCiAgdGhlbWVfc21GYWNldA0KIyBnZ3NhdmUoIlByaW1zUFBUX0FsbEFBX2JveHBsb3QucG5nIix3aWR0aCA9IDYsIGhlaWdodCA9IDQuNSwgZHBpID0gMzAwKQ0KDQojIyBib3hwbG90OiB0ZW1wDQpwcDMgPC0gdnBkLmFhICU+JSANCiAgbXV0YXRlKFBlcmNBQVdldERpZmYzZi5yZWROV0kgPSBQZXJjV2V0M2YtUGVyY1dldE5XSSkgJT4lIA0KICBtdXRhdGUoVGVtcEludCA9IGFzLmZhY3Rvcihhcy5pbnRlZ2VyKFByaXNtVE1lYW4pKSkgJT4lDQogIG11dGF0ZShxdWFydGlsZS5QcmlzbVRNZWFuID0gbnRpbGUoUHJpc21UTWVhbiwgMTApKSAlPiUgDQogICMgbXV0YXRlKHQgPSBtYXBfaW50KC54PS4kUHJpc21QUFQsIC5mID0gY3V0X2VxdWFsX3JhbmdlcykpDQogICMgZ2dwbG90KGFlcyh4ID0gcXVhcnRpbGUuUFBULCB5ID0gUGVyY0FBV2V0RGlmZjNmLnJlZE5XSSkpICsNCiAgZ2dwbG90KGFlcyh4ID0gUHJpc21UTWVhbiwgeSA9IFBlcmNBQVdldERpZmYzZi5yZWROV0kpKSArDQogICMgZ2VvbV9wb2ludChhbHBoYSA9IC4wNTEsIGNvbG9yID0gJ2RhcmtncmV5Jywgc2l6ZSA9IDIuNSkgKw0KICBnZW9tX2JveHBsb3QoYWVzKGdyb3VwPVRlbXBJbnQpLCBvdXRsaWVyLnNoYXBlID0gTkEsIGZpbGwgPSAiaXZvcnkyIikgKw0KICBsYWJzKHggPSAiVGVtcGVyYXR1cmUgKEMpIiwgeSA9ICJEaWZmZXJlbmNlIGluICUgQUEgbWFwcGVkIiwgdGl0bGUgPSAiTWVhbiB0ZW1wZXJhdHVyZSIpICsNCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSkgKw0KICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICdyZWQnLCBhbHBoYT0wLjYsIGx0eSA9ICdkYXNoZWQnLCBzaXplID0gMS4yKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVFJVRSkgKw0KICB0aGVtZV9zbUZhY2V0DQojIGdnc2F2ZSgiUHJpbXNURU1QX0FsbEFBX2JveHBsb3QucG5nIix3aWR0aCA9IDYsIGhlaWdodCA9IDQuNSwgZHBpID0gMzAwKQ0KDQoNCiMgcHAzIDwtIGNvd3Bsb3Q6OnBsb3RfZ3JpZChwcDEsIHBwMiwgbGFiZWxzID0gYygiQSIsICJCIiksIG5yb3cgPSAyLCBhbGlnbiA9ICJWIikNCg0KIyBzYXZlX3Bsb3QocHAzLCBmaWxlbmFtZSA9ICIycGFuZWxfcGxvdC5wbmciLG5jb2wgPSAxLCBiYXNlX2hlaWdodCA9IDYsIGJhc2Vfd2lkdGggPSA3LjUpDQoNCiMgIyMjIFRlcm5hcnlwbG90IC4uLiBpbnRlcnN0aW5nYiBidXQgbm90IG5vdw0KIyBsaWJyYXJ5KGdndGVybikNCiMgZGF0YSgnRmVsZHNwYXInKQ0KIyBnZ3Rlcm4oRmVsZHNwYXIsYWVzKEFiLEFuLE9yKSkgKyANCiMgIGdlb21fZGVuc2l0eV90ZXJuKGFlcyhjb2xvcj0uLmxldmVsLi4pLGJpbnM9NSkgKw0KIyAgZ2VvbV9wb2ludCgpDQojIA0KIyBnZ3Rlcm4odnBkLmFhLGFlcyhQcmlzbVBQVCxQcmlzbVRNZWFuLHZwZE14MzB5cikpICsgDQojICBnZW9tX2RlbnNpdHlfdGVybihhZXMoY29sb3I9Li5sZXZlbC4uKSxiaW5zPTUpICsNCiMgIGdlb21fcG9pbnQoKQ0KIyANCiMgIyAjIyMgaGV4IHBsb3QNCiMgIyB2cGQuYWEgJT4lIA0KIyAjICAgbXV0YXRlKFBlcmNBQVdldERpZmYzZi5yZWROV0kgPSBQZXJjV2V0M2YtUGVyY1dldE5XSSkgJT4lIA0KIyAjICAgbXV0YXRlKHZwZEludCA9IGFzLmZhY3Rvcihhcy5pbnRlZ2VyKHZwZE14MzB5cikpKSAlPiUgDQojICMgICBnZ3Bsb3QoYWVzKHggPSB2cGRNeDMweXIsIHkgPSBQZXJjQUFXZXREaWZmM2YucmVkTldJKSkgKw0KIyAjICAgZ2VvbV9oZXgoYmlucz0zNSwgYWxwaGEgPSAwLjk1KSArDQojICMgICBzY2FsZV9maWxsX3ZpcmlkaXMoZGlyZWN0aW9uID0gLTEpICsNCiMgIyAgIGdlb21fcXVhbnRpbGUoKSANCg0KDQpgYGANCiMjIyBDbGltYXRldmFycyBzY2F0dGVycGxvdHMNCmBgYHtyfQ0KDQpwbG90MDEgPC0gdnBkLmFhICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBQcmlzbVBQVCwgeSA9IGRpZmYuQUFwZXJjV2V0KSkgKw0KICBnZW9tX3BvaW50KGFscGhhID0gMC4wOCkgKw0KICBnZW9tX3Ntb290aCgpICsNCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgbHR5ID0gJ2Rhc2hlZCcsY29sb3I9J3JlZCcsc2l6ZT0xLjIpICsNCiAgbGFicyh4PSJQcmVjaXBpdGF0aW9uIChtbSkiLCB5ID0gIkRpZmZlcmVuY2UgaW4gJUFBIG1hcHBlZCIpDQpwbG90MDENCiMgc2F2ZV9wbG90KHBsb3QgPSBwbG90MDEsZmlsZW5hbWUgPSAicHB0X3ZzX0RpZmZBQS5wbmciKQ0KDQpgYGANCg0KIyMjIExvb2tpbmcgYXQgM2YgcG9seWdvbiBkaXRyaWJ1dGlvbg0KYGBge3J9DQoNCkYzcG9seSA8LSBtYXAyKC54ID0gImRhdGEvRmluYWxfc2hhcGVmaWxlL3YxNV9kYXRhIiwgLnkgPSAiRmluM0ZfQUF2MTRESVMiLCAuZiA9ICByZWFkT0dSKSAjIyMgTm90ZTogdGhpcyBhbHNvIHdvcmtzDQojICMjIyBWaWV3IGF0dHJpYnV0ZSBkYXRhDQoNCg0KRjNwb2x5LnRibCA8LSBhc190aWJibGUoRjNwb2x5W1sxXV1AZGF0YSkgDQojIG5hbWVzKEYzcG9seS50YmwpDQoNCkYzcG9seS50YmwgPC0gbGVmdF9qb2luKEYzcG9seS50YmwsZWNvcmVnLmx1LGJ5PSJBQXYxNGlkIikNCg0KIyBGM3BvbHkudGJsICU+JSBkYXRhdGFibGUoKQ0KDQojIyBzdW1tYXJpemUgdG90YWwgQUEgYXJlYQ0KRjNwb2x5LnRibCAlPiUgDQogICMgbmFtZXMoKSAlPiUgDQogIHN1bW1hcml6ZShzdW0ucG9seUhhID0gc3VtKFBvbHlBcmVhSGEpLCBtZWFuLnBvbHlIYSA9IG1lYW4oUG9seUFyZWFIYSwgbmEucm0gPSBUUlVFKSwgbWVkLnBvbHlIYSA9IG1lZGlhbihQb2x5QXJlYUhhKSwgY250LnBvbHkgPSBuKCksIG1pbi5wb2x5SGEgPSBtaW4oUG9seUFyZWFIYSksIG1heC5wb2x5SGEgPSBtYXgoUG9seUFyZWFIYSkpICU+JQ0KICBtdXRhdGUoc3VtLnBvbHlBY3JlcyA9IDIuNDcxMDUqc3VtLnBvbHlIYSkgJT4lIA0KICBtdXRhdGUobWVhbi5wb2x5QWNyZXMgPSAyLjQ3MTA1Km1lYW4ucG9seUhhKSAlPiUgDQogIG11dGF0ZShtZWQucG9seUFjcmVzID0gMi40NzEwNSptZWQucG9seUhhKSAlPiUgDQogIG11dGF0ZShtaW4ucG9seUFjcmVzID0gMi40NzEwNSptaW4ucG9seUhhKSAlPiUgDQogIG11dGF0ZShtYXgucG9seUFjcmVzID0gMi40NzEwNSptYXgucG9seUhhKQ0KDQoNCkYzcG9seS50YmwgPC0gRjNwb2x5LnRibCAlPiUNCiAgbXV0YXRlKFBvbHlBcmVhQWNyZSA9IFBvbHlBcmVhSGEqMi40NzEwNSkgDQogIA0KRjNwb2x5LnRibCAlPiUgZGF0YXRhYmxlKCkNCg0KYGBgDQoNCg==